From 0dd0a5bc033a95ce980ccd13004afeac35521409 Mon Sep 17 00:00:00 2001 From: steveklabnik Date: Thu, 5 Apr 2018 13:27:41 -0400 Subject: initialize the rustc book --- src/doc/rustc/.gitignore | 1 + src/doc/rustc/book.toml | 5 +++++ src/doc/rustc/src/SUMMARY.md | 3 +++ src/doc/rustc/src/chapter_1.md | 1 + 4 files changed, 10 insertions(+) create mode 100644 src/doc/rustc/.gitignore create mode 100644 src/doc/rustc/book.toml create mode 100644 src/doc/rustc/src/SUMMARY.md create mode 100644 src/doc/rustc/src/chapter_1.md (limited to 'src') diff --git a/src/doc/rustc/.gitignore b/src/doc/rustc/.gitignore new file mode 100644 index 00000000000..7585238efed --- /dev/null +++ b/src/doc/rustc/.gitignore @@ -0,0 +1 @@ +book diff --git a/src/doc/rustc/book.toml b/src/doc/rustc/book.toml new file mode 100644 index 00000000000..821ad8fb09c --- /dev/null +++ b/src/doc/rustc/book.toml @@ -0,0 +1,5 @@ +[book] +authors = ["steveklabnik"] +multilingual = false +src = "src" +title = "The rustc book" diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md new file mode 100644 index 00000000000..7390c82896e --- /dev/null +++ b/src/doc/rustc/src/SUMMARY.md @@ -0,0 +1,3 @@ +# Summary + +- [Chapter 1](./chapter_1.md) diff --git a/src/doc/rustc/src/chapter_1.md b/src/doc/rustc/src/chapter_1.md new file mode 100644 index 00000000000..b743fda3546 --- /dev/null +++ b/src/doc/rustc/src/chapter_1.md @@ -0,0 +1 @@ +# Chapter 1 -- cgit 1.4.1-3-g733a5 From b99418d4b031d8586b6767283a8628ba5cbca1b1 Mon Sep 17 00:00:00 2001 From: steveklabnik Date: Thu, 5 Apr 2018 14:41:48 -0400 Subject: Add rustc book to the build system --- src/bootstrap/builder.rs | 4 ++-- src/bootstrap/doc.rs | 1 + src/bootstrap/test.rs | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 3f5ec4933d0..16e29427c60 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -323,7 +323,7 @@ impl<'a> Builder<'a> { test::Cargotest, test::Cargo, test::Rls, test::ErrorIndex, test::Distcheck, test::RunMakeFullDeps, test::Nomicon, test::Reference, test::RustdocBook, test::RustByExample, - test::TheBook, test::UnstableBook, + test::TheBook, test::UnstableBook, test::RustcBook, test::Rustfmt, test::Miri, test::Clippy, test::RustdocJS, test::RustdocTheme, // Run run-make last, since these won't pass without make on Windows test::RunMake), @@ -331,7 +331,7 @@ impl<'a> Builder<'a> { Kind::Doc => describe!(doc::UnstableBook, doc::UnstableBookGen, doc::TheBook, doc::Standalone, doc::Std, doc::Test, doc::WhitelistedRustc, doc::Rustc, doc::ErrorIndex, doc::Nomicon, doc::Reference, doc::Rustdoc, doc::RustByExample, - doc::CargoBook), + doc::RustcBook, doc::CargoBook), Kind::Dist => describe!(dist::Docs, dist::RustcDocs, dist::Mingw, dist::Rustc, dist::DebuggerScripts, dist::Std, dist::Analysis, dist::Src, dist::PlainSourceTarball, dist::Cargo, dist::Rls, dist::Rustfmt, dist::Extended, diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 4237ded2215..0618d1d89aa 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -71,6 +71,7 @@ book!( Nomicon, "src/doc/nomicon", "nomicon"; Reference, "src/doc/reference", "reference"; Rustdoc, "src/doc/rustdoc", "rustdoc"; + RustcBook, "src/doc/rustc", "rustc"; RustByExample, "src/doc/rust-by-example", "rust-by-example"; ); diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index c175d2c6901..569bd841726 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1121,6 +1121,7 @@ test_book!( Nomicon, "src/doc/nomicon", "nomicon", default=false; Reference, "src/doc/reference", "reference", default=false; RustdocBook, "src/doc/rustdoc", "rustdoc", default=true; + RustcBook, "src/doc/rustc", "rustc", default=true; RustByExample, "src/doc/rust-by-example", "rust-by-example", default=false; TheBook, "src/doc/book", "book", default=false; UnstableBook, "src/doc/unstable-book", "unstable-book", default=true; -- cgit 1.4.1-3-g733a5 From 7de5b6034d035f8dc85cb073b2dde3b611a3d822 Mon Sep 17 00:00:00 2001 From: steveklabnik Date: Thu, 5 Apr 2018 14:53:58 -0400 Subject: update doc index to link to the rustc book --- src/doc/index.md | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/doc/index.md b/src/doc/index.md index 2ea889da1fd..3a4f51069fc 100644 --- a/src/doc/index.md +++ b/src/doc/index.md @@ -43,6 +43,10 @@ Rust's standard library has [extensive API documentation](std/index.html), with explanations of how to use various things, as well as example code for accomplishing various tasks. +## The Rustc Book + +[The Rustc Book](rustc/index.html) describes the Rust compiler, `rustc`. + ## The Cargo Book [The Cargo Book](cargo/index.html) is a guide to Cargo, Rust's build tool and dependency manager. -- cgit 1.4.1-3-g733a5 From c942bf42fcb7dfb39ad68aebd0365c14818bdcfb Mon Sep 17 00:00:00 2001 From: steveklabnik Date: Fri, 6 Apr 2018 09:11:09 -0400 Subject: Add a TOC --- src/doc/rustc/src/SUMMARY.md | 14 ++++++++++++-- src/doc/rustc/src/chapter_1.md | 1 - src/doc/rustc/src/codegen-options/index.md | 1 + src/doc/rustc/src/command-line-arguments/index.md | 1 + src/doc/rustc/src/contributing.md | 1 + src/doc/rustc/src/lints/groups.md | 1 + src/doc/rustc/src/lints/index.md | 1 + src/doc/rustc/src/lints/levels.md | 1 + src/doc/rustc/src/lints/listing/allowed-by-default.md | 1 + src/doc/rustc/src/lints/listing/deny-by-default.md | 1 + src/doc/rustc/src/lints/listing/index.md | 1 + src/doc/rustc/src/lints/listing/warn-by-default.md | 1 + src/doc/rustc/src/what-is-rustc.md | 1 + 13 files changed, 23 insertions(+), 3 deletions(-) delete mode 100644 src/doc/rustc/src/chapter_1.md create mode 100644 src/doc/rustc/src/codegen-options/index.md create mode 100644 src/doc/rustc/src/command-line-arguments/index.md create mode 100644 src/doc/rustc/src/contributing.md create mode 100644 src/doc/rustc/src/lints/groups.md create mode 100644 src/doc/rustc/src/lints/index.md create mode 100644 src/doc/rustc/src/lints/levels.md create mode 100644 src/doc/rustc/src/lints/listing/allowed-by-default.md create mode 100644 src/doc/rustc/src/lints/listing/deny-by-default.md create mode 100644 src/doc/rustc/src/lints/listing/index.md create mode 100644 src/doc/rustc/src/lints/listing/warn-by-default.md create mode 100644 src/doc/rustc/src/what-is-rustc.md (limited to 'src') diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 7390c82896e..197ff6ac410 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -1,3 +1,13 @@ -# Summary +# The Rustc Book -- [Chapter 1](./chapter_1.md) +- [What is rustc?](what-is-rustc.md) +- [Command-line arguments](command-line-arguments/index.md) +- [Lints](lints/index.md) + - [Lint levels](lints/levels.md) + - [Lint Groups](lints/groups.md) + - [Lint listing](lints/listing/index.md) + - [Allowed-by-default lints](lints/listing/allowed-by-default.md) + - [Warn-by-default lints](lints/listing/warn-by-default.md) + - [Deny-by-default lints](lints/listing/deny-by-default.md) +- [Codegen options](codegen-options/index.md) +- [Contributing to `rustc`](contributing.md) \ No newline at end of file diff --git a/src/doc/rustc/src/chapter_1.md b/src/doc/rustc/src/chapter_1.md deleted file mode 100644 index b743fda3546..00000000000 --- a/src/doc/rustc/src/chapter_1.md +++ /dev/null @@ -1 +0,0 @@ -# Chapter 1 diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md new file mode 100644 index 00000000000..4350db56ef6 --- /dev/null +++ b/src/doc/rustc/src/codegen-options/index.md @@ -0,0 +1 @@ +# Codegen options diff --git a/src/doc/rustc/src/command-line-arguments/index.md b/src/doc/rustc/src/command-line-arguments/index.md new file mode 100644 index 00000000000..162c0e48d4e --- /dev/null +++ b/src/doc/rustc/src/command-line-arguments/index.md @@ -0,0 +1 @@ +# Command-line arguments diff --git a/src/doc/rustc/src/contributing.md b/src/doc/rustc/src/contributing.md new file mode 100644 index 00000000000..e21b6fbd14a --- /dev/null +++ b/src/doc/rustc/src/contributing.md @@ -0,0 +1 @@ +# Contributing to rustc diff --git a/src/doc/rustc/src/lints/groups.md b/src/doc/rustc/src/lints/groups.md new file mode 100644 index 00000000000..f35b53b6b99 --- /dev/null +++ b/src/doc/rustc/src/lints/groups.md @@ -0,0 +1 @@ +# Lint Groups diff --git a/src/doc/rustc/src/lints/index.md b/src/doc/rustc/src/lints/index.md new file mode 100644 index 00000000000..112c576a22c --- /dev/null +++ b/src/doc/rustc/src/lints/index.md @@ -0,0 +1 @@ +# Lints diff --git a/src/doc/rustc/src/lints/levels.md b/src/doc/rustc/src/lints/levels.md new file mode 100644 index 00000000000..6aed1e979f3 --- /dev/null +++ b/src/doc/rustc/src/lints/levels.md @@ -0,0 +1 @@ +# Lint levels diff --git a/src/doc/rustc/src/lints/listing/allowed-by-default.md b/src/doc/rustc/src/lints/listing/allowed-by-default.md new file mode 100644 index 00000000000..19c4d94edbb --- /dev/null +++ b/src/doc/rustc/src/lints/listing/allowed-by-default.md @@ -0,0 +1 @@ +# Allowed-by-default lints diff --git a/src/doc/rustc/src/lints/listing/deny-by-default.md b/src/doc/rustc/src/lints/listing/deny-by-default.md new file mode 100644 index 00000000000..0f6fd4fe931 --- /dev/null +++ b/src/doc/rustc/src/lints/listing/deny-by-default.md @@ -0,0 +1 @@ +# Deny-by-default lints diff --git a/src/doc/rustc/src/lints/listing/index.md b/src/doc/rustc/src/lints/listing/index.md new file mode 100644 index 00000000000..e279644e644 --- /dev/null +++ b/src/doc/rustc/src/lints/listing/index.md @@ -0,0 +1 @@ +# Lint listing diff --git a/src/doc/rustc/src/lints/listing/warn-by-default.md b/src/doc/rustc/src/lints/listing/warn-by-default.md new file mode 100644 index 00000000000..5342b954a09 --- /dev/null +++ b/src/doc/rustc/src/lints/listing/warn-by-default.md @@ -0,0 +1 @@ +# Warn-by-default lints diff --git a/src/doc/rustc/src/what-is-rustc.md b/src/doc/rustc/src/what-is-rustc.md new file mode 100644 index 00000000000..ac4c33e4b71 --- /dev/null +++ b/src/doc/rustc/src/what-is-rustc.md @@ -0,0 +1 @@ +# What is rustc? -- cgit 1.4.1-3-g733a5 From 4f6ed513d11baa71d39a1a048a6ccb67846775a1 Mon Sep 17 00:00:00 2001 From: steveklabnik Date: Fri, 6 Apr 2018 09:12:02 -0400 Subject: fix authorship in book.toml --- src/doc/rustc/book.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/doc/rustc/book.toml b/src/doc/rustc/book.toml index 821ad8fb09c..8adc05c5137 100644 --- a/src/doc/rustc/book.toml +++ b/src/doc/rustc/book.toml @@ -1,5 +1,5 @@ [book] -authors = ["steveklabnik"] +authors = ["The Rust Project Developers"] multilingual = false src = "src" title = "The rustc book" -- cgit 1.4.1-3-g733a5 From 5424dc46b719a86d94578ab260798c21bc42ea7e Mon Sep 17 00:00:00 2001 From: steveklabnik Date: Fri, 6 Apr 2018 09:32:57 -0400 Subject: write headings for command line arguments --- src/doc/rustc/src/SUMMARY.md | 2 +- src/doc/rustc/src/command-line-arguments.md | 57 +++++++++++++++++++++++ src/doc/rustc/src/command-line-arguments/index.md | 1 - 3 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 src/doc/rustc/src/command-line-arguments.md delete mode 100644 src/doc/rustc/src/command-line-arguments/index.md (limited to 'src') diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 197ff6ac410..ba70c745327 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -1,7 +1,7 @@ # The Rustc Book - [What is rustc?](what-is-rustc.md) -- [Command-line arguments](command-line-arguments/index.md) +- [Command-line arguments](command-line-arguments.md) - [Lints](lints/index.md) - [Lint levels](lints/levels.md) - [Lint Groups](lints/groups.md) diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md new file mode 100644 index 00000000000..7ea3e806e4a --- /dev/null +++ b/src/doc/rustc/src/command-line-arguments.md @@ -0,0 +1,57 @@ +# Command-line arguments + +Here's a list of command-line arguments to `rustc` and what they do. + +## `-h`/`--help`: get help + +## `--cfg`: configure the compilation environment + +## `-L`: add a directory to the library search path. + +## `-l`: link the generated crate to a native library + +## `--crate-type`: a list of types of crates for the compiler to emit + +## `--crate-name`: specify the name of the crate being built + +## `--emit`: emit output other than a crate + +## `--print`: print compiler information + +## `-g`: include debug information + +## `-O`: optimize your code + +## `-o`: filename of the output + +## `--out-dir`: directory to write the output in + +## `--explain`: provide a detailed explanation of an error message + +## `--test`: build a test harness + +## `--target`: select a target triple to build + +## `-W`: set lint warnings + +## `-A`: set lint allowed + +## `-D`: set lint denied + +## `-F`: set lint forbidden + +## `--cap-lints`: set the most restrictive lint level + +## `-C`/`--codegen`: code generation options + +## `-V`/`--verision`: print a version + +## `-v`/`--verbose`: use verbose output + +## `--extern`: specify where an external library is located + +## `--sysroot`: Override the system root + +## `--error-format`: control how errors are produced + +## `--color`: configur coloring of output \ No newline at end of file diff --git a/src/doc/rustc/src/command-line-arguments/index.md b/src/doc/rustc/src/command-line-arguments/index.md deleted file mode 100644 index 162c0e48d4e..00000000000 --- a/src/doc/rustc/src/command-line-arguments/index.md +++ /dev/null @@ -1 +0,0 @@ -# Command-line arguments -- cgit 1.4.1-3-g733a5 From cd553642488f0f0ca070647a080e93fe85719930 Mon Sep 17 00:00:00 2001 From: steveklabnik Date: Fri, 6 Apr 2018 09:33:10 -0400 Subject: write 'what is rustc' --- src/doc/rustc/src/what-is-rustc.md | 67 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) (limited to 'src') diff --git a/src/doc/rustc/src/what-is-rustc.md b/src/doc/rustc/src/what-is-rustc.md index ac4c33e4b71..bed1b71c24e 100644 --- a/src/doc/rustc/src/what-is-rustc.md +++ b/src/doc/rustc/src/what-is-rustc.md @@ -1 +1,68 @@ # What is rustc? + +Welcome to "The rustc book"! `rustc` is the compiler for the Rust programming +language, provided by the project itself. Compilers take your source code and +produce binary code, either as a library or executable. + +Most Rust programmers don't invoke `rustc` directly, but instead do it through +[Cargo](../cargo/index.html). It's all in service of `rustc` though! If you +want to see how Cargo calls `rustc`, you can + +```bash +$ cargo build --verbose +``` + +And it will print out each `rustc` invocation. This book can help you +understand what each of these options does. Additionally, while most +Rustaceans use Cargo, not all do: sometimes they integrate `rustc` into other +build systems. This book should provide a guide to all of the options you'd +need to do so. + +## Basic usage + +Let's say you've got a little hello world program in a file `hello.rs`: + +```rust +fn main() { + println!("Hello, world!"); +} +``` + +To turn this source code into an executable, you can use `rustc`: + +```bash +$ rustc hello.rs +$ ./hello # on a *NIX +$ .\hello.exe # on Windows +``` + +Note that we only ever pass `rustc` the *crate root*, not every file we wish +to compile. For example, if we had a `main.rs` that looked like this: + +```rust,ignore +mod foo; + +fn main() { + foo::hello(); +} +``` + +And a `foo.rs` that had this: + +```rust,ignore +fn hello() { + println!("Hello, world!"); +} +``` + +To compile this, we'd run this command: + +```bash +$ rustc main.rs +``` + +No need to tell `rustc` about `foo.rs`; the `mod` statements give it +everything that it needs. This is different than how you would use a C +compiler, where you invoke the compiler on each file, and then link +everything together. In other words, the *crate* is a translation unit, not a +particular module. \ No newline at end of file -- cgit 1.4.1-3-g733a5 From 78b076dadb0d8ac51be84ab3748e71a70abffa90 Mon Sep 17 00:00:00 2001 From: steveklabnik Date: Fri, 6 Apr 2018 09:33:26 -0400 Subject: add targets to TOC --- src/doc/rustc/src/SUMMARY.md | 3 +++ src/doc/rustc/src/targets/built-in.md | 1 + src/doc/rustc/src/targets/custom.md | 1 + src/doc/rustc/src/targets/index.md | 1 + 4 files changed, 6 insertions(+) create mode 100644 src/doc/rustc/src/targets/built-in.md create mode 100644 src/doc/rustc/src/targets/custom.md create mode 100644 src/doc/rustc/src/targets/index.md (limited to 'src') diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index ba70c745327..e4c0939fd46 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -10,4 +10,7 @@ - [Warn-by-default lints](lints/listing/warn-by-default.md) - [Deny-by-default lints](lints/listing/deny-by-default.md) - [Codegen options](codegen-options/index.md) +- [Targets](targets/index.md) + - [Built-in Targets](targets/built-in.md) + - [Custom Targets](targets/custom.md) - [Contributing to `rustc`](contributing.md) \ No newline at end of file diff --git a/src/doc/rustc/src/targets/built-in.md b/src/doc/rustc/src/targets/built-in.md new file mode 100644 index 00000000000..819d74457fe --- /dev/null +++ b/src/doc/rustc/src/targets/built-in.md @@ -0,0 +1 @@ +# Built-in Targets diff --git a/src/doc/rustc/src/targets/custom.md b/src/doc/rustc/src/targets/custom.md new file mode 100644 index 00000000000..59039ce67ba --- /dev/null +++ b/src/doc/rustc/src/targets/custom.md @@ -0,0 +1 @@ +# Custom Targets diff --git a/src/doc/rustc/src/targets/index.md b/src/doc/rustc/src/targets/index.md new file mode 100644 index 00000000000..01d0a4c8c0e --- /dev/null +++ b/src/doc/rustc/src/targets/index.md @@ -0,0 +1 @@ +# Targets -- cgit 1.4.1-3-g733a5 From 50b3a3d1216fd68b483c88b603ec6c742e51c054 Mon Sep 17 00:00:00 2001 From: steveklabnik Date: Fri, 6 Apr 2018 12:32:16 -0400 Subject: add a lot of text about lints --- src/doc/rustc/src/lints/groups.md | 28 ++ src/doc/rustc/src/lints/index.md | 27 ++ src/doc/rustc/src/lints/levels.md | 251 ++++++++++++ .../rustc/src/lints/listing/allowed-by-default.md | 451 +++++++++++++++++++++ src/doc/rustc/src/lints/listing/deny-by-default.md | 15 + src/doc/rustc/src/lints/listing/index.md | 4 + src/doc/rustc/src/lints/listing/warn-by-default.md | 48 +++ 7 files changed, 824 insertions(+) (limited to 'src') diff --git a/src/doc/rustc/src/lints/groups.md b/src/doc/rustc/src/lints/groups.md index f35b53b6b99..46b717f3387 100644 --- a/src/doc/rustc/src/lints/groups.md +++ b/src/doc/rustc/src/lints/groups.md @@ -1 +1,29 @@ # Lint Groups + +`rustc` has the concept of a "lint group", where you can toggle several warnings +through one name. + +For example, the `nonstandard-style` lint sets `non-camel-case-types`, +`non-snake-case`, and `non-upper-case-globals` all at once. So these are +equivalent: + +```bash +$ rustc -D nonstandard-style +$ rustc -D non-camel-case-types -D non-snake-case -D non-upper-case-globals +``` + +Here's a list of each lint group, and the lints that they are made up of: + +| group | description | lints | +|---------------------|---------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| nonstandard-style | Violation of standard naming conventions | non-camel-case-types, non-snake-case, non-upper-case-globals | +| warnings | all lints that would be issuing warnings | all lints that would be issuing warnings | +| edition-2018 | Lints that will be turned into errors in Rust 2018 | tyvar-behind-raw-pointer | +| rust-2018-idioms | Lints to nudge you toward idiomatic features of Rust 2018 | bare-trait-object, unreachable-pub | +| unused | These lints detect things being declared but not used | unused-imports, unused-variables, unused-assignments, dead-code, unused-mut, unreachable-code, unreachable-patterns, unused-must-use, unused-unsafe, path-statements, unused-attributes, unused-macros, unused-allocation, unused-doc-comment, unused-extern-crates, unused-features, unused-parens | +| future-incompatible | Lints that detect code that has future-compatibility problems | private-in-public, pub-use-of-private-extern-crate, patterns-in-fns-without-body, safe-extern-statics, invalid-type-param-default, legacy-directory-ownership, legacy-imports, legacy-constructor-visibility, missing-fragment-specifier, illegal-floating-point-literal-pattern, anonymous-parameters, parenthesized-params-in-types-and-modules, late-bound-lifetime-arguments, safe-packed-borrows, incoherent-fundamental-impls, tyvar-behind-raw-pointer, unstable-name-collision | + +Additionally, there's a `bad-style` lint group that's a deprecated alias for `nonstandard-style`. + +Finally, you can also see the table above by invoking `rustc -W help`. This will give you the exact values for the specific +compiler you have installed. \ No newline at end of file diff --git a/src/doc/rustc/src/lints/index.md b/src/doc/rustc/src/lints/index.md index 112c576a22c..4706a10c908 100644 --- a/src/doc/rustc/src/lints/index.md +++ b/src/doc/rustc/src/lints/index.md @@ -1 +1,28 @@ # Lints + +In software, a "lint" is a tool used to help improve your source code. The +Rust compiler contains a number of lints, and when it compiles your code, it will +also run the lints. These lints may produce a warning, an error, or nothing at all, +depending on how you've configured things. + +Here's a small example: + +```rust +$ cat main.rs +fn main() { + let x = 5; +} +> rustc main.rs +warning: unused variable: `x` + --> main.rs:2:9 + | +2 | let x = 5; + | ^ + | + = note: #[warn(unused_variables)] on by default + = note: to avoid this warning, consider using `_x` instead +``` + +This is the `unused_variables` lint, and it tells you that you've introduced +a variable that you don't use in your code. That's not *wrong*, so it's not +an error, but it might be a bug, so you get a warning. \ No newline at end of file diff --git a/src/doc/rustc/src/lints/levels.md b/src/doc/rustc/src/lints/levels.md index 6aed1e979f3..f2d7241e648 100644 --- a/src/doc/rustc/src/lints/levels.md +++ b/src/doc/rustc/src/lints/levels.md @@ -1 +1,252 @@ # Lint levels + +In `rustc`, lints are divided into four *levels*: + +1. allow +2. warn +3. deny +4. forbid + +Each lint has a default level (explained in the lint listing later in this +chapter), and the compiler has a default warning level. First, let's explain +what these levels mean, and then we'll talk about configuration. + +## allow + +These lints exist, but by default, do nothing. For example, consider this +source: + +```rust +pub fn foo() {} +``` + +Compiling this file produces no warnings: + +```rust +$ rustc lib.rs --crate-type=lib +$ +``` + +But this code violates the `missing_docs` lint. + +These lints exist mostly to be manually turned on via configuration, as we'll +talk about later in this section. + +## warn + +The 'warn' lint level will produce a warning if you violate the lint. For example, +this code runs afoul of the `unused_variable` lint: + +```rust +pub fn foo() { + let x = 5; +} +``` + +This will produce this warning: + +```bash +> rustc lib.rs --crate-type=lib +warning: unused variable: `x` + --> lib.rs:2:9 + | +2 | let x = 5; + | ^ + | + = note: #[warn(unused_variables)] on by default + = note: to avoid this warning, consider using `_x` instead +``` + +## deny + +A 'deny' lint produces an error if you violate it. For example, this code +runs into the `exceeding_bitshifts` lint. + +```rust +fn main() { + 100u8 << 10; +} +``` + +```bash +> rustc main.rs +error: bitshift exceeds the type's number of bits + --> main.rs:2:13 + | +2 | 100u8 << 10; + | ^^^^^^^^^^^ + | + = note: #[deny(exceeding_bitshifts)] on by default +``` + +What's the difference between an error from a lint and a regular old error? +Lints are configurable via levels, so in a similar way to 'allow' lints, +warnings that are 'deny' by default let you allow them. Similarly, you may +wish to set up a lint that is `warn` by default to produce an error instead. +This lint level gives you that. + +## forbid + +'forbid' is a special lint level that's stronger than 'deny'. It's the same +as 'deny' in that a lint at this level will produce an error, but unlike the +'deny' level, the 'forbid' level can not be overridden to be anything lower +than an error. + +## Configuring warning levels + +Remember our `missing_docs` example from the 'allow' lint level? + +```bash +$ cat lib.rs +pub fn foo() {} +$ rustc lib.rs --crate-type=lib +$ +``` + +We can configure this lint to operate at a higher level, both with +compiler flags, as well as with an attribute in the source code. + +You can also "cap" lints so that the compiler can choose to ignore +certain lint levels. We'll talk about that last. + +### Via compiler flag + +The `-A`, `-W`, `-D`, and `-F` flags let you turn one or more lints +into allowed, warning, deny, or forbid levels, like this: + +```bash +$ rustc lib.rs --crate-type=lib -W missing-docs +warning: missing documentation for crate + --> lib.rs:1:1 + | +1 | pub fn foo() {} + | ^^^^^^^^^^^^ + | + = note: requested on the command line with `-W missing-docs` + +warning: missing documentation for a function + --> lib.rs:1:1 + | +1 | pub fn foo() {} + | ^^^^^^^^^^^^ +> rustc lib.rs --crate-type=lib -D missing-docs +error: missing documentation for crate + --> lib.rs:1:1 + | +1 | pub fn foo() {} + | ^^^^^^^^^^^^ + | + = note: requested on the command line with `-D missing-docs` + +error: missing documentation for a function + --> lib.rs:1:1 + | +1 | pub fn foo() {} + | ^^^^^^^^^^^^ + +error: aborting due to 2 previous errors +``` + +You can also pass each flag more than once for changing multiple lints: + +```bash +rustc lib.rs --crate-type=lib -D missing-docs -D unused-variables +``` + +And of course, you can mix these four flags together: + +```bash +rustc lib.rs --crate-type=lib -D missing-docs -A unused-variables +``` + +### Via an attribute + +You can also modify the lint level with a crate-wide attribute: + +```bash +> cat lib.rs +#![warn(missing_docs)] + +pub fn foo() {} +$ rustc lib.rs --crate-type=lib +warning: missing documentation for crate + --> lib.rs:1:1 + | +1 | / #![warn(missing_docs)] +2 | | +3 | | pub fn foo() {} + | |_______________^ + | +note: lint level defined here + --> lib.rs:1:9 + | +1 | #![warn(missing_docs)] + | ^^^^^^^^^^^^ + +warning: missing documentation for a function + --> lib.rs:3:1 + | +3 | pub fn foo() {} + | ^^^^^^^^^^^^ +``` + +All four, `warn`, `allow`, `deny`, and `forbid` all work this way. + +You can also pass in multiple lints per attribute: + +```rust +#![warn(missing_docs, unused_variables)] + +pub fn foo() {} +``` + +And use multiple attributes together: + +```rust +#![warn(missing_docs)] +#![deny(unused_variables)] + +pub fn foo() {} +``` + +### Capping lints + +`rustc` supports a flag, `--cap-lints LEVEL` that sets the "lint cap level." +This is the maximum level for all lints. So for example, if we take our +code sample from the "deny" lint level above: + +```rust +fn main() { + 100u8 << 10; +} +``` + +And we compile it, capping lints to warn: + +```bash +$ rustc lib.rs --cap-lints warn +warning: bitshift exceeds the type's number of bits + --> lib.rs:2:5 + | +2 | 100u8 << 10; + | ^^^^^^^^^^^ + | + = note: #[warn(exceeding_bitshifts)] on by default + +warning: this expression will panic at run-time + --> lib.rs:2:5 + | +2 | 100u8 << 10; + | ^^^^^^^^^^^ attempt to shift left with overflow +``` + +It now only warns, rather than errors. We can go further and allow all lints: + +```bash +$ rustc lib.rs --cap-lints allow +$ +``` + +This feature is used heavily by Cargo; it will pass `--cap-lints allow` when +compiling your dependencies, so that if they have any warnings, they do not +pollute the output of your build. \ No newline at end of file diff --git a/src/doc/rustc/src/lints/listing/allowed-by-default.md b/src/doc/rustc/src/lints/listing/allowed-by-default.md index 19c4d94edbb..61c7c5e8896 100644 --- a/src/doc/rustc/src/lints/listing/allowed-by-default.md +++ b/src/doc/rustc/src/lints/listing/allowed-by-default.md @@ -1 +1,452 @@ # Allowed-by-default lints + +These lints are all set to the 'allow' level by default. As such, they won't show up +unless you set them to a higher lint level with a flag or attribute. + +## anonymous-parameters + +This lint detects anonymous parameters. Some example code that triggers this lint: + +```rust +trait Foo { + fn foo(usize); +} +``` + +When set to 'deny', this will produce: + +```text +error: use of deprecated anonymous parameter + --> src/lib.rs:5:11 + | +5 | fn foo(usize); + | ^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #41686 +``` + +This syntax is mostly a historical accident, and can be worked around quite +easily: + +```rust +trait Foo { + fn foo(_: usize); +} +``` + +## bare-trait-object + +This lint suggests using `dyn Trait` for trait objects. Some example code +that triggers this lint: + +```rust +#![feature(dyn_trait)] + +trait Trait { } + +fn takes_trait_object(_: Box) { +} +``` + +When set to 'deny', this will produce: + +```text +error: trait objects without an explicit `dyn` are deprecated + --> src/lib.rs:7:30 + | +7 | fn takes_trait_object(_: Box) { + | ^^^^^ help: use `dyn`: `dyn Trait` + | +``` + +To fix it, do as the help message suggests: + +```rust +#![feature(dyn_trait)] +#![deny(bare_trait_object)] + +trait Trait { } + +fn takes_trait_object(_: Box) { +} +``` + +## box-pointers + +This lints use of the Box type. Some example code that triggers this lint: + +```rust +struct Foo { + x: Box, +} +``` + +When set to 'deny', this will produce: + +```text +error: type uses owned (Box type) pointers: std::boxed::Box + --> src/lib.rs:6:5 + | +6 | x: Box //~ ERROR type uses owned + | ^^^^^^^^^^^^^ + | +``` + +This lint is mostly historical, and not particularly useful. `Box` used to +be built into the language, and the only way to do heap allocation. Today's +Rust can call into other allocators, etc. + +## elided-lifetime-in-path + +This lint detects the use of hidden lifetime parameters. Some example code +that triggers this lint: + +```rust +struct Foo<'a> { + x: &'a u32 +} + +fn foo(x: &Foo) { +} +``` + +When set to 'deny', this will produce: + +```text +error: hidden lifetime parameters are deprecated, try `Foo<'_>` + --> src/lib.rs:5:12 + | +5 | fn foo(x: &Foo) { + | ^^^ + | +``` + +Lifetime elision elides this lifetime, but that is being deprecated. + +## missing-copy-implementations + +This lint detects potentially-forgotten implementations of `Copy`. Some +example code that triggers this lint: + +```rust +pub struct Foo { + pub field: i32 +} +``` + +When set to 'deny', this will produce: + +```text +error: type could implement `Copy`; consider adding `impl Copy` + --> src/main.rs:3:1 + | +3 | / pub struct Foo { //~ ERROR type could implement `Copy`; consider adding `impl Copy` +4 | | pub field: i32 +5 | | } + | |_^ + | +``` + +You can fix the lint by deriving `Copy`. + +This lint is set to 'allow' because this code isn't bad; it's common to write +newtypes like this specifically so that a `Copy` type is no longer `Copy`. + +## missing-debug-implementations + +This lint detects missing implementations of `fmt::Debug`. Some example code +that triggers this lint: + +```rust +pub struct Foo; +``` + +When set to 'deny', this will produce: + +```text +error: type does not implement `fmt::Debug`; consider adding #[derive(Debug)] or a manual implementation + --> src/main.rs:3:1 + | +3 | pub struct Foo; + | ^^^^^^^^^^^^^^^ + | +``` + +You can fix the lint by deriving `Debug`. + +## missing-docs + +This lint detects missing documentation for public items. Some example code +that triggers this lint: + +```rust +pub fn foo() {} +``` + +When set to 'deny', this will produce: + +```text +error: missing documentation for crate + --> src/main.rs:1:1 + | +1 | / #![deny(missing_docs)] +2 | | +3 | | pub fn foo() {} +4 | | +5 | | fn main() {} + | |____________^ + | + +error: missing documentation for a function + --> src/main.rs:3:1 + | +3 | pub fn foo() {} + | ^^^^^^^^^^^^ + +``` + +To fix the lint, add documentation to all items. + +## single-use-lifetime + +This lint detects lifetimes that are only used once. Some example code that +triggers this lint: + +```rust +struct Foo<'x> { + x: &'x u32 +} +``` + +When set to 'deny', this will produce: + +```text +error: lifetime name `'x` only used once + --> src/main.rs:3:12 + | +3 | struct Foo<'x> { + | ^^ + | +``` + +## trivial-casts + +This lint detects trivial casts which could be removed. Some example code +that triggers this lint: + +```rust +let x: &u32 = &42; +let _ = x as *const u32; +``` + +When set to 'deny', this will produce: + +```text +error: trivial cast: `&u32` as `*const u32`. Cast can be replaced by coercion, this might require type ascription or a temporary variable + --> src/main.rs:5:13 + | +5 | let _ = x as *const u32; + | ^^^^^^^^^^^^^^^ + | +note: lint level defined here + --> src/main.rs:1:9 + | +1 | #![deny(trivial_casts)] + | ^^^^^^^^^^^^^ +``` + +## trivial-numeric-casts + +This lint detects trivial casts of numeric types which could be removed. Some +example code that triggers this lint: + +```rust +let x = 42i32 as i32; +``` + +When set to 'deny', this will produce: + +```text +error: trivial numeric cast: `i32` as `i32`. Cast can be replaced by coercion, this might require type ascription or a temporary variable + --> src/main.rs:4:13 + | +4 | let x = 42i32 as i32; + | ^^^^^^^^^^^^ + | +``` + +## unreachable-pub + +This lint triggers for `pub` items not reachable from the crate root. Some +example code that triggers this lint: + +```rust +mod foo { + pub mod bar { + + } +} +``` + +When set to 'deny', this will produce: + +```text +error: unreachable `pub` item + --> src/main.rs:4:5 + | +4 | pub mod bar { + | ---^^^^^^^^ + | | + | help: consider restricting its visibility: `pub(crate)` + | +``` + +## unsafe-code + +This lint catches usage of `unsafe` code. Some example code that triggers this lint: + +```rust +fn main() { + unsafe { + + } +} +``` + +When set to 'deny', this will produce: + +```text +error: usage of an `unsafe` block + --> src/main.rs:4:5 + | +4 | / unsafe { +5 | | +6 | | } + | |_____^ + | +``` + +## unstable-features + +This lint is deprecated and no longer used. + +## unused-extern-crates + +This lint guards against `extern crate` items that are never used. Some +example code that triggers this lint: + +```rust +extern crate semver; +``` + +When set to 'deny', this will produce: + +```text +error: unused extern crate + --> src/main.rs:3:1 + | +3 | extern crate semver; + | ^^^^^^^^^^^^^^^^^^^^ + | +``` + +## unused-import-braces + +This lint catches unnecessary braces around an imported item. Some example +code that triggers this lint: + +```rust +use test::{A}; + +mod test { + struct A; +} +``` + +When set to 'deny', this will produce: + +```text +error: braces around A is unnecessary + --> src/main.rs:3:1 + | +3 | use test::{A}; + | ^^^^^^^^^^^^^^ + | +``` + +To fix it, `use test::A;` + +## unused-qualifications + +This lint detects unnecessarily qualified names. Some example code that triggers this lint: + +```rust +mod foo { + pub fn bar() {} +} + +fn main() { + use foo::bar; + foo::bar(); +} +``` + +When set to 'deny', this will produce: + +```text +error: unnecessary qualification + --> src/main.rs:9:5 + | +9 | foo::bar(); + | ^^^^^^^^ + | +``` + +You can call `bar()` directly, without the `foo::`. + +## unused-results + +This lint checks for the unused result of an expression in a statement. Some +example code that triggers this lint: + +```rust +fn foo() -> T { panic!() } + +fn main() { + foo::(); +} +``` + +When set to 'deny', this will produce: + +```text +error: unused result + --> src/main.rs:6:5 + | +6 | foo::(); + | ^^^^^^^^^^^^^^^ + | +``` + +## variant-size-differences + +This lint detects enums with widely varying variant sizes. Some example code that triggers this lint: + +```rust +enum En { + V0(u8), + VBig([u8; 1024]), //~ ERROR variant is more than three times larger +} +``` + +When set to 'deny', this will produce: + +```text +error: enum variant is more than three times larger (1024 bytes) than the next largest + --> src/main.rs:5:5 + | +5 | VBig([u8; 1024]), //~ ERROR variant is more than three times larger + | ^^^^^^^^^^^^^^^^ + | +``` \ No newline at end of file diff --git a/src/doc/rustc/src/lints/listing/deny-by-default.md b/src/doc/rustc/src/lints/listing/deny-by-default.md index 0f6fd4fe931..54e857c885d 100644 --- a/src/doc/rustc/src/lints/listing/deny-by-default.md +++ b/src/doc/rustc/src/lints/listing/deny-by-default.md @@ -1 +1,16 @@ # Deny-by-default lints + +These lints are all set to the 'deny' level by default. + + exceeding-bitshifts deny shift exceeds the type's number of bits + invalid-type-param-default deny type parameter default erroneously allowed in invalid location + legacy-constructor-visibility deny detects use of struct constructors that would be invisible with new visibility rules + legacy-directory-ownership deny non-inline, non-`#[path]` modules (e.g. `mod foo;`) were erroneously allowed in some files not named `mod.rs` + legacy-imports deny detects names that resolve to ambiguous glob imports with RFC 1560 + missing-fragment-specifier deny detects missing fragment specifiers in unused `macro_rules!` patterns + mutable-transmutes deny mutating transmuted &mut T from &T may cause undefined behavior + no-mangle-const-items deny const items will not have their symbols exported + parenthesized-params-in-types-and-modules deny detects parenthesized generic parameters in type and module names + pub-use-of-private-extern-crate deny detect public re-exports of private extern crates + safe-extern-statics deny safe access to extern statics was erroneously allowed + unknown-crate-types deny unknown crate type found in #[crate_type] directive \ No newline at end of file diff --git a/src/doc/rustc/src/lints/listing/index.md b/src/doc/rustc/src/lints/listing/index.md index e279644e644..18cd2fe32a3 100644 --- a/src/doc/rustc/src/lints/listing/index.md +++ b/src/doc/rustc/src/lints/listing/index.md @@ -1 +1,5 @@ # Lint listing + +This section lists out all of the lints, grouped by their default lint levels. + +You can also see this list by running `rustc -W help`. \ No newline at end of file diff --git a/src/doc/rustc/src/lints/listing/warn-by-default.md b/src/doc/rustc/src/lints/listing/warn-by-default.md index 5342b954a09..531cf7606b1 100644 --- a/src/doc/rustc/src/lints/listing/warn-by-default.md +++ b/src/doc/rustc/src/lints/listing/warn-by-default.md @@ -1 +1,49 @@ # Warn-by-default lints + +These lints are all set to the 'warn' level by default. + + const-err warn constant evaluation detected erroneous expression + dead-code warn detect unused, unexported items + deprecated warn detects use of deprecated items + illegal-floating-point-literal-pattern warn floating-point literals cannot be used in patterns + improper-ctypes warn proper use of libc types in foreign modules + incoherent-fundamental-impls warn potentially-conflicting impls were erroneously allowed + late-bound-lifetime-arguments warn detects generic lifetime arguments in path segments with late bound lifetime parameters + non-camel-case-types warn types, variants, traits and type parameters should have camel case names + non-shorthand-field-patterns warn using `Struct { x: x }` instead of `Struct { x }` in a pattern + non-snake-case warn variables, methods, functions, lifetime parameters and modules should have snake case names + non-upper-case-globals warn static constants should have uppercase identifiers + no-mangle-generic-items warn generic items must be mangled + overflowing-literals warn literal out of range for its type + path-statements warn path statements with no effect + patterns-in-fns-without-body warn patterns in functions without body were erroneously allowed + plugin-as-library warn compiler plugin used as ordinary library in non-plugin crate + private-in-public warn detect private items in public interfaces not caught by the old implementation + private-no-mangle-fns warn functions marked #[no_mangle] should be exported + private-no-mangle-statics warn statics marked #[no_mangle] should be exported + renamed-and-removed-lints warn lints that have been renamed or removed + safe-packed-borrows warn safe borrows of fields of packed structs were was erroneously allowed + stable-features warn stable features found in #[feature] directive + type-alias-bounds warn bounds in type aliases are not enforced + tyvar-behind-raw-pointer warn raw pointer to an inference variable + unconditional-recursion warn functions that cannot return without calling themselves + unions-with-drop-fields warn use of unions that contain fields with possibly non-trivial drop code + unknown-lints warn unrecognized lint attribute + unreachable-code warn detects unreachable code paths + unreachable-patterns warn detects unreachable patterns + unstable-name-collision warn detects name collision with an existing but unstable method + unused-allocation warn detects unnecessary allocations that can be eliminated + unused-assignments warn detect assignments that will never be read + unused-attributes warn detects attributes that were not used by the compiler + unused-comparisons warn comparisons made useless by limits of the types involved + unused-doc-comment warn detects doc comments that aren't used by rustdoc + unused-features warn unused or unknown features found in crate-level #[feature] directives + unused-imports warn imports that are never used + unused-macros warn detects macros that were not used + unused-must-use warn unused result of a type flagged as #[must_use] + unused-mut warn detect mut variables which don't need to be mutable + unused-parens warn `if`, `match`, `while` and `return` do not need parentheses + unused-unsafe warn unnecessary use of an `unsafe` block + unused-variables warn detect variables which are not used in any way + warnings warn mass-change the level for lints which produce warnings + while-true warn suggest using `loop { }` instead of `while true { }` \ No newline at end of file -- cgit 1.4.1-3-g733a5 From df81ca37645835d41ae67d9f8e682244f40d53e7 Mon Sep 17 00:00:00 2001 From: steveklabnik Date: Fri, 6 Apr 2018 13:08:33 -0400 Subject: document deny by default lints --- src/doc/rustc/src/lints/listing/deny-by-default.md | 249 ++++++++++++++++++++- 1 file changed, 237 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/doc/rustc/src/lints/listing/deny-by-default.md b/src/doc/rustc/src/lints/listing/deny-by-default.md index 54e857c885d..a361c117b10 100644 --- a/src/doc/rustc/src/lints/listing/deny-by-default.md +++ b/src/doc/rustc/src/lints/listing/deny-by-default.md @@ -2,15 +2,240 @@ These lints are all set to the 'deny' level by default. - exceeding-bitshifts deny shift exceeds the type's number of bits - invalid-type-param-default deny type parameter default erroneously allowed in invalid location - legacy-constructor-visibility deny detects use of struct constructors that would be invisible with new visibility rules - legacy-directory-ownership deny non-inline, non-`#[path]` modules (e.g. `mod foo;`) were erroneously allowed in some files not named `mod.rs` - legacy-imports deny detects names that resolve to ambiguous glob imports with RFC 1560 - missing-fragment-specifier deny detects missing fragment specifiers in unused `macro_rules!` patterns - mutable-transmutes deny mutating transmuted &mut T from &T may cause undefined behavior - no-mangle-const-items deny const items will not have their symbols exported - parenthesized-params-in-types-and-modules deny detects parenthesized generic parameters in type and module names - pub-use-of-private-extern-crate deny detect public re-exports of private extern crates - safe-extern-statics deny safe access to extern statics was erroneously allowed - unknown-crate-types deny unknown crate type found in #[crate_type] directive \ No newline at end of file +## exceeding-bitshifts + +This lint detects that a shift exceeds the type's number of bits. Some +example code that triggers this lint: + +```rust +1_i32 << 32; +``` + +This will produce: + +```text +error: bitshift exceeds the type's number of bits + --> src/main.rs:2:5 + | +2 | 1_i32 << 32; + | ^^^^^^^^^^^ + | +``` + +## invalid-type-param-default + +This lint detects type parameter default erroneously allowed in invalid location. Some +example code that triggers this lint: + +```rust +fn foo(t: T) {} +``` + +This will produce: + +```text +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions. + --> src/main.rs:4:8 + | +4 | fn foo(t: T) {} + | ^ + | + = note: #[deny(invalid_type_param_default)] on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #36887 +``` + +## legacy-constructor-visibility + +[RFC 1506](https://github.com/rust-lang/rfcs/blob/master/text/1506-adt-kinds.md) modified some +visibility rules, and changed the visibility of struct constructors. Some +example code that triggers this lint: + +```rust +mod m { + pub struct S(u8); + + fn f() { + // this is trying to use S from the 'use' line, but becuase the `u8` is + // not pub, it is private + ::S; + } +} + +use m::S; +``` + +This will produce: + +```text +error: private struct constructors are not usable through re-exports in outer modules + --> src/main.rs:5:9 + | +5 | ::S; + | ^^^ + | + = note: #[deny(legacy_constructor_visibility)] on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #39207 +``` + + +## legacy-directory-ownership + +The legacy_directory_ownership warning is issued when + +* There is a non-inline module with a #[path] attribute (e.g. #[path = "foo.rs"] mod bar;), +* The module's file ("foo.rs" in the above example) is not named "mod.rs", and +* The module's file contains a non-inline child module without a #[path] attribute. + +The warning can be fixed by renaming the parent module to "mod.rs" and moving +it into its own directory if appropriate. + +## legacy-imports + +This lint detects names that resolve to ambiguous glob imports. Some example +code that triggers this lint: + +```rust +pub struct Foo; + +mod bar { + struct Foo; + + mod baz { + use *; + use bar::*; + fn f(_: Foo) {} + } +} +``` + +This will produce: + +```text +error: `Foo` is ambiguous + --> src/main.rs:9:17 + | +7 | use *; + | - `Foo` could refer to the name imported here +8 | use bar::*; + | ------ `Foo` could also refer to the name imported here +9 | fn f(_: Foo) {} + | ^^^ + | + = note: #[deny(legacy_imports)] on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #38260 +``` + + +## missing-fragment-specifier + +The missing_fragment_specifier warning is issued when an unused pattern in a +`macro_rules!` macro definition has a meta-variable (e.g. `$e`) that is not +followed by a fragment specifier (e.g. `:expr`). + +This warning can always be fixed by removing the unused pattern in the +`macro_rules!` macro definition. + +## mutable-transmutes + +This lint catches transmuting from `&T` to `&mut T` becuase it is undefined +behavior. Some example code that triggers this lint: + +```rust +unsafe { + let y = std::mem::transmute::<&i32, &mut i32>(&5); +} +``` + +This will produce: + +```text +error: mutating transmuted &mut T from &T may cause undefined behavior, consider instead using an UnsafeCell + --> src/main.rs:3:17 + | +3 | let y = std::mem::transmute::<&i32, &mut i32>(&5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +``` + + +## no-mangle-const-items + +This lint detects any `const` items with the `#[no_mangle]` attribute. +Constants do not have their symbols exported, and therefore, this probably +means you meant to use a `static`, not a `const. Some example code that +triggers this lint: + +```rust +#[no_mangle] +const FOO: i32 = 5; +``` + +This will produce: + +```text +error: const items should never be #[no_mangle] + --> src/main.rs:3:1 + | +3 | const FOO: i32 = 5; + | -----^^^^^^^^^^^^^^ + | | + | help: try a static value: `pub static` + | +``` + +## parenthesized-params-in-types-and-modules + +This lint detects incorrect parentheses. Some example code that triggers this +lint: + +```rust +let x = 5 as usize(); +``` + +This will produce: + +```text +error: parenthesized parameters may only be used with a trait + --> src/main.rs:2:21 + | +2 | let x = 5 as usize(); + | ^^ + | + = note: #[deny(parenthesized_params_in_types_and_modules)] on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #42238 +``` + +To fix it, remove the `()`s. + +## pub-use-of-private-extern-crate + +This lint detects a specific situation of re-exporting a private `extern crate`; + +## safe-extern-statics + +In older versions of Rust, there was a soundness issue where `extern static`s were allowed +to be accessed in safe code. This lint now catches and denies this kind of code. + +## unknown-crate-types + +This lint detects an unknown crate type found in a `#[crate_type]` directive. Some +example code that triggers this lint: + +```rust +#![crate_type="lol"] +``` + +This will produce: + +```text +error: invalid `crate_type` value + --> src/lib.rs:1:1 + | +1 | #![crate_type="lol"] + | ^^^^^^^^^^^^^^^^^^^^ + | +``` \ No newline at end of file -- cgit 1.4.1-3-g733a5 From 758a77d46c684fc646e8ec08065d23eb53c6444d Mon Sep 17 00:00:00 2001 From: steveklabnik Date: Fri, 6 Apr 2018 15:06:53 -0400 Subject: more lints --- .../rustc/src/lints/listing/allowed-by-default.md | 2 +- src/doc/rustc/src/lints/listing/warn-by-default.md | 1079 +++++++++++++++++++- 2 files changed, 1035 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/src/doc/rustc/src/lints/listing/allowed-by-default.md b/src/doc/rustc/src/lints/listing/allowed-by-default.md index 61c7c5e8896..a432c00e060 100644 --- a/src/doc/rustc/src/lints/listing/allowed-by-default.md +++ b/src/doc/rustc/src/lints/listing/allowed-by-default.md @@ -436,7 +436,7 @@ This lint detects enums with widely varying variant sizes. Some example code tha ```rust enum En { V0(u8), - VBig([u8; 1024]), //~ ERROR variant is more than three times larger + VBig([u8; 1024]), } ``` diff --git a/src/doc/rustc/src/lints/listing/warn-by-default.md b/src/doc/rustc/src/lints/listing/warn-by-default.md index 531cf7606b1..a8f3400687c 100644 --- a/src/doc/rustc/src/lints/listing/warn-by-default.md +++ b/src/doc/rustc/src/lints/listing/warn-by-default.md @@ -2,48 +2,1037 @@ These lints are all set to the 'warn' level by default. - const-err warn constant evaluation detected erroneous expression - dead-code warn detect unused, unexported items - deprecated warn detects use of deprecated items - illegal-floating-point-literal-pattern warn floating-point literals cannot be used in patterns - improper-ctypes warn proper use of libc types in foreign modules - incoherent-fundamental-impls warn potentially-conflicting impls were erroneously allowed - late-bound-lifetime-arguments warn detects generic lifetime arguments in path segments with late bound lifetime parameters - non-camel-case-types warn types, variants, traits and type parameters should have camel case names - non-shorthand-field-patterns warn using `Struct { x: x }` instead of `Struct { x }` in a pattern - non-snake-case warn variables, methods, functions, lifetime parameters and modules should have snake case names - non-upper-case-globals warn static constants should have uppercase identifiers - no-mangle-generic-items warn generic items must be mangled - overflowing-literals warn literal out of range for its type - path-statements warn path statements with no effect - patterns-in-fns-without-body warn patterns in functions without body were erroneously allowed - plugin-as-library warn compiler plugin used as ordinary library in non-plugin crate - private-in-public warn detect private items in public interfaces not caught by the old implementation - private-no-mangle-fns warn functions marked #[no_mangle] should be exported - private-no-mangle-statics warn statics marked #[no_mangle] should be exported - renamed-and-removed-lints warn lints that have been renamed or removed - safe-packed-borrows warn safe borrows of fields of packed structs were was erroneously allowed - stable-features warn stable features found in #[feature] directive - type-alias-bounds warn bounds in type aliases are not enforced - tyvar-behind-raw-pointer warn raw pointer to an inference variable - unconditional-recursion warn functions that cannot return without calling themselves - unions-with-drop-fields warn use of unions that contain fields with possibly non-trivial drop code - unknown-lints warn unrecognized lint attribute - unreachable-code warn detects unreachable code paths - unreachable-patterns warn detects unreachable patterns - unstable-name-collision warn detects name collision with an existing but unstable method - unused-allocation warn detects unnecessary allocations that can be eliminated - unused-assignments warn detect assignments that will never be read - unused-attributes warn detects attributes that were not used by the compiler - unused-comparisons warn comparisons made useless by limits of the types involved - unused-doc-comment warn detects doc comments that aren't used by rustdoc - unused-features warn unused or unknown features found in crate-level #[feature] directives - unused-imports warn imports that are never used - unused-macros warn detects macros that were not used - unused-must-use warn unused result of a type flagged as #[must_use] - unused-mut warn detect mut variables which don't need to be mutable - unused-parens warn `if`, `match`, `while` and `return` do not need parentheses - unused-unsafe warn unnecessary use of an `unsafe` block - unused-variables warn detect variables which are not used in any way - warnings warn mass-change the level for lints which produce warnings - while-true warn suggest using `loop { }` instead of `while true { }` \ No newline at end of file +## const-err + +This lint detects an erroneous expression while doing constant evaluation. Some +example code that triggers this lint: + +```rust +let b = 200u8 + 200u8; +``` + +This will produce: + +```text +warning: attempt to add with overflow + --> src/main.rs:2:9 + | +2 | let b = 200u8 + 200u8; + | ^^^^^^^^^^^^^ + | +``` + +## dead-code + +This lint detects detect unused, unexported items. Some +example code that triggers this lint: + +```rust +fn foo() {} +``` + +This will produce: + +```text +warning: function is never used: `foo` + --> src/lib.rs:2:1 + | +2 | fn foo() {} + | ^^^^^^^^ + | +``` + +## deprecated + +This lint detects detects use of deprecated items. Some +example code that triggers this lint: + +```rust +#[deprecated] +fn foo() {} + +fn bar() { + foo(); +} +``` + +This will produce: + +```text +warning: use of deprecated item 'foo' + --> src/lib.rs:7:5 + | +7 | foo(); + | ^^^ + | +``` + +## illegal-floating-point-literal-pattern + +This lint detects floating-point literals used in patterns. Some example code +that triggers this lint: + +```rust +let x = 42.0; + +match x { + 5.0 => {}, + _ => {}, +} +``` + +This will produce: + +```text +warning: floating-point literals cannot be used in patterns + --> src/main.rs:4:9 + | +4 | 5.0 => {}, + | ^^^ + | + = note: #[warn(illegal_floating_point_literal_pattern)] on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #41620 +``` + +## improper-ctypes + +This lint detects proper use of libc types in foreign modules. Some +example code that triggers this lint: + +```rust +extern "C" { + static STATIC: String; +} +``` + +This will produce: + +```text +warning: found struct without foreign-function-safe representation annotation in foreign module, consider adding a #[repr(C)] attribute to the type + --> src/main.rs:2:20 + | +2 | static STATIC: String; + | ^^^^^^ + | +``` + +## incoherent-fundamental-impls + +This lint detects potentially-conflicting impls that were erroneously allowed. Some +example code that triggers this lint: + +```rust +pub trait Trait1 { + type Output; +} + +pub trait Trait2 {} + +pub struct A; + +impl Trait1 for T where T: Trait2 { + type Output = (); +} + +impl Trait1> for A { + type Output = i32; +} +``` + +This will produce: + +```text +warning: conflicting implementations of trait `Trait1>` for type `A`: (E0119) + --> src/main.rs:13:1 + | +9 | impl Trait1 for T where T: Trait2 { + | --------------------------------------------- first implementation here +... +13 | impl Trait1> for A { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `A` + | + = note: #[warn(incoherent_fundamental_impls)] on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #46205 + = note: downstream crates may implement trait `Trait2>` for type `A` +``` + +## late-bound-lifetime-arguments + +This lint detects detects generic lifetime arguments in path segments with +late bound lifetime parameters. Some example code that triggers this lint: + +```rust +struct S; + +impl S { + fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {} +} + +fn main() { + S.late::<'static>(&0, &0); +} +``` + +This will produce: + +```text +warning: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> src/main.rs:8:14 + | +4 | fn late<'a, 'b>(self, _: &'a u8, _: &'b u8) {} + | -- the late bound lifetime parameter is introduced here +... +8 | S.late::<'static>(&0, &0); + | ^^^^^^^ + | + = note: #[warn(late_bound_lifetime_arguments)] on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #42868 +``` + +## non-camel-case-types + +This lint detects types, variants, traits and type parameters that don't have +camel case names. Some example code that triggers this lint: + +```rust +struct s; +``` + +This will produce: + +```text +warning: type `s` should have a camel case name such as `S` + --> src/main.rs:1:1 + | +1 | struct s; + | ^^^^^^^^^ + | +``` + +## non-shorthand-field-patterns + +This lint detects using `Struct { x: x }` instead of `Struct { x }` in a pattern. Some +example code that triggers this lint: + +```rust +struct Point { + x: i32, + y: i32, +} + + +fn main() { + let p = Point { + x: 5, + y: 5, + }; + + match p { + Point { x: x, y: y } => (), + } +} +``` + +This will produce: + +```text +warning: the `x:` in this pattern is redundant + --> src/main.rs:14:17 + | +14 | Point { x: x, y: y } => (), + | --^^ + | | + | help: remove this + | + +warning: the `y:` in this pattern is redundant + --> src/main.rs:14:23 + | +14 | Point { x: x, y: y } => (), + | --^^ + | | + | help: remove this + +``` + +## non-snake-case + +This lint detects variables, methods, functions, lifetime parameters and +modules that don't have snake case names. Some example code that triggers +this lint: + +```rust +let X = 5; +``` + +This will produce: + +```text +warning: variable `X` should have a snake case name such as `x` + --> src/main.rs:2:9 + | +2 | let X = 5; + | ^ + | +``` + +## non-upper-case-globals + +This lint detects static constants that don't have uppercase identifiers. +Some example code that triggers this lint: + +```rust +static x: i32 = 5; +``` + +This will produce: + +```text +warning: static variable `x` should have an upper case name such as `X` + --> src/main.rs:1:1 + | +1 | static x: i32 = 5; + | ^^^^^^^^^^^^^^^^^^ + | +``` + +## no-mangle-generic-items + +This lint detects generic items must be mangled. Some +example code that triggers this lint: + +```rust +#[no_mangle] +fn foo(t: T) { + +} +``` + +This will produce: + +```text +warning: functions generic over types must be mangled + --> src/main.rs:2:1 + | +1 | #[no_mangle] + | ------------ help: remove this attribute +2 | / fn foo(t: T) { +3 | | +4 | | } + | |_^ + | +``` + +## overflowing-literals + +This lint detects literal out of range for its type. Some +example code that triggers this lint: + +```rust +let x: u8 = 1000; +``` + +This will produce: + +```text +warning: literal out of range for u8 + --> src/main.rs:2:17 + | +2 | let x: u8 = 1000; + | ^^^^ + | +``` + +## path-statements + +This lint detects path statements with no effect. Some example code that +triggers this lint: + +```rust +let x = 42; + +x; +``` + +This will produce: + +```text +warning: path statement with no effect + --> src/main.rs:3:5 + | +3 | x; + | ^^ + | +``` + +## patterns-in-fns-without-body + +This lint detects patterns in functions without body were that were +previously erroneously allowed. Some example code that triggers this lint: + +```rust +trait Trait { + fn foo(mut arg: u8); +} +``` + +This will produce: + +```text +warning: patterns aren't allowed in methods without bodies + --> src/main.rs:2:12 + | +2 | fn foo(mut arg: u8); + | ^^^^^^^ + | + = note: #[warn(patterns_in_fns_without_body)] on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #35203 +``` + +To fix this, remove the pattern; it can be used in the implementation without +being used in the definition. That is: + +```rust +trait Trait { + fn foo(arg: u8); +} + +impl Trait for i32 { + fn foo(mut arg: u8) { + + } +} +``` + +## plugin-as-library + +This lint detects when compiler plugins are used as ordinary library in +non-plugin crate. Some example code that triggers this lint: + +```rust +#![feature(plugin)] +#![plugin(macro_crate_test)] + +extern crate macro_crate_test; +``` + +## private-in-public + +This lint detects detect private items in public interfaces not caught by the old implementation. Some +example code that triggers this lint: + +```rust +pub trait Trait { + type A; +} + +pub struct S; + +mod foo { + struct Z; + + impl ::Trait for ::S { + type A = Z; + } +} +``` + +This will produce: + +```text +error[E0446]: private type `foo::Z` in public interface + --> src/main.rs:11:9 + | +11 | type A = Z; + | ^^^^^^^^^^^ can't leak private type +``` + +## private-no-mangle-fns + +This lint detects functions marked `#[no_mangle]` that are also private. +Given that private functions aren't exposed publicly, and `#[no_mangle]` +controls the public symbol, this combination is erroneous. Some example code +that triggers this lint: + +```rust +#[no_mangle] +fn foo() {} +``` + +This will produce: + +```text +warning: function is marked #[no_mangle], but not exported + --> src/main.rs:2:1 + | +2 | fn foo() {} + | -^^^^^^^^^^ + | | + | help: try making it public: `pub` + | +``` + +To fix this, either make it public or remove the `#[no_mangle]`. + +## private-no-mangle-statics + +This lint detects any statics marked `#[no_mangle]` that are private. +Given that private statics aren't exposed publicly, and `#[no_mangle]` +controls the public symbol, this combination is erroneous. Some example code +that triggers this lint: + +```rust +#[no_mangle] +static X: i32 = 4; +``` + +This will produce: + +```text +warning: static is marked #[no_mangle], but not exported + --> src/main.rs:2:1 + | +2 | static X: i32 = 4; + | -^^^^^^^^^^^^^^^^^ + | | + | help: try making it public: `pub` + | +``` + +To fix this, either make it public or remove the `#[no_mangle]`. + +## renamed-and-removed-lints + +This lint detects lints that have been renamed or removed. Some +example code that triggers this lint: + +```rust +#![deny(raw_pointer_derive)] +``` + +This will produce: + +```text +warning: lint raw_pointer_derive has been removed: using derive with raw pointers is ok + --> src/main.rs:1:9 + | +1 | #![deny(raw_pointer_derive)] + | ^^^^^^^^^^^^^^^^^^ + | +``` + +To fix this, either remove the lint or use the new name. + +## safe-packed-borrows + +This lint detects borrowing a field in the interior of a packed structure +with alignment other than 1. Some example code that triggers this lint: + +```rust +#[repr(packed)] +pub struct Unaligned(pub T); + +pub struct Foo { + start: u8, + data: Unaligned, +} + +fn main() { + let x = Foo { start: 0, data: Unaligned(1) }; + let y = &x.data.0; +} +``` + +This will produce: + +```text +warning: borrow of packed field requires unsafe function or block (error E0133) + --> src/main.rs:11:13 + | +11 | let y = &x.data.0; + | ^^^^^^^^^ + | + = note: #[warn(safe_packed_borrows)] on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #46043 +``` + +## stable-features + +This lint detects a `#[feature]` attribute that's since been made stable. Some +example code that triggers this lint: + +```rust +#![feature(test_accepted_feature)] +``` + +This will produce: + +```text +warning: this feature has been stable since 1.0.0. Attribute no longer needed + --> src/main.rs:1:12 + | +1 | #![feature(test_accepted_feature)] + | ^^^^^^^^^^^^^^^^^^^^^ + | +``` + +To fix, simply remove the `#![feature]` attribute, as it's no longer needed. + +## type-alias-bounds + +This lint detects bounds in type aliases. These are not currently enforced. +Some example code that triggers this lint: + +```rust +type SendVec = Vec; +``` + +This will produce: + +```text +warning: type alias is never used: `SendVec` + --> src/main.rs:1:1 + | +1 | type SendVec = Vec; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +``` + +## tyvar-behind-raw-pointer + +This lint detects raw pointer to an inference variable. Some +example code that triggers this lint: + +```rust +let data = std::ptr::null(); +let _ = &data as *const *const (); + +if data.is_null() {} +``` + +This will produce: + +```text +warning: type annotations needed + --> src/main.rs:4:13 + | +4 | if data.is_null() {} + | ^^^^^^^ + | + = note: #[warn(tyvar_behind_raw_pointer)] on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = note: for more information, see issue #46906 +``` + +## unconditional-recursion + +This lint detects functions that cannot return without calling themselves. +Some example code that triggers this lint: + +```rust +fn foo() { + foo(); +} +``` + +This will produce: + +```text +warning: function cannot return without recurring + --> src/main.rs:1:1 + | +1 | fn foo() { + | ^^^^^^^^ cannot return without recurring +2 | foo(); + | ----- recursive call site + | +``` + +## unions-with-drop-fields + +This lint detects use of unions that contain fields with possibly non-trivial drop code. Some +example code that triggers this lint: + +```rust +#![feature(untagged_unions)] + +union U { + s: String, +} +``` + +This will produce: + +```text +warning: union contains a field with possibly non-trivial drop code, drop code of union fields is ignored when dropping the union + --> src/main.rs:4:5 + | +4 | s: String, + | ^^^^^^^^^ + | +``` + +## unknown-lints + +This lint detects unrecognized lint attribute. Some +example code that triggers this lint: + +```rust +#[allow(not_a_real_lint)] +``` + +This will produce: + +```text +warning: unknown lint: `not_a_real_lint` + --> src/main.rs:1:10 + | +1 | #![allow(not_a_real_lint)] + | ^^^^^^^^^^^^^^^ + | +``` + +## unreachable-code + +This lint detects detects unreachable code paths. Some example code that +triggers this lint: + +```rust +panic!("we never go past here!"); + +let x = 5; +``` + +This will produce: + +```text +warning: unreachable statement + --> src/main.rs:4:5 + | +4 | let x = 5; + | ^^^^^^^^^^ + | +``` + +## unreachable-patterns + +This lint detects detects unreachable patterns. Some +example code that triggers this lint: + +```rust +let x = 5; +match x { + y => (), + 5 => (), +} +``` + +This will produce: + +```text +warning: unreachable pattern + --> src/main.rs:5:5 + | +5 | 5 => (), + | ^ + | +``` + +The `y` pattern will always match, so the five is impossible to reach. +Remember, match arms match in order, you probably wanted to put the `5` case +above the `y` case. + +## unstable-name-collision + +This lint detects that you've used a name that the standard library plans to +add in the future, which means that your code may fail to compile without +additional type annotations in the future. Either rename, or add those +annotations now. + +## unused-allocation + +This lint detects detects unnecessary allocations that can be eliminated. + +## unused-assignments + +This lint detects detect assignments that will never be read. Some +example code that triggers this lint: + +```rust +let mut x = 5; +x = 6; +``` + +This will produce: + +```text +warning: value assigned to `x` is never read + --> src/main.rs:4:5 + | +4 | x = 6; + | ^ + | +``` + +## unused-attributes + +This lint detects detects attributes that were not used by the compiler. Some +example code that triggers this lint: + +```rust +#![feature(custom_attribute)] + +#![mutable_doc] +``` + +This will produce: + +```text +warning: unused attribute + --> src/main.rs:4:1 + | +4 | #![mutable_doc] + | ^^^^^^^^^^^^^^^ + | +``` + +## unused-comparisons + +This lint detects comparisons made useless by limits of the types involved. Some +example code that triggers this lint: + +```rust +fn foo(x: u8) { + x >= 0; +} +``` + +This will produce: + +```text +warning: comparison is useless due to type limits + --> src/main.rs:6:5 + | +6 | x >= 0; + | ^^^^^^ + | +``` + +## unused-doc-comment + +This lint detects detects doc comments that aren't used by rustdoc. Some +example code that triggers this lint: + +```rust +/// docs for x +let x = 12; +``` + +This will produce: + +```text +warning: doc comment not used by rustdoc + --> src/main.rs:2:5 + | +2 | /// docs for x + | ^^^^^^^^^^^^^^ + | +``` + +## unused-features + +This lint detects unused or unknown features found in crate-level #[feature] directives. +To fix this, simply remove the feature flag. + +## unused-imports + +This lint detects imports that are never used. Some +example code that triggers this lint: + +```rust +use std::collections::HashMap; +``` + +This will produce: + +```text +warning: unused import: `std::collections::HashMap` + --> src/main.rs:1:5 + | +1 | use std::collections::HashMap; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +``` + +## unused-macros + +This lint detects detects macros that were not used. Some example code that +triggers this lint: + +```rust +macro_rules! unused { + () => {}; +} + +fn main() { +} +``` + +This will produce: + +```text +warning: unused macro definition + --> src/main.rs:1:1 + | +1 | / macro_rules! unused { +2 | | () => {}; +3 | | } + | |_^ + | +``` + +## unused-must-use + +This lint detects unused result of a type flagged as #[must_use]. Some +example code that triggers this lint: + +```rust +fn returns_result() -> Result<(), ()> { + Ok(()) +} + +fn main() { + returns_result(); +} +``` + +This will produce: + +```text +warning: unused `std::result::Result` which must be used + --> src/main.rs:6:5 + | +6 | returns_result(); + | ^^^^^^^^^^^^^^^^^ + | +``` + +## unused-mut + +This lint detects detect mut variables which don't need to be mutable. Some +example code that triggers this lint: + +```rust +let mut x = 5; +``` + +This will produce: + +```text +warning: variable does not need to be mutable + --> src/main.rs:2:9 + | +2 | let mut x = 5; + | ----^ + | | + | help: remove this `mut` + | +``` + +## unused-parens + +This lint detects `if`, `match`, `while` and `return` with parentheses; they +do not need them. Some example code that triggers this lint: + +```rust +if(true) {} +``` + +This will produce: + +```text +warning: unnecessary parentheses around `if` condition + --> src/main.rs:2:7 + | +2 | if(true) {} + | ^^^^^^ help: remove these parentheses + | +``` + +## unused-unsafe + +This lint detects unnecessary use of an `unsafe` block. Some +example code that triggers this lint: + +```rust +unsafe {} +``` + +This will produce: + +```text +warning: unnecessary `unsafe` block + --> src/main.rs:2:5 + | +2 | unsafe {} + | ^^^^^^ unnecessary `unsafe` block + | +``` + +## unused-variables + +This lint detects detect variables which are not used in any way. Some +example code that triggers this lint: + +```rust +let x = 5; +``` + +This will produce: + +```text +warning: unused variable: `x` + --> src/main.rs:2:9 + | +2 | let x = 5; + | ^ help: consider using `_x` instead + | +``` + +## warnings + +This lint is a bit special; by changing its level, you change every other warning +that would produce a warning to whatever value you'd like: + +```rust +#![deny(warnings)] +``` + +As such, you won't ever trigger this lint in your code directly. + +## while-true + +This lint detects `while true { }`. Some example code that triggers this +lint: + +```rust +while true { + +} +``` + +This will produce: + +```text +warning: denote infinite loops with `loop { ... }` + --> src/main.rs:2:5 + | +2 | while true { + | ^^^^^^^^^^ help: use `loop` + | +``` \ No newline at end of file -- cgit 1.4.1-3-g733a5 From 142c52f4a3f7db42613239953d4615ab5a0ac3c6 Mon Sep 17 00:00:00 2001 From: steveklabnik Date: Fri, 6 Apr 2018 15:18:16 -0400 Subject: fix tests --- src/doc/rustc/src/lints/index.md | 4 ++-- src/doc/rustc/src/lints/levels.md | 8 ++++---- src/doc/rustc/src/lints/listing/allowed-by-default.md | 11 ++++++----- src/doc/rustc/src/lints/listing/deny-by-default.md | 18 +++++++++--------- src/doc/rustc/src/lints/listing/warn-by-default.md | 15 ++++++++------- 5 files changed, 29 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/doc/rustc/src/lints/index.md b/src/doc/rustc/src/lints/index.md index 4706a10c908..bf345a24389 100644 --- a/src/doc/rustc/src/lints/index.md +++ b/src/doc/rustc/src/lints/index.md @@ -7,7 +7,7 @@ depending on how you've configured things. Here's a small example: -```rust +```bash $ cat main.rs fn main() { let x = 5; @@ -25,4 +25,4 @@ warning: unused variable: `x` This is the `unused_variables` lint, and it tells you that you've introduced a variable that you don't use in your code. That's not *wrong*, so it's not -an error, but it might be a bug, so you get a warning. \ No newline at end of file +an error, but it might be a bug, so you get a warning. diff --git a/src/doc/rustc/src/lints/levels.md b/src/doc/rustc/src/lints/levels.md index f2d7241e648..83b65cd648e 100644 --- a/src/doc/rustc/src/lints/levels.md +++ b/src/doc/rustc/src/lints/levels.md @@ -22,7 +22,7 @@ pub fn foo() {} Compiling this file produces no warnings: -```rust +```bash $ rustc lib.rs --crate-type=lib $ ``` @@ -62,7 +62,7 @@ warning: unused variable: `x` A 'deny' lint produces an error if you violate it. For example, this code runs into the `exceeding_bitshifts` lint. -```rust +```rust,ignore fn main() { 100u8 << 10; } @@ -215,7 +215,7 @@ pub fn foo() {} This is the maximum level for all lints. So for example, if we take our code sample from the "deny" lint level above: -```rust +```rust,ignore fn main() { 100u8 << 10; } @@ -249,4 +249,4 @@ $ This feature is used heavily by Cargo; it will pass `--cap-lints allow` when compiling your dependencies, so that if they have any warnings, they do not -pollute the output of your build. \ No newline at end of file +pollute the output of your build. diff --git a/src/doc/rustc/src/lints/listing/allowed-by-default.md b/src/doc/rustc/src/lints/listing/allowed-by-default.md index a432c00e060..e1a3f96a6fe 100644 --- a/src/doc/rustc/src/lints/listing/allowed-by-default.md +++ b/src/doc/rustc/src/lints/listing/allowed-by-default.md @@ -336,7 +336,7 @@ This lint is deprecated and no longer used. This lint guards against `extern crate` items that are never used. Some example code that triggers this lint: -```rust +```rust,ignore extern crate semver; ``` @@ -359,9 +359,10 @@ code that triggers this lint: ```rust use test::{A}; -mod test { - struct A; +pub mod test { + pub struct A; } +# fn main() {} ``` When set to 'deny', this will produce: @@ -410,7 +411,7 @@ You can call `bar()` directly, without the `foo::`. This lint checks for the unused result of an expression in a statement. Some example code that triggers this lint: -```rust +```rust,no_run fn foo() -> T { panic!() } fn main() { @@ -449,4 +450,4 @@ error: enum variant is more than three times larger (1024 bytes) than the next l 5 | VBig([u8; 1024]), //~ ERROR variant is more than three times larger | ^^^^^^^^^^^^^^^^ | -``` \ No newline at end of file +``` diff --git a/src/doc/rustc/src/lints/listing/deny-by-default.md b/src/doc/rustc/src/lints/listing/deny-by-default.md index a361c117b10..0c49f2f7b36 100644 --- a/src/doc/rustc/src/lints/listing/deny-by-default.md +++ b/src/doc/rustc/src/lints/listing/deny-by-default.md @@ -7,7 +7,7 @@ These lints are all set to the 'deny' level by default. This lint detects that a shift exceeds the type's number of bits. Some example code that triggers this lint: -```rust +```rust,ignore 1_i32 << 32; ``` @@ -27,7 +27,7 @@ error: bitshift exceeds the type's number of bits This lint detects type parameter default erroneously allowed in invalid location. Some example code that triggers this lint: -```rust +```rust,ignore fn foo(t: T) {} ``` @@ -51,7 +51,7 @@ error: defaults for type parameters are only allowed in `struct`, `enum`, `type` visibility rules, and changed the visibility of struct constructors. Some example code that triggers this lint: -```rust +```rust,ignore mod m { pub struct S(u8); @@ -96,7 +96,7 @@ it into its own directory if appropriate. This lint detects names that resolve to ambiguous glob imports. Some example code that triggers this lint: -```rust +```rust,ignore pub struct Foo; mod bar { @@ -143,7 +143,7 @@ This warning can always be fixed by removing the unused pattern in the This lint catches transmuting from `&T` to `&mut T` becuase it is undefined behavior. Some example code that triggers this lint: -```rust +```rust,ignore unsafe { let y = std::mem::transmute::<&i32, &mut i32>(&5); } @@ -168,7 +168,7 @@ Constants do not have their symbols exported, and therefore, this probably means you meant to use a `static`, not a `const. Some example code that triggers this lint: -```rust +```rust,ignore #[no_mangle] const FOO: i32 = 5; ``` @@ -191,7 +191,7 @@ error: const items should never be #[no_mangle] This lint detects incorrect parentheses. Some example code that triggers this lint: -```rust +```rust,ignore let x = 5 as usize(); ``` @@ -225,7 +225,7 @@ to be accessed in safe code. This lint now catches and denies this kind of code. This lint detects an unknown crate type found in a `#[crate_type]` directive. Some example code that triggers this lint: -```rust +```rust,ignore #![crate_type="lol"] ``` @@ -238,4 +238,4 @@ error: invalid `crate_type` value 1 | #![crate_type="lol"] | ^^^^^^^^^^^^^^^^^^^^ | -``` \ No newline at end of file +``` diff --git a/src/doc/rustc/src/lints/listing/warn-by-default.md b/src/doc/rustc/src/lints/listing/warn-by-default.md index a8f3400687c..1171f75caa1 100644 --- a/src/doc/rustc/src/lints/listing/warn-by-default.md +++ b/src/doc/rustc/src/lints/listing/warn-by-default.md @@ -7,7 +7,7 @@ These lints are all set to the 'warn' level by default. This lint detects an erroneous expression while doing constant evaluation. Some example code that triggers this lint: -```rust +```rust,ignore let b = 200u8 + 200u8; ``` @@ -413,7 +413,7 @@ impl Trait for i32 { This lint detects when compiler plugins are used as ordinary library in non-plugin crate. Some example code that triggers this lint: -```rust +```rust,ignore #![feature(plugin)] #![plugin(macro_crate_test)] @@ -425,7 +425,7 @@ extern crate macro_crate_test; This lint detects detect private items in public interfaces not caught by the old implementation. Some example code that triggers this lint: -```rust +```rust,ignore pub trait Trait { type A; } @@ -439,6 +439,7 @@ mod foo { type A = Z; } } +# fn main() {} ``` This will produce: @@ -682,7 +683,7 @@ warning: union contains a field with possibly non-trivial drop code, drop code o This lint detects unrecognized lint attribute. Some example code that triggers this lint: -```rust +```rust,ignore #[allow(not_a_real_lint)] ``` @@ -702,7 +703,7 @@ warning: unknown lint: `not_a_real_lint` This lint detects detects unreachable code paths. Some example code that triggers this lint: -```rust +```rust,no_run panic!("we never go past here!"); let x = 5; @@ -1020,7 +1021,7 @@ As such, you won't ever trigger this lint in your code directly. This lint detects `while true { }`. Some example code that triggers this lint: -```rust +```rust,no_run while true { } @@ -1035,4 +1036,4 @@ warning: denote infinite loops with `loop { ... }` 2 | while true { | ^^^^^^^^^^ help: use `loop` | -``` \ No newline at end of file +``` -- cgit 1.4.1-3-g733a5 From cb6a19925a542dcf07c4318adb751d5aa4773465 Mon Sep 17 00:00:00 2001 From: steveklabnik Date: Tue, 10 Apr 2018 16:35:28 -0400 Subject: add codegen options section --- src/doc/rustc/src/codegen-options/index.md | 208 +++++++++++++++++++++++++++++ 1 file changed, 208 insertions(+) (limited to 'src') diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index 4350db56ef6..70dae9314c1 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -1 +1,209 @@ # Codegen options + +All of these options are passed to `rustc` via the `-C` flag, short for "codegen." You can see +a version of this list for your exact compiler by running `rustc -C help`. + +## ar + +This option is deprecated and does nothing. + +## linker + +This flag lets you control which linker `rustc` invokes to link your code. + +## link-arg=val + +This flag lets you append a single extra argument to the linker invocation. + +"Append" is significant; you can pass this flag multiple times to add multiple arguments. + +## link-args + +This flag lets you append multiple extra arguments to the linker invocation. The +options should be separated by spaces. + +## link-dead-code + +Normally, the linker will remove dead code. This flag disables this behavior. + +An example of when this flag might be useful is when trying to construct code coverage +metrics. + +## lto + +This flag instructs LLVM to use [link time +optimizations](https://llvm.org/docs/LinkTimeOptimization.html). + +It takes one of two values, `thin` and `fat`. 'thin' LTO [is a new feature of +LLVM](http://blog.llvm.org/2016/06/thinlto-scalable-and-incremental-lto.html), +'fat' referring to the classic version of LTO. + +## target-cpu + +This instructs `rustc` to generate code specifically for a particular processor. + +You can run `rustc --print target-cpus` to see the valid options to pass +here. Additionally, `native` can be passed to use the processor of the host +machine. + +## target-feature + +Individual targets will support different features; this flag lets you control +enabling or disabling a feature. + +To see the valid options and an example of use, run `rustc --print +target-features`. + +## passes + +This flag can be used to add extra LLVM passes to the compilation. + +The list must be separated by spaces. + +## llvm-args + +This flag can be used to pass a list of arguments directly to LLVM. + +The list must be separated by spaces. + +## save-temps + +`rustc` will generate temporary files during compilation; normally it will +delete them after it's done with its work. This option will cause them to be +preserved instead of removed. + +## rpath + +This option allows you to set the value of +[`rpath`](https://en.wikipedia.org/wiki/Rpath). + +## overflow-checks + +This flag allows you to control the behavior of integer overflow. This flag +can be passed many options: + +* To turn overflow checks on: `y`, `yes`, or `on`. +* To turn overflow checks off: `n`, `no`, or `off`. + +## no-prepopulate-passes + +The pass manager comes pre-populated with a list of passes; this flag +ensures that list is empty. + +## no-vectorize-loops + +By default, `rustc` will attempt to [vectorize +loops](https://llvm.org/docs/Vectorizers.html#the-loop-vectorizer). This +flag will turn that behavior off. + +## no-vectorize-slp + +By default, `rustc` will attempt to vectorize loops using [superword-level +parallism](https://llvm.org/docs/Vectorizers.html#the-slp-vectorizer). This +flag will turn that behavior off. + +## soft-float + +This option will make `rustc` generate code using "soft floats." By default, +a lot of hardware supports floating point instructions, and so the code generated +will take advantage of this. "soft floats" emulate floating point instructions +in software. + +## prefer-dynamic + +By default, `rustc` prefers to statically link dependencies. This option will +make it use dynamic linking instead. + +## no-integrated-as + +LLVM comes with an internal assembler; this option will let you use an +external assembler instead. + +## no-redzone + +This flag allows you to disable [the +red zone](https://en.wikipedia.org/wiki/Red_zone_\(computing\)). This flag can +be passed many options: + +* To enable the red zone: `y`, `yes`, or `on`. +* To disable it: `n`, `no`, or `off`. + +## relocation-model + +This option lets you choose which relocation model to use. + +To find the valid options for this flag, run `rustc --print relocation-models`. + +## code-model=val + +This option lets you choose which code model to use. + +To find the valid options for this flag, run `rustc --print code-models`. + +## metadata + +This option allows you to control the metadata used for symbol mangling. + +## extra-filename + +This option allows you to put extra data in each output filename. + +## codegen-units + +This flag lets you control how many threads are used when doing +code generation. + +Increasing paralellism may speed up compile times, but may also +produce slower code. + +## remark + +This flag lets you print remarks for these optimization passes. + +The list of passes should be separated by spaces. + +`all` will remark on every pass. + +## no-stack-check + +This option is deprecated and does nothing. + +## debuginfo + +This flag lets you control debug information: + +* `0`: no debug info at all +* `1`: line tables only +* `2`: full debug info + +## opt-level + +This flag lets you control the optimization level. + +* `0`: no optimizations +* `1`: basic optimizations +* `2`: some optimizations +* `3`: all optimizations +* `s`: optimize for binary size +* `z`: optimize for binary size, but also turn off loop vectorization. + +## debug-assertions + +This flag lets you turn `cfg(debug_assertions)` on or off. + +## inline-threshold + +This option lets you set the threshold for inlining a function. + +The default is 225. + +## panic + +This option lets you control what happens when the code panics. + +* `abort`: terminate the process upon panic +* `unwind`: unwind the stack upon panic + +## incremental + +This flag allows you to enable incremental compilation. \ No newline at end of file -- cgit 1.4.1-3-g733a5 From f817d1960a4d495a20689bc7ed22847561afd216 Mon Sep 17 00:00:00 2001 From: Daiki Mizukami Date: Tue, 10 Apr 2018 17:13:32 +0900 Subject: std: Mark `ptr::Unique` with `#[doc(hidden)]` --- src/libcore/ptr.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 5a54de06b5e..a1307a6d599 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -2511,6 +2511,7 @@ impl PartialOrd for *mut T { reason = "use NonNull instead and consider PhantomData \ (if you also use #[may_dangle]), Send, and/or Sync")] #[allow(deprecated)] +#[doc(hidden)] pub struct Unique { pointer: NonZero<*const T>, // NOTE: this marker has no consequences for variance, but is necessary -- cgit 1.4.1-3-g733a5 From 54d6bcbf70112ceb0efa4579ab9f6d5673588889 Mon Sep 17 00:00:00 2001 From: Daiki Mizukami Date: Wed, 11 Apr 2018 18:24:47 +0900 Subject: alloc: Mark `Box::into_unique` with `#[doc(hidden)]` --- src/liballoc/boxed.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 71b53cc88e5..bf7921ea1a2 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -184,6 +184,7 @@ impl Box { #[unstable(feature = "ptr_internals", issue = "0", reason = "use into_raw_non_null instead")] #[inline] + #[doc(hidden)] pub fn into_unique(b: Box) -> Unique { let unique = b.0; mem::forget(b); -- cgit 1.4.1-3-g733a5 From cd3f6cf3fef900c7461cc02d4bb4cd226d7c5b6e Mon Sep 17 00:00:00 2001 From: steveklabnik Date: Mon, 16 Apr 2018 12:57:01 -0400 Subject: fill out command line arguments --- src/doc/rustc/src/command-line-arguments.md | 63 ++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md index 7ea3e806e4a..488102f926a 100644 --- a/src/doc/rustc/src/command-line-arguments.md +++ b/src/doc/rustc/src/command-line-arguments.md @@ -4,54 +4,113 @@ Here's a list of command-line arguments to `rustc` and what they do. ## `-h`/`--help`: get help +This flag will print out help information for `rustc`. + ## `--cfg`: configure the compilation environment -## `-L`: add a directory to the library search path. +This flag can turn on or off various `#[cfg]` settings. + +## `-L`: add a directory to the library search path + +When looking for external crates, a directory passed to this flag will be searched. ## `-l`: link the generated crate to a native library +This flag allows you to specify linking to a specific native library when building +a crate. + ## `--crate-type`: a list of types of crates for the compiler to emit +This instructs `rustc` on which crate type to build. + ## `--crate-name`: specify the name of the crate being built +This informs `rustc` of the name of your crate. + ## `--emit`: emit output other than a crate +Instead of producing a crate, this flag can print out things like the assembly or LLVM-IR. + ## `--print`: print compiler information +This flag prints out various information about the compiler. + ## `-g`: include debug information +A synonym for `-C debug-level=2`. + ## `-O`: optimize your code +A synonym for `-C opt-level=2`. + ## `-o`: filename of the output +This flag controls the output filename. + ## `--out-dir`: directory to write the output in +The outputted crate will be written to this directory. + ## `--explain`: provide a detailed explanation of an error message +Each error of `rustc`'s comes with an error code; this will print +out a longer explanation of a given error. + ## `--test`: build a test harness +When compiling this crate, `rustc` will ignore your `main` function +and instead produce a test harness. + ## `--target`: select a target triple to build +This controls which [target](targets/index.html) to produce. + ## `-W`: set lint warnings +This flag will set which lints should be set to the [warn level](lints/levels.html#warn). + ## `-A`: set lint allowed +This flag will set which lints should be set to the [allow level](lints/levels.html#allow). + ## `-D`: set lint denied +This flag will set which lints should be set to the [deny level](lints/levels.html#deny). + ## `-F`: set lint forbidden +This flag will set which lints should be set to the [forbid level](lints/levels.html#forbid). + ## `--cap-lints`: set the most restrictive lint level +This flag lets you 'cap' lints, for more, [see here](lints/levels.html#capping-lints). + ## `-C`/`--codegen`: code generation options +This flag will allow you to set [codegen options](codegen-options/index.html). + ## `-V`/`--verision`: print a version +This flag will print out `rustc`'s version. + ## `-v`/`--verbose`: use verbose output +This flag, when combined with other flags, makes them produce extra output. + ## `--extern`: specify where an external library is located +This flag allows you to pass the name and location of an external crate that will +be linked into the crate you're buildling. + ## `--sysroot`: Override the system root +The "sysroot" is where `rustc` looks for the crates that come with the Rust +distribution; this flag allows that to be overridden. + ## `--error-format`: control how errors are produced -## `--color`: configur coloring of output \ No newline at end of file +This flag lets you control the format of errors. + +## `--color`: configur coloring of output + +This flag lets you control color settings of the output. \ No newline at end of file -- cgit 1.4.1-3-g733a5 From b204968239188719b34929195e28b2cce25eb836 Mon Sep 17 00:00:00 2001 From: steveklabnik Date: Mon, 16 Apr 2018 12:57:09 -0400 Subject: fill out contributing --- src/doc/rustc/src/contributing.md | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/doc/rustc/src/contributing.md b/src/doc/rustc/src/contributing.md index e21b6fbd14a..fcb8e6b27db 100644 --- a/src/doc/rustc/src/contributing.md +++ b/src/doc/rustc/src/contributing.md @@ -1 +1,6 @@ # Contributing to rustc + +We'd love to have your help improving `rustc`! To that end, we've written [a +whole book](https://rust-lang-nursery.github.io/rustc-guide/) on its +internals, how it works, and how to get started working on it. To learn +more, you'll want to check that out. \ No newline at end of file -- cgit 1.4.1-3-g733a5 From 00c860e8a908ae09eee0a3508a377fc6b7003d8c Mon Sep 17 00:00:00 2001 From: steveklabnik Date: Mon, 16 Apr 2018 12:57:16 -0400 Subject: write docs for targets --- src/doc/rustc/src/targets/built-in.md | 9 +++++++++ src/doc/rustc/src/targets/custom.md | 16 ++++++++++++++++ src/doc/rustc/src/targets/index.md | 13 +++++++++++++ 3 files changed, 38 insertions(+) (limited to 'src') diff --git a/src/doc/rustc/src/targets/built-in.md b/src/doc/rustc/src/targets/built-in.md index 819d74457fe..8620346e5b7 100644 --- a/src/doc/rustc/src/targets/built-in.md +++ b/src/doc/rustc/src/targets/built-in.md @@ -1 +1,10 @@ # Built-in Targets + +`rustc` ships with the ability to compile to many targets automatically, we +call these "built-in" targets, and they generally correspond to targets that +the team is supporting directly. + +To see the list of built-in targets, you can run `rustc --print target-list`, +or look at [the API +docs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_back/target/#modules). +Each module there defines a builder for a particular target. \ No newline at end of file diff --git a/src/doc/rustc/src/targets/custom.md b/src/doc/rustc/src/targets/custom.md index 59039ce67ba..0691afc60ea 100644 --- a/src/doc/rustc/src/targets/custom.md +++ b/src/doc/rustc/src/targets/custom.md @@ -1 +1,17 @@ # Custom Targets + +If you'd like to build for a target that is not yet supported by `rustc`, you can use a +"custom target specification" to define a target. These target specification files +are JSON. To see the JSON for the host target, you can run: + +```bash +$ rustc +nightly -Z unstable-options --print target-spec-json +``` + +To see it for a different target, add the `--target` flag: + +```bash +$ rustc +nightly -Z unstable-options --target=wasm32-unknown-unknown --print target-spec-json +``` + +To use a custom target, see [`xargo`](https://github.com/japaric/xargo). \ No newline at end of file diff --git a/src/doc/rustc/src/targets/index.md b/src/doc/rustc/src/targets/index.md index 01d0a4c8c0e..cea7ce4dea5 100644 --- a/src/doc/rustc/src/targets/index.md +++ b/src/doc/rustc/src/targets/index.md @@ -1 +1,14 @@ # Targets + +`rustc` is a cross-compiler by default. This means that you can use any compiler to build for any +architecture. The list of *targets* are the possible architectures that you can build for. + +You can see the API docs for a given target +[here](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_back/target/struct.Target.html), all +of these options can be set on a per-target basis. + +To compile to a particular target, use the `--target` flag: + +```bash +$ rustc src/main.rs --target=wasm32-unknown-unknown +``` \ No newline at end of file -- cgit 1.4.1-3-g733a5 From 43b24c6c83acbd7ef63a97cf45b1a622d2cd61b0 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Thu, 19 Apr 2018 07:47:07 +0900 Subject: Pass the right type to box_free() in MIR Currently, MIR just passes the raw Box to box_free(), which happens to work because practically, it's the same thing. But that might not be true in the future, with Box. The MIR inline pass actually fixes up the argument while inlining box_free, but this is not enabled by default and doesn't necessarily happen (the inline threshold needs to be passed). This change effectively moves what the MIR inline pass does to the elaborate_drops pass, so that box_free() is passed the raw pointer instead of the Box. --- src/librustc_mir/transform/inline.rs | 65 +------------------------------- src/librustc_mir/util/elaborate_drops.rs | 39 +++++++++++++++---- 2 files changed, 34 insertions(+), 70 deletions(-) (limited to 'src') diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 2dd805ccf9b..b81bb5c81ca 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -379,8 +379,6 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { TerminatorKind::Call { args, destination: Some(destination), cleanup, .. } => { debug!("Inlined {:?} into {:?}", callsite.callee, self.source); - let is_box_free = Some(callsite.callee) == self.tcx.lang_items().box_free_fn(); - let mut local_map = IndexVec::with_capacity(callee_mir.local_decls.len()); let mut scope_map = IndexVec::with_capacity(callee_mir.visibility_scopes.len()); let mut promoted_map = IndexVec::with_capacity(callee_mir.promoted.len()); @@ -460,24 +458,8 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { let return_block = destination.1; - let args : Vec<_> = if is_box_free { - assert!(args.len() == 1); - // box_free takes a Box, but is defined with a *mut T, inlining - // needs to generate the cast. - // FIXME: we should probably just generate correct MIR in the first place... - - let arg = if let Operand::Move(ref place) = args[0] { - place.clone() - } else { - bug!("Constant arg to \"box_free\""); - }; - - let ptr_ty = args[0].ty(caller_mir, self.tcx); - vec![self.cast_box_free_arg(arg, ptr_ty, &callsite, caller_mir)] - } else { - // Copy the arguments if needed. - self.make_call_args(args, &callsite, caller_mir) - }; + // Copy the arguments if needed. + let args: Vec<_> = self.make_call_args(args, &callsite, caller_mir); let bb_len = caller_mir.basic_blocks().len(); let mut integrator = Integrator { @@ -518,49 +500,6 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { } } - fn cast_box_free_arg(&self, arg: Place<'tcx>, ptr_ty: Ty<'tcx>, - callsite: &CallSite<'tcx>, caller_mir: &mut Mir<'tcx>) -> Local { - let arg = Rvalue::Ref( - self.tcx.types.re_erased, - BorrowKind::Mut { allow_two_phase_borrow: false }, - arg.deref()); - - let ty = arg.ty(caller_mir, self.tcx); - let ref_tmp = LocalDecl::new_temp(ty, callsite.location.span); - let ref_tmp = caller_mir.local_decls.push(ref_tmp); - let ref_tmp = Place::Local(ref_tmp); - - let ref_stmt = Statement { - source_info: callsite.location, - kind: StatementKind::Assign(ref_tmp.clone(), arg) - }; - - caller_mir[callsite.bb] - .statements.push(ref_stmt); - - let pointee_ty = match ptr_ty.sty { - ty::TyRawPtr(tm) | ty::TyRef(_, tm) => tm.ty, - _ if ptr_ty.is_box() => ptr_ty.boxed_ty(), - _ => bug!("Invalid type `{:?}` for call to box_free", ptr_ty) - }; - let ptr_ty = self.tcx.mk_mut_ptr(pointee_ty); - - let raw_ptr = Rvalue::Cast(CastKind::Misc, Operand::Move(ref_tmp), ptr_ty); - - let cast_tmp = LocalDecl::new_temp(ptr_ty, callsite.location.span); - let cast_tmp = caller_mir.local_decls.push(cast_tmp); - - let cast_stmt = Statement { - source_info: callsite.location, - kind: StatementKind::Assign(Place::Local(cast_tmp), raw_ptr) - }; - - caller_mir[callsite.bb] - .statements.push(cast_stmt); - - cast_tmp - } - fn make_call_args( &self, args: Vec>, diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index 19f33ef5d45..1564db1ee2a 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -876,14 +876,39 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> let unit_temp = Place::Local(self.new_temp(tcx.mk_nil())); let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem); let substs = tcx.mk_substs(iter::once(Kind::from(ty))); + let ref_ty = tcx.mk_ref(tcx.types.re_erased, ty::TypeAndMut { + ty: ty, + mutbl: hir::Mutability::MutMutable + }); + let ptr_ty = tcx.mk_mut_ptr(ty); + let ref_tmp = Place::Local(self.new_temp(ref_ty)); + let ptr_tmp = Place::Local(self.new_temp(ptr_ty)); - let call = TerminatorKind::Call { - func: Operand::function_handle(tcx, free_func, substs, self.source_info.span), - args: vec![Operand::Move(self.place.clone())], - destination: Some((unit_temp, target)), - cleanup: None - }; // FIXME(#43234) - let free_block = self.new_block(unwind, call); + let free_block = BasicBlockData { + statements: vec![ + self.assign(&ref_tmp, Rvalue::Ref( + tcx.types.re_erased, + BorrowKind::Mut { allow_two_phase_borrow: false }, + self.place.clone().deref() + )), + self.assign(&ptr_tmp, Rvalue::Cast( + CastKind::Misc, + Operand::Move(ref_tmp), + ptr_ty, + )), + ], + terminator: Some(Terminator { + kind: TerminatorKind::Call { + func: Operand::function_handle(tcx, free_func, substs, self.source_info.span), + args: vec![Operand::Move(ptr_tmp)], + destination: Some((unit_temp, target)), + cleanup: None + }, // FIXME(#43234) + source_info: self.source_info, + }), + is_cleanup: unwind.is_cleanup() + }; + let free_block = self.elaborator.patch().new_block(free_block); let block_start = Location { block: free_block, statement_index: 0 }; self.elaborator.clear_drop_flag(block_start, self.path, DropFlagMode::Shallow); -- cgit 1.4.1-3-g733a5 From dfa611146c7acd692f760619d25bfabf7261eaf5 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Thu, 19 Apr 2018 10:50:50 +0900 Subject: Remove the explicit box_free type check Because box_free is now passed a pointer instead of a Box, we can stop relying on TypeChecked::check_box_free_inputs, because TypeChecker::check_call_inputs should be enough, like for all other function calls. It seems it was not actually reached anyways in cases where it would have made a difference. (issue #50071) --- .../borrow_check/nll/type_check/mod.rs | 70 +--------------------- 1 file changed, 1 insertion(+), 69 deletions(-) (limited to 'src') diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index acd246b7031..78e0b1c2cc1 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -918,11 +918,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { )); } - if self.is_box_free(func) { - self.check_box_free_inputs(mir, term, &sig, args, term_location); - } else { - self.check_call_inputs(mir, term, &sig, args, term_location); - } + self.check_call_inputs(mir, term, &sig, args, term_location); } TerminatorKind::Assert { ref cond, ref msg, .. @@ -1026,70 +1022,6 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } } - fn is_box_free(&self, operand: &Operand<'tcx>) -> bool { - match *operand { - Operand::Constant(ref c) => match c.ty.sty { - ty::TyFnDef(ty_def_id, _) => { - Some(ty_def_id) == self.tcx().lang_items().box_free_fn() - } - _ => false, - }, - _ => false, - } - } - - fn check_box_free_inputs( - &mut self, - mir: &Mir<'tcx>, - term: &Terminator<'tcx>, - sig: &ty::FnSig<'tcx>, - args: &[Operand<'tcx>], - term_location: Location, - ) { - debug!("check_box_free_inputs"); - - // box_free takes a Box as a pointer. Allow for that. - - if sig.inputs().len() != 1 { - span_mirbug!(self, term, "box_free should take 1 argument"); - return; - } - - let pointee_ty = match sig.inputs()[0].sty { - ty::TyRawPtr(mt) => mt.ty, - _ => { - span_mirbug!(self, term, "box_free should take a raw ptr"); - return; - } - }; - - if args.len() != 1 { - span_mirbug!(self, term, "box_free called with wrong # of args"); - return; - } - - let ty = args[0].ty(mir, self.tcx()); - let arg_ty = match ty.sty { - ty::TyRawPtr(mt) => mt.ty, - ty::TyAdt(def, _) if def.is_box() => ty.boxed_ty(), - _ => { - span_mirbug!(self, term, "box_free called with bad arg ty"); - return; - } - }; - - if let Err(terr) = self.sub_types(arg_ty, pointee_ty, term_location.at_self()) { - span_mirbug!( - self, - term, - "bad box_free arg ({:?} <- {:?}): {:?}", - pointee_ty, - arg_ty, - terr - ); - } - } - fn check_iscleanup(&mut self, mir: &Mir<'tcx>, block_data: &BasicBlockData<'tcx>) { let is_cleanup = block_data.is_cleanup; self.last_span = block_data.terminator().source_info.span; -- cgit 1.4.1-3-g733a5 From 6614fa0981f5d5555f7cd2f11e258fe989e98032 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Thu, 19 Apr 2018 15:26:16 +0900 Subject: Support an alternative form for box_free box_free currently takes a pointer. With the prospect of the Box type definition changing in the future to include an allocator, box_free will also need to be aware of this. In order to prepare for that future, we allow box_free to take a form where its argument are the fields of the Box. e.g. if Box is defined as `Box(A, B, C)`, then box_free signature becomes `box_free(a: A, b: B, c: C)`. We however still allow the current form (taking a pointer), so that the same compiler can handle both forms, which helps with bootstrap. --- src/librustc_mir/util/elaborate_drops.rs | 68 +++++++++++++++++++++----------- 1 file changed, 44 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index 1564db1ee2a..cc91bbf9061 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -337,18 +337,19 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> self.drop_ladder(fields, succ, unwind).0 } - fn open_drop_for_box<'a>(&mut self, ty: Ty<'tcx>) -> BasicBlock + fn open_drop_for_box<'a>(&mut self, adt: &'tcx ty::AdtDef, substs: &'tcx Substs<'tcx>) + -> BasicBlock { - debug!("open_drop_for_box({:?}, {:?})", self, ty); + debug!("open_drop_for_box({:?}, {:?}, {:?})", self, adt, substs); let interior = self.place.clone().deref(); let interior_path = self.elaborator.deref_subpath(self.path); let succ = self.succ; // FIXME(#43234) let unwind = self.unwind; - let succ = self.box_free_block(ty, succ, unwind); + let succ = self.box_free_block(adt, substs, succ, unwind); let unwind_succ = self.unwind.map(|unwind| { - self.box_free_block(ty, unwind, Unwind::InCleanup) + self.box_free_block(adt, substs, unwind, Unwind::InCleanup) }); self.drop_subpath(&interior, interior_path, succ, unwind_succ) @@ -791,11 +792,12 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> ty::TyTuple(tys) => { self.open_drop_for_tuple(tys) } - ty::TyAdt(def, _) if def.is_box() => { - self.open_drop_for_box(ty.boxed_ty()) - } ty::TyAdt(def, substs) => { - self.open_drop_for_adt(def, substs) + if def.is_box() { + self.open_drop_for_box(def, substs) + } else { + self.open_drop_for_adt(def, substs) + } } ty::TyDynamic(..) => { let unwind = self.unwind; // FIXME(#43234) @@ -858,34 +860,40 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> fn box_free_block<'a>( &mut self, - ty: Ty<'tcx>, + adt: &'tcx ty::AdtDef, + substs: &'tcx Substs<'tcx>, target: BasicBlock, unwind: Unwind, ) -> BasicBlock { - let block = self.unelaborated_free_block(ty, target, unwind); + let block = self.unelaborated_free_block(adt, substs, target, unwind); self.drop_flag_test_block(block, target, unwind) } fn unelaborated_free_block<'a>( &mut self, - ty: Ty<'tcx>, + adt: &'tcx ty::AdtDef, + substs: &'tcx Substs<'tcx>, target: BasicBlock, unwind: Unwind ) -> BasicBlock { let tcx = self.tcx(); let unit_temp = Place::Local(self.new_temp(tcx.mk_nil())); let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem); - let substs = tcx.mk_substs(iter::once(Kind::from(ty))); - let ref_ty = tcx.mk_ref(tcx.types.re_erased, ty::TypeAndMut { - ty: ty, - mutbl: hir::Mutability::MutMutable - }); - let ptr_ty = tcx.mk_mut_ptr(ty); - let ref_tmp = Place::Local(self.new_temp(ref_ty)); - let ptr_tmp = Place::Local(self.new_temp(ptr_ty)); - - let free_block = BasicBlockData { - statements: vec![ + let free_sig = tcx.fn_sig(free_func).skip_binder().clone(); + let free_inputs = free_sig.inputs(); + // If the box_free function takes a *mut T, transform the Box into + // such a pointer before calling box_free. Otherwise, pass it all + // the fields in the Box as individual arguments. + let (stmts, args) = if free_inputs.len() == 1 && free_inputs[0].is_mutable_pointer() { + let ty = substs.type_at(0); + let ref_ty = tcx.mk_ref(tcx.types.re_erased, ty::TypeAndMut { + ty: ty, + mutbl: hir::Mutability::MutMutable + }); + let ptr_ty = tcx.mk_mut_ptr(ty); + let ref_tmp = Place::Local(self.new_temp(ref_ty)); + let ptr_tmp = Place::Local(self.new_temp(ptr_ty)); + let stmts = vec![ self.assign(&ref_tmp, Rvalue::Ref( tcx.types.re_erased, BorrowKind::Mut { allow_two_phase_borrow: false }, @@ -896,11 +904,23 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> Operand::Move(ref_tmp), ptr_ty, )), - ], + ]; + (stmts, vec![Operand::Move(ptr_tmp)]) + } else { + let args = adt.variants[0].fields.iter().enumerate().map(|(i, f)| { + let field = Field::new(i); + let field_ty = f.ty(self.tcx(), substs); + Operand::Move(self.place.clone().field(field, field_ty)) + }).collect(); + (vec![], args) + }; + + let free_block = BasicBlockData { + statements: stmts, terminator: Some(Terminator { kind: TerminatorKind::Call { func: Operand::function_handle(tcx, free_func, substs, self.source_info.span), - args: vec![Operand::Move(ptr_tmp)], + args: args, destination: Some((unit_temp, target)), cleanup: None }, // FIXME(#43234) -- cgit 1.4.1-3-g733a5 From 64f5233c445406cc576b9ce371af3211c05a26e4 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Thu, 19 Apr 2018 16:20:53 +0900 Subject: Adapt the owned_box lang item to allow a Box type with defaulted parameters A Box type with associated allocator would, on its own, be a backwards incompatible change, because of the additional parameter, but if that additional parameter has a default, then backwards compatibility with the current definition of the type is preserved. But the owned_box lang item currently doesn't allow such extra parameters, so add support for this. --- src/librustc/ty/context.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 28ad5edbd2d..6e1ccab0a53 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -34,7 +34,7 @@ use middle::resolve_lifetime::{self, ObjectLifetimeDefault}; use middle::stability; use mir::{self, Mir, interpret}; use mir::interpret::{Value, PrimVal}; -use ty::subst::{Kind, Substs}; +use ty::subst::{Kind, Substs, Subst}; use ty::ReprOptions; use ty::Instance; use traits; @@ -2319,7 +2319,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn mk_box(self, ty: Ty<'tcx>) -> Ty<'tcx> { let def_id = self.require_lang_item(lang_items::OwnedBoxLangItem); let adt_def = self.adt_def(def_id); - let substs = self.mk_substs(iter::once(Kind::from(ty))); + let generics = self.generics_of(def_id); + let mut substs = vec![Kind::from(ty)]; + // Add defaults for other generic params if there are some. + for def in generics.types.iter().skip(1) { + assert!(def.has_default); + let ty = self.type_of(def.def_id).subst(self, &substs); + substs.push(ty.into()); + } + let substs = self.mk_substs(substs.into_iter()); self.mk_ty(TyAdt(adt_def, substs)) } -- cgit 1.4.1-3-g733a5 From 5d5fb97b6e8085cb920c1c10a9b298c3c7f2a53d Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sat, 21 Apr 2018 11:24:52 +0200 Subject: Remove hack around comparisons of i1 values (fixes #40980) The regression test still passes without that 2 years old hack. The underlying LLVM bug has probably been fixed upstream since then. --- src/librustc_trans/mir/rvalue.rs | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'src') diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index 93702bfbbf3..8b512ebcb00 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -514,7 +514,6 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { let is_float = input_ty.is_fp(); let is_signed = input_ty.is_signed(); let is_nil = input_ty.is_nil(); - let is_bool = input_ty.is_bool(); match op { mir::BinOp::Add => if is_float { bx.fadd(lhs, rhs) @@ -564,15 +563,6 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { lhs, rhs ) } else { - let (lhs, rhs) = if is_bool { - // FIXME(#36856) -- extend the bools into `i8` because - // LLVM's i1 comparisons are broken. - (bx.zext(lhs, Type::i8(bx.cx)), - bx.zext(rhs, Type::i8(bx.cx))) - } else { - (lhs, rhs) - }; - bx.icmp( base::bin_op_to_icmp_predicate(op.to_hir_binop(), is_signed), lhs, rhs -- cgit 1.4.1-3-g733a5 From 91aa267eda21be36d7cae43b6809eba63f1aac4c Mon Sep 17 00:00:00 2001 From: Aaron Aaeng Date: Sat, 21 Apr 2018 16:06:48 -0600 Subject: Make must_use lint cover all binary/unary operators --- src/libcore/ops/arith.rs | 6 ++ src/libcore/ops/bit.rs | 6 ++ src/libcore/ops/deref.rs | 1 + src/librustc_lint/unused.rs | 42 +++++++---- src/test/ui/lint/must-use-ops.rs | 52 ++++++++++++++ src/test/ui/lint/must-use-ops.stderr | 132 +++++++++++++++++++++++++++++++++++ 6 files changed, 224 insertions(+), 15 deletions(-) create mode 100644 src/test/ui/lint/must-use-ops.rs create mode 100644 src/test/ui/lint/must-use-ops.stderr (limited to 'src') diff --git a/src/libcore/ops/arith.rs b/src/libcore/ops/arith.rs index 88db019b02f..8fd06e7bb4b 100644 --- a/src/libcore/ops/arith.rs +++ b/src/libcore/ops/arith.rs @@ -93,6 +93,7 @@ pub trait Add { type Output; /// Performs the `+` operation. + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] fn add(self, rhs: RHS) -> Self::Output; } @@ -189,6 +190,7 @@ pub trait Sub { type Output; /// Performs the `-` operation. + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] fn sub(self, rhs: RHS) -> Self::Output; } @@ -307,6 +309,7 @@ pub trait Mul { type Output; /// Performs the `*` operation. + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] fn mul(self, rhs: RHS) -> Self::Output; } @@ -429,6 +432,7 @@ pub trait Div { type Output; /// Performs the `/` operation. + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] fn div(self, rhs: RHS) -> Self::Output; } @@ -512,6 +516,7 @@ pub trait Rem { type Output = Self; /// Performs the `%` operation. + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] fn rem(self, rhs: RHS) -> Self::Output; } @@ -595,6 +600,7 @@ pub trait Neg { type Output; /// Performs the unary `-` operation. + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] fn neg(self) -> Self::Output; } diff --git a/src/libcore/ops/bit.rs b/src/libcore/ops/bit.rs index 81c4455cef4..9bde02abe64 100644 --- a/src/libcore/ops/bit.rs +++ b/src/libcore/ops/bit.rs @@ -46,6 +46,7 @@ pub trait Not { type Output; /// Performs the unary `!` operation. + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] fn not(self) -> Self::Output; } @@ -128,6 +129,7 @@ pub trait BitAnd { type Output; /// Performs the `&` operation. + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] fn bitand(self, rhs: RHS) -> Self::Output; } @@ -210,6 +212,7 @@ pub trait BitOr { type Output; /// Performs the `|` operation. + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] fn bitor(self, rhs: RHS) -> Self::Output; } @@ -295,6 +298,7 @@ pub trait BitXor { type Output; /// Performs the `^` operation. + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] fn bitxor(self, rhs: RHS) -> Self::Output; } @@ -381,6 +385,7 @@ pub trait Shl { type Output; /// Performs the `<<` operation. + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] fn shl(self, rhs: RHS) -> Self::Output; } @@ -488,6 +493,7 @@ pub trait Shr { type Output; /// Performs the `>>` operation. + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] fn shr(self, rhs: RHS) -> Self::Output; } diff --git a/src/libcore/ops/deref.rs b/src/libcore/ops/deref.rs index 4ce0740130b..3903e85768c 100644 --- a/src/libcore/ops/deref.rs +++ b/src/libcore/ops/deref.rs @@ -75,6 +75,7 @@ pub trait Deref { type Target: ?Sized; /// Dereferences the value. + #[must_use] #[stable(feature = "rust1", since = "1.0.0")] fn deref(&self) -> &Self::Target; } diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index bf86f6a6952..5ec8305de78 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -91,23 +91,35 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { let def_id = def.def_id(); fn_warned = check_must_use(cx, def_id, s.span, "return value of "); } - - if let hir::ExprBinary(bin_op, ..) = expr.node { - match bin_op.node { - // Hardcoding the comparison operators here seemed more - // expedient than the refactoring that would be needed to - // look up the `#[must_use]` attribute which does exist on - // the comparison trait methods - hir::BiEq | hir::BiLt | hir::BiLe | hir::BiNe | hir::BiGe | hir::BiGt => { - let msg = "unused comparison which must be used"; - cx.span_lint(UNUSED_MUST_USE, expr.span, msg); - op_warned = true; - }, - _ => {}, - } + let must_use_op = match expr.node { + // Hardcoding operators here seemed more expedient than the + // refactoring that would be needed to look up the `#[must_use]` + // attribute which does exist on the comparison trait methods + hir::ExprBinary(bin_op, ..) => { + match bin_op.node { + hir::BiEq | hir::BiLt | hir::BiLe | hir::BiNe | hir::BiGe | hir::BiGt => { + Some("comparison") + }, + hir::BiAdd | hir::BiSub | hir::BiDiv | hir::BiMul | hir::BiRem => { + Some("arithmetic operation") + }, + hir::BiAnd | hir::BiOr => { + Some("logical operation") + }, + hir::BiBitXor | hir::BiBitAnd | hir::BiBitOr | hir::BiShl | hir::BiShr => { + Some("bitwise operation") + }, + } + }, + hir::ExprUnary(..) => Some("unary operation"), + _ => None + }; + if let Some(must_use_op) = must_use_op { + cx.span_lint(UNUSED_MUST_USE, expr.span, + &format!("unused {} which must be used", must_use_op)); + op_warned = true; } } - if !(ty_warned || fn_warned || op_warned) { cx.span_lint(UNUSED_RESULTS, s.span, "unused result"); } diff --git a/src/test/ui/lint/must-use-ops.rs b/src/test/ui/lint/must-use-ops.rs new file mode 100644 index 00000000000..4ed82ab3b40 --- /dev/null +++ b/src/test/ui/lint/must-use-ops.rs @@ -0,0 +1,52 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Issue #50124 - Test warning for unused operator expressions + +// compile-pass + +#![feature(fn_must_use)] +#![warn(unused_must_use)] + +fn main() { + let val = 1; + let val_pointer = &val; + +// Comparison Operators + val == 1; + val < 1; + val <= 1; + val != 1; + val >= 1; + val > 1; + +// Arithmetic Operators + val + 2; + val - 2; + val / 2; + val * 2; + val % 2; + +// Logical Operators + true && true; + false || true; + +// Bitwise Operators + 5 ^ val; + 5 & val; + 5 | val; + 5 << val; + 5 >> val; + +// Unary Operators + !val; + -val; + *val_pointer; +} diff --git a/src/test/ui/lint/must-use-ops.stderr b/src/test/ui/lint/must-use-ops.stderr new file mode 100644 index 00000000000..f444ef09075 --- /dev/null +++ b/src/test/ui/lint/must-use-ops.stderr @@ -0,0 +1,132 @@ +warning: unused comparison which must be used + --> $DIR/must-use-ops.rs:23:5 + | +LL | val == 1; + | ^^^^^^^^ + | +note: lint level defined here + --> $DIR/must-use-ops.rs:16:9 + | +LL | #![warn(unused_must_use)] + | ^^^^^^^^^^^^^^^ + +warning: unused comparison which must be used + --> $DIR/must-use-ops.rs:24:5 + | +LL | val < 1; + | ^^^^^^^ + +warning: unused comparison which must be used + --> $DIR/must-use-ops.rs:25:5 + | +LL | val <= 1; + | ^^^^^^^^ + +warning: unused comparison which must be used + --> $DIR/must-use-ops.rs:26:5 + | +LL | val != 1; + | ^^^^^^^^ + +warning: unused comparison which must be used + --> $DIR/must-use-ops.rs:27:5 + | +LL | val >= 1; + | ^^^^^^^^ + +warning: unused comparison which must be used + --> $DIR/must-use-ops.rs:28:5 + | +LL | val > 1; + | ^^^^^^^ + +warning: unused arithmetic operation which must be used + --> $DIR/must-use-ops.rs:31:5 + | +LL | val + 2; + | ^^^^^^^ + +warning: unused arithmetic operation which must be used + --> $DIR/must-use-ops.rs:32:5 + | +LL | val - 2; + | ^^^^^^^ + +warning: unused arithmetic operation which must be used + --> $DIR/must-use-ops.rs:33:5 + | +LL | val / 2; + | ^^^^^^^ + +warning: unused arithmetic operation which must be used + --> $DIR/must-use-ops.rs:34:5 + | +LL | val * 2; + | ^^^^^^^ + +warning: unused arithmetic operation which must be used + --> $DIR/must-use-ops.rs:35:5 + | +LL | val % 2; + | ^^^^^^^ + +warning: unused logical operation which must be used + --> $DIR/must-use-ops.rs:38:5 + | +LL | true && true; + | ^^^^^^^^^^^^ + +warning: unused logical operation which must be used + --> $DIR/must-use-ops.rs:39:5 + | +LL | false || true; + | ^^^^^^^^^^^^^ + +warning: unused bitwise operation which must be used + --> $DIR/must-use-ops.rs:42:5 + | +LL | 5 ^ val; + | ^^^^^^^ + +warning: unused bitwise operation which must be used + --> $DIR/must-use-ops.rs:43:5 + | +LL | 5 & val; + | ^^^^^^^ + +warning: unused bitwise operation which must be used + --> $DIR/must-use-ops.rs:44:5 + | +LL | 5 | val; + | ^^^^^^^ + +warning: unused bitwise operation which must be used + --> $DIR/must-use-ops.rs:45:5 + | +LL | 5 << val; + | ^^^^^^^^ + +warning: unused bitwise operation which must be used + --> $DIR/must-use-ops.rs:46:5 + | +LL | 5 >> val; + | ^^^^^^^^ + +warning: unused unary operation which must be used + --> $DIR/must-use-ops.rs:49:5 + | +LL | !val; + | ^^^^ + +warning: unused unary operation which must be used + --> $DIR/must-use-ops.rs:50:5 + | +LL | -val; + | ^^^^ + +warning: unused unary operation which must be used + --> $DIR/must-use-ops.rs:51:5 + | +LL | *val_pointer; + | ^^^^^^^^^^^^ + -- cgit 1.4.1-3-g733a5 From 40f2ca2c95f374ceeb13169af77db9d17901c001 Mon Sep 17 00:00:00 2001 From: est31 Date: Sun, 22 Apr 2018 13:34:42 +0200 Subject: 'label can start expressions let foo = 'label: loop { break 'label 42; }; is valid Rust code. --- src/libsyntax/parse/token.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 44394384c7a..938711ca1d4 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -277,9 +277,10 @@ impl Token { DotDot | DotDotDot | DotDotEq | // range notation Lt | BinOp(Shl) | // associated path ModSep | // global path + Lifetime(..) | // labeled loop Pound => true, // expression attributes Interpolated(ref nt) => match nt.0 { - NtIdent(..) | NtExpr(..) | NtBlock(..) | NtPath(..) => true, + NtIdent(..) | NtExpr(..) | NtBlock(..) | NtPath(..) | NtLifetime(..) => true, _ => false, }, _ => false, -- cgit 1.4.1-3-g733a5 From edee60d872094dfb1a0ddf65bd5097cf16ad89a2 Mon Sep 17 00:00:00 2001 From: est31 Date: Mon, 23 Apr 2018 11:18:04 +0200 Subject: Add tests --- src/test/ui/lifetime_starts_expressions.rs | 23 +++++++++++++++++++++++ src/test/ui/lifetime_starts_expressions.stderr | 14 ++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 src/test/ui/lifetime_starts_expressions.rs create mode 100644 src/test/ui/lifetime_starts_expressions.stderr (limited to 'src') diff --git a/src/test/ui/lifetime_starts_expressions.rs b/src/test/ui/lifetime_starts_expressions.rs new file mode 100644 index 00000000000..ffe1d7c353b --- /dev/null +++ b/src/test/ui/lifetime_starts_expressions.rs @@ -0,0 +1,23 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn foo() -> u32 { + return 'label: loop { break 'label 42; }; +} + +fn bar() -> u32 { + loop { break 'label: loop { break 'label 42; }; } + //~^ ERROR expected identifier, found keyword `loop` + //~| ERROR expected type, found keyword `loop` +} + +pub fn main() { + foo(); +} diff --git a/src/test/ui/lifetime_starts_expressions.stderr b/src/test/ui/lifetime_starts_expressions.stderr new file mode 100644 index 00000000000..de42f1daa1e --- /dev/null +++ b/src/test/ui/lifetime_starts_expressions.stderr @@ -0,0 +1,14 @@ +error: expected identifier, found keyword `loop` + --> $DIR/lifetime_starts_expressions.rs:16:26 + | +LL | loop { break 'label: loop { break 'label 42; }; } + | ^^^^ expected identifier, found keyword + +error: expected type, found keyword `loop` + --> $DIR/lifetime_starts_expressions.rs:16:26 + | +LL | loop { break 'label: loop { break 'label 42; }; } + | ^^^^ expecting a type here because of type ascription + +error: aborting due to 2 previous errors + -- cgit 1.4.1-3-g733a5 From ac79c41edc2ed9d7125009dd5f21bdcc9fecb3c8 Mon Sep 17 00:00:00 2001 From: steveklabnik Date: Mon, 23 Apr 2018 11:58:11 -0400 Subject: review nits --- src/doc/rustc/src/codegen-options/index.md | 4 ++-- src/doc/rustc/src/lints/levels.md | 4 ++-- src/doc/rustc/src/lints/listing/deny-by-default.md | 2 +- src/doc/rustc/src/targets/index.md | 7 +++---- 4 files changed, 8 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index 70dae9314c1..eff09428902 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -99,7 +99,7 @@ flag will turn that behavior off. ## no-vectorize-slp By default, `rustc` will attempt to vectorize loops using [superword-level -parallism](https://llvm.org/docs/Vectorizers.html#the-slp-vectorizer). This +parallelism](https://llvm.org/docs/Vectorizers.html#the-slp-vectorizer). This flag will turn that behavior off. ## soft-float @@ -206,4 +206,4 @@ This option lets you control what happens when the code panics. ## incremental -This flag allows you to enable incremental compilation. \ No newline at end of file +This flag allows you to enable incremental compilation. diff --git a/src/doc/rustc/src/lints/levels.md b/src/doc/rustc/src/lints/levels.md index 83b65cd648e..19bb6707d22 100644 --- a/src/doc/rustc/src/lints/levels.md +++ b/src/doc/rustc/src/lints/levels.md @@ -45,8 +45,8 @@ pub fn foo() { This will produce this warning: -```bash -> rustc lib.rs --crate-type=lib +```console +$ rustc lib.rs --crate-type=lib warning: unused variable: `x` --> lib.rs:2:9 | diff --git a/src/doc/rustc/src/lints/listing/deny-by-default.md b/src/doc/rustc/src/lints/listing/deny-by-default.md index 0c49f2f7b36..e7ec6af8be1 100644 --- a/src/doc/rustc/src/lints/listing/deny-by-default.md +++ b/src/doc/rustc/src/lints/listing/deny-by-default.md @@ -165,7 +165,7 @@ error: mutating transmuted &mut T from &T may cause undefined behavior, consider This lint detects any `const` items with the `#[no_mangle]` attribute. Constants do not have their symbols exported, and therefore, this probably -means you meant to use a `static`, not a `const. Some example code that +means you meant to use a `static`, not a `const`. Some example code that triggers this lint: ```rust,ignore diff --git a/src/doc/rustc/src/targets/index.md b/src/doc/rustc/src/targets/index.md index cea7ce4dea5..07e3a79471f 100644 --- a/src/doc/rustc/src/targets/index.md +++ b/src/doc/rustc/src/targets/index.md @@ -3,12 +3,11 @@ `rustc` is a cross-compiler by default. This means that you can use any compiler to build for any architecture. The list of *targets* are the possible architectures that you can build for. -You can see the API docs for a given target -[here](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_back/target/struct.Target.html), all -of these options can be set on a per-target basis. +To see all the options that you can set with a target, see the docs +[here](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_back/target/struct.Target.html). To compile to a particular target, use the `--target` flag: ```bash $ rustc src/main.rs --target=wasm32-unknown-unknown -``` \ No newline at end of file +``` -- cgit 1.4.1-3-g733a5 From d2dc21df02a6f24b0c5629d3c3ebc7c9b85d20da Mon Sep 17 00:00:00 2001 From: bobtwinkles Date: Sat, 21 Apr 2018 18:00:09 -0400 Subject: Add documentation for SyntaxContext::remove_mark --- src/libsyntax_pos/hygiene.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'src') diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index 5e96b5ce673..6eb662744c3 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -238,6 +238,22 @@ impl SyntaxContext { }) } + /// Pulls a single mark off of the syntax context. This effectively moves the + /// context up one macro definition level. That is, if we have a nested macro + /// definition as follows: + /// + /// ```rust + /// macro_rules! f { + /// macro_rules! g { + /// ... + /// } + /// } + /// ``` + /// + /// and we have a SyntaxContext that is referring to something declared by an invocation + /// of g (call it g1), calling remove_mark will result in the SyntaxContext for the + /// invocation of f that created g1. + /// Returns the mark that was removed. pub fn remove_mark(&mut self) -> Mark { HygieneData::with(|data| { let outer_mark = data.syntax_contexts[self.0 as usize].outer_mark; -- cgit 1.4.1-3-g733a5 From 263b36b071ba8b52cd4f79ca36494b05d4762430 Mon Sep 17 00:00:00 2001 From: bobtwinkles Date: Sat, 21 Apr 2018 18:15:54 -0400 Subject: Implement parent() on `syntax_pos::Span` ... and reimplement proc_macro::Span::parent using it. This function turns out to be useful in the compiler as well --- src/libproc_macro/lib.rs | 2 +- src/libsyntax_pos/lib.rs | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index e171216523a..4d24353a383 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -270,7 +270,7 @@ impl Span { /// `self` was generated from, if any. #[unstable(feature = "proc_macro", issue = "38356")] pub fn parent(&self) -> Option { - self.0.ctxt().outer().expn_info().map(|i| Span(i.call_site)) + self.0.parent().map(|x| { Span(x) }) } /// The span for the origin source code that `self` was generated from. If diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 9a7d1fd8ee6..19f52d83a01 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -291,6 +291,12 @@ impl Span { self.ctxt().outer().expn_info().map(|info| info.call_site.source_callsite()).unwrap_or(self) } + /// The `Span for the tokens in the previous macro expansion from which `self` was generated, + /// if any + pub fn parent(self) -> Option { + self.ctxt().outer().expn_info().map(|i| i.call_site) + } + /// Return the source callee. /// /// Returns None if the supplied span has no expansion trace, -- cgit 1.4.1-3-g733a5 From 498dbe44537998bd4bba6c28232a22e9243b9c67 Mon Sep 17 00:00:00 2001 From: bobtwinkles Date: Sat, 21 Apr 2018 18:20:17 -0400 Subject: Implement a least upper bound for marks. This is useful when trying to compute when something is lexically before something else, but they aren't necessarily in the same SyntaxContext --- src/libsyntax_pos/hygiene.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'src') diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index 6eb662744c3..8e9564d0ac1 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -21,6 +21,7 @@ use symbol::{Ident, Symbol}; use serialize::{Encodable, Decodable, Encoder, Decoder}; use std::collections::HashMap; +use rustc_data_structures::fx::FxHashSet; use std::fmt; /// A SyntaxContext represents a chain of macro expansions (represented by marks). @@ -117,6 +118,32 @@ impl Mark { true }) } + + /// Computes a mark such that both input marks are descendants of (or equal to) the returned + /// mark. That is, the following holds: + /// + /// ```rust + /// let lub = lub(a, b); + /// assert!(a.is_descendant_of(lub)) + /// assert!(b.is_descendant_of(lub)) + /// ``` + pub fn lub(mut a: Mark, mut b: Mark) -> Mark { + HygieneData::with(|data| { + // Compute the path from a to the root + let mut a_path = FxHashSet::(); + while a != Mark::root() { + a_path.insert(a); + a = data.marks[a.0 as usize].parent; + } + + // While the path from b to the root hasn't intersected, move up the tree + while !a_path.contains(&b) { + b = data.marks[b.0 as usize].parent; + } + + b + }) + } } pub struct HygieneData { -- cgit 1.4.1-3-g733a5 From 36475d947b4c39ec9dcaad137d51019c8b861918 Mon Sep 17 00:00:00 2001 From: steveklabnik Date: Tue, 24 Apr 2018 12:21:08 -0400 Subject: more nits --- src/doc/rustc/src/command-line-arguments.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md index 488102f926a..e2b001832fe 100644 --- a/src/doc/rustc/src/command-line-arguments.md +++ b/src/doc/rustc/src/command-line-arguments.md @@ -89,7 +89,7 @@ This flag lets you 'cap' lints, for more, [see here](lints/levels.html#capping-l This flag will allow you to set [codegen options](codegen-options/index.html). -## `-V`/`--verision`: print a version +## `-V`/`--version`: print a version This flag will print out `rustc`'s version. @@ -111,6 +111,6 @@ distribution; this flag allows that to be overridden. This flag lets you control the format of errors. -## `--color`: configur coloring of output +## `--color`: configure coloring of output -This flag lets you control color settings of the output. \ No newline at end of file +This flag lets you control color settings of the output. -- cgit 1.4.1-3-g733a5 From b9c44ebd3f3048ff3630868d15051eb00086637a Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 24 Apr 2018 15:42:27 -0700 Subject: Use enum for approximate suggestions --- src/librustc_errors/diagnostic.rs | 17 ++++++++++------- src/librustc_errors/diagnostic_builder.rs | 7 +++++-- src/librustc_errors/lib.rs | 10 +++++++++- src/libsyntax/json.rs | 10 +++++----- 4 files changed, 29 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index 40e4efb397d..bfeb351f1a4 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -11,6 +11,7 @@ use CodeSuggestion; use SubstitutionPart; use Substitution; +use SuggestionApproximate; use Level; use std::fmt; use syntax_pos::{MultiSpan, Span}; @@ -222,7 +223,7 @@ impl Diagnostic { }], msg: msg.to_owned(), show_code_when_inline: false, - approximate: false, + approximate: SuggestionApproximate::Unspecified, }); self } @@ -253,7 +254,7 @@ impl Diagnostic { }], msg: msg.to_owned(), show_code_when_inline: true, - approximate: false, + approximate: SuggestionApproximate::Unspecified, }); self } @@ -269,7 +270,7 @@ impl Diagnostic { }).collect(), msg: msg.to_owned(), show_code_when_inline: true, - approximate: false, + approximate: SuggestionApproximate::Unspecified, }); self } @@ -277,7 +278,8 @@ impl Diagnostic { /// This is a suggestion that may contain mistakes or fillers and should /// be read and understood by a human. pub fn span_approximate_suggestion(&mut self, sp: Span, msg: &str, - suggestion: String) -> &mut Self { + suggestion: String, + approximate: SuggestionApproximate) -> &mut Self { self.suggestions.push(CodeSuggestion { substitutions: vec![Substitution { parts: vec![SubstitutionPart { @@ -287,13 +289,14 @@ impl Diagnostic { }], msg: msg.to_owned(), show_code_when_inline: true, - approximate: true, + approximate, }); self } pub fn span_approximate_suggestions(&mut self, sp: Span, msg: &str, - suggestions: Vec) -> &mut Self { + suggestions: Vec, + approximate: SuggestionApproximate) -> &mut Self { self.suggestions.push(CodeSuggestion { substitutions: suggestions.into_iter().map(|snippet| Substitution { parts: vec![SubstitutionPart { @@ -303,7 +306,7 @@ impl Diagnostic { }).collect(), msg: msg.to_owned(), show_code_when_inline: true, - approximate: true, + approximate, }); self } diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs index 945ecce7ab3..31eacb527ee 100644 --- a/src/librustc_errors/diagnostic_builder.rs +++ b/src/librustc_errors/diagnostic_builder.rs @@ -11,6 +11,7 @@ use Diagnostic; use DiagnosticId; use DiagnosticStyledString; +use SuggestionApproximate; use Level; use Handler; @@ -190,12 +191,14 @@ impl<'a> DiagnosticBuilder<'a> { forward!(pub fn span_approximate_suggestion(&mut self, sp: Span, msg: &str, - suggestion: String) + suggestion: String, + approximate: SuggestionApproximate) -> &mut Self); forward!(pub fn span_approximate_suggestions(&mut self, sp: Span, msg: &str, - suggestions: Vec) + suggestions: Vec, + approximate: SuggestionApproximate) -> &mut Self); forward!(pub fn set_span>(&mut self, sp: S) -> &mut Self); forward!(pub fn code(&mut self, s: DiagnosticId) -> &mut Self); diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index ce3efef08cc..9abb5b38c05 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -56,6 +56,14 @@ mod lock; use syntax_pos::{BytePos, Loc, FileLinesResult, FileMap, FileName, MultiSpan, Span, NO_EXPANSION}; +#[derive(Copy, Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)] +pub enum SuggestionApproximate { + MachineApplicable, + HasPlaceholders, + MaybeIncorrect, + Unspecified +} + #[derive(Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)] pub struct CodeSuggestion { /// Each substitute can have multiple variants due to multiple @@ -87,7 +95,7 @@ pub struct CodeSuggestion { /// Sometimes we may show suggestions with placeholders, /// which are useful for users but not useful for /// tools like rustfix - pub approximate: bool, + pub approximate: SuggestionApproximate, } #[derive(Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)] diff --git a/src/libsyntax/json.rs b/src/libsyntax/json.rs index b4f34fb12e3..dd77e441499 100644 --- a/src/libsyntax/json.rs +++ b/src/libsyntax/json.rs @@ -23,7 +23,7 @@ use codemap::{CodeMap, FilePathMapping}; use syntax_pos::{self, MacroBacktrace, Span, SpanLabel, MultiSpan}; use errors::registry::Registry; use errors::{DiagnosticBuilder, SubDiagnostic, CodeSuggestion, CodeMapper}; -use errors::DiagnosticId; +use errors::{DiagnosticId, SuggestionApproximate}; use errors::emitter::{Emitter, EmitterWriter}; use rustc_data_structures::sync::{self, Lrc}; @@ -138,7 +138,7 @@ struct DiagnosticSpan { suggested_replacement: Option, /// If the suggestion is approximate #[rustc_serialize_exclude_null] - suggestion_approximate: Option, + suggestion_approximate: Option, /// Macro invocations that created the code at this span, if any. expansion: Option>, } @@ -239,7 +239,7 @@ impl Diagnostic { impl DiagnosticSpan { fn from_span_label(span: SpanLabel, - suggestion: Option<(&String, bool)>, + suggestion: Option<(&String, SuggestionApproximate)>, je: &JsonEmitter) -> DiagnosticSpan { Self::from_span_etc(span.span, @@ -252,7 +252,7 @@ impl DiagnosticSpan { fn from_span_etc(span: Span, is_primary: bool, label: Option, - suggestion: Option<(&String, bool)>, + suggestion: Option<(&String, SuggestionApproximate)>, je: &JsonEmitter) -> DiagnosticSpan { // obtain the full backtrace from the `macro_backtrace` @@ -272,7 +272,7 @@ impl DiagnosticSpan { fn from_span_full(span: Span, is_primary: bool, label: Option, - suggestion: Option<(&String, bool)>, + suggestion: Option<(&String, SuggestionApproximate)>, mut backtrace: vec::IntoIter, je: &JsonEmitter) -> DiagnosticSpan { -- cgit 1.4.1-3-g733a5 From cc48ae5a64a4e648211a2e7c9f37df0c5d6c32a6 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 11 Apr 2018 15:41:22 -0700 Subject: compiletest: detect non-ICE compiler panics --- src/tools/compiletest/src/runtest.rs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index aabf2e6f8f0..4a7f902a892 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1166,6 +1166,8 @@ impl<'test> TestCx<'test> { for line in proc_res.stderr.lines() { if line.contains("error: internal compiler error") { self.fatal_proc_rec("compiler encountered internal error", proc_res); + } else if line.contains(" panicked at ") { + self.fatal_proc_rec("compiler panicked", proc_res); } } } -- cgit 1.4.1-3-g733a5 From a42db7dbfd6ffdcc0c60246d688dc09376c2a1ef Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 20 Apr 2018 11:37:41 -0700 Subject: Add a stopgap for #49889 --- src/librustc/ty/sty.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 310fcbcfcb3..320191167be 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -885,8 +885,10 @@ impl<'a, 'gcx, 'tcx> ParamTy { } pub fn is_self(&self) -> bool { - if self.name == keywords::SelfType.name().as_str() { - assert_eq!(self.idx, 0); + // FIXME(#50125): Ignoring `Self` with `idx != 0` might lead to weird behavior elsewhere, + // but this should only be possible when using `-Z continue-parse-after-error` like + // `compile-fail/issue-36638.rs`. + if self.name == keywords::SelfType.name().as_str() && self.idx == 0 { true } else { false -- cgit 1.4.1-3-g733a5 From fedee138343eebbe1f7d52d4d3587f8ce5929c9c Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 24 Apr 2018 16:17:31 -0700 Subject: Disable two-phase-reservation-sharing-interference[nll_beyond] A comment already stated that this test should be disabled, but its `should_fail` is not enough to excuse it from a compiler panic. Remove it from the `revisions` list to disable it harder. --- .../compile-fail/borrowck/two-phase-reservation-sharing-interference.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/test/compile-fail/borrowck/two-phase-reservation-sharing-interference.rs b/src/test/compile-fail/borrowck/two-phase-reservation-sharing-interference.rs index 1333167b780..1e86603c19e 100644 --- a/src/test/compile-fail/borrowck/two-phase-reservation-sharing-interference.rs +++ b/src/test/compile-fail/borrowck/two-phase-reservation-sharing-interference.rs @@ -10,7 +10,7 @@ // ignore-tidy-linelength -// revisions: nll_beyond nll_target +// revisions: nll_target // The following revisions are disabled due to missing support from two-phase beyond autorefs //[nll_beyond]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two-phase-beyond-autoref -- cgit 1.4.1-3-g733a5 From bd8c177d49c95d94f163e9bb3c3397f38ab72640 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Fri, 20 Apr 2018 10:24:53 +0900 Subject: Switch box_free to take the destructured contents of Box As of now, Box only contains a Unique pointer, so this is the sole argument to box_free. Consequently, we remove the code supporting the previous box_free signature. We however keep the old definition for bootstrapping purpose. --- src/liballoc/alloc.rs | 14 ++++++-- src/liballoc/arc.rs | 5 +-- src/liballoc/rc.rs | 5 +-- src/librustc_mir/util/elaborate_drops.rs | 61 +++++++------------------------- 4 files changed, 29 insertions(+), 56 deletions(-) (limited to 'src') diff --git a/src/liballoc/alloc.rs b/src/liballoc/alloc.rs index 68a617e0ffe..ed860678765 100644 --- a/src/liballoc/alloc.rs +++ b/src/liballoc/alloc.rs @@ -16,7 +16,7 @@ issue = "32838")] use core::intrinsics::{min_align_of_val, size_of_val}; -use core::ptr::NonNull; +use core::ptr::{NonNull, Unique}; use core::usize; #[doc(inline)] @@ -170,9 +170,17 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { } } -#[cfg_attr(not(test), lang = "box_free")] +#[cfg(stage0)] +#[lang = "box_free"] +#[inline] +unsafe fn old_box_free(ptr: *mut T) { + box_free(Unique::new_unchecked(ptr)) +} + +#[cfg_attr(not(any(test, stage0)), lang = "box_free")] #[inline] -pub(crate) unsafe fn box_free(ptr: *mut T) { +pub(crate) unsafe fn box_free(ptr: Unique) { + let ptr = ptr.as_ptr(); let size = size_of_val(&*ptr); let align = min_align_of_val(&*ptr); // We do not allocate for Box when T is ZST, so deallocation is also not necessary. diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 225b055d8ee..a1ec5cd2208 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -566,7 +566,8 @@ impl Arc { fn from_box(v: Box) -> Arc { unsafe { - let bptr = Box::into_raw(v); + let box_unique = Box::into_unique(v); + let bptr = box_unique.as_ptr(); let value_size = size_of_val(&*bptr); let ptr = Self::allocate_for_ptr(bptr); @@ -578,7 +579,7 @@ impl Arc { value_size); // Free the allocation without dropping its contents - box_free(bptr); + box_free(box_unique); Arc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData } } diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index de0422d82bb..c495d300805 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -681,7 +681,8 @@ impl Rc { fn from_box(v: Box) -> Rc { unsafe { - let bptr = Box::into_raw(v); + let box_unique = Box::into_unique(v); + let bptr = box_unique.as_ptr(); let value_size = size_of_val(&*bptr); let ptr = Self::allocate_for_ptr(bptr); @@ -693,7 +694,7 @@ impl Rc { value_size); // Free the allocation without dropping its contents - box_free(bptr); + box_free(box_unique); Rc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData } } diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index cc91bbf9061..02020c3b7a4 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -879,56 +879,19 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> let tcx = self.tcx(); let unit_temp = Place::Local(self.new_temp(tcx.mk_nil())); let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem); - let free_sig = tcx.fn_sig(free_func).skip_binder().clone(); - let free_inputs = free_sig.inputs(); - // If the box_free function takes a *mut T, transform the Box into - // such a pointer before calling box_free. Otherwise, pass it all - // the fields in the Box as individual arguments. - let (stmts, args) = if free_inputs.len() == 1 && free_inputs[0].is_mutable_pointer() { - let ty = substs.type_at(0); - let ref_ty = tcx.mk_ref(tcx.types.re_erased, ty::TypeAndMut { - ty: ty, - mutbl: hir::Mutability::MutMutable - }); - let ptr_ty = tcx.mk_mut_ptr(ty); - let ref_tmp = Place::Local(self.new_temp(ref_ty)); - let ptr_tmp = Place::Local(self.new_temp(ptr_ty)); - let stmts = vec![ - self.assign(&ref_tmp, Rvalue::Ref( - tcx.types.re_erased, - BorrowKind::Mut { allow_two_phase_borrow: false }, - self.place.clone().deref() - )), - self.assign(&ptr_tmp, Rvalue::Cast( - CastKind::Misc, - Operand::Move(ref_tmp), - ptr_ty, - )), - ]; - (stmts, vec![Operand::Move(ptr_tmp)]) - } else { - let args = adt.variants[0].fields.iter().enumerate().map(|(i, f)| { - let field = Field::new(i); - let field_ty = f.ty(self.tcx(), substs); - Operand::Move(self.place.clone().field(field, field_ty)) - }).collect(); - (vec![], args) - }; + let args = adt.variants[0].fields.iter().enumerate().map(|(i, f)| { + let field = Field::new(i); + let field_ty = f.ty(self.tcx(), substs); + Operand::Move(self.place.clone().field(field, field_ty)) + }).collect(); - let free_block = BasicBlockData { - statements: stmts, - terminator: Some(Terminator { - kind: TerminatorKind::Call { - func: Operand::function_handle(tcx, free_func, substs, self.source_info.span), - args: args, - destination: Some((unit_temp, target)), - cleanup: None - }, // FIXME(#43234) - source_info: self.source_info, - }), - is_cleanup: unwind.is_cleanup() - }; - let free_block = self.elaborator.patch().new_block(free_block); + let call = TerminatorKind::Call { + func: Operand::function_handle(tcx, free_func, substs, self.source_info.span), + args: args, + destination: Some((unit_temp, target)), + cleanup: None + }; // FIXME(#43234) + let free_block = self.new_block(unwind, call); let block_start = Location { block: free_block, statement_index: 0 }; self.elaborator.clear_drop_flag(block_start, self.path, DropFlagMode::Shallow); -- cgit 1.4.1-3-g733a5 From 011df4ac88b5ef31443f2bde8eea29b917445099 Mon Sep 17 00:00:00 2001 From: z4v1er <38393857+z4v1er@users.noreply.github.com> Date: Wed, 25 Apr 2018 13:51:51 +0300 Subject: Fix type --- src/libcore/slice/mod.rs | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index cc42acd77ae..83e8a6e4b68 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -880,7 +880,6 @@ macro_rules! slice_core_methods { () => { #[inline] pub fn split_last(&self) -> Option<(&T, &[T])> { SliceExt::split_last(self) - } /// Returns the last and all the rest of the elements of the slice, or `None` if it is empty. -- cgit 1.4.1-3-g733a5 From a95bff3ed40e46e89ca778b7674304bad92bc16e Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Wed, 25 Apr 2018 15:57:33 +0200 Subject: Bump bootstrap compiler to 2018-04-24 --- src/stage0.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/stage0.txt b/src/stage0.txt index e8db3358cf0..a5ad2b315a1 100644 --- a/src/stage0.txt +++ b/src/stage0.txt @@ -12,7 +12,7 @@ # source tarball for a stable release you'll likely see `1.x.0` for rustc and # `0.x.0` for Cargo where they were released on `date`. -date: 2018-04-04 +date: 2018-04-24 rustc: beta cargo: beta -- cgit 1.4.1-3-g733a5 From a5655b81a3bad56beaa161662177192681832532 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sat, 31 Mar 2018 12:09:10 +0200 Subject: Move description of the Error trait to its own doc-comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit … rather than the module’s. Remove code definition of the Error trait from its doc-comment It was out of date, and rustdoc already shows the same information. Add a default impl for Error::description and document it as deprecated. It is redundant with Display while being much less flexible for implementors. This is only a "soft" deprecation: it is not worth the hassle of a warning to existing users. Tweak Error trait docs to reflect actual requirements --- src/libstd/error.rs | 63 ++++++++++++++++++++--------------------------------- 1 file changed, 24 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/libstd/error.rs b/src/libstd/error.rs index 749b8ccc13d..0954649653c 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -9,34 +9,6 @@ // except according to those terms. //! Traits for working with Errors. -//! -//! # The `Error` trait -//! -//! `Error` is a trait representing the basic expectations for error values, -//! i.e. values of type `E` in [`Result`]. At a minimum, errors must provide -//! a description, but they may optionally provide additional detail (via -//! [`Display`]) and cause chain information: -//! -//! ``` -//! use std::fmt::Display; -//! -//! trait Error: Display { -//! fn description(&self) -> &str; -//! -//! fn cause(&self) -> Option<&Error> { None } -//! } -//! ``` -//! -//! The [`cause`] method is generally used when errors cross "abstraction -//! boundaries", i.e. when a one module must report an error that is "caused" -//! by an error from a lower-level module. This setup makes it possible for the -//! high-level module to provide its own errors that do not commit to any -//! particular implementation, but also reveal some of its implementation for -//! debugging via [`cause`] chains. -//! -//! [`Result`]: ../result/enum.Result.html -//! [`Display`]: ../fmt/trait.Display.html -//! [`cause`]: trait.Error.html#method.cause #![stable(feature = "rust1", since = "1.0.0")] @@ -63,33 +35,46 @@ use num; use str; use string; -/// Base functionality for all errors in Rust. +/// `Error` is a trait representing the basic expectations for error values, +/// i.e. values of type `E` in [`Result`]. Errors must describe +/// themselves through the [`Display`] and [`Debug`] traits, and may provide +/// cause chain information: +/// +/// The [`cause`] method is generally used when errors cross "abstraction +/// boundaries", i.e. when a one module must report an error that is "caused" +/// by an error from a lower-level module. This setup makes it possible for the +/// high-level module to provide its own errors that do not commit to any +/// particular implementation, but also reveal some of its implementation for +/// debugging via [`cause`] chains. +/// +/// [`Result`]: ../result/enum.Result.html +/// [`Display`]: ../fmt/trait.Display.html +/// [`cause`]: trait.Error.html#method.cause #[stable(feature = "rust1", since = "1.0.0")] pub trait Error: Debug + Display { - /// A short description of the error. + /// **This method is soft-deprecated.** /// - /// The description should only be used for a simple message. - /// It should not contain newlines or sentence-ending punctuation, - /// to facilitate embedding in larger user-facing strings. - /// For showing formatted error messages with more information see - /// [`Display`]. + /// Although using it won’t cause compilation warning, + /// new code should use [`Display`] instead + /// and new `impl`s can omit it. /// /// [`Display`]: ../fmt/trait.Display.html /// /// # Examples /// /// ``` - /// use std::error::Error; - /// /// match "xc".parse::() { /// Err(e) => { - /// println!("Error: {}", e.description()); + /// // Print `e` itself, not `e.description()`. + /// println!("Error: {}", e); /// } /// _ => println!("No error"), /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] - fn description(&self) -> &str; + fn description(&self) -> &str { + "" + } /// The lower-level cause of this error, if any. /// -- cgit 1.4.1-3-g733a5 From f6a833a99a76e015cae0410f20af9f3767a14911 Mon Sep 17 00:00:00 2001 From: Kornel Date: Sun, 22 Apr 2018 19:17:08 +0100 Subject: Suggest alternatives to Error::description() --- src/libstd/error.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/libstd/error.rs b/src/libstd/error.rs index 0954649653c..817eea5eaf1 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -58,6 +58,8 @@ pub trait Error: Debug + Display { /// new code should use [`Display`] instead /// and new `impl`s can omit it. /// + /// To obtain error description as a string, use `to_string()`. + /// /// [`Display`]: ../fmt/trait.Display.html /// /// # Examples @@ -73,7 +75,7 @@ pub trait Error: Debug + Display { /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn description(&self) -> &str { - "" + "description() is deprecated; use Display" } /// The lower-level cause of this error, if any. -- cgit 1.4.1-3-g733a5 From 1912f39e7c024f2ee5c5ea618efdcbe92590b863 Mon Sep 17 00:00:00 2001 From: Kornel Date: Sun, 22 Apr 2018 21:11:15 +0100 Subject: Update book submodule to pass linkchecker test --- src/doc/book | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/doc/book b/src/doc/book index b889e1e30c5..6237a75790c 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit b889e1e30c5e9953834aa9fa6c982bb28df46ac9 +Subproject commit 6237a75790cd2e0ca22961b55f64a83319e73464 -- cgit 1.4.1-3-g733a5 From 256096da9ee680366b839f912e8d3ecccc0da033 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Wed, 25 Apr 2018 16:33:02 -0500 Subject: Make Vec::new const --- src/liballoc/raw_vec.rs | 16 ++++++++++++++++ src/liballoc/vec.rs | 2 +- src/libcore/ptr.rs | 5 ++--- src/test/run-pass/vec-const-new.rs | 15 +++++++++++++++ 4 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 src/test/run-pass/vec-const-new.rs (limited to 'src') diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index 7ef0a27fc72..dc8ad9ee061 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -68,6 +68,16 @@ impl RawVec { } } + /// Like `empty` but parametrized over the choice of allocator for the returned `RawVec`. + pub const fn empty_in(a: A) -> Self { + // Unique::empty() doubles as "unallocated" and "zero-sized allocation" + RawVec { + ptr: Unique::empty(), + cap: 0, + a, + } + } + /// Like `with_capacity` but parameterized over the choice of /// allocator for the returned RawVec. #[inline] @@ -124,6 +134,12 @@ impl RawVec { Self::new_in(Global) } + /// Create a `RawVec` with capcity 0 (on the system heap), regardless of `T`, without + /// allocating. + pub fn empty() -> Self { + Self::empty_in(Global) + } + /// Creates a RawVec (on the system heap) with exactly the /// capacity and alignment requirements for a `[T; cap]`. This is /// equivalent to calling RawVec::new when `cap` is 0 or T is diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index b184404c15b..757606607bb 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -324,7 +324,7 @@ impl Vec { #[stable(feature = "rust1", since = "1.0.0")] pub fn new() -> Vec { Vec { - buf: RawVec::new(), + buf: RawVec::empty(), len: 0, } } diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 74bb264cc67..b612a278a34 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -2551,10 +2551,9 @@ impl Unique { /// This is useful for initializing types which lazily allocate, like /// `Vec::new` does. // FIXME: rename to dangling() to match NonNull? - pub fn empty() -> Self { + pub const fn empty() -> Self { unsafe { - let ptr = mem::align_of::() as *mut T; - Unique::new_unchecked(ptr) + Unique::new_unchecked(mem::align_of::() as *mut T) } } } diff --git a/src/test/run-pass/vec-const-new.rs b/src/test/run-pass/vec-const-new.rs new file mode 100644 index 00000000000..02d8cfdcf98 --- /dev/null +++ b/src/test/run-pass/vec-const-new.rs @@ -0,0 +1,15 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test that Vec::new() can be used for constants + +const MY_VEC: Vec = Vec::new(); + +pub fn main() {} -- cgit 1.4.1-3-g733a5 From a2105b8e21a71f513e6840ec0571cad5c1a36012 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Wed, 25 Apr 2018 16:42:57 -0500 Subject: make RawVec::empty const --- src/liballoc/raw_vec.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index dc8ad9ee061..fe18979fb51 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -54,6 +54,7 @@ pub struct RawVec { } impl RawVec { + // FIXME: this should be made `const` when `if` statements are allowed /// Like `new` but parameterized over the choice of allocator for /// the returned RawVec. pub fn new_in(a: A) -> Self { @@ -68,6 +69,7 @@ impl RawVec { } } + // FIXME: this should removed when `new_in` can be made `const` /// Like `empty` but parametrized over the choice of allocator for the returned `RawVec`. pub const fn empty_in(a: A) -> Self { // Unique::empty() doubles as "unallocated" and "zero-sized allocation" @@ -134,9 +136,10 @@ impl RawVec { Self::new_in(Global) } + // FIXME: this should removed when `new` can be made `const` /// Create a `RawVec` with capcity 0 (on the system heap), regardless of `T`, without /// allocating. - pub fn empty() -> Self { + pub const fn empty() -> Self { Self::empty_in(Global) } -- cgit 1.4.1-3-g733a5 From 4e2cd4104a39c1e0562c3fb00085a1a3f4f22291 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 25 Apr 2018 14:51:06 -0700 Subject: Approximate -> Applicability --- src/librustc/session/config.rs | 2 +- src/librustc/session/mod.rs | 4 ++-- src/librustc_errors/diagnostic.rs | 20 ++++++++++---------- src/librustc_errors/diagnostic_builder.rs | 10 +++++----- src/librustc_errors/lib.rs | 4 ++-- src/librustdoc/core.rs | 2 +- src/libsyntax/json.rs | 26 +++++++++++++------------- 7 files changed, 34 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 456e83f4700..08bb5ed97a4 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1270,7 +1270,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, dep_info_omit_d_target: bool = (false, parse_bool, [TRACKED], "in dep-info output, omit targets for tracking dependencies of the dep-info files \ themselves"), - approximate_suggestions: bool = (false, parse_bool, [UNTRACKED], + suggestion_applicability: bool = (false, parse_bool, [UNTRACKED], "include machine-applicability of suggestions in JSON output"), unpretty: Option = (None, parse_unpretty, [UNTRACKED], "Present the input source, unstable (and less-pretty) variants; diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 5e4dee7fb60..5c0e66ffc7e 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -1002,7 +1002,7 @@ pub fn build_session_with_codemap( Some(registry), codemap.clone(), pretty, - sopts.debugging_opts.approximate_suggestions, + sopts.debugging_opts.suggestion_applicability, ).ui_testing(sopts.debugging_opts.ui_testing), ), (config::ErrorOutputType::Json(pretty), Some(dst)) => Box::new( @@ -1011,7 +1011,7 @@ pub fn build_session_with_codemap( Some(registry), codemap.clone(), pretty, - sopts.debugging_opts.approximate_suggestions, + sopts.debugging_opts.suggestion_applicability, ).ui_testing(sopts.debugging_opts.ui_testing), ), (config::ErrorOutputType::Short(color_config), None) => Box::new( diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index bfeb351f1a4..75401f21862 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -11,7 +11,7 @@ use CodeSuggestion; use SubstitutionPart; use Substitution; -use SuggestionApproximate; +use Applicability; use Level; use std::fmt; use syntax_pos::{MultiSpan, Span}; @@ -223,7 +223,7 @@ impl Diagnostic { }], msg: msg.to_owned(), show_code_when_inline: false, - approximate: SuggestionApproximate::Unspecified, + applicability: Applicability::Unspecified, }); self } @@ -254,7 +254,7 @@ impl Diagnostic { }], msg: msg.to_owned(), show_code_when_inline: true, - approximate: SuggestionApproximate::Unspecified, + applicability: Applicability::Unspecified, }); self } @@ -270,16 +270,16 @@ impl Diagnostic { }).collect(), msg: msg.to_owned(), show_code_when_inline: true, - approximate: SuggestionApproximate::Unspecified, + applicability: Applicability::Unspecified, }); self } /// This is a suggestion that may contain mistakes or fillers and should /// be read and understood by a human. - pub fn span_approximate_suggestion(&mut self, sp: Span, msg: &str, + pub fn span_suggestion_with_applicability(&mut self, sp: Span, msg: &str, suggestion: String, - approximate: SuggestionApproximate) -> &mut Self { + applicability: Applicability) -> &mut Self { self.suggestions.push(CodeSuggestion { substitutions: vec![Substitution { parts: vec![SubstitutionPart { @@ -289,14 +289,14 @@ impl Diagnostic { }], msg: msg.to_owned(), show_code_when_inline: true, - approximate, + applicability, }); self } - pub fn span_approximate_suggestions(&mut self, sp: Span, msg: &str, + pub fn span_suggestions_with_applicability(&mut self, sp: Span, msg: &str, suggestions: Vec, - approximate: SuggestionApproximate) -> &mut Self { + applicability: Applicability) -> &mut Self { self.suggestions.push(CodeSuggestion { substitutions: suggestions.into_iter().map(|snippet| Substitution { parts: vec![SubstitutionPart { @@ -306,7 +306,7 @@ impl Diagnostic { }).collect(), msg: msg.to_owned(), show_code_when_inline: true, - approximate, + applicability, }); self } diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs index 31eacb527ee..7e9ca8633a5 100644 --- a/src/librustc_errors/diagnostic_builder.rs +++ b/src/librustc_errors/diagnostic_builder.rs @@ -11,7 +11,7 @@ use Diagnostic; use DiagnosticId; use DiagnosticStyledString; -use SuggestionApproximate; +use Applicability; use Level; use Handler; @@ -188,17 +188,17 @@ impl<'a> DiagnosticBuilder<'a> { msg: &str, suggestions: Vec) -> &mut Self); - forward!(pub fn span_approximate_suggestion(&mut self, + forward!(pub fn span_suggestion_with_applicability(&mut self, sp: Span, msg: &str, suggestion: String, - approximate: SuggestionApproximate) + applicability: Applicability) -> &mut Self); - forward!(pub fn span_approximate_suggestions(&mut self, + forward!(pub fn span_suggestions_with_applicability(&mut self, sp: Span, msg: &str, suggestions: Vec, - approximate: SuggestionApproximate) + applicability: Applicability) -> &mut Self); forward!(pub fn set_span>(&mut self, sp: S) -> &mut Self); forward!(pub fn code(&mut self, s: DiagnosticId) -> &mut Self); diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 9abb5b38c05..c2b442e9497 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -57,7 +57,7 @@ mod lock; use syntax_pos::{BytePos, Loc, FileLinesResult, FileMap, FileName, MultiSpan, Span, NO_EXPANSION}; #[derive(Copy, Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)] -pub enum SuggestionApproximate { +pub enum Applicability { MachineApplicable, HasPlaceholders, MaybeIncorrect, @@ -95,7 +95,7 @@ pub struct CodeSuggestion { /// Sometimes we may show suggestions with placeholders, /// which are useful for users but not useful for /// tools like rustfix - pub approximate: SuggestionApproximate, + pub applicability: Applicability, } #[derive(Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)] diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 2bd1e72f0eb..65b442c8bb8 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -177,7 +177,7 @@ pub fn run_core(search_paths: SearchPaths, None, codemap.clone(), pretty, - sessopts.debugging_opts.approximate_suggestions, + sessopts.debugging_opts.suggestion_applicability, ).ui_testing(sessopts.debugging_opts.ui_testing) ), ErrorOutputType::Short(color_config) => Box::new( diff --git a/src/libsyntax/json.rs b/src/libsyntax/json.rs index dd77e441499..2f15e75093b 100644 --- a/src/libsyntax/json.rs +++ b/src/libsyntax/json.rs @@ -23,7 +23,7 @@ use codemap::{CodeMap, FilePathMapping}; use syntax_pos::{self, MacroBacktrace, Span, SpanLabel, MultiSpan}; use errors::registry::Registry; use errors::{DiagnosticBuilder, SubDiagnostic, CodeSuggestion, CodeMapper}; -use errors::{DiagnosticId, SuggestionApproximate}; +use errors::{DiagnosticId, Applicability}; use errors::emitter::{Emitter, EmitterWriter}; use rustc_data_structures::sync::{self, Lrc}; @@ -39,7 +39,7 @@ pub struct JsonEmitter { cm: Lrc, pretty: bool, /// Whether "approximate suggestions" are enabled in the config - approximate_suggestions: bool, + suggestion_applicability: bool, ui_testing: bool, } @@ -47,13 +47,13 @@ impl JsonEmitter { pub fn stderr(registry: Option, code_map: Lrc, pretty: bool, - approximate_suggestions: bool) -> JsonEmitter { + suggestion_applicability: bool) -> JsonEmitter { JsonEmitter { dst: Box::new(io::stderr()), registry, cm: code_map, pretty, - approximate_suggestions, + suggestion_applicability, ui_testing: false, } } @@ -68,13 +68,13 @@ impl JsonEmitter { registry: Option, code_map: Lrc, pretty: bool, - approximate_suggestions: bool) -> JsonEmitter { + suggestion_applicability: bool) -> JsonEmitter { JsonEmitter { dst, registry, cm: code_map, pretty, - approximate_suggestions, + suggestion_applicability, ui_testing: false, } } @@ -138,7 +138,7 @@ struct DiagnosticSpan { suggested_replacement: Option, /// If the suggestion is approximate #[rustc_serialize_exclude_null] - suggestion_approximate: Option, + suggestion_applicability: Option, /// Macro invocations that created the code at this span, if any. expansion: Option>, } @@ -239,7 +239,7 @@ impl Diagnostic { impl DiagnosticSpan { fn from_span_label(span: SpanLabel, - suggestion: Option<(&String, SuggestionApproximate)>, + suggestion: Option<(&String, Applicability)>, je: &JsonEmitter) -> DiagnosticSpan { Self::from_span_etc(span.span, @@ -252,7 +252,7 @@ impl DiagnosticSpan { fn from_span_etc(span: Span, is_primary: bool, label: Option, - suggestion: Option<(&String, SuggestionApproximate)>, + suggestion: Option<(&String, Applicability)>, je: &JsonEmitter) -> DiagnosticSpan { // obtain the full backtrace from the `macro_backtrace` @@ -272,7 +272,7 @@ impl DiagnosticSpan { fn from_span_full(span: Span, is_primary: bool, label: Option, - suggestion: Option<(&String, SuggestionApproximate)>, + suggestion: Option<(&String, Applicability)>, mut backtrace: vec::IntoIter, je: &JsonEmitter) -> DiagnosticSpan { @@ -301,7 +301,7 @@ impl DiagnosticSpan { }) }); - let suggestion_approximate = if je.approximate_suggestions { + let suggestion_applicability = if je.suggestion_applicability { suggestion.map(|x| x.1) } else { None @@ -318,7 +318,7 @@ impl DiagnosticSpan { is_primary, text: DiagnosticSpanLine::from_span(span, je), suggested_replacement: suggestion.map(|x| x.0.clone()), - suggestion_approximate, + suggestion_applicability, expansion: backtrace_step, label, } @@ -344,7 +344,7 @@ impl DiagnosticSpan { }; DiagnosticSpan::from_span_label(span_label, Some((&suggestion_inner.snippet, - suggestion.approximate)), + suggestion.applicability)), je) }) }) -- cgit 1.4.1-3-g733a5 From 259ae181391933040389e7e4206e792ad66b1487 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 24 Apr 2018 13:22:41 +1000 Subject: Implement LazyBTreeMap and use it in a few places. This is a thin wrapper around BTreeMap that avoids allocating upon creation. It speeds up some rustc-perf benchmarks by up to 3.6%. --- src/librustc/infer/higher_ranked/mod.rs | 12 +-- src/librustc/infer/mod.rs | 6 +- src/librustc/ty/fold.rs | 8 +- src/librustc_data_structures/lazy_btree_map.rs | 108 +++++++++++++++++++++++++ src/librustc_data_structures/lib.rs | 1 + 5 files changed, 123 insertions(+), 12 deletions(-) create mode 100644 src/librustc_data_structures/lazy_btree_map.rs (limited to 'src') diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs index d44f2ec9549..a8555a3458f 100644 --- a/src/librustc/infer/higher_ranked/mod.rs +++ b/src/librustc/infer/higher_ranked/mod.rs @@ -19,7 +19,7 @@ use super::{CombinedSnapshot, use super::combine::CombineFields; use super::region_constraints::{TaintDirections}; -use std::collections::BTreeMap; +use rustc_data_structures::lazy_btree_map::LazyBTreeMap; use ty::{self, TyCtxt, Binder, TypeFoldable}; use ty::error::TypeError; use ty::relate::{Relate, RelateResult, TypeRelation}; @@ -247,7 +247,8 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> { snapshot: &CombinedSnapshot<'a, 'tcx>, debruijn: ty::DebruijnIndex, new_vars: &[ty::RegionVid], - a_map: &BTreeMap>, + a_map: &LazyBTreeMap>, r0: ty::Region<'tcx>) -> ty::Region<'tcx> { // Regions that pre-dated the LUB computation stay as they are. @@ -343,7 +344,8 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> { snapshot: &CombinedSnapshot<'a, 'tcx>, debruijn: ty::DebruijnIndex, new_vars: &[ty::RegionVid], - a_map: &BTreeMap>, + a_map: &LazyBTreeMap>, a_vars: &[ty::RegionVid], b_vars: &[ty::RegionVid], r0: ty::Region<'tcx>) @@ -412,7 +414,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> { fn rev_lookup<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, span: Span, - a_map: &BTreeMap>, + a_map: &LazyBTreeMap>, r: ty::Region<'tcx>) -> ty::Region<'tcx> { for (a_br, a_r) in a_map { @@ -435,7 +437,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> { } fn var_ids<'a, 'gcx, 'tcx>(fields: &CombineFields<'a, 'gcx, 'tcx>, - map: &BTreeMap>) + map: &LazyBTreeMap>) -> Vec { map.iter() .map(|(_, &r)| match *r { diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 40cc43c3ca6..553926dba8f 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -28,9 +28,9 @@ use ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric}; use ty::fold::TypeFoldable; use ty::relate::RelateResult; use traits::{self, ObligationCause, PredicateObligations}; +use rustc_data_structures::lazy_btree_map::LazyBTreeMap; use rustc_data_structures::unify as ut; use std::cell::{Cell, RefCell, Ref, RefMut}; -use std::collections::BTreeMap; use std::fmt; use syntax::ast; use errors::DiagnosticBuilder; @@ -187,7 +187,7 @@ pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { /// A map returned by `skolemize_late_bound_regions()` indicating the skolemized /// region that each late-bound region was replaced with. -pub type SkolemizationMap<'tcx> = BTreeMap>; +pub type SkolemizationMap<'tcx> = LazyBTreeMap>; /// See `error_reporting` module for more details #[derive(Clone, Debug)] @@ -1216,7 +1216,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { span: Span, lbrct: LateBoundRegionConversionTime, value: &ty::Binder) - -> (T, BTreeMap>) + -> (T, LazyBTreeMap>) where T : TypeFoldable<'tcx> { self.tcx.replace_late_bound_regions( diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 8071cd0c639..80bdc4f89df 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -43,8 +43,8 @@ use middle::const_val::ConstVal; use hir::def_id::DefId; use ty::{self, Binder, Ty, TyCtxt, TypeFlags}; +use rustc_data_structures::lazy_btree_map::LazyBTreeMap; use std::fmt; -use std::collections::BTreeMap; use util::nodemap::FxHashSet; /// The TypeFoldable trait is implemented for every type that can be folded. @@ -334,7 +334,7 @@ struct RegionReplacer<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { tcx: TyCtxt<'a, 'gcx, 'tcx>, current_depth: u32, fld_r: &'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a), - map: BTreeMap> + map: LazyBTreeMap> } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { @@ -349,7 +349,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn replace_late_bound_regions(self, value: &Binder, mut f: F) - -> (T, BTreeMap>) + -> (T, LazyBTreeMap>) where F : FnMut(ty::BoundRegion) -> ty::Region<'tcx>, T : TypeFoldable<'tcx>, { @@ -462,7 +462,7 @@ impl<'a, 'gcx, 'tcx> RegionReplacer<'a, 'gcx, 'tcx> { tcx, current_depth: 1, fld_r, - map: BTreeMap::default() + map: LazyBTreeMap::default() } } } diff --git a/src/librustc_data_structures/lazy_btree_map.rs b/src/librustc_data_structures/lazy_btree_map.rs new file mode 100644 index 00000000000..74f91af10fe --- /dev/null +++ b/src/librustc_data_structures/lazy_btree_map.rs @@ -0,0 +1,108 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::collections::btree_map; +use std::collections::BTreeMap; + +/// A thin wrapper around BTreeMap that avoids allocating upon creation. +/// +/// Vec, HashSet and HashMap all have the nice feature that they don't do any +/// heap allocation when creating a new structure of the default size. In +/// contrast, BTreeMap *does* allocate in that situation. The compiler uses +/// B-Tree maps in some places such that many maps are created but few are +/// inserted into, so having a BTreeMap alternative that avoids allocating on +/// creation is a performance win. +/// +/// Only a fraction of BTreeMap's functionality is currently supported. +/// Additional functionality should be added on demand. +#[derive(Debug)] +pub struct LazyBTreeMap(Option>); + +impl LazyBTreeMap { + pub fn new() -> LazyBTreeMap { + LazyBTreeMap(None) + } + + pub fn iter(&self) -> Iter { + Iter(self.0.as_ref().map(|btm| btm.iter())) + } + + pub fn is_empty(&self) -> bool { + self.0.as_ref().map_or(true, |btm| btm.is_empty()) + } +} + +impl LazyBTreeMap { + fn instantiate(&mut self) -> &mut BTreeMap { + if let Some(ref mut btm) = self.0 { + btm + } else { + let btm = BTreeMap::new(); + self.0 = Some(btm); + self.0.as_mut().unwrap() + } + } + + pub fn insert(&mut self, key: K, value: V) -> Option { + self.instantiate().insert(key, value) + } + + pub fn entry(&mut self, key: K) -> btree_map::Entry { + self.instantiate().entry(key) + } + + pub fn values<'a>(&'a self) -> Values<'a, K, V> { + Values(self.0.as_ref().map(|btm| btm.values())) + } +} + +impl Default for LazyBTreeMap { + fn default() -> LazyBTreeMap { + LazyBTreeMap::new() + } +} + +impl<'a, K: 'a, V: 'a> IntoIterator for &'a LazyBTreeMap { + type Item = (&'a K, &'a V); + type IntoIter = Iter<'a, K, V>; + + fn into_iter(self) -> Iter<'a, K, V> { + self.iter() + } +} + +pub struct Iter<'a, K: 'a, V: 'a>(Option>); + +impl<'a, K: 'a, V: 'a> Iterator for Iter<'a, K, V> { + type Item = (&'a K, &'a V); + + fn next(&mut self) -> Option<(&'a K, &'a V)> { + self.0.as_mut().and_then(|iter| iter.next()) + } + + fn size_hint(&self) -> (usize, Option) { + self.0.as_ref().map_or_else(|| (0, Some(0)), |iter| iter.size_hint()) + } +} + +pub struct Values<'a, K: 'a, V: 'a>(Option>); + +impl<'a, K, V> Iterator for Values<'a, K, V> { + type Item = &'a V; + + fn next(&mut self) -> Option<&'a V> { + self.0.as_mut().and_then(|values| values.next()) + } + + fn size_hint(&self) -> (usize, Option) { + self.0.as_ref().map_or_else(|| (0, Some(0)), |values| values.size_hint()) + } +} + diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index ba1d73dc268..154c086614c 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -56,6 +56,7 @@ pub mod bitvec; pub mod graph; pub mod indexed_set; pub mod indexed_vec; +pub mod lazy_btree_map; pub mod obligation_forest; pub mod sip128; pub mod snapshot_map; -- cgit 1.4.1-3-g733a5 From 3ca6ad922eb6d8c3139d961c844a0194eaf58770 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Tue, 27 Mar 2018 16:44:03 +0200 Subject: Use ScalarPair for tagged enums --- src/librustc/ty/layout.rs | 81 ++++++++++++++++++++++++++++++---- src/test/codegen/align-struct.rs | 3 +- src/test/codegen/function-arguments.rs | 12 +++++ src/test/codegen/lifetime_start_end.rs | 8 ++-- 4 files changed, 90 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 77e2e9447f1..cfed0839acb 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1622,7 +1622,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { } // Create the set of structs that represent each variant. - let mut variants = variants.into_iter().enumerate().map(|(i, field_layouts)| { + let mut layout_variants = variants.iter().enumerate().map(|(i, field_layouts)| { let mut st = univariant_uninterned(&field_layouts, &def.repr, StructKind::Prefixed(min_ity.size(), prefix_align))?; st.variants = Variants::Single { index: i }; @@ -1683,7 +1683,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { // Patch up the variants' first few fields. let old_ity_size = min_ity.size(); let new_ity_size = ity.size(); - for variant in &mut variants { + for variant in &mut layout_variants { if variant.abi == Abi::Uninhabited { continue; } @@ -1710,15 +1710,80 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { value: Int(ity, signed), valid_range: (min as u128 & tag_mask)..=(max as u128 & tag_mask), }; - let abi = if tag.value.size(dl) == size { - Abi::Scalar(tag.clone()) - } else { - Abi::Aggregate { sized: true } - }; + let mut abi = Abi::Aggregate { sized: true }; + if tag.value.size(dl) == size { + abi = Abi::Scalar(tag.clone()); + } else if !tag.is_bool() { + // HACK(nox): Blindly using ScalarPair for all tagged enums + // where applicable leads to Option being handled as {i1, i8}, + // which later confuses SROA and some loop optimisations, + // ultimately leading to the repeat-trusted-len test + // failing. We make the trade-off of using ScalarPair only + // for types where the tag isn't a boolean. + let mut common_prim = None; + for (field_layouts, layout_variant) in variants.iter().zip(&layout_variants) { + let offsets = match layout_variant.fields { + FieldPlacement::Arbitrary { ref offsets, .. } => offsets, + _ => bug!(), + }; + let mut fields = field_layouts + .iter() + .zip(offsets) + .filter(|p| !p.0.is_zst()); + let (field, offset) = match (fields.next(), fields.next()) { + (None, None) => continue, + (Some(pair), None) => pair, + _ => { + common_prim = None; + break; + } + }; + let prim = match field.details.abi { + Abi::Scalar(ref scalar) => scalar.value, + _ => { + common_prim = None; + break; + } + }; + if let Some(pair) = common_prim { + // This is pretty conservative. We could go fancier + // by conflating things like i32 and u32, or even + // realising that (u8, u8) could just cohabit with + // u16 or even u32. + if pair != (prim, offset) { + common_prim = None; + break; + } + } else { + common_prim = Some((prim, offset)); + } + } + if let Some((prim, offset)) = common_prim { + let pair = scalar_pair(tag.clone(), scalar_unit(prim)); + let pair_offsets = match pair.fields { + FieldPlacement::Arbitrary { + ref offsets, + ref memory_index + } => { + assert_eq!(memory_index, &[0, 1]); + offsets + } + _ => bug!() + }; + if pair_offsets[0] == Size::from_bytes(0) && + pair_offsets[1] == *offset && + align == pair.align && + size == pair.size { + // We can use `ScalarPair` only when it matches our + // already computed layout (including `#[repr(C)]`). + abi = pair.abi; + } + } + } tcx.intern_layout(LayoutDetails { variants: Variants::Tagged { discr: tag, - variants + variants: layout_variants, }, fields: FieldPlacement::Arbitrary { offsets: vec![Size::from_bytes(0)], diff --git a/src/test/codegen/align-struct.rs b/src/test/codegen/align-struct.rs index 155319cb154..f306608f432 100644 --- a/src/test/codegen/align-struct.rs +++ b/src/test/codegen/align-struct.rs @@ -29,7 +29,6 @@ pub enum Enum4 { A(i32), B(i32), } -// CHECK: %Enum4 = type { [0 x i32], i32, [1 x i32] } // CHECK: %"Enum4::A" = type { [1 x i32], i32, [0 x i32] } pub enum Enum64 { @@ -59,7 +58,7 @@ pub fn nested64(a: Align64, b: i32, c: i32, d: i8) -> Nested64 { // CHECK-LABEL: @enum4 #[no_mangle] pub fn enum4(a: i32) -> Enum4 { -// CHECK: %e4 = alloca %Enum4, align 4 +// CHECK: %e4 = alloca { i32, i32 }, align 4 let e4 = Enum4::A(a); e4 } diff --git a/src/test/codegen/function-arguments.rs b/src/test/codegen/function-arguments.rs index de302c69056..40a9ea5a181 100644 --- a/src/test/codegen/function-arguments.rs +++ b/src/test/codegen/function-arguments.rs @@ -145,6 +145,18 @@ pub fn return_slice(x: &[u16]) -> &[u16] { x } +// CHECK: { i16, i16 } @enum_id_1(i16 %x.0, i16 %x.1) +#[no_mangle] +pub fn enum_id_1(x: Option>) -> Option> { + x +} + +// CHECK: i16 @enum_id_2(i16) +#[no_mangle] +pub fn enum_id_2(x: Option) -> Option { + x +} + // CHECK: noalias i8* @allocator() #[no_mangle] #[allocator] diff --git a/src/test/codegen/lifetime_start_end.rs b/src/test/codegen/lifetime_start_end.rs index 62aa93398ac..ea3f0de5d08 100644 --- a/src/test/codegen/lifetime_start_end.rs +++ b/src/test/codegen/lifetime_start_end.rs @@ -25,16 +25,16 @@ pub fn test() { let b = &Some(a); &b; // keep variable in an alloca -// CHECK: [[S_b:%[0-9]+]] = bitcast %"core::option::Option"** %b to i8* +// CHECK: [[S_b:%[0-9]+]] = bitcast { i32, i32 }** %b to i8* // CHECK: call void @llvm.lifetime.start{{.*}}(i{{[0-9 ]+}}, i8* [[S_b]]) -// CHECK: [[S__4:%[0-9]+]] = bitcast %"core::option::Option"* %_4 to i8* +// CHECK: [[S__4:%[0-9]+]] = bitcast { i32, i32 }* %_4 to i8* // CHECK: call void @llvm.lifetime.start{{.*}}(i{{[0-9 ]+}}, i8* [[S__4]]) -// CHECK: [[E_b:%[0-9]+]] = bitcast %"core::option::Option"** %b to i8* +// CHECK: [[E_b:%[0-9]+]] = bitcast { i32, i32 }** %b to i8* // CHECK: call void @llvm.lifetime.end{{.*}}(i{{[0-9 ]+}}, i8* [[E_b]]) -// CHECK: [[E__4:%[0-9]+]] = bitcast %"core::option::Option"* %_4 to i8* +// CHECK: [[E__4:%[0-9]+]] = bitcast { i32, i32 }* %_4 to i8* // CHECK: call void @llvm.lifetime.end{{.*}}(i{{[0-9 ]+}}, i8* [[E__4]]) } -- cgit 1.4.1-3-g733a5 From 2e4f66a86f7baa5644d18bb2adc07a8cd1c7409d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 26 Apr 2018 15:35:24 +1000 Subject: Make dump_{alloc,allocs,local}() no-ops when tracing is disabled. Because they traverse data structures and build up strings, which is wasted effort if those strings aren't printed. The patch also removes some now-unnecessary log_enabled! tests at call sites. --- src/librustc_mir/interpret/eval_context.rs | 7 ++++--- src/librustc_mir/interpret/memory.rs | 6 ++++++ src/librustc_mir/interpret/place.rs | 4 +--- 3 files changed, 11 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index b98ab218de5..90f1b5dda01 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -749,9 +749,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M } } - if log_enabled!(::log::Level::Trace) { - self.dump_local(dest); - } + self.dump_local(dest); Ok(()) } @@ -1538,6 +1536,9 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M pub fn dump_local(&self, place: Place) { // Debug output + if !log_enabled!(::log::Level::Trace) { + return; + } match place { Place::Local { frame, local } => { let mut allocs = Vec::new(); diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 5e156e9271f..7f8205b8327 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -334,11 +334,17 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> { /// For debugging, print an allocation and all allocations it points to, recursively. pub fn dump_alloc(&self, id: AllocId) { + if !log_enabled!(::log::Level::Trace) { + return; + } self.dump_allocs(vec![id]); } /// For debugging, print a list of allocations and all allocations they point to, recursively. pub fn dump_allocs(&self, mut allocs: Vec) { + if !log_enabled!(::log::Level::Trace) { + return; + } use std::fmt::Write; allocs.sort(); allocs.dedup(); diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 456f5fd75db..2d57ff44b47 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -218,9 +218,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { } }; - if log_enabled!(::log::Level::Trace) { - self.dump_local(place); - } + self.dump_local(place); Ok(place) } -- cgit 1.4.1-3-g733a5 From 30e3f1a620b06b6edd697c55858ea9f251a4332a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 25 Apr 2018 20:10:58 +0200 Subject: Add more doc aliases --- src/libcore/cmp.rs | 12 ++++++++++++ src/libcore/fmt/mod.rs | 2 ++ src/libcore/ops/bit.rs | 10 ++++++++++ src/libcore/ops/deref.rs | 3 +++ src/libcore/ops/range.rs | 6 ++++++ 5 files changed, 33 insertions(+) (limited to 'src') diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index c91aa06609d..13e838773a5 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -106,6 +106,8 @@ use self::Ordering::*; /// ``` #[lang = "eq"] #[stable(feature = "rust1", since = "1.0.0")] +#[doc(alias = "==")] +#[doc(alias = "!=")] #[rustc_on_unimplemented = "can't compare `{Self}` with `{Rhs}`"] pub trait PartialEq { /// This method tests for `self` and `other` values to be equal, and is used @@ -160,6 +162,8 @@ pub trait PartialEq { /// } /// impl Eq for Book {} /// ``` +#[doc(alias = "==")] +#[doc(alias = "!=")] #[stable(feature = "rust1", since = "1.0.0")] pub trait Eq: PartialEq { // this method is used solely by #[deriving] to assert @@ -428,6 +432,10 @@ impl Ord for Reverse { /// } /// ``` #[lang = "ord"] +#[doc(alias = "<")] +#[doc(alias = ">")] +#[doc(alias = "<=")] +#[doc(alias = ">=")] #[stable(feature = "rust1", since = "1.0.0")] pub trait Ord: Eq + PartialOrd { /// This method returns an `Ordering` between `self` and `other`. @@ -599,6 +607,10 @@ impl PartialOrd for Ordering { /// ``` #[lang = "partial_ord"] #[stable(feature = "rust1", since = "1.0.0")] +#[doc(alias = ">")] +#[doc(alias = "<")] +#[doc(alias = "<=")] +#[doc(alias = ">=")] #[rustc_on_unimplemented = "can't compare `{Self}` with `{Rhs}`"] pub trait PartialOrd: PartialEq { /// This method returns an ordering between `self` and `other` values if one exists. diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index a8430f14410..99e3012c9bf 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -547,6 +547,7 @@ impl<'a> Display for Arguments<'a> { message="`{Self}` doesn't implement `{Debug}`", label="`{Self}` cannot be formatted using `:?` because it doesn't implement `{Debug}`", )] +#[doc(alias = "{:?}")] #[lang = "debug_trait"] pub trait Debug { /// Formats the value using the given formatter. @@ -612,6 +613,7 @@ pub trait Debug { label="`{Self}` cannot be formatted with the default formatter; \ try using `:?` instead if you are using a format string", )] +#[doc(alias = "{}")] #[stable(feature = "rust1", since = "1.0.0")] pub trait Display { /// Formats the value using the given formatter. diff --git a/src/libcore/ops/bit.rs b/src/libcore/ops/bit.rs index 81c4455cef4..02b6f62db6e 100644 --- a/src/libcore/ops/bit.rs +++ b/src/libcore/ops/bit.rs @@ -119,6 +119,7 @@ not_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } /// assert_eq!(bv1 & bv2, expected); /// ``` #[lang = "bitand"] +#[doc(alias = "&")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_on_unimplemented(message="no implementation for `{Self} & {RHS}`", label="no implementation for `{Self} & {RHS}`")] @@ -201,6 +202,7 @@ bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } /// assert_eq!(bv1 | bv2, expected); /// ``` #[lang = "bitor"] +#[doc(alias = "|")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_on_unimplemented(message="no implementation for `{Self} | {RHS}`", label="no implementation for `{Self} | {RHS}`")] @@ -286,6 +288,7 @@ bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } /// assert_eq!(bv1 ^ bv2, expected); /// ``` #[lang = "bitxor"] +#[doc(alias = "^")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_on_unimplemented(message="no implementation for `{Self} ^ {RHS}`", label="no implementation for `{Self} ^ {RHS}`")] @@ -372,6 +375,7 @@ bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } /// SpinVector { vec: vec![2, 3, 4, 0, 1] }); /// ``` #[lang = "shl"] +#[doc(alias = "<<")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_on_unimplemented(message="no implementation for `{Self} << {RHS}`", label="no implementation for `{Self} << {RHS}`")] @@ -479,6 +483,7 @@ shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 isize i128 } /// SpinVector { vec: vec![3, 4, 0, 1, 2] }); /// ``` #[lang = "shr"] +#[doc(alias = ">>")] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_on_unimplemented(message="no implementation for `{Self} >> {RHS}`", label="no implementation for `{Self} >> {RHS}`")] @@ -593,6 +598,7 @@ shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } /// assert_eq!(bv, expected); /// ``` #[lang = "bitand_assign"] +#[doc(alias = "&=")] #[stable(feature = "op_assign_traits", since = "1.8.0")] #[rustc_on_unimplemented(message="no implementation for `{Self} &= {Rhs}`", label="no implementation for `{Self} &= {Rhs}`")] @@ -641,6 +647,7 @@ bitand_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } /// assert_eq!(prefs, PersonalPreferences { likes_cats: true, likes_dogs: true }); /// ``` #[lang = "bitor_assign"] +#[doc(alias = "|=")] #[stable(feature = "op_assign_traits", since = "1.8.0")] #[rustc_on_unimplemented(message="no implementation for `{Self} |= {Rhs}`", label="no implementation for `{Self} |= {Rhs}`")] @@ -689,6 +696,7 @@ bitor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } /// assert_eq!(personality, Personality { has_soul: true, likes_knitting: false}); /// ``` #[lang = "bitxor_assign"] +#[doc(alias = "^=")] #[stable(feature = "op_assign_traits", since = "1.8.0")] #[rustc_on_unimplemented(message="no implementation for `{Self} ^= {Rhs}`", label="no implementation for `{Self} ^= {Rhs}`")] @@ -735,6 +743,7 @@ bitxor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } /// assert_eq!(scalar, Scalar(16)); /// ``` #[lang = "shl_assign"] +#[doc(alias = "<<=")] #[stable(feature = "op_assign_traits", since = "1.8.0")] #[rustc_on_unimplemented(message="no implementation for `{Self} <<= {Rhs}`", label="no implementation for `{Self} <<= {Rhs}`")] @@ -802,6 +811,7 @@ shl_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize } /// assert_eq!(scalar, Scalar(4)); /// ``` #[lang = "shr_assign"] +#[doc(alias = ">>=")] #[stable(feature = "op_assign_traits", since = "1.8.0")] #[rustc_on_unimplemented(message="no implementation for `{Self} >>= {Rhs}`", label="no implementation for `{Self} >>= {Rhs}`")] diff --git a/src/libcore/ops/deref.rs b/src/libcore/ops/deref.rs index 4ce0740130b..332d154170f 100644 --- a/src/libcore/ops/deref.rs +++ b/src/libcore/ops/deref.rs @@ -68,6 +68,8 @@ /// assert_eq!('a', *x); /// ``` #[lang = "deref"] +#[doc(alias = "*")] +#[doc(alias = "&*")] #[stable(feature = "rust1", since = "1.0.0")] pub trait Deref { /// The resulting type after dereferencing. @@ -162,6 +164,7 @@ impl<'a, T: ?Sized> Deref for &'a mut T { /// assert_eq!('b', *x); /// ``` #[lang = "deref_mut"] +#[doc(alias = "*")] #[stable(feature = "rust1", since = "1.0.0")] pub trait DerefMut: Deref { /// Mutably dereferences the value. diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs index 6f3e3b50885..d70f7ae66f9 100644 --- a/src/libcore/ops/range.rs +++ b/src/libcore/ops/range.rs @@ -45,6 +45,7 @@ use fmt; /// [`IntoIterator`]: ../iter/trait.Iterator.html /// [`Iterator`]: ../iter/trait.IntoIterator.html /// [slicing index]: ../slice/trait.SliceIndex.html +#[doc(alias = "..")] #[derive(Copy, Clone, PartialEq, Eq, Hash)] #[stable(feature = "rust1", since = "1.0.0")] pub struct RangeFull; @@ -74,6 +75,7 @@ impl fmt::Debug for RangeFull { /// assert_eq!(arr[1.. ], [ 'b', 'c', 'd']); /// assert_eq!(arr[1..3], [ 'b', 'c' ]); // Range /// ``` +#[doc(alias = "..")] #[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 #[stable(feature = "rust1", since = "1.0.0")] pub struct Range { @@ -175,6 +177,7 @@ impl> Range { /// ``` /// /// [`Iterator`]: ../iter/trait.IntoIterator.html +#[doc(alias = "..")] #[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 #[stable(feature = "rust1", since = "1.0.0")] pub struct RangeFrom { @@ -256,6 +259,7 @@ impl> RangeFrom { /// [`IntoIterator`]: ../iter/trait.Iterator.html /// [`Iterator`]: ../iter/trait.IntoIterator.html /// [slicing index]: ../slice/trait.SliceIndex.html +#[doc(alias = "..")] #[derive(Copy, Clone, PartialEq, Eq, Hash)] #[stable(feature = "rust1", since = "1.0.0")] pub struct RangeTo { @@ -323,6 +327,7 @@ impl> RangeTo { /// assert_eq!(arr[ ..=2], [0,1,2 ]); /// assert_eq!(arr[1..=2], [ 1,2 ]); // RangeInclusive /// ``` +#[doc(alias = "..=")] #[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 #[stable(feature = "inclusive_range", since = "1.26.0")] pub struct RangeInclusive { @@ -449,6 +454,7 @@ impl> RangeInclusive { /// [`IntoIterator`]: ../iter/trait.Iterator.html /// [`Iterator`]: ../iter/trait.IntoIterator.html /// [slicing index]: ../slice/trait.SliceIndex.html +#[doc(alias = "..=")] #[derive(Copy, Clone, PartialEq, Eq, Hash)] #[stable(feature = "inclusive_range", since = "1.26.0")] pub struct RangeToInclusive { -- cgit 1.4.1-3-g733a5 From 98c2e0976d6c4d0d3bd22e477b504f1a6f9b4ffa Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Mon, 23 Apr 2018 13:54:09 +0900 Subject: Do not ICE on generics mismatch with non-local traits Fixes #49841 --- src/librustc_typeck/check/compare_method.rs | 3 +-- src/test/compile-fail/impl-trait/impl-generic-mismatch.rs | 11 +++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index e1e3dea9a2a..2003e0cc3d2 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -730,8 +730,7 @@ fn compare_synthetic_generics<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, if impl_ty.synthetic != trait_ty.synthetic { let impl_node_id = tcx.hir.as_local_node_id(impl_ty.def_id).unwrap(); let impl_span = tcx.hir.span(impl_node_id); - let trait_node_id = tcx.hir.as_local_node_id(trait_ty.def_id).unwrap(); - let trait_span = tcx.hir.span(trait_node_id); + let trait_span = tcx.def_span(trait_ty.def_id); let mut err = struct_span_err!(tcx.sess, impl_span, E0643, diff --git a/src/test/compile-fail/impl-trait/impl-generic-mismatch.rs b/src/test/compile-fail/impl-trait/impl-generic-mismatch.rs index eea7ca20957..d6707f59011 100644 --- a/src/test/compile-fail/impl-trait/impl-generic-mismatch.rs +++ b/src/test/compile-fail/impl-trait/impl-generic-mismatch.rs @@ -28,4 +28,15 @@ impl Bar for () { //~^ Error method `bar` has incompatible signature for trait } +// With non-local trait (#49841): + +use std::hash::{Hash, Hasher}; + +struct X; + +impl Hash for X { + fn hash(&self, hasher: &mut impl Hasher) {} + //~^ Error method `hash` has incompatible signature for trait +} + fn main() {} -- cgit 1.4.1-3-g733a5 From a2a9cc68fe44a4a667dddd01c17b3dcceefb5a5a Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 26 Apr 2018 06:56:37 -0700 Subject: rustc: Disable threads in LLD for wasm Upstream bug reports (rustwasm/wasm-bindgen#119) show that this may be the culprit of odd crashes/hangs. The linker is a tiny fraction of build time anyway right now so let's disable it and figure out how to possibly reenable it later if necessary. --- src/librustc_trans/back/linker.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs index e001e809ee5..883625a2dd7 100644 --- a/src/librustc_trans/back/linker.rs +++ b/src/librustc_trans/back/linker.rs @@ -959,7 +959,11 @@ impl Linker for WasmLd { } fn finalize(&mut self) -> Command { - self.cmd.arg("--threads"); + // There have been reports in the wild (rustwasm/wasm-bindgen#119) of + // using threads causing weird hangs and bugs. Disable it entirely as + // this isn't yet the bottleneck of compilation at all anyway. + self.cmd.arg("--no-threads"); + self.cmd.arg("-z").arg("stack-size=1048576"); // FIXME we probably shouldn't pass this but instead pass an explicit -- cgit 1.4.1-3-g733a5 From 2a58875fa2eafadf1dfaa0d3f474e3bd937ee671 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 26 Apr 2018 13:31:24 -0400 Subject: improved debug output --- src/librustc/traits/fulfill.rs | 2 +- src/librustc/traits/project.rs | 10 ++++++++-- src/librustc_traits/normalize_erasing_regions.rs | 2 ++ 3 files changed, 11 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index 1c091d68a2e..5ec2e32b6a4 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -112,7 +112,7 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> { selcx, register_region_obligations: self.register_region_obligations }); - debug!("select: outcome={:?}", outcome); + debug!("select: outcome={:#?}", outcome); // FIXME: if we kept the original cache key, we could mark projection // obligations as complete for the projection cache here. diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 1c7942139e9..0c35e20324c 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -196,7 +196,10 @@ pub fn poly_project_and_unify_type<'cx, 'gcx, 'tcx>( let span = obligation.cause.span; match infcx.leak_check(false, span, &skol_map, snapshot) { Ok(()) => Ok(infcx.plug_leaks(skol_map, snapshot, result)), - Err(e) => Err(MismatchedProjectionTypes { err: e }), + Err(e) => { + debug!("poly_project_and_unify_type: leak check encountered error {:?}", e); + Err(MismatchedProjectionTypes { err: e }) + } } } Err(e) => { @@ -243,7 +246,10 @@ fn project_and_unify_type<'cx, 'gcx, 'tcx>( obligations.extend(inferred_obligations); Ok(Some(obligations)) }, - Err(err) => Err(MismatchedProjectionTypes { err: err }), + Err(err) => { + debug!("project_and_unify_type: equating types encountered error {:?}", err); + Err(MismatchedProjectionTypes { err: err }) + } } } diff --git a/src/librustc_traits/normalize_erasing_regions.rs b/src/librustc_traits/normalize_erasing_regions.rs index 1857df5717b..299433d479d 100644 --- a/src/librustc_traits/normalize_erasing_regions.rs +++ b/src/librustc_traits/normalize_erasing_regions.rs @@ -17,6 +17,8 @@ crate fn normalize_ty_after_erasing_regions<'tcx>( tcx: TyCtxt<'_, 'tcx, 'tcx>, goal: ParamEnvAnd<'tcx, Ty<'tcx>>, ) -> Ty<'tcx> { + debug!("normalize_ty_after_erasing_regions(goal={:#?})", goal); + let ParamEnvAnd { param_env, value } = goal; tcx.sess.perf_stats.normalize_ty_after_erasing_regions.fetch_add(1, Ordering::Relaxed); tcx.infer_ctxt().enter(|infcx| { -- cgit 1.4.1-3-g733a5 From 0361e5938c17ca8761f955767756f972df018926 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 26 Apr 2018 13:31:31 -0400 Subject: use `reveal_all` during drop elaboration This used to happen by default as part of the normalization routine that was being used. --- src/librustc_mir/shim.rs | 2 +- src/librustc_mir/transform/elaborate_drops.rs | 2 +- src/librustc_mir/util/elaborate_drops.rs | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 6a0f42c6dbb..59501f1474f 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -210,7 +210,7 @@ fn build_drop_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, if let Some(..) = ty { let patch = { - let param_env = tcx.param_env(def_id); + let param_env = tcx.param_env(def_id).with_reveal_all(); let mut elaborator = DropShimElaborator { mir: &mir, patch: MirPatch::new(&mir), diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs index 2e8dd623d74..f63a5ef301a 100644 --- a/src/librustc_mir/transform/elaborate_drops.rs +++ b/src/librustc_mir/transform/elaborate_drops.rs @@ -50,7 +50,7 @@ impl MirPass for ElaborateDrops { (hir::BodyOwnerKind::Fn, None) => {}, _ => return } - let param_env = tcx.param_env(src.def_id); + let param_env = tcx.param_env(src.def_id).with_reveal_all(); let move_data = MoveData::gather_moves(mir, tcx).unwrap(); let elaborate_patch = { let mir = &*mir; diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index 19f33ef5d45..e5719407da6 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -13,6 +13,7 @@ use rustc::hir; use rustc::mir::*; use rustc::middle::const_val::ConstVal; use rustc::middle::lang_items; +use rustc::traits::Reveal; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::subst::{Kind, Substs}; use rustc::ty::util::IntTypeExt; @@ -206,6 +207,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> let field = Field::new(i); let subpath = self.elaborator.field_subpath(variant_path, field); + assert_eq!(self.elaborator.param_env().reveal, Reveal::All); let field_ty = self.tcx().normalize_erasing_regions( self.elaborator.param_env(), f.ty(self.tcx(), substs), -- cgit 1.4.1-3-g733a5 From 86e9a7ac43b7fc2de4fdc2127de568d523ce5284 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 26 Apr 2018 13:42:22 -0400 Subject: add regression test Fixes #49685 --- src/test/run-pass/issue-49685.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/test/run-pass/issue-49685.rs (limited to 'src') diff --git a/src/test/run-pass/issue-49685.rs b/src/test/run-pass/issue-49685.rs new file mode 100644 index 00000000000..1e4e7955323 --- /dev/null +++ b/src/test/run-pass/issue-49685.rs @@ -0,0 +1,22 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for #49685: drop elaboration was not revealing the +// value of `impl Trait` returns, leading to an ICE. + +fn main() { + let _ = Some(()) + .into_iter() + .flat_map(|_| Some(()).into_iter().flat_map(func)); +} + +fn func(_: ()) -> impl Iterator { + Some(()).into_iter().flat_map(|_| vec![]) +} -- cgit 1.4.1-3-g733a5 From 20ef0e001a1620436073d01f43a4a462d1967902 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Thu, 26 Apr 2018 12:46:28 -0500 Subject: make Vec::new const :P --- src/liballoc/vec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 757606607bb..1d95f76fd77 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -322,7 +322,7 @@ impl Vec { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn new() -> Vec { + pub const fn new() -> Vec { Vec { buf: RawVec::empty(), len: 0, -- cgit 1.4.1-3-g733a5 From acf0adf7984d7bfc9bf5f81465471976c0f6b626 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 25 Apr 2018 19:50:32 +0200 Subject: Add setting to go to item if there is only one result --- src/librustdoc/html/render.rs | 2 + src/librustdoc/html/static/main.js | 88 ++++++++++++++++++++++++-------------- 2 files changed, 59 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 0ae946c4182..0784c7b10e8 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1594,6 +1594,8 @@ impl<'a> Settings<'a> { settings: vec![ ("item-declarations", "Auto-hide item declarations.", true), ("item-attributes", "Auto-hide item attributes.", true), + ("go-to-only-result", "Directly go to item in search if there is only one result", + false), ], root_path, suffix, diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 58a57f43d37..bcad2eb19f5 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -1013,7 +1013,8 @@ 'returned': sortResults(results_returned, true), 'others': sortResults(results), }; - if (ALIASES[window.currentCrate][query.raw]) { + if (ALIASES && ALIASES[window.currentCrate] && + ALIASES[window.currentCrate][query.raw]) { var aliases = ALIASES[window.currentCrate][query.raw]; for (var i = 0; i < aliases.length; ++i) { ret['others'].unshift(aliases[i]); @@ -1188,6 +1189,44 @@ return '' + path.replace(/::/g, '::'); } + function buildHrefAndPath(item) { + var displayPath; + var href; + var type = itemTypes[item.ty]; + var name = item.name; + + if (type === 'mod') { + displayPath = item.path + '::'; + href = rootPath + item.path.replace(/::/g, '/') + '/' + + name + '/index.html'; + } else if (type === "primitive") { + displayPath = ""; + href = rootPath + item.path.replace(/::/g, '/') + + '/' + type + '.' + name + '.html'; + } else if (type === "externcrate") { + displayPath = ""; + href = rootPath + name + '/index.html'; + } else if (item.parent !== undefined) { + var myparent = item.parent; + var anchor = '#' + type + '.' + name; + var parentType = itemTypes[myparent.ty]; + if (parentType === "primitive") { + displayPath = myparent.name + '::'; + } else { + displayPath = item.path + '::' + myparent.name + '::'; + } + href = rootPath + item.path.replace(/::/g, '/') + + '/' + parentType + + '.' + myparent.name + + '.html' + anchor; + } else { + displayPath = item.path + '::'; + href = rootPath + item.path.replace(/::/g, '/') + + '/' + type + '.' + name + '.html'; + } + return [displayPath, href]; + } + function addTab(array, query, display) { var extraStyle = ''; if (display === false) { @@ -1211,35 +1250,9 @@ name = item.name; type = itemTypes[item.ty]; - if (type === 'mod') { - displayPath = item.path + '::'; - href = rootPath + item.path.replace(/::/g, '/') + '/' + - name + '/index.html'; - } else if (type === "primitive") { - displayPath = ""; - href = rootPath + item.path.replace(/::/g, '/') + - '/' + type + '.' + name + '.html'; - } else if (type === "externcrate") { - displayPath = ""; - href = rootPath + name + '/index.html'; - } else if (item.parent !== undefined) { - var myparent = item.parent; - var anchor = '#' + type + '.' + name; - var parentType = itemTypes[myparent.ty]; - if (parentType === "primitive") { - displayPath = myparent.name + '::'; - } else { - displayPath = item.path + '::' + myparent.name + '::'; - } - href = rootPath + item.path.replace(/::/g, '/') + - '/' + parentType + - '.' + myparent.name + - '.html' + anchor; - } else { - displayPath = item.path + '::'; - href = rootPath + item.path.replace(/::/g, '/') + - '/' + type + '.' + name + '.html'; - } + var res = buildHrefAndPath(item); + var href = res[1]; + var displayPath = res[0]; output += '' + '' + @@ -1268,6 +1281,16 @@ } function showResults(results) { + if (results['others'].length === 1 && + getCurrentValue('rustdoc-go-to-only-result') === "true") { + var elem = document.createElement('a'); + var res = buildHrefAndPath(results['others'][0]); + elem.href = res[1]; + elem.style.display = 'none'; + // For firefox, we need the element to be in the DOM so it can be clicked. + document.body.appendChild(elem); + elem.click(); + } var output, query = getQuery(search_input.value); currentResults = query.id; @@ -1721,6 +1744,9 @@ function toggleAllDocs(pageId) { var toggle = document.getElementById("toggle-all-docs"); + if (!toggle) { + return; + } if (hasClass(toggle, "will-expand")) { updateLocalStorage("rustdoc-collapse", "false"); removeClass(toggle, "will-expand"); @@ -1977,7 +2003,7 @@ collapseDocs(e.previousSibling.childNodes[0], "toggle"); } } - }) + }); autoCollapseAllImpls(getPageId()); -- cgit 1.4.1-3-g733a5 From 90656441a9dfbc42b6f5f1f25abeead66012bb00 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sun, 22 Apr 2018 18:40:54 +0200 Subject: Emit range metadata on calls returning scalars (fixes #50157) --- src/librustc_target/abi/mod.rs | 19 ++++++++++++++++++- src/librustc_target/lib.rs | 1 + src/librustc_trans/abi.rs | 22 ++++++++++++++++++++-- src/librustc_trans/lib.rs | 1 + src/librustc_trans/mir/block.rs | 4 ++-- src/librustc_trans/mir/place.rs | 23 +++++++---------------- src/test/codegen/call-metadata.rs | 29 +++++++++++++++++++++++++++++ 7 files changed, 78 insertions(+), 21 deletions(-) create mode 100644 src/test/codegen/call-metadata.rs (limited to 'src') diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index 18dd04c0ee8..346e5667a7b 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -14,7 +14,7 @@ pub use self::Primitive::*; use spec::Target; use std::cmp; -use std::ops::{Add, Deref, Sub, Mul, AddAssign, RangeInclusive}; +use std::ops::{Add, Deref, Sub, Mul, AddAssign, Range, RangeInclusive}; pub mod call; @@ -544,6 +544,23 @@ impl Scalar { false } } + + /// Returns the valid range as a `x..y` range. + /// + /// If `x` and `y` are equal, the range is full, not empty. + pub fn valid_range_exclusive(&self, cx: C) -> Range { + // For a (max) value of -1, max will be `-1 as usize`, which overflows. + // However, that is fine here (it would still represent the full range), + // i.e., if the range is everything. + let bits = self.value.size(cx).bits(); + assert!(bits <= 128); + let mask = !0u128 >> (128 - bits); + let start = self.valid_range.start; + let end = self.valid_range.end; + assert_eq!(start, start & mask); + assert_eq!(end, end & mask); + start..(end.wrapping_add(1) & mask) + } } /// Describes how the fields of a type are located in memory. diff --git a/src/librustc_target/lib.rs b/src/librustc_target/lib.rs index 8f491157439..927d5c7e15a 100644 --- a/src/librustc_target/lib.rs +++ b/src/librustc_target/lib.rs @@ -29,6 +29,7 @@ #![feature(const_fn)] #![feature(fs_read_write)] #![feature(inclusive_range)] +#![feature(inclusive_range_fields)] #![feature(slice_patterns)] #[macro_use] diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs index 483f36afe27..1d0d7ec601f 100644 --- a/src/librustc_trans/abi.rs +++ b/src/librustc_trans/abi.rs @@ -265,7 +265,7 @@ pub trait FnTypeExt<'a, 'tcx> { fn llvm_type(&self, cx: &CodegenCx<'a, 'tcx>) -> Type; fn llvm_cconv(&self) -> llvm::CallConv; fn apply_attrs_llfn(&self, llfn: ValueRef); - fn apply_attrs_callsite(&self, callsite: ValueRef); + fn apply_attrs_callsite(&self, bx: &Builder<'a, 'tcx>, callsite: ValueRef); } impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> { @@ -640,7 +640,7 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> { } } - fn apply_attrs_callsite(&self, callsite: ValueRef) { + fn apply_attrs_callsite(&self, bx: &Builder<'a, 'tcx>, callsite: ValueRef) { let mut i = 0; let mut apply = |attrs: &ArgAttributes| { attrs.apply_callsite(llvm::AttributePlace::Argument(i), callsite); @@ -653,6 +653,24 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> { PassMode::Indirect(ref attrs) => apply(attrs), _ => {} } + if let layout::Abi::Scalar(ref scalar) = self.ret.layout.abi { + // If the value is a boolean, the range is 0..2 and that ultimately + // become 0..0 when the type becomes i1, which would be rejected + // by the LLVM verifier. + match scalar.value { + layout::Int(..) if !scalar.is_bool() => { + let range = scalar.valid_range_exclusive(bx.cx); + if range.start != range.end { + // FIXME(nox): This causes very weird type errors about + // SHL operators in constants in stage 2 with LLVM 3.9. + if unsafe { llvm::LLVMRustVersionMajor() >= 4 } { + bx.range_metadata(callsite, range); + } + } + } + _ => {} + } + } for arg in &self.args { if arg.pad.is_some() { apply(&ArgAttributes::new()); diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index dab01abd335..96a10e8b99d 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -25,6 +25,7 @@ #![allow(unused_attributes)] #![feature(libc)] #![feature(quote)] +#![feature(range_contains)] #![feature(rustc_diagnostic_macros)] #![feature(slice_sort_by_cached_key)] #![feature(optin_builtin_traits)] diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index 36f03605fea..b9e272e993e 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -127,7 +127,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { ret_bx, llblock(this, cleanup), cleanup_bundle); - fn_ty.apply_attrs_callsite(invokeret); + fn_ty.apply_attrs_callsite(&bx, invokeret); if let Some((ret_dest, target)) = destination { let ret_bx = this.build_block(target); @@ -136,7 +136,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { } } else { let llret = bx.call(fn_ptr, &llargs, cleanup_bundle); - fn_ty.apply_attrs_callsite(llret); + fn_ty.apply_attrs_callsite(&bx, llret); if this.mir[bb].is_cleanup { // Cleanup is always the cold path. Don't inline // drop glue. Also, when there is a deeply-nested diff --git a/src/librustc_trans/mir/place.rs b/src/librustc_trans/mir/place.rs index b340d91b027..680c7038998 100644 --- a/src/librustc_trans/mir/place.rs +++ b/src/librustc_trans/mir/place.rs @@ -91,24 +91,15 @@ impl<'a, 'tcx> PlaceRef<'tcx> { } let scalar_load_metadata = |load, scalar: &layout::Scalar| { - let (min, max) = (scalar.valid_range.start, scalar.valid_range.end); - let max_next = max.wrapping_add(1); - let bits = scalar.value.size(bx.cx).bits(); - assert!(bits <= 128); - let mask = !0u128 >> (128 - bits); - // For a (max) value of -1, max will be `-1 as usize`, which overflows. - // However, that is fine here (it would still represent the full range), - // i.e., if the range is everything. The lo==hi case would be - // rejected by the LLVM verifier (it would mean either an - // empty set, which is impossible, or the entire range of the - // type, which is pointless). + let vr = scalar.valid_range.clone(); match scalar.value { - layout::Int(..) if max_next & mask != min & mask => { - // llvm::ConstantRange can deal with ranges that wrap around, - // so an overflow on (max + 1) is fine. - bx.range_metadata(load, min..max_next); + layout::Int(..) => { + let range = scalar.valid_range_exclusive(bx.cx); + if range.start != range.end { + bx.range_metadata(load, range); + } } - layout::Pointer if 0 < min && min < max => { + layout::Pointer if vr.start < vr.end && !vr.contains(&0) => { bx.nonnull_metadata(load); } _ => {} diff --git a/src/test/codegen/call-metadata.rs b/src/test/codegen/call-metadata.rs new file mode 100644 index 00000000000..20d42ed852d --- /dev/null +++ b/src/test/codegen/call-metadata.rs @@ -0,0 +1,29 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Checks that range metadata gets emitted on calls to functions returning a +// scalar value. + +// compile-flags: -C no-prepopulate-passes +// min-llvm-version 4.0 + + +#![crate_type = "lib"] + +pub fn test() { + // CHECK: call i8 @some_true(), !range [[R0:![0-9]+]] + // CHECK: [[R0]] = !{i8 0, i8 3} + some_true(); +} + +#[no_mangle] +fn some_true() -> Option { + Some(true) +} -- cgit 1.4.1-3-g733a5 From d92d1935cb01cfa469a725f041e4c1d8a2ee9564 Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Thu, 26 Apr 2018 14:19:21 -0700 Subject: Don't ICE on tuple struct ctor with incorrect arg count --- src/librustc/traits/error_reporting.rs | 6 ++++++ src/test/ui/mismatched_types/closure-arg-count.rs | 6 ++++++ src/test/ui/mismatched_types/closure-arg-count.stderr | 17 ++++++++++++++++- 3 files changed, 28 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 33abc0c7e15..3eb45439001 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -976,6 +976,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ArgKind::Arg(format!("{}", field.name), "_".to_string()) }).collect::>()) } + hir::map::NodeStructCtor(ref variant_data) => { + (self.tcx.sess.codemap().def_span(self.tcx.hir.span(variant_data.id())), + variant_data.fields() + .iter().map(|_| ArgKind::Arg("_".to_owned(), "_".to_owned())) + .collect()) + } _ => panic!("non-FnLike node found: {:?}", node), } } diff --git a/src/test/ui/mismatched_types/closure-arg-count.rs b/src/test/ui/mismatched_types/closure-arg-count.rs index 34232e81cbd..9eb11148a8b 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.rs +++ b/src/test/ui/mismatched_types/closure-arg-count.rs @@ -39,7 +39,13 @@ fn main() { let _it = vec![1, 2, 3].into_iter().map(usize::checked_add); //~^ ERROR function is expected to take + + call(Foo); + //~^ ERROR function is expected to take } fn foo() {} fn qux(x: usize, y: usize) {} + +fn call(_: F) where F: FnOnce() -> R {} +struct Foo(u8); diff --git a/src/test/ui/mismatched_types/closure-arg-count.stderr b/src/test/ui/mismatched_types/closure-arg-count.stderr index 6451c0d06fa..6270e794498 100644 --- a/src/test/ui/mismatched_types/closure-arg-count.stderr +++ b/src/test/ui/mismatched_types/closure-arg-count.stderr @@ -116,6 +116,21 @@ error[E0593]: function is expected to take 1 argument, but it takes 2 arguments LL | let _it = vec![1, 2, 3].into_iter().map(usize::checked_add); | ^^^ expected function that takes 1 argument -error: aborting due to 12 previous errors +error[E0593]: function is expected to take 0 arguments, but it takes 1 argument + --> $DIR/closure-arg-count.rs:43:5 + | +LL | call(Foo); + | ^^^^ expected function that takes 0 arguments +... +LL | struct Foo(u8); + | --------------- takes 1 argument + | +note: required by `call` + --> $DIR/closure-arg-count.rs:50:1 + | +LL | fn call(_: F) where F: FnOnce() -> R {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 13 previous errors For more information about this error, try `rustc --explain E0593`. -- cgit 1.4.1-3-g733a5 From c1492fe3039d014809960f91b2a95fe30e5d6b9c Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 8 Apr 2018 15:34:35 +0300 Subject: Add one more prelude layer for extern crate names passed with `--extern` --- src/librustc_resolve/lib.rs | 36 +++++++++++++++++----- src/libsyntax/feature_gate.rs | 5 ++- src/test/run-make-fulldeps/extern-prelude/Makefile | 12 ++++++++ src/test/run-make-fulldeps/extern-prelude/basic.rs | 16 ++++++++++ .../run-make-fulldeps/extern-prelude/ep-lib.rs | 17 ++++++++++ .../run-make-fulldeps/extern-prelude/ep-vec.rs | 13 ++++++++ .../extern-prelude/feature-gate.rs | 13 ++++++++ .../extern-prelude/relative-only.rs | 19 ++++++++++++ .../run-make-fulldeps/extern-prelude/shadow-mod.rs | 24 +++++++++++++++ .../extern-prelude/shadow-prelude.rs | 17 ++++++++++ src/test/run-pass/extern-prelude-no-speculative.rs | 21 +++++++++++++ src/test/ui/feature-gate-extern_prelude.rs | 11 +++++++ src/test/ui/feature-gate-extern_prelude.stderr | 8 +++++ 13 files changed, 204 insertions(+), 8 deletions(-) create mode 100644 src/test/run-make-fulldeps/extern-prelude/Makefile create mode 100644 src/test/run-make-fulldeps/extern-prelude/basic.rs create mode 100644 src/test/run-make-fulldeps/extern-prelude/ep-lib.rs create mode 100644 src/test/run-make-fulldeps/extern-prelude/ep-vec.rs create mode 100644 src/test/run-make-fulldeps/extern-prelude/feature-gate.rs create mode 100644 src/test/run-make-fulldeps/extern-prelude/relative-only.rs create mode 100644 src/test/run-make-fulldeps/extern-prelude/shadow-mod.rs create mode 100644 src/test/run-make-fulldeps/extern-prelude/shadow-prelude.rs create mode 100644 src/test/run-pass/extern-prelude-no-speculative.rs create mode 100644 src/test/ui/feature-gate-extern_prelude.rs create mode 100644 src/test/ui/feature-gate-extern_prelude.stderr (limited to 'src') diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 127331152c1..26c0ede48b7 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1407,6 +1407,7 @@ pub struct Resolver<'a> { graph_root: Module<'a>, prelude: Option>, + extern_prelude: FxHashSet, /// n.b. This is used only for better diagnostics, not name resolution itself. has_self: FxHashSet, @@ -1715,6 +1716,7 @@ impl<'a> Resolver<'a> { // AST. graph_root, prelude: None, + extern_prelude: session.opts.externs.iter().map(|kv| Symbol::intern(kv.0)).collect(), has_self: FxHashSet(), field_names: FxHashMap(), @@ -1970,13 +1972,32 @@ impl<'a> Resolver<'a> { } } - match self.prelude { - Some(prelude) if !module.no_implicit_prelude => { - self.resolve_ident_in_module_unadjusted(prelude, ident, ns, false, false, path_span) - .ok().map(LexicalScopeBinding::Item) + if !module.no_implicit_prelude { + // `record_used` means that we don't try to load crates during speculative resolution + if record_used && ns == TypeNS && self.extern_prelude.contains(&ident.name) { + if !self.session.features_untracked().extern_prelude { + feature_err(&self.session.parse_sess, "extern_prelude", + ident.span, GateIssue::Language, + "access to extern crates through prelude is experimental").emit(); + } + + let crate_id = self.crate_loader.process_path_extern(ident.name, ident.span); + let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }); + self.populate_module_if_necessary(crate_root); + + let binding = (crate_root, ty::Visibility::Public, + ident.span, Mark::root()).to_name_binding(self.arenas); + return Some(LexicalScopeBinding::Item(binding)); + } + if let Some(prelude) = self.prelude { + if let Ok(binding) = self.resolve_ident_in_module_unadjusted(prelude, ident, ns, + false, false, path_span) { + return Some(LexicalScopeBinding::Item(binding)); + } } - _ => None, } + + None } fn hygienic_lexical_parent(&mut self, mut module: Module<'a>, span: &mut Span) @@ -3587,8 +3608,9 @@ impl<'a> Resolver<'a> { // We can see through blocks } else { // Items from the prelude - if let Some(prelude) = self.prelude { - if !module.no_implicit_prelude { + if !module.no_implicit_prelude { + names.extend(self.extern_prelude.iter().cloned()); + if let Some(prelude) = self.prelude { add_module_candidates(prelude, &mut names); } } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 0331e90164f..832e655d3b1 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -397,7 +397,7 @@ declare_features! ( (active, generic_associated_types, "1.23.0", Some(44265), None), // Resolve absolute paths as paths from other crates - (active, extern_absolute_paths, "1.24.0", Some(44660), None), + (active, extern_absolute_paths, "1.24.0", Some(44660), Some(Edition::Edition2018)), // `foo.rs` as an alternative to `foo/mod.rs` (active, non_modrs_mods, "1.24.0", Some(44660), Some(Edition::Edition2018)), @@ -466,6 +466,9 @@ declare_features! ( // #[doc(alias = "...")] (active, doc_alias, "1.27.0", Some(50146), None), + + // Access to crate names passed via `--extern` through prelude + (active, extern_prelude, "1.27.0", Some(44660), Some(Edition::Edition2018)), ); declare_features! ( diff --git a/src/test/run-make-fulldeps/extern-prelude/Makefile b/src/test/run-make-fulldeps/extern-prelude/Makefile new file mode 100644 index 00000000000..aa8158c6eb3 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-prelude/Makefile @@ -0,0 +1,12 @@ +-include ../tools.mk + +all: + $(RUSTC) ep-lib.rs + $(RUSTC) ep-vec.rs + + $(RUSTC) basic.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib + $(RUSTC) shadow-mod.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib + $(RUSTC) shadow-prelude.rs --extern Vec=$(TMPDIR)/libep_vec.rlib + $(RUSTC) feature-gate.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib 2>&1 | $(CGREP) "access to extern crates through prelude is experimental" + $(RUSTC) relative-only.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib 2>&1 | $(CGREP) "unresolved import" + $(RUSTC) relative-only.rs --extern ep_lib=$(TMPDIR)/libep_lib.rlib 2>&1 | $(CGREP) "failed to resolve" diff --git a/src/test/run-make-fulldeps/extern-prelude/basic.rs b/src/test/run-make-fulldeps/extern-prelude/basic.rs new file mode 100644 index 00000000000..b8d6a772e2a --- /dev/null +++ b/src/test/run-make-fulldeps/extern-prelude/basic.rs @@ -0,0 +1,16 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(extern_prelude)] + +fn main() { + let s = ep_lib::S; // It works + s.external(); +} diff --git a/src/test/run-make-fulldeps/extern-prelude/ep-lib.rs b/src/test/run-make-fulldeps/extern-prelude/ep-lib.rs new file mode 100644 index 00000000000..dac0a3ce760 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-prelude/ep-lib.rs @@ -0,0 +1,17 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "rlib"] + +pub struct S; + +impl S { + pub fn external(&self) {} +} diff --git a/src/test/run-make-fulldeps/extern-prelude/ep-vec.rs b/src/test/run-make-fulldeps/extern-prelude/ep-vec.rs new file mode 100644 index 00000000000..f750a26f9e6 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-prelude/ep-vec.rs @@ -0,0 +1,13 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "rlib"] + +pub fn new(arg1: f32, arg2: ()) {} diff --git a/src/test/run-make-fulldeps/extern-prelude/feature-gate.rs b/src/test/run-make-fulldeps/extern-prelude/feature-gate.rs new file mode 100644 index 00000000000..49763f3ba6a --- /dev/null +++ b/src/test/run-make-fulldeps/extern-prelude/feature-gate.rs @@ -0,0 +1,13 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let s = ep_lib::S; // Feature error +} diff --git a/src/test/run-make-fulldeps/extern-prelude/relative-only.rs b/src/test/run-make-fulldeps/extern-prelude/relative-only.rs new file mode 100644 index 00000000000..0cd56b93de6 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-prelude/relative-only.rs @@ -0,0 +1,19 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Extern prelude names are not available by absolute paths + +#![feature(extern_prelude)] + +use ep_lib::S; + +fn main() { + let s = ::ep_lib::S; +} diff --git a/src/test/run-make-fulldeps/extern-prelude/shadow-mod.rs b/src/test/run-make-fulldeps/extern-prelude/shadow-mod.rs new file mode 100644 index 00000000000..52213c8d4f9 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-prelude/shadow-mod.rs @@ -0,0 +1,24 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Local module shadows `ep_lib` from extern prelude + +mod ep_lib { + pub struct S; + + impl S { + pub fn internal(&self) {} + } +} + +fn main() { + let s = ep_lib::S; + s.internal(); // OK +} diff --git a/src/test/run-make-fulldeps/extern-prelude/shadow-prelude.rs b/src/test/run-make-fulldeps/extern-prelude/shadow-prelude.rs new file mode 100644 index 00000000000..de1c4d16d39 --- /dev/null +++ b/src/test/run-make-fulldeps/extern-prelude/shadow-prelude.rs @@ -0,0 +1,17 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Extern prelude shadows standard library prelude + +#![feature(extern_prelude)] + +fn main() { + let x = Vec::new(0f32, ()); // OK +} diff --git a/src/test/run-pass/extern-prelude-no-speculative.rs b/src/test/run-pass/extern-prelude-no-speculative.rs new file mode 100644 index 00000000000..ff3aec439aa --- /dev/null +++ b/src/test/run-pass/extern-prelude-no-speculative.rs @@ -0,0 +1,21 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: --extern LooksLikeExternCrate=/path/to/nowhere + +mod m { + pub struct LooksLikeExternCrate; +} + +fn main() { + // OK, speculative resolution for `unused_qualifications` doesn't try + // to resolve this as an extern crate and load that crate + let s = m::LooksLikeExternCrate {}; +} diff --git a/src/test/ui/feature-gate-extern_prelude.rs b/src/test/ui/feature-gate-extern_prelude.rs new file mode 100644 index 00000000000..8d3a30305bd --- /dev/null +++ b/src/test/ui/feature-gate-extern_prelude.rs @@ -0,0 +1,11 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +can-only-test-this-in-run-make-fulldeps //~ ERROR expected one of `!` or `::`, found `-` diff --git a/src/test/ui/feature-gate-extern_prelude.stderr b/src/test/ui/feature-gate-extern_prelude.stderr new file mode 100644 index 00000000000..5abf369baf9 --- /dev/null +++ b/src/test/ui/feature-gate-extern_prelude.stderr @@ -0,0 +1,8 @@ +error: expected one of `!` or `::`, found `-` + --> $DIR/feature-gate-extern_prelude.rs:11:4 + | +LL | can-only-test-this-in-run-make-fulldeps //~ ERROR expected one of `!` or `::`, found `-` + | ^ expected one of `!` or `::` here + +error: aborting due to previous error + -- cgit 1.4.1-3-g733a5 From 73e0c1e968caaf7b70d659e58c0a40782c60f8da Mon Sep 17 00:00:00 2001 From: bobtwinkles Date: Thu, 26 Apr 2018 18:28:34 -0400 Subject: Fix review nits --- src/libproc_macro/lib.rs | 2 +- src/libsyntax_pos/hygiene.rs | 10 +++++----- src/libsyntax_pos/lib.rs | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index 4d24353a383..f51dbc3772f 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -270,7 +270,7 @@ impl Span { /// `self` was generated from, if any. #[unstable(feature = "proc_macro", issue = "38356")] pub fn parent(&self) -> Option { - self.0.parent().map(|x| { Span(x) }) + self.0.parent().map(Span) } /// The span for the origin source code that `self` was generated from. If diff --git a/src/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index 8e9564d0ac1..658408519b9 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -123,11 +123,11 @@ impl Mark { /// mark. That is, the following holds: /// /// ```rust - /// let lub = lub(a, b); - /// assert!(a.is_descendant_of(lub)) - /// assert!(b.is_descendant_of(lub)) + /// let la = least_ancestor(a, b); + /// assert!(a.is_descendant_of(la)) + /// assert!(b.is_descendant_of(la)) /// ``` - pub fn lub(mut a: Mark, mut b: Mark) -> Mark { + pub fn least_ancestor(mut a: Mark, mut b: Mark) -> Mark { HygieneData::with(|data| { // Compute the path from a to the root let mut a_path = FxHashSet::(); @@ -138,7 +138,7 @@ impl Mark { // While the path from b to the root hasn't intersected, move up the tree while !a_path.contains(&b) { - b = data.marks[b.0 as usize].parent; + b = data.marks[b.0 as usize].parent; } b diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 19f52d83a01..8d37b4aa396 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -291,7 +291,7 @@ impl Span { self.ctxt().outer().expn_info().map(|info| info.call_site.source_callsite()).unwrap_or(self) } - /// The `Span for the tokens in the previous macro expansion from which `self` was generated, + /// The `Span` for the tokens in the previous macro expansion from which `self` was generated, /// if any pub fn parent(self) -> Option { self.ctxt().outer().expn_info().map(|i| i.call_site) -- cgit 1.4.1-3-g733a5 From 20ad427af014aa6f8734629baa922c52f1ee8b77 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 26 Apr 2018 17:09:08 -0700 Subject: rustc: Emit `uwtable` for allocator shims This commit emits the `uwtable` attribute to LLVM for platforms that require it for the allocator shims that we generate to ensure that they can hopefully get unwound past. This is a stab in the dark at helping https://bugzilla.mozilla.org/show_bug.cgi?id=1456150 along. --- src/librustc_trans/allocator.rs | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/librustc_trans/allocator.rs b/src/librustc_trans/allocator.rs index ffebb959ebf..871fe98ec01 100644 --- a/src/librustc_trans/allocator.rs +++ b/src/librustc_trans/allocator.rs @@ -11,6 +11,7 @@ use std::ffi::CString; use std::ptr; +use attributes; use libc::c_uint; use rustc::middle::allocator::AllocatorKind; use rustc::ty::TyCtxt; @@ -67,6 +68,9 @@ pub(crate) unsafe fn trans(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind) if tcx.sess.target.target.options.default_hidden_visibility { llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden); } + if tcx.sess.target.target.options.requires_uwtable { + attributes::emit_uwtable(llfn, true); + } let callee = CString::new(kind.fn_name(method.name)).unwrap(); let callee = llvm::LLVMRustGetOrInsertFunction(llmod, -- cgit 1.4.1-3-g733a5 From 79f71f976a2c55794a120cb77cb8dfbf35bb0a25 Mon Sep 17 00:00:00 2001 From: Aravind Gollakota Date: Thu, 5 Apr 2018 12:29:18 -0500 Subject: Refactor overflow handling in traits::select to propagate overflow instead of aborting eagerly We store the obligation that caused the overflow as part of the OverflowError, and report it at the public API endpoints (rather than in the implementation internals). --- src/librustc/traits/error_reporting.rs | 5 + src/librustc/traits/mod.rs | 2 + src/librustc/traits/select.rs | 174 +++++++++++++++++++------------- src/librustc/traits/structural_impls.rs | 1 + 4 files changed, 113 insertions(+), 69 deletions(-) (limited to 'src') diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 33abc0c7e15..686008cc1ef 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -24,6 +24,7 @@ use super::{ SelectionContext, SelectionError, ObjectSafetyViolation, + Overflow, }; use errors::DiagnosticBuilder; @@ -830,6 +831,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } err.struct_error(self.tcx, span, "constant expression") } + + Overflow(_) => { + bug!("overflow should be handled before the `report_selection_error` path"); + } }; self.note_obligation_cause(&mut err, obligation); err.emit(); diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 728d9f1a027..6101d37956a 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -349,6 +349,8 @@ pub enum SelectionError<'tcx> { ty::error::TypeError<'tcx>), TraitNotObjectSafe(DefId), ConstEvalFailure(ConstEvalErr<'tcx>), + // upon overflow, stores the obligation that hit the recursion limit + Overflow(TraitObligation<'tcx>), } pub struct FulfillmentError<'tcx> { diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index f43f5cf3e3f..e65bfa7a72e 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -22,7 +22,7 @@ use super::project; use super::project::{normalize_with_depth, Normalized, ProjectionCacheKey}; use super::{PredicateObligation, TraitObligation, ObligationCause}; use super::{ObligationCauseCode, BuiltinDerivedObligation, ImplDerivedObligation}; -use super::{SelectionError, Unimplemented, OutputTypeParameterMismatch}; +use super::{SelectionError, Unimplemented, OutputTypeParameterMismatch, Overflow}; use super::{ObjectCastObligation, Obligation}; use super::TraitNotObjectSafe; use super::Selection; @@ -408,6 +408,17 @@ impl EvaluationResult { } } +#[derive(Clone, Debug, PartialEq, Eq)] +/// Indicates that trait evaluation caused overflow. Stores the obligation +/// that hit the recursion limit. +pub struct OverflowError<'tcx>(TraitObligation<'tcx>); + +impl<'tcx> From> for SelectionError<'tcx> { + fn from(OverflowError(o): OverflowError<'tcx>) -> SelectionError<'tcx> { + SelectionError::Overflow(o) + } +} + #[derive(Clone)] pub struct EvaluationCache<'tcx> { hashmap: RefCell, WithDepNode>> @@ -528,12 +539,21 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { assert!(!obligation.predicate.has_escaping_regions()); let stack = self.push_stack(TraitObligationStackList::empty(), obligation); - let ret = match self.candidate_from_obligation(&stack)? { - None => None, - Some(candidate) => Some(self.confirm_candidate(obligation, candidate)?) + + let candidate = match self.candidate_from_obligation(&stack) { + Err(SelectionError::Overflow(o)) => + self.infcx().report_overflow_error(&o, true), + Err(e) => { return Err(e); }, + Ok(None) => { return Ok(None); }, + Ok(Some(candidate)) => candidate }; - Ok(ret) + match self.confirm_candidate(obligation, candidate) { + Err(SelectionError::Overflow(o)) => + self.infcx().report_overflow_error(&o, true), + Err(e) => Err(e), + Ok(candidate) => Ok(Some(candidate)) + } } /////////////////////////////////////////////////////////////////////////// @@ -554,10 +574,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { debug!("evaluate_obligation({:?})", obligation); - self.probe(|this, _| { + match self.probe(|this, _| { this.evaluate_predicate_recursively(TraitObligationStackList::empty(), obligation) - .may_apply() - }) + }) { + Ok(result) => result.may_apply(), + Err(OverflowError(o)) => self.infcx().report_overflow_error(&o, true) + } } /// Evaluates whether the obligation `obligation` can be satisfied, @@ -570,10 +592,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { debug!("evaluate_obligation_conservatively({:?})", obligation); - self.probe(|this, _| { + match self.probe(|this, _| { this.evaluate_predicate_recursively(TraitObligationStackList::empty(), obligation) - == EvaluatedToOk - }) + }) { + Ok(result) => result == EvaluatedToOk, + Err(OverflowError(o)) => self.infcx().report_overflow_error(&o, true) + } } /// Evaluates the predicates in `predicates` recursively. Note that @@ -582,29 +606,29 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { fn evaluate_predicates_recursively<'a,'o,I>(&mut self, stack: TraitObligationStackList<'o, 'tcx>, predicates: I) - -> EvaluationResult + -> Result> where I : IntoIterator>, 'tcx:'a { let mut result = EvaluatedToOk; for obligation in predicates { - let eval = self.evaluate_predicate_recursively(stack, obligation); + let eval = self.evaluate_predicate_recursively(stack, obligation)?; debug!("evaluate_predicate_recursively({:?}) = {:?}", obligation, eval); if let EvaluatedToErr = eval { // fast-path - EvaluatedToErr is the top of the lattice, // so we don't need to look on the other predicates. - return EvaluatedToErr; + return Ok(EvaluatedToErr); } else { result = cmp::max(result, eval); } } - result + Ok(result) } fn evaluate_predicate_recursively<'o>(&mut self, previous_stack: TraitObligationStackList<'o, 'tcx>, obligation: &PredicateObligation<'tcx>) - -> EvaluationResult + -> Result> { debug!("evaluate_predicate_recursively({:?})", obligation); @@ -620,11 +644,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // does this code ever run? match self.infcx.subtype_predicate(&obligation.cause, obligation.param_env, p) { Some(Ok(InferOk { obligations, .. })) => { - self.evaluate_predicates_recursively(previous_stack, &obligations); - EvaluatedToOk + self.evaluate_predicates_recursively(previous_stack, &obligations) }, - Some(Err(_)) => EvaluatedToErr, - None => EvaluatedToAmbig, + Some(Err(_)) => Ok(EvaluatedToErr), + None => Ok(EvaluatedToAmbig), } } @@ -636,21 +659,21 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { Some(obligations) => self.evaluate_predicates_recursively(previous_stack, obligations.iter()), None => - EvaluatedToAmbig, + Ok(EvaluatedToAmbig), } } ty::Predicate::TypeOutlives(..) | ty::Predicate::RegionOutlives(..) => { // we do not consider region relationships when // evaluating trait matches - EvaluatedToOk + Ok(EvaluatedToOk) } ty::Predicate::ObjectSafe(trait_def_id) => { if self.tcx().is_object_safe(trait_def_id) { - EvaluatedToOk + Ok(EvaluatedToOk) } else { - EvaluatedToErr + Ok(EvaluatedToErr) } } @@ -668,10 +691,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { result } Ok(None) => { - EvaluatedToAmbig + Ok(EvaluatedToAmbig) } Err(_) => { - EvaluatedToErr + Ok(EvaluatedToErr) } } } @@ -680,13 +703,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { match self.infcx.closure_kind(closure_def_id, closure_substs) { Some(closure_kind) => { if closure_kind.extends(kind) { - EvaluatedToOk + Ok(EvaluatedToOk) } else { - EvaluatedToErr + Ok(EvaluatedToErr) } } None => { - EvaluatedToAmbig + Ok(EvaluatedToAmbig) } } } @@ -707,16 +730,16 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { promoted: None }; match self.tcx().const_eval(param_env.and(cid)) { - Ok(_) => EvaluatedToOk, - Err(_) => EvaluatedToErr + Ok(_) => Ok(EvaluatedToOk), + Err(_) => Ok(EvaluatedToErr) } } else { - EvaluatedToErr + Ok(EvaluatedToErr) } } None => { // Inference variables still left in param_env or substs. - EvaluatedToAmbig + Ok(EvaluatedToAmbig) } } } @@ -726,7 +749,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { fn evaluate_trait_predicate_recursively<'o>(&mut self, previous_stack: TraitObligationStackList<'o, 'tcx>, mut obligation: TraitObligation<'tcx>) - -> EvaluationResult + -> Result> { debug!("evaluate_trait_predicate_recursively({:?})", obligation); @@ -745,22 +768,23 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { debug!("CACHE HIT: EVAL({:?})={:?}", fresh_trait_ref, result); - return result; + return Ok(result); } let (result, dep_node) = self.in_task(|this| this.evaluate_stack(&stack)); + let result = result?; debug!("CACHE MISS: EVAL({:?})={:?}", fresh_trait_ref, result); self.insert_evaluation_cache(obligation.param_env, fresh_trait_ref, dep_node, result); - result + Ok(result) } fn evaluate_stack<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) - -> EvaluationResult + -> Result> { // In intercrate mode, whenever any of the types are unbound, // there can always be an impl. Even if there are no impls in @@ -815,7 +839,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } } } - return EvaluatedToAmbig; + return Ok(EvaluatedToAmbig); } if unbound_input_types && stack.iter().skip(1).any( @@ -825,7 +849,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { { debug!("evaluate_stack({:?}) --> unbound argument, recursive --> giving up", stack.fresh_trait_ref); - return EvaluatedToUnknown; + return Ok(EvaluatedToUnknown); } // If there is any previous entry on the stack that precisely @@ -860,18 +884,19 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { if self.coinductive_match(cycle) { debug!("evaluate_stack({:?}) --> recursive, coinductive", stack.fresh_trait_ref); - return EvaluatedToOk; + return Ok(EvaluatedToOk); } else { debug!("evaluate_stack({:?}) --> recursive, inductive", stack.fresh_trait_ref); - return EvaluatedToRecur; + return Ok(EvaluatedToRecur); } } match self.candidate_from_obligation(stack) { Ok(Some(c)) => self.evaluate_candidate(stack, &c), - Ok(None) => EvaluatedToAmbig, - Err(..) => EvaluatedToErr + Ok(None) => Ok(EvaluatedToAmbig), + Err(Overflow(o)) => Err(OverflowError(o)), + Err(..) => Ok(EvaluatedToErr) } } @@ -909,7 +934,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { fn evaluate_candidate<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>, candidate: &SelectionCandidate<'tcx>) - -> EvaluationResult + -> Result> { debug!("evaluate_candidate: depth={} candidate={:?}", stack.obligation.recursion_depth, candidate); @@ -921,12 +946,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { stack.list(), selection.nested_obligations().iter()) } - Err(..) => EvaluatedToErr + Err(..) => Ok(EvaluatedToErr) } - }); + })?; debug!("evaluate_candidate: depth={} result={:?}", stack.obligation.recursion_depth, result); - result + Ok(result) } fn check_evaluation_cache(&self, @@ -1000,7 +1025,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // not update) the cache. let recursion_limit = *self.infcx.tcx.sess.recursion_limit.get(); if stack.obligation.recursion_depth >= recursion_limit { - self.infcx().report_overflow_error(&stack.obligation, true); + return Err(Overflow(stack.obligation.clone())); } // Check the cache. Note that we skolemize the trait-ref @@ -1081,9 +1106,15 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { debug!("evaluate_stack: intercrate_ambiguity_causes is some"); // Heuristics: show the diagnostics when there are no candidates in crate. if let Ok(candidate_set) = self.assemble_candidates(stack) { - if !candidate_set.ambiguous && candidate_set.vec.iter().all(|c| { - !self.evaluate_candidate(stack, &c).may_apply() - }) { + let no_candidates_apply = + candidate_set + .vec + .iter() + .map(|c| self.evaluate_candidate(stack, &c)) + .collect::, OverflowError<'_>>>()? + .iter() + .all(|r| !r.may_apply()); + if !candidate_set.ambiguous && no_candidates_apply { let trait_ref = stack.obligation.predicate.skip_binder().trait_ref; let self_ty = trait_ref.self_ty(); let trait_desc = trait_ref.to_string(); @@ -1151,18 +1182,21 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } // Winnow, but record the exact outcome of evaluation, which - // is needed for specialization. - let mut candidates: Vec<_> = candidates.into_iter().filter_map(|c| { - let eval = self.evaluate_candidate(stack, &c); - if eval.may_apply() { - Some(EvaluatedCandidate { + // is needed for specialization. Propagate overflow if it occurs. + let candidates: Result>, _> = candidates + .into_iter() + .map(|c| match self.evaluate_candidate(stack, &c) { + Ok(eval) if eval.may_apply() => Ok(Some(EvaluatedCandidate { candidate: c, evaluation: eval, - }) - } else { - None - } - }).collect(); + })), + Ok(_) => Ok(None), + Err(OverflowError(o)) => Err(Overflow(o)), + }) + .collect(); + + let mut candidates: Vec = + candidates?.into_iter().filter_map(|c| c).collect(); // If there are STILL multiple candidate, we can further // reduce the list by dropping duplicates -- including @@ -1537,12 +1571,14 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let matching_bounds = all_bounds.filter(|p| p.def_id() == stack.obligation.predicate.def_id()); - let matching_bounds = - matching_bounds.filter( - |bound| self.evaluate_where_clause(stack, bound.clone()).may_apply()); - - let param_candidates = - matching_bounds.map(|bound| ParamCandidate(bound)); + // keep only those bounds which may apply, and propagate overflow if it occurs + let mut param_candidates = vec![]; + for bound in matching_bounds { + let wc = self.evaluate_where_clause(stack, bound.clone())?; + if wc.may_apply() { + param_candidates.push(ParamCandidate(bound)); + } + } candidates.vec.extend(param_candidates); @@ -1552,14 +1588,14 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { fn evaluate_where_clause<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>, where_clause_trait_ref: ty::PolyTraitRef<'tcx>) - -> EvaluationResult + -> Result> { self.probe(move |this, _| { match this.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) { Ok(obligations) => { this.evaluate_predicates_recursively(stack.list(), obligations.iter()) } - Err(()) => EvaluatedToErr + Err(()) => Ok(EvaluatedToErr) } }) } diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index 1e3e4160de1..c124cd7942a 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -177,6 +177,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::SelectionError<'a> { super::ConstEvalFailure(ref err) => { tcx.lift(err).map(super::ConstEvalFailure) } + super::Overflow(_) => bug!() // FIXME: ape ConstEvalFailure? } } } -- cgit 1.4.1-3-g733a5 From 3ab3a9f50994b6e15de7fe92acf5a196ea6575c9 Mon Sep 17 00:00:00 2001 From: Aravind Gollakota Date: Thu, 8 Mar 2018 18:30:37 -0600 Subject: Create a canonical trait query for `evaluate_obligation` --- src/librustc/dep_graph/dep_node.rs | 4 +- src/librustc/traits/mod.rs | 2 +- src/librustc/traits/query/evaluate_obligation.rs | 54 ++++++++++++++++++++++++ src/librustc/traits/query/mod.rs | 4 ++ src/librustc/traits/select.rs | 33 +++++++++++---- src/librustc/ty/maps/config.rs | 8 +++- src/librustc/ty/maps/keys.rs | 12 +++++- src/librustc/ty/maps/mod.rs | 10 ++++- src/librustc/ty/maps/plumbing.rs | 1 + src/librustc_traits/evaluate_obligation.rs | 40 ++++++++++++++++++ src/librustc_traits/lib.rs | 2 + 11 files changed, 155 insertions(+), 15 deletions(-) create mode 100644 src/librustc/traits/query/evaluate_obligation.rs create mode 100644 src/librustc_traits/evaluate_obligation.rs (limited to 'src') diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 18bf54297af..e4f432e7caf 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -70,7 +70,8 @@ use rustc_data_structures::stable_hasher::{StableHasher, HashStable}; use std::fmt; use std::hash::Hash; use syntax_pos::symbol::InternedString; -use traits::query::{CanonicalProjectionGoal, CanonicalTyGoal}; +use traits::query::{CanonicalProjectionGoal, + CanonicalTyGoal, CanonicalPredicateGoal}; use ty::{TyCtxt, Instance, InstanceDef, ParamEnv, ParamEnvAnd, PolyTraitRef, Ty}; use ty::subst::Substs; @@ -643,6 +644,7 @@ define_dep_nodes!( <'tcx> [] NormalizeProjectionTy(CanonicalProjectionGoal<'tcx>), [] NormalizeTyAfterErasingRegions(ParamEnvAnd<'tcx, Ty<'tcx>>), [] DropckOutlives(CanonicalTyGoal<'tcx>), + [] EvaluateObligation(CanonicalPredicateGoal<'tcx>), [] SubstituteNormalizeAndTestPredicates { key: (DefId, &'tcx Substs<'tcx>) }, diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 6101d37956a..031a3677aa3 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -41,7 +41,7 @@ pub use self::object_safety::ObjectSafetyViolation; pub use self::object_safety::MethodViolationCode; pub use self::on_unimplemented::{OnUnimplementedDirective, OnUnimplementedNote}; pub use self::select::{EvaluationCache, SelectionContext, SelectionCache}; -pub use self::select::IntercrateAmbiguityCause; +pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError}; pub use self::specialize::{OverlapError, specialization_graph, translate_substs}; pub use self::specialize::{SpecializesCache, find_associated_item}; pub use self::engine::TraitEngine; diff --git a/src/librustc/traits/query/evaluate_obligation.rs b/src/librustc/traits/query/evaluate_obligation.rs new file mode 100644 index 00000000000..88c51d006db --- /dev/null +++ b/src/librustc/traits/query/evaluate_obligation.rs @@ -0,0 +1,54 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use infer::InferCtxt; +use infer::canonical::{Canonical, Canonicalize}; +use traits::{EvaluationResult, PredicateObligation}; +use traits::query::CanonicalPredicateGoal; +use ty::{ParamEnvAnd, Predicate, TyCtxt}; + +impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { + /// Evaluates whether the predicate can be satisfied (by any means) + /// in the given `ParamEnv`. + pub fn predicate_may_hold( + &self, + obligation: &PredicateObligation<'tcx>, + ) -> bool { + let (c_pred, _) = + self.canonicalize_query(&obligation.param_env.and(obligation.predicate)); + + self.tcx.global_tcx().evaluate_obligation(c_pred).may_apply() + } + + /// Evaluates whether the predicate can be satisfied in the given + /// `ParamEnv`, and returns `false` if not certain. However, this is + /// not entirely accurate if inference variables are involved. + pub fn predicate_must_hold( + &self, + obligation: &PredicateObligation<'tcx>, + ) -> bool { + let (c_pred, _) = + self.canonicalize_query(&obligation.param_env.and(obligation.predicate)); + + self.tcx.global_tcx().evaluate_obligation(c_pred) == + EvaluationResult::EvaluatedToOk + } +} + +impl<'gcx: 'tcx, 'tcx> Canonicalize<'gcx, 'tcx> for ParamEnvAnd<'tcx, Predicate<'tcx>> { + type Canonicalized = CanonicalPredicateGoal<'gcx>; + + fn intern( + _gcx: TyCtxt<'_, 'gcx, 'gcx>, + value: Canonical<'gcx, Self::Lifted>, + ) -> Self::Canonicalized { + value + } +} diff --git a/src/librustc/traits/query/mod.rs b/src/librustc/traits/query/mod.rs index f1f9256f825..096633ddab2 100644 --- a/src/librustc/traits/query/mod.rs +++ b/src/librustc/traits/query/mod.rs @@ -19,6 +19,7 @@ use infer::canonical::Canonical; use ty::{self, Ty}; pub mod dropck_outlives; +pub mod evaluate_obligation; pub mod normalize; pub mod normalize_erasing_regions; @@ -27,6 +28,9 @@ pub type CanonicalProjectionGoal<'tcx> = pub type CanonicalTyGoal<'tcx> = Canonical<'tcx, ty::ParamEnvAnd<'tcx, Ty<'tcx>>>; +pub type CanonicalPredicateGoal<'tcx> = + Canonical<'tcx, ty::ParamEnvAnd<'tcx, ty::Predicate<'tcx>>>; + #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub struct NoSolution; diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index e65bfa7a72e..3dedfcd357e 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -319,7 +319,7 @@ enum BuiltinImplConditions<'tcx> { /// all the "potential success" candidates can potentially succeed, /// so they are no-ops when unioned with a definite error, and within /// the categories it's easy to see that the unions are correct. -enum EvaluationResult { +pub enum EvaluationResult { /// Evaluation successful EvaluatedToOk, /// Evaluation is known to be ambiguous - it *might* hold for some @@ -385,7 +385,7 @@ enum EvaluationResult { } impl EvaluationResult { - fn may_apply(self) -> bool { + pub fn may_apply(self) -> bool { match self { EvaluatedToOk | EvaluatedToAmbig | @@ -408,10 +408,18 @@ impl EvaluationResult { } } +impl_stable_hash_for!(enum self::EvaluationResult { + EvaluatedToOk, + EvaluatedToAmbig, + EvaluatedToUnknown, + EvaluatedToRecur, + EvaluatedToErr +}); + #[derive(Clone, Debug, PartialEq, Eq)] /// Indicates that trait evaluation caused overflow. Stores the obligation /// that hit the recursion limit. -pub struct OverflowError<'tcx>(TraitObligation<'tcx>); +pub struct OverflowError<'tcx>(pub TraitObligation<'tcx>); impl<'tcx> From> for SelectionError<'tcx> { fn from(OverflowError(o): OverflowError<'tcx>) -> SelectionError<'tcx> { @@ -574,9 +582,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { debug!("evaluate_obligation({:?})", obligation); - match self.probe(|this, _| { - this.evaluate_predicate_recursively(TraitObligationStackList::empty(), obligation) - }) { + match self.evaluate_obligation_recursively(obligation) { Ok(result) => result.may_apply(), Err(OverflowError(o)) => self.infcx().report_overflow_error(&o, true) } @@ -592,14 +598,23 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { debug!("evaluate_obligation_conservatively({:?})", obligation); - match self.probe(|this, _| { - this.evaluate_predicate_recursively(TraitObligationStackList::empty(), obligation) - }) { + match self.evaluate_obligation_recursively(obligation) { Ok(result) => result == EvaluatedToOk, Err(OverflowError(o)) => self.infcx().report_overflow_error(&o, true) } } + /// Evaluates whether the obligation `obligation` can be satisfied and returns + /// an `EvaluationResult`. + pub fn evaluate_obligation_recursively(&mut self, + obligation: &PredicateObligation<'tcx>) + -> Result> + { + self.probe(|this, _| { + this.evaluate_predicate_recursively(TraitObligationStackList::empty(), obligation) + }) + } + /// Evaluates the predicates in `predicates` recursively. Note that /// this applies projections in the predicates, and therefore /// is run within an inference probe. diff --git a/src/librustc/ty/maps/config.rs b/src/librustc/ty/maps/config.rs index 735fe06560f..1fd0632580c 100644 --- a/src/librustc/ty/maps/config.rs +++ b/src/librustc/ty/maps/config.rs @@ -11,7 +11,7 @@ use dep_graph::SerializedDepNodeIndex; use hir::def_id::{CrateNum, DefId, DefIndex}; use mir::interpret::{GlobalId}; -use traits::query::{CanonicalProjectionGoal, CanonicalTyGoal}; +use traits::query::{CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal}; use ty::{self, ParamEnvAnd, Ty, TyCtxt}; use ty::subst::Substs; use ty::maps::queries; @@ -73,6 +73,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::normalize_ty_after_erasing_region } } +impl<'tcx> QueryDescription<'tcx> for queries::evaluate_obligation<'tcx> { + fn describe(_tcx: TyCtxt, goal: CanonicalPredicateGoal<'tcx>) -> String { + format!("evaluating trait selection obligation `{}`", goal.value.value) + } +} + impl<'tcx> QueryDescription<'tcx> for queries::is_copy_raw<'tcx> { fn describe(_tcx: TyCtxt, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> String { format!("computing whether `{}` is `Copy`", env.value) diff --git a/src/librustc/ty/maps/keys.rs b/src/librustc/ty/maps/keys.rs index 72f2cb49abc..da29f23589e 100644 --- a/src/librustc/ty/maps/keys.rs +++ b/src/librustc/ty/maps/keys.rs @@ -11,7 +11,7 @@ //! Defines the set of legal keys that can be used in queries. use hir::def_id::{CrateNum, DefId, LOCAL_CRATE, DefIndex}; -use traits::query::{CanonicalProjectionGoal, CanonicalTyGoal}; +use traits::query::{CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal}; use ty::{self, Ty, TyCtxt}; use ty::subst::Substs; use ty::fast_reject::SimplifiedType; @@ -200,3 +200,13 @@ impl<'tcx> Key for CanonicalTyGoal<'tcx> { DUMMY_SP } } + +impl<'tcx> Key for CanonicalPredicateGoal<'tcx> { + fn map_crate(&self) -> CrateNum { + LOCAL_CRATE + } + + fn default_span(&self, _tcx: TyCtxt) -> Span { + DUMMY_SP + } +} diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index f5cb3643de8..9343eccd38e 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -32,8 +32,9 @@ use mir; use mir::interpret::{GlobalId}; use session::{CompileResult, CrateDisambiguator}; use session::config::OutputFilenames; -use traits::Vtable; -use traits::query::{CanonicalProjectionGoal, CanonicalTyGoal, NoSolution}; +use traits::{self, Vtable}; +use traits::query::{CanonicalPredicateGoal, CanonicalProjectionGoal, + CanonicalTyGoal, NoSolution}; use traits::query::dropck_outlives::{DtorckConstraint, DropckOutlivesResult}; use traits::query::normalize::NormalizationResult; use traits::specialization_graph; @@ -433,6 +434,11 @@ define_maps! { <'tcx> NoSolution, >, + /// Do not call this query directly: invoke `infcx.predicate_may_hold()` or + /// `infcx.predicate_must_hold()` instead. + [] fn evaluate_obligation: + EvaluateObligation(CanonicalPredicateGoal<'tcx>) -> traits::EvaluationResult, + [] fn substitute_normalize_and_test_predicates: substitute_normalize_and_test_predicates_node((DefId, &'tcx Substs<'tcx>)) -> bool, diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index 61a4eb58531..1cde745d4d8 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -977,6 +977,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::NormalizeProjectionTy | DepKind::NormalizeTyAfterErasingRegions | DepKind::DropckOutlives | + DepKind::EvaluateObligation | DepKind::SubstituteNormalizeAndTestPredicates | DepKind::InstanceDefSizeEstimate | DepKind::ProgramClausesForEnv | diff --git a/src/librustc_traits/evaluate_obligation.rs b/src/librustc_traits/evaluate_obligation.rs new file mode 100644 index 00000000000..f43733f4637 --- /dev/null +++ b/src/librustc_traits/evaluate_obligation.rs @@ -0,0 +1,40 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use rustc::traits::{EvaluationResult, Obligation, ObligationCause, + OverflowError, SelectionContext}; +use rustc::traits::query::CanonicalPredicateGoal; +use rustc::ty::{ParamEnvAnd, TyCtxt}; +use syntax::codemap::DUMMY_SP; + +crate fn evaluate_obligation<'tcx>( + tcx: TyCtxt<'_, 'tcx, 'tcx>, + goal: CanonicalPredicateGoal<'tcx>, +) -> EvaluationResult { + tcx.infer_ctxt().enter(|ref infcx| { + let ( + ParamEnvAnd { + param_env, + value: predicate, + }, + _canonical_inference_vars, + ) = infcx.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &goal); + + let mut selcx = SelectionContext::new(&infcx); + let obligation = Obligation::new(ObligationCause::dummy(), param_env, predicate); + + match selcx.evaluate_obligation_recursively(&obligation) { + Ok(result) => result, + Err(OverflowError(o)) => { + infcx.report_overflow_error(&o, true) + } + } + }) +} diff --git a/src/librustc_traits/lib.rs b/src/librustc_traits/lib.rs index 90c870096e1..7f18fac2db5 100644 --- a/src/librustc_traits/lib.rs +++ b/src/librustc_traits/lib.rs @@ -22,6 +22,7 @@ extern crate syntax; extern crate syntax_pos; mod dropck_outlives; +mod evaluate_obligation; mod normalize_projection_ty; mod normalize_erasing_regions; mod util; @@ -38,6 +39,7 @@ pub fn provide(p: &mut Providers) { normalize_erasing_regions::normalize_ty_after_erasing_regions, program_clauses_for: lowering::program_clauses_for, program_clauses_for_env: lowering::program_clauses_for_env, + evaluate_obligation: evaluate_obligation::evaluate_obligation, ..*p }; } -- cgit 1.4.1-3-g733a5 From bc16b8e92a8e7dcf14b9c94b9248b5ad6957b1f4 Mon Sep 17 00:00:00 2001 From: Aravind Gollakota Date: Sun, 8 Apr 2018 01:56:27 -0500 Subject: Port existing callers of `evaluate_obligation` to the new canonical trait query Except the one in coherence, which needs support for intercrate mode. --- src/librustc/traits/coherence.rs | 3 +++ src/librustc/traits/error_reporting.rs | 8 +++----- src/librustc/traits/fulfill.rs | 2 +- src/librustc/traits/mod.rs | 3 +-- src/librustc_typeck/check/autoderef.rs | 4 ++-- src/librustc_typeck/check/method/mod.rs | 3 +-- src/librustc_typeck/check/method/probe.rs | 4 ++-- src/librustc_typeck/check/method/suggest.rs | 4 ++-- src/test/ui/impl-trait/auto-trait-leak.stderr | 2 ++ 9 files changed, 17 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index 31f8af1f968..2e271669ed7 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -155,6 +155,9 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>, predicate: p }) .chain(obligations) .find(|o| !selcx.evaluate_obligation(o)); + // FIXME: the call to `selcx.evaluate_obligation` above should be ported + // to the canonical trait query form, `infcx.predicate_may_hold`, once + // the new system supports intercrate mode (which coherence needs). if let Some(failing_obligation) = opt_failing_obligation { debug!("overlap: obligation unsatisfiable {:?}", failing_obligation); diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 686008cc1ef..98684825d91 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -660,8 +660,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { predicate: ty::Predicate::Trait(predicate), .. obligation.clone() }; - let mut selcx = SelectionContext::new(self); - if selcx.evaluate_obligation(&unit_obligation) { + if self.predicate_may_hold(&unit_obligation) { err.note("the trait is implemented for `()`. \ Possibly this error has been caused by changes to \ Rust's type-inference algorithm \ @@ -877,7 +876,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { .count(); let mut trait_type = trait_ref.self_ty(); - let mut selcx = SelectionContext::new(self); for refs_remaining in 0..refs_number { if let ty::TypeVariants::TyRef(_, ty::TypeAndMut{ ty: t_type, mutbl: _ }) = @@ -891,7 +889,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { obligation.param_env, new_trait_ref.to_predicate()); - if selcx.evaluate_obligation(&new_obligation) { + if self.predicate_may_hold(&new_obligation) { let sp = self.tcx.sess.codemap() .span_take_while(span, |c| c.is_whitespace() || *c == '&'); @@ -1327,7 +1325,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { cleaned_pred.to_predicate() ); - selcx.evaluate_obligation(&obligation) + self.predicate_may_hold(&obligation) }) } diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index 1c091d68a2e..7bd0148b3c4 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -333,7 +333,7 @@ fn process_predicate<'a, 'gcx, 'tcx>( if data.is_global() { // no type variables present, can use evaluation for better caching. // FIXME: consider caching errors too. - if selcx.evaluate_obligation_conservatively(&obligation) { + if selcx.infcx().predicate_must_hold(&obligation) { debug!("selecting trait `{:?}` at depth {} evaluated to holds", data, obligation.recursion_depth); return Ok(Some(vec![])) diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 031a3677aa3..f09981dd8fc 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -552,8 +552,7 @@ pub fn type_known_to_meet_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx predicate: trait_ref.to_predicate(), }; - let result = SelectionContext::new(infcx) - .evaluate_obligation_conservatively(&obligation); + let result = infcx.predicate_must_hold(&obligation); debug!("type_known_to_meet_ty={:?} bound={} => {:?}", ty, infcx.tcx.item_path_str(def_id), result); diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs index a87058d1fa5..3199ff17ae9 100644 --- a/src/librustc_typeck/check/autoderef.rs +++ b/src/librustc_typeck/check/autoderef.rs @@ -120,15 +120,15 @@ impl<'a, 'gcx, 'tcx> Autoderef<'a, 'gcx, 'tcx> { let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id); - let mut selcx = traits::SelectionContext::new(self.fcx); let obligation = traits::Obligation::new(cause.clone(), self.fcx.param_env, trait_ref.to_predicate()); - if !selcx.evaluate_obligation(&obligation) { + if !self.fcx.predicate_may_hold(&obligation) { debug!("overloaded_deref_ty: cannot match obligation"); return None; } + let mut selcx = traits::SelectionContext::new(self.fcx); let normalized = traits::normalize_projection_type(&mut selcx, self.fcx.param_env, ty::ProjectionTy::from_ref_and_name( diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 5f55ee6163b..5f904a9419b 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -277,8 +277,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { poly_trait_ref.to_predicate()); // Now we want to know if this can be matched - let mut selcx = traits::SelectionContext::new(self); - if !selcx.evaluate_obligation(&obligation) { + if !self.predicate_may_hold(&obligation) { debug!("--> Cannot match obligation"); return None; // Cannot be matched, no such method resolution is possible. } diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index b41a6dcf384..476ae680973 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -1173,7 +1173,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { let predicate = trait_ref.to_predicate(); let obligation = traits::Obligation::new(cause.clone(), self.param_env, predicate); - if !selcx.evaluate_obligation(&obligation) { + if !self.predicate_may_hold(&obligation) { if self.probe(|_| self.select_trait_candidate(trait_ref).is_err()) { // This candidate's primary obligation doesn't even // select - don't bother registering anything in @@ -1201,7 +1201,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { // Evaluate those obligations to see if they might possibly hold. for o in candidate_obligations.into_iter().chain(sub_obligations) { let o = self.resolve_type_vars_if_possible(&o); - if !selcx.evaluate_obligation(&o) { + if !self.predicate_may_hold(&o) { result = ProbeResult::NoMatch; if let &ty::Predicate::Trait(ref pred) = &o.predicate { possibly_unsatisfied_predicates.push(pred.skip_binder().trait_ref); diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index d8907866467..2dc7c7fe71a 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -19,7 +19,7 @@ use hir::def::Def; use hir::def_id::{CRATE_DEF_INDEX, DefId}; use middle::lang_items::FnOnceTraitLangItem; use namespace::Namespace; -use rustc::traits::{Obligation, SelectionContext}; +use rustc::traits::Obligation; use util::nodemap::FxHashSet; use syntax::ast; @@ -65,7 +65,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.body_id, self.param_env, poly_trait_ref.to_predicate()); - SelectionContext::new(self).evaluate_obligation(&obligation) + self.predicate_may_hold(&obligation) }) }) } diff --git a/src/test/ui/impl-trait/auto-trait-leak.stderr b/src/test/ui/impl-trait/auto-trait-leak.stderr index 3b20451b102..efa9a58d633 100644 --- a/src/test/ui/impl-trait/auto-trait-leak.stderr +++ b/src/test/ui/impl-trait/auto-trait-leak.stderr @@ -34,6 +34,7 @@ error[E0391]: cycle detected when processing `cycle1` LL | fn cycle1() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ | +note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`... note: ...which requires processing `cycle2::{{impl-Trait}}`... --> $DIR/auto-trait-leak.rs:49:16 | @@ -44,6 +45,7 @@ note: ...which requires processing `cycle2`... | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`... note: ...which requires processing `cycle1::{{impl-Trait}}`... --> $DIR/auto-trait-leak.rs:42:16 | -- cgit 1.4.1-3-g733a5 From 3dd26b8a3ef9e10dd92f1c958e97493dfbd8788d Mon Sep 17 00:00:00 2001 From: Aravind Gollakota Date: Sun, 8 Apr 2018 02:04:46 -0500 Subject: Simplify trait selector's evaluation API slightly --- src/librustc/traits/coherence.rs | 4 ++-- src/librustc/traits/select.rs | 24 ++++-------------------- 2 files changed, 6 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index 2e271669ed7..5a626e7b82c 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -154,8 +154,8 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>, recursion_depth: 0, predicate: p }) .chain(obligations) - .find(|o| !selcx.evaluate_obligation(o)); - // FIXME: the call to `selcx.evaluate_obligation` above should be ported + .find(|o| !selcx.predicate_may_hold_fatal(o)); + // FIXME: the call to `selcx.predicate_may_hold_fatal` above should be ported // to the canonical trait query form, `infcx.predicate_may_hold`, once // the new system supports intercrate mode (which coherence needs). diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 3dedfcd357e..aae21e62051 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -575,11 +575,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // we can be sure it does not. /// Evaluates whether the obligation `obligation` can be satisfied (by any means). - pub fn evaluate_obligation(&mut self, - obligation: &PredicateObligation<'tcx>) - -> bool + pub fn predicate_may_hold_fatal(&mut self, + obligation: &PredicateObligation<'tcx>) + -> bool { - debug!("evaluate_obligation({:?})", + debug!("predicate_may_hold_fatal({:?})", obligation); match self.evaluate_obligation_recursively(obligation) { @@ -588,22 +588,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } } - /// Evaluates whether the obligation `obligation` can be satisfied, - /// and returns `false` if not certain. However, this is not entirely - /// accurate if inference variables are involved. - pub fn evaluate_obligation_conservatively(&mut self, - obligation: &PredicateObligation<'tcx>) - -> bool - { - debug!("evaluate_obligation_conservatively({:?})", - obligation); - - match self.evaluate_obligation_recursively(obligation) { - Ok(result) => result == EvaluatedToOk, - Err(OverflowError(o)) => self.infcx().report_overflow_error(&o, true) - } - } - /// Evaluates whether the obligation `obligation` can be satisfied and returns /// an `EvaluationResult`. pub fn evaluate_obligation_recursively(&mut self, -- cgit 1.4.1-3-g733a5 From e5535fc7ddf73f03c3adf2ea4097a171b2f5587f Mon Sep 17 00:00:00 2001 From: Aravind Gollakota Date: Thu, 19 Apr 2018 02:28:03 -0500 Subject: Introduce trait query mode and use it to set overflow error handling policy in traits::select --- src/librustc/traits/mod.rs | 13 +++++++ src/librustc/traits/select.rs | 56 ++++++++++++++++++++++++------ src/librustc_traits/evaluate_obligation.rs | 4 +-- 3 files changed, 60 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index f09981dd8fc..6a8a000b58a 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -74,6 +74,19 @@ pub enum IntercrateMode { Fixed } +// The mode that trait queries run in +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum TraitQueryMode { + // Standard/un-canonicalized queries get accurate + // spans etc. passed in and hence can do reasonable + // error reporting on their own. + Standard, + // Canonicalized queries get dummy spans and hence + // must generally propagate errors to + // pre-canonicalization callsites. + Canonical, +} + /// An `Obligation` represents some trait reference (e.g. `int:Eq`) for /// which the vtable must be found. The process of finding a vtable is /// called "resolving" the `Obligation`. This process consists of diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index aae21e62051..342b163b2f7 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -17,7 +17,7 @@ use self::EvaluationResult::*; use super::coherence::{self, Conflict}; use super::DerivedObligationCause; -use super::IntercrateMode; +use super::{IntercrateMode, TraitQueryMode}; use super::project; use super::project::{normalize_with_depth, Normalized, ProjectionCacheKey}; use super::{PredicateObligation, TraitObligation, ObligationCause}; @@ -87,7 +87,12 @@ pub struct SelectionContext<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> { /// Controls whether or not to filter out negative impls when selecting. /// This is used in librustdoc to distinguish between the lack of an impl /// and a negative impl - allow_negative_impls: bool + allow_negative_impls: bool, + + /// The mode that trait queries run in, which informs our error handling + /// policy. In essence, canonicalized queries need their errors propagated + /// rather than immediately reported because we do not have accurate spans. + query_mode: TraitQueryMode, } #[derive(Clone, Debug)] @@ -440,6 +445,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { intercrate: None, intercrate_ambiguity_causes: None, allow_negative_impls: false, + query_mode: TraitQueryMode::Standard, } } @@ -452,6 +458,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { intercrate: Some(mode), intercrate_ambiguity_causes: None, allow_negative_impls: false, + query_mode: TraitQueryMode::Standard, } } @@ -464,6 +471,20 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { intercrate: None, intercrate_ambiguity_causes: None, allow_negative_impls, + query_mode: TraitQueryMode::Standard, + } + } + + pub fn with_query_mode(infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>, + query_mode: TraitQueryMode) -> SelectionContext<'cx, 'gcx, 'tcx> { + debug!("with_query_mode({:?})", query_mode); + SelectionContext { + infcx, + freshener: infcx.freshener(), + intercrate: None, + intercrate_ambiguity_causes: None, + allow_negative_impls: false, + query_mode, } } @@ -548,17 +569,20 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let stack = self.push_stack(TraitObligationStackList::empty(), obligation); + // `select` is currently only called in standard query mode + assert!(self.query_mode == TraitQueryMode::Standard); + let candidate = match self.candidate_from_obligation(&stack) { - Err(SelectionError::Overflow(o)) => - self.infcx().report_overflow_error(&o, true), + Err(SelectionError::Overflow(_)) => + bug!("Overflow should be caught earlier in standard query mode"), Err(e) => { return Err(e); }, Ok(None) => { return Ok(None); }, Ok(Some(candidate)) => candidate }; match self.confirm_candidate(obligation, candidate) { - Err(SelectionError::Overflow(o)) => - self.infcx().report_overflow_error(&o, true), + Err(SelectionError::Overflow(_)) => + bug!("Overflow should be caught earlier in standard query mode"), Err(e) => Err(e), Ok(candidate) => Ok(Some(candidate)) } @@ -582,10 +606,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { debug!("predicate_may_hold_fatal({:?})", obligation); - match self.evaluate_obligation_recursively(obligation) { - Ok(result) => result.may_apply(), - Err(OverflowError(o)) => self.infcx().report_overflow_error(&o, true) - } + // This fatal query is a stopgap that should only be used in standard mode, + // where we do not expect overflow to be propagated. + assert!(self.query_mode == TraitQueryMode::Standard); + + self.evaluate_obligation_recursively(obligation) + .expect("Overflow should be caught earlier in standard query mode") + .may_apply() } /// Evaluates whether the obligation `obligation` can be satisfied and returns @@ -1024,7 +1051,14 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // not update) the cache. let recursion_limit = *self.infcx.tcx.sess.recursion_limit.get(); if stack.obligation.recursion_depth >= recursion_limit { - return Err(Overflow(stack.obligation.clone())); + match self.query_mode { + TraitQueryMode::Standard => { + self.infcx().report_overflow_error(&stack.obligation, true); + }, + TraitQueryMode::Canonical => { + return Err(Overflow(stack.obligation.clone())); + }, + } } // Check the cache. Note that we skolemize the trait-ref diff --git a/src/librustc_traits/evaluate_obligation.rs b/src/librustc_traits/evaluate_obligation.rs index f43733f4637..a9cf35c4d70 100644 --- a/src/librustc_traits/evaluate_obligation.rs +++ b/src/librustc_traits/evaluate_obligation.rs @@ -9,7 +9,7 @@ // except according to those terms. use rustc::traits::{EvaluationResult, Obligation, ObligationCause, - OverflowError, SelectionContext}; + OverflowError, SelectionContext, TraitQueryMode}; use rustc::traits::query::CanonicalPredicateGoal; use rustc::ty::{ParamEnvAnd, TyCtxt}; use syntax::codemap::DUMMY_SP; @@ -27,7 +27,7 @@ crate fn evaluate_obligation<'tcx>( _canonical_inference_vars, ) = infcx.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &goal); - let mut selcx = SelectionContext::new(&infcx); + let mut selcx = SelectionContext::with_query_mode(&infcx, TraitQueryMode::Canonical); let obligation = Obligation::new(ObligationCause::dummy(), param_env, predicate); match selcx.evaluate_obligation_recursively(&obligation) { -- cgit 1.4.1-3-g733a5 From 5cb0372160d4c97b967aa46e05ceb850be0cce44 Mon Sep 17 00:00:00 2001 From: Aravind Gollakota Date: Thu, 19 Apr 2018 02:49:21 -0500 Subject: Remove the stored obligation in OverflowError to simplify things We will shortly refactor things so that it is no longer needed --- src/librustc/traits/error_reporting.rs | 2 +- src/librustc/traits/mod.rs | 3 +-- src/librustc/traits/select.rs | 39 +++++++++++++++--------------- src/librustc/traits/structural_impls.rs | 2 +- src/librustc_traits/evaluate_obligation.rs | 4 +-- 5 files changed, 24 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 98684825d91..285d530a38a 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -831,7 +831,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { err.struct_error(self.tcx, span, "constant expression") } - Overflow(_) => { + Overflow => { bug!("overflow should be handled before the `report_selection_error` path"); } }; diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 6a8a000b58a..dd5208e908e 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -362,8 +362,7 @@ pub enum SelectionError<'tcx> { ty::error::TypeError<'tcx>), TraitNotObjectSafe(DefId), ConstEvalFailure(ConstEvalErr<'tcx>), - // upon overflow, stores the obligation that hit the recursion limit - Overflow(TraitObligation<'tcx>), + Overflow, } pub struct FulfillmentError<'tcx> { diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 342b163b2f7..fdf6dcf4bf3 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -421,14 +421,13 @@ impl_stable_hash_for!(enum self::EvaluationResult { EvaluatedToErr }); -#[derive(Clone, Debug, PartialEq, Eq)] -/// Indicates that trait evaluation caused overflow. Stores the obligation -/// that hit the recursion limit. -pub struct OverflowError<'tcx>(pub TraitObligation<'tcx>); +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +/// Indicates that trait evaluation caused overflow. +pub struct OverflowError; -impl<'tcx> From> for SelectionError<'tcx> { - fn from(OverflowError(o): OverflowError<'tcx>) -> SelectionError<'tcx> { - SelectionError::Overflow(o) +impl<'tcx> From for SelectionError<'tcx> { + fn from(OverflowError: OverflowError) -> SelectionError<'tcx> { + SelectionError::Overflow } } @@ -573,7 +572,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { assert!(self.query_mode == TraitQueryMode::Standard); let candidate = match self.candidate_from_obligation(&stack) { - Err(SelectionError::Overflow(_)) => + Err(SelectionError::Overflow) => bug!("Overflow should be caught earlier in standard query mode"), Err(e) => { return Err(e); }, Ok(None) => { return Ok(None); }, @@ -581,7 +580,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { }; match self.confirm_candidate(obligation, candidate) { - Err(SelectionError::Overflow(_)) => + Err(SelectionError::Overflow) => bug!("Overflow should be caught earlier in standard query mode"), Err(e) => Err(e), Ok(candidate) => Ok(Some(candidate)) @@ -619,7 +618,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { /// an `EvaluationResult`. pub fn evaluate_obligation_recursively(&mut self, obligation: &PredicateObligation<'tcx>) - -> Result> + -> Result { self.probe(|this, _| { this.evaluate_predicate_recursively(TraitObligationStackList::empty(), obligation) @@ -632,7 +631,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { fn evaluate_predicates_recursively<'a,'o,I>(&mut self, stack: TraitObligationStackList<'o, 'tcx>, predicates: I) - -> Result> + -> Result where I : IntoIterator>, 'tcx:'a { let mut result = EvaluatedToOk; @@ -654,7 +653,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { fn evaluate_predicate_recursively<'o>(&mut self, previous_stack: TraitObligationStackList<'o, 'tcx>, obligation: &PredicateObligation<'tcx>) - -> Result> + -> Result { debug!("evaluate_predicate_recursively({:?})", obligation); @@ -775,7 +774,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { fn evaluate_trait_predicate_recursively<'o>(&mut self, previous_stack: TraitObligationStackList<'o, 'tcx>, mut obligation: TraitObligation<'tcx>) - -> Result> + -> Result { debug!("evaluate_trait_predicate_recursively({:?})", obligation); @@ -810,7 +809,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { fn evaluate_stack<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) - -> Result> + -> Result { // In intercrate mode, whenever any of the types are unbound, // there can always be an impl. Even if there are no impls in @@ -921,7 +920,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { match self.candidate_from_obligation(stack) { Ok(Some(c)) => self.evaluate_candidate(stack, &c), Ok(None) => Ok(EvaluatedToAmbig), - Err(Overflow(o)) => Err(OverflowError(o)), + Err(Overflow) => Err(OverflowError), Err(..) => Ok(EvaluatedToErr) } } @@ -960,7 +959,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { fn evaluate_candidate<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>, candidate: &SelectionCandidate<'tcx>) - -> Result> + -> Result { debug!("evaluate_candidate: depth={} candidate={:?}", stack.obligation.recursion_depth, candidate); @@ -1056,7 +1055,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { self.infcx().report_overflow_error(&stack.obligation, true); }, TraitQueryMode::Canonical => { - return Err(Overflow(stack.obligation.clone())); + return Err(Overflow); }, } } @@ -1144,7 +1143,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { .vec .iter() .map(|c| self.evaluate_candidate(stack, &c)) - .collect::, OverflowError<'_>>>()? + .collect::, OverflowError>>()? .iter() .all(|r| !r.may_apply()); if !candidate_set.ambiguous && no_candidates_apply { @@ -1224,7 +1223,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { evaluation: eval, })), Ok(_) => Ok(None), - Err(OverflowError(o)) => Err(Overflow(o)), + Err(OverflowError) => Err(Overflow), }) .collect(); @@ -1621,7 +1620,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { fn evaluate_where_clause<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>, where_clause_trait_ref: ty::PolyTraitRef<'tcx>) - -> Result> + -> Result { self.probe(move |this, _| { match this.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) { diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index c124cd7942a..d7e42655bbb 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -177,7 +177,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::SelectionError<'a> { super::ConstEvalFailure(ref err) => { tcx.lift(err).map(super::ConstEvalFailure) } - super::Overflow(_) => bug!() // FIXME: ape ConstEvalFailure? + super::Overflow => bug!() // FIXME: ape ConstEvalFailure? } } } diff --git a/src/librustc_traits/evaluate_obligation.rs b/src/librustc_traits/evaluate_obligation.rs index a9cf35c4d70..f346bb8dc99 100644 --- a/src/librustc_traits/evaluate_obligation.rs +++ b/src/librustc_traits/evaluate_obligation.rs @@ -32,8 +32,8 @@ crate fn evaluate_obligation<'tcx>( match selcx.evaluate_obligation_recursively(&obligation) { Ok(result) => result, - Err(OverflowError(o)) => { - infcx.report_overflow_error(&o, true) + Err(OverflowError) => { + infcx.report_overflow_error(&obligation, true) } } }) -- cgit 1.4.1-3-g733a5 From d5b2e907444cb202407771eee9dd41c2518c1724 Mon Sep 17 00:00:00 2001 From: Aravind Gollakota Date: Thu, 19 Apr 2018 03:15:36 -0500 Subject: Retry canonical trait query in standard mode if overflow occurs This is slightly hacky and hopefully only a somewhat temporary solution. --- src/librustc/traits/query/evaluate_obligation.rs | 32 ++++++++++++++++++------ src/librustc/traits/select.rs | 19 ++++++++------ src/librustc/ty/maps/mod.rs | 5 ++-- src/librustc_traits/evaluate_obligation.rs | 9 ++----- 4 files changed, 41 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/librustc/traits/query/evaluate_obligation.rs b/src/librustc/traits/query/evaluate_obligation.rs index 88c51d006db..4e028cac49a 100644 --- a/src/librustc/traits/query/evaluate_obligation.rs +++ b/src/librustc/traits/query/evaluate_obligation.rs @@ -10,7 +10,8 @@ use infer::InferCtxt; use infer::canonical::{Canonical, Canonicalize}; -use traits::{EvaluationResult, PredicateObligation}; +use traits::{EvaluationResult, PredicateObligation, SelectionContext, + TraitQueryMode, OverflowError}; use traits::query::CanonicalPredicateGoal; use ty::{ParamEnvAnd, Predicate, TyCtxt}; @@ -21,10 +22,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { &self, obligation: &PredicateObligation<'tcx>, ) -> bool { - let (c_pred, _) = - self.canonicalize_query(&obligation.param_env.and(obligation.predicate)); - - self.tcx.global_tcx().evaluate_obligation(c_pred).may_apply() + self.evaluate_obligation(obligation).may_apply() } /// Evaluates whether the predicate can be satisfied in the given @@ -34,11 +32,29 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> { &self, obligation: &PredicateObligation<'tcx>, ) -> bool { + self.evaluate_obligation(obligation) == EvaluationResult::EvaluatedToOk + } + + // Helper function that canonicalizes and runs the query, as well as handles + // overflow. + fn evaluate_obligation( + &self, + obligation: &PredicateObligation<'tcx>, + ) -> EvaluationResult { let (c_pred, _) = self.canonicalize_query(&obligation.param_env.and(obligation.predicate)); - - self.tcx.global_tcx().evaluate_obligation(c_pred) == - EvaluationResult::EvaluatedToOk + // Run canonical query. If overflow occurs, rerun from scratch but this time + // in standard trait query mode so that overflow is handled appropriately + // within `SelectionContext`. + match self.tcx.global_tcx().evaluate_obligation(c_pred) { + Ok(result) => result, + Err(OverflowError) => { + let mut selcx = + SelectionContext::with_query_mode(&self, TraitQueryMode::Standard); + selcx.evaluate_obligation_recursively(obligation) + .expect("Overflow should be caught earlier in standard query mode") + } + } } } diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index fdf6dcf4bf3..4ba3655bb64 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -425,6 +425,8 @@ impl_stable_hash_for!(enum self::EvaluationResult { /// Indicates that trait evaluation caused overflow. pub struct OverflowError; +impl_stable_hash_for!(struct OverflowError { }); + impl<'tcx> From for SelectionError<'tcx> { fn from(OverflowError: OverflowError) -> SelectionError<'tcx> { SelectionError::Overflow @@ -568,20 +570,23 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let stack = self.push_stack(TraitObligationStackList::empty(), obligation); - // `select` is currently only called in standard query mode - assert!(self.query_mode == TraitQueryMode::Standard); - let candidate = match self.candidate_from_obligation(&stack) { - Err(SelectionError::Overflow) => - bug!("Overflow should be caught earlier in standard query mode"), + Err(SelectionError::Overflow) => { + // In standard mode, overflow must have been caught and reported + // earlier. + assert!(self.query_mode == TraitQueryMode::Canonical); + return Err(SelectionError::Overflow); + }, Err(e) => { return Err(e); }, Ok(None) => { return Ok(None); }, Ok(Some(candidate)) => candidate }; match self.confirm_candidate(obligation, candidate) { - Err(SelectionError::Overflow) => - bug!("Overflow should be caught earlier in standard query mode"), + Err(SelectionError::Overflow) => { + assert!(self.query_mode == TraitQueryMode::Canonical); + return Err(SelectionError::Overflow); + }, Err(e) => Err(e), Ok(candidate) => Ok(Some(candidate)) } diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index 9343eccd38e..cb929225bcd 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -436,8 +436,9 @@ define_maps! { <'tcx> /// Do not call this query directly: invoke `infcx.predicate_may_hold()` or /// `infcx.predicate_must_hold()` instead. - [] fn evaluate_obligation: - EvaluateObligation(CanonicalPredicateGoal<'tcx>) -> traits::EvaluationResult, + [] fn evaluate_obligation: EvaluateObligation( + CanonicalPredicateGoal<'tcx> + ) -> Result, [] fn substitute_normalize_and_test_predicates: substitute_normalize_and_test_predicates_node((DefId, &'tcx Substs<'tcx>)) -> bool, diff --git a/src/librustc_traits/evaluate_obligation.rs b/src/librustc_traits/evaluate_obligation.rs index f346bb8dc99..21259bbcd38 100644 --- a/src/librustc_traits/evaluate_obligation.rs +++ b/src/librustc_traits/evaluate_obligation.rs @@ -17,7 +17,7 @@ use syntax::codemap::DUMMY_SP; crate fn evaluate_obligation<'tcx>( tcx: TyCtxt<'_, 'tcx, 'tcx>, goal: CanonicalPredicateGoal<'tcx>, -) -> EvaluationResult { +) -> Result { tcx.infer_ctxt().enter(|ref infcx| { let ( ParamEnvAnd { @@ -30,11 +30,6 @@ crate fn evaluate_obligation<'tcx>( let mut selcx = SelectionContext::with_query_mode(&infcx, TraitQueryMode::Canonical); let obligation = Obligation::new(ObligationCause::dummy(), param_env, predicate); - match selcx.evaluate_obligation_recursively(&obligation) { - Ok(result) => result, - Err(OverflowError) => { - infcx.report_overflow_error(&obligation, true) - } - } + selcx.evaluate_obligation_recursively(&obligation) }) } -- cgit 1.4.1-3-g733a5 From e423dcc7133f20c8da2609dba96afeeab1efbc5a Mon Sep 17 00:00:00 2001 From: Aravind Gollakota Date: Sun, 22 Apr 2018 16:48:38 -0500 Subject: Update a compile-fail test --- src/test/compile-fail/issue-23080-2.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/test/compile-fail/issue-23080-2.rs b/src/test/compile-fail/issue-23080-2.rs index 2aa87f8424b..fc365a4b9aa 100644 --- a/src/test/compile-fail/issue-23080-2.rs +++ b/src/test/compile-fail/issue-23080-2.rs @@ -10,6 +10,8 @@ // ignore-tidy-linelength +//~^^^^^^^^^^^^ ERROR + #![feature(optin_builtin_traits)] unsafe auto trait Trait { @@ -22,5 +24,4 @@ fn call_method(x: T) {} fn main() { // ICE call_method(()); - //~^ ERROR } -- cgit 1.4.1-3-g733a5 From 4d52751d12429f4508f9a3c537521ba1113fabf5 Mon Sep 17 00:00:00 2001 From: John Kåre Alsaker Date: Wed, 11 Apr 2018 23:02:41 +0200 Subject: Rename InternedString to LocalInternedString and introduce a new thread-safe InternedString --- src/librustc/hir/lowering.rs | 4 +- src/librustc/hir/map/def_collector.rs | 33 ++-- src/librustc/hir/map/definitions.rs | 6 +- src/librustc/ich/impls_syntax.rs | 28 +++- src/librustc/lib.rs | 1 + src/librustc/traits/on_unimplemented.rs | 6 +- src/librustc/ty/context.rs | 2 +- src/librustc/ty/item_path.rs | 11 +- src/librustc/ty/maps/values.rs | 2 +- src/librustc/ty/mod.rs | 14 +- src/librustc/ty/sty.rs | 2 +- src/librustc/util/ppaux.rs | 2 +- src/librustc_driver/test.rs | 4 +- src/librustc_incremental/assert_module_sources.rs | 2 +- src/librustc_metadata/cstore_impl.rs | 2 +- src/librustc_metadata/decoder.rs | 16 +- src/librustc_mir/build/expr/into.rs | 2 +- src/librustc_mir/interpret/const_eval.rs | 2 +- src/librustc_mir/monomorphize/item.rs | 2 +- src/librustc_mir/monomorphize/partitioning.rs | 14 +- src/librustc_mir/transform/check_unsafety.rs | 12 +- src/librustc_mir/transform/qualify_consts.rs | 2 +- src/librustc_resolve/build_reduced_graph.rs | 5 +- src/librustc_trans/back/symbol_export.rs | 2 +- src/librustc_trans/base.rs | 2 +- src/librustc_trans/callee.rs | 2 +- src/librustc_trans/common.rs | 6 +- src/librustc_trans/consts.rs | 2 +- src/librustc_trans/context.rs | 6 +- src/librustc_trans/debuginfo/metadata.rs | 2 +- src/librustc_trans/debuginfo/mod.rs | 2 +- src/librustc_trans/debuginfo/namespace.rs | 2 +- src/librustc_trans/debuginfo/type_names.rs | 4 +- src/librustc_trans/intrinsic.rs | 2 +- src/librustc_trans/mir/block.rs | 2 +- src/librustc_trans/trans_item.rs | 2 +- src/librustc_trans_utils/symbol_names.rs | 6 +- src/librustc_typeck/astconv.rs | 4 +- src/librustc_typeck/check/intrinsic.rs | 4 +- src/librustc_typeck/check/mod.rs | 4 +- src/librustc_typeck/check/wfcheck.rs | 2 +- src/librustc_typeck/collect.rs | 18 +- src/librustdoc/clean/auto_trait.rs | 4 +- src/librustdoc/clean/mod.rs | 12 +- src/libsyntax_pos/symbol.rs | 192 ++++++++++++++++++---- 45 files changed, 307 insertions(+), 149 deletions(-) (limited to 'src') diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 4023521147e..f5d590f25c8 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -655,7 +655,7 @@ impl<'a> LoweringContext<'a> { self.resolver.definitions().create_def_with_parent( parent_id.index, def_node_id, - DefPathData::LifetimeDef(str_name), + DefPathData::LifetimeDef(str_name.as_interned_str()), DefIndexAddressSpace::High, Mark::root(), span, @@ -1302,7 +1302,7 @@ impl<'a> LoweringContext<'a> { self.context.resolver.definitions().create_def_with_parent( self.parent, def_node_id, - DefPathData::LifetimeDef(name.name().as_str()), + DefPathData::LifetimeDef(name.name().as_interned_str()), DefIndexAddressSpace::High, Mark::root(), lifetime.span, diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index bfe21549e45..ebd8e623582 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -107,18 +107,18 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { // information we encapsulate into let def_data = match i.node { ItemKind::Impl(..) => DefPathData::Impl, - ItemKind::Trait(..) => DefPathData::Trait(i.ident.name.as_str()), + ItemKind::Trait(..) => DefPathData::Trait(i.ident.name.as_interned_str()), ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) | ItemKind::TraitAlias(..) | ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) => - DefPathData::TypeNs(i.ident.name.as_str()), + DefPathData::TypeNs(i.ident.name.as_interned_str()), ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => { return visit::walk_item(self, i); } - ItemKind::Mod(..) => DefPathData::Module(i.ident.name.as_str()), + ItemKind::Mod(..) => DefPathData::Module(i.ident.name.as_interned_str()), ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) => - DefPathData::ValueNs(i.ident.name.as_str()), - ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.name.as_str()), + DefPathData::ValueNs(i.ident.name.as_interned_str()), + ItemKind::MacroDef(..) => DefPathData::MacroDef(i.ident.name.as_interned_str()), ItemKind::Mac(..) => return self.visit_macro_invoc(i.id, false), ItemKind::GlobalAsm(..) => DefPathData::Misc, ItemKind::Use(..) => { @@ -133,7 +133,8 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { for v in &enum_definition.variants { let variant_def_index = this.create_def(v.node.data.id(), - DefPathData::EnumVariant(v.node.ident.name.as_str()), + DefPathData::EnumVariant(v.node.ident + .name.as_interned_str()), REGULAR_SPACE, v.span); this.with_parent(variant_def_index, |this| { @@ -141,7 +142,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { let name = field.ident.map(|ident| ident.name) .unwrap_or_else(|| Symbol::intern(&index.to_string())); this.create_def(field.id, - DefPathData::Field(name.as_str()), + DefPathData::Field(name.as_interned_str()), REGULAR_SPACE, field.span); } @@ -165,7 +166,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { let name = field.ident.map(|ident| ident.name) .unwrap_or_else(|| Symbol::intern(&index.to_string())); this.create_def(field.id, - DefPathData::Field(name.as_str()), + DefPathData::Field(name.as_interned_str()), REGULAR_SPACE, field.span); } @@ -187,7 +188,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { } let def = self.create_def(foreign_item.id, - DefPathData::ValueNs(foreign_item.ident.name.as_str()), + DefPathData::ValueNs(foreign_item.ident.name.as_interned_str()), REGULAR_SPACE, foreign_item.span); @@ -201,7 +202,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { GenericParam::Lifetime(ref lifetime_def) => { self.create_def( lifetime_def.lifetime.id, - DefPathData::LifetimeDef(lifetime_def.lifetime.ident.name.as_str()), + DefPathData::LifetimeDef(lifetime_def.lifetime.ident.name.as_interned_str()), REGULAR_SPACE, lifetime_def.lifetime.ident.span ); @@ -209,7 +210,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { GenericParam::Type(ref ty_param) => { self.create_def( ty_param.id, - DefPathData::TypeParam(ty_param.ident.name.as_str()), + DefPathData::TypeParam(ty_param.ident.name.as_interned_str()), REGULAR_SPACE, ty_param.ident.span ); @@ -222,8 +223,10 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_trait_item(&mut self, ti: &'a TraitItem) { let def_data = match ti.node { TraitItemKind::Method(..) | TraitItemKind::Const(..) => - DefPathData::ValueNs(ti.ident.name.as_str()), - TraitItemKind::Type(..) => DefPathData::AssocTypeInTrait(ti.ident.name.as_str()), + DefPathData::ValueNs(ti.ident.name.as_interned_str()), + TraitItemKind::Type(..) => { + DefPathData::AssocTypeInTrait(ti.ident.name.as_interned_str()) + }, TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id, false), }; @@ -240,8 +243,8 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_impl_item(&mut self, ii: &'a ImplItem) { let def_data = match ii.node { ImplItemKind::Method(..) | ImplItemKind::Const(..) => - DefPathData::ValueNs(ii.ident.name.as_str()), - ImplItemKind::Type(..) => DefPathData::AssocTypeInImpl(ii.ident.name.as_str()), + DefPathData::ValueNs(ii.ident.name.as_interned_str()), + ImplItemKind::Type(..) => DefPathData::AssocTypeInImpl(ii.ident.name.as_interned_str()), ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id, false), }; diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index 12f146ef491..616dc22486d 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -701,7 +701,7 @@ impl DefPathData { Typeof => "{{typeof}}", }; - Symbol::intern(s).as_str() + Symbol::intern(s).as_interned_str() } pub fn to_string(&self) -> String { @@ -731,7 +731,7 @@ macro_rules! define_global_metadata_kind { definitions.create_def_with_parent( CRATE_DEF_INDEX, ast::DUMMY_NODE_ID, - DefPathData::GlobalMetaData(instance.name().as_str()), + DefPathData::GlobalMetaData(instance.name().as_interned_str()), GLOBAL_MD_ADDRESS_SPACE, Mark::root(), DUMMY_SP @@ -746,7 +746,7 @@ macro_rules! define_global_metadata_kind { let def_key = DefKey { parent: Some(CRATE_DEF_INDEX), disambiguated_data: DisambiguatedDefPathData { - data: DefPathData::GlobalMetaData(self.name().as_str()), + data: DefPathData::GlobalMetaData(self.name().as_interned_str()), disambiguator: 0, } }; diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index d7e16ab3620..c1e86473996 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -19,7 +19,7 @@ use std::mem; use syntax::ast; use syntax::feature_gate; use syntax::parse::token; -use syntax::symbol::InternedString; +use syntax::symbol::{InternedString, LocalInternedString}; use syntax::tokenstream; use syntax_pos::FileMap; @@ -34,8 +34,7 @@ impl<'a> HashStable> for InternedString { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - let s: &str = &**self; - s.hash_stable(hcx, hasher); + self.with(|s| s.hash_stable(hcx, hasher)) } } @@ -50,6 +49,27 @@ impl<'a> ToStableHashKey> for InternedString { } } +impl<'a> HashStable> for LocalInternedString { + #[inline] + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { + let s: &str = &**self; + s.hash_stable(hcx, hasher); + } +} + +impl<'a> ToStableHashKey> for LocalInternedString { + type KeyType = LocalInternedString; + + #[inline] + fn to_stable_hash_key(&self, + _: &StableHashingContext<'a>) + -> LocalInternedString { + self.clone() + } +} + impl<'a> HashStable> for ast::Name { #[inline] fn hash_stable(&self, @@ -66,7 +86,7 @@ impl<'a> ToStableHashKey> for ast::Name { fn to_stable_hash_key(&self, _: &StableHashingContext<'a>) -> InternedString { - self.as_str() + self.as_interned_str() } } diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index f85d0a9bf0c..c2b1d7f0914 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -58,6 +58,7 @@ #![feature(nonzero)] #![feature(proc_macro_internals)] #![feature(quote)] +#![feature(optin_builtin_traits)] #![feature(refcell_replace_swap)] #![feature(rustc_diagnostic_macros)] #![feature(slice_patterns)] diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs index 405dafdff2b..d1fd70ae02d 100644 --- a/src/librustc/traits/on_unimplemented.rs +++ b/src/librustc/traits/on_unimplemented.rs @@ -18,10 +18,10 @@ use util::nodemap::FxHashMap; use syntax::ast::{MetaItem, NestedMetaItem}; use syntax::attr; use syntax_pos::Span; -use syntax_pos::symbol::InternedString; +use syntax_pos::symbol::LocalInternedString; #[derive(Clone, Debug)] -pub struct OnUnimplementedFormatString(InternedString); +pub struct OnUnimplementedFormatString(LocalInternedString); #[derive(Debug)] pub struct OnUnimplementedDirective { @@ -225,7 +225,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedDirective { impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString { pub fn try_parse(tcx: TyCtxt<'a, 'gcx, 'tcx>, trait_def_id: DefId, - from: InternedString, + from: LocalInternedString, err_sp: Span) -> Result { diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 4f49b159ad3..d38c003ef8a 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -2471,7 +2471,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn mk_self_type(self) -> Ty<'tcx> { - self.mk_param(0, keywords::SelfType.name().as_str()) + self.mk_param(0, keywords::SelfType.name().as_interned_str()) } pub fn mk_param_from_def(self, def: &ty::TypeParameterDef) -> Ty<'tcx> { diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 2819141c81b..752b7f69a6a 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -14,7 +14,7 @@ use ty::{self, Ty, TyCtxt}; use middle::cstore::{ExternCrate, ExternCrateSource}; use syntax::ast; use syntax::symbol::Symbol; -use syntax::symbol::InternedString; +use syntax::symbol::LocalInternedString; use std::cell::Cell; @@ -131,7 +131,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { { let visible_parent_map = self.visible_parent_map(LOCAL_CRATE); - let (mut cur_def, mut cur_path) = (external_def_id, Vec::::new()); + let (mut cur_def, mut cur_path) = (external_def_id, Vec::::new()); loop { // If `cur_def` is a direct or injected extern crate, push the path to the crate // followed by the path to the item within the crate and return. @@ -168,8 +168,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } let data = cur_def_key.disambiguated_data.data; - let symbol = - data.get_opt_name().unwrap_or_else(|| Symbol::intern("").as_str()); + let symbol = data.get_opt_name().map(|n| n.as_str()).unwrap_or_else(|| { + Symbol::intern("").as_str() + }); cur_path.push(symbol); match visible_parent_map.get(&cur_def) { @@ -221,7 +222,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { data @ DefPathData::GlobalMetaData(..) => { let parent_def_id = self.parent_def_id(def_id).unwrap(); self.push_item_path(buffer, parent_def_id); - buffer.push(&data.as_interned_str()); + buffer.push(&data.as_interned_str().as_symbol().as_str()); } DefPathData::StructCtor => { // present `X` instead of `X::{{constructor}}` let parent_def_id = self.parent_def_id(def_id).unwrap(); diff --git a/src/librustc/ty/maps/values.rs b/src/librustc/ty/maps/values.rs index 8d38d7dbbbb..d3d06248792 100644 --- a/src/librustc/ty/maps/values.rs +++ b/src/librustc/ty/maps/values.rs @@ -37,7 +37,7 @@ impl<'tcx> Value<'tcx> for Ty<'tcx> { impl<'tcx> Value<'tcx> for ty::SymbolName { fn from_cycle_error<'a>(_: TyCtxt<'a, 'tcx, 'tcx>) -> Self { - ty::SymbolName { name: Symbol::intern("").as_str() } + ty::SymbolName { name: Symbol::intern("").as_interned_str() } } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index de043668410..19532bc80aa 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -51,7 +51,7 @@ use std::mem; use syntax::ast::{self, DUMMY_NODE_ID, Name, Ident, NodeId}; use syntax::attr; use syntax::ext::hygiene::Mark; -use syntax::symbol::{Symbol, InternedString}; +use syntax::symbol::{Symbol, LocalInternedString, InternedString}; use syntax_pos::{DUMMY_SP, Span}; use rustc_data_structures::accumulate_vec::IntoIter as AccIntoIter; @@ -2463,7 +2463,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn item_name(self, id: DefId) -> InternedString { if id.index == CRATE_DEF_INDEX { - self.original_crate_name(id.krate).as_str() + self.original_crate_name(id.krate).as_interned_str() } else { let def_key = self.def_key(id); // The name of a StructCtor is that of its struct parent. @@ -2820,15 +2820,13 @@ impl_stable_hash_for!(struct self::SymbolName { impl SymbolName { pub fn new(name: &str) -> SymbolName { SymbolName { - name: Symbol::intern(name).as_str() + name: Symbol::intern(name).as_interned_str() } } -} - -impl Deref for SymbolName { - type Target = str; - fn deref(&self) -> &str { &self.name } + pub fn as_str(&self) -> LocalInternedString { + self.name.as_str() + } } impl fmt::Display for SymbolName { diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 0dfae13cc75..2220f2b0aaf 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -864,7 +864,7 @@ impl<'a, 'gcx, 'tcx> ParamTy { } pub fn for_self() -> ParamTy { - ParamTy::new(0, keywords::SelfType.name().as_str()) + ParamTy::new(0, keywords::SelfType.name().as_interned_str()) } pub fn for_def(def: &ty::TypeParameterDef) -> ParamTy { diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 905776373bd..b777f513e6d 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -462,7 +462,7 @@ impl PrintContext { 0 => Symbol::intern("'r"), 1 => Symbol::intern("'s"), i => Symbol::intern(&format!("'t{}", i-2)), - }.as_str() + }.as_interned_str() } // Replace any anonymous late-bound regions with named diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 47c49fbe9ef..d2ee3d8743c 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -303,11 +303,11 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { pub fn t_param(&self, index: u32) -> Ty<'tcx> { let name = format!("T{}", index); - self.infcx.tcx.mk_param(index, Symbol::intern(&name).as_str()) + self.infcx.tcx.mk_param(index, Symbol::intern(&name).as_interned_str()) } pub fn re_early_bound(&self, index: u32, name: &'static str) -> ty::Region<'tcx> { - let name = Symbol::intern(name).as_str(); + let name = Symbol::intern(name).as_interned_str(); self.infcx.tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion { def_id: self.infcx.tcx.hir.local_def_id(ast::CRATE_NODE_ID), index, diff --git a/src/librustc_incremental/assert_module_sources.rs b/src/librustc_incremental/assert_module_sources.rs index 46ba94f2061..6906dacfc5e 100644 --- a/src/librustc_incremental/assert_module_sources.rs +++ b/src/librustc_incremental/assert_module_sources.rs @@ -74,7 +74,7 @@ impl<'a, 'tcx> AssertModuleSource<'a, 'tcx> { let mname = self.field(attr, MODULE); let mangled_cgu_name = CodegenUnit::mangle_name(&mname.as_str()); - let mangled_cgu_name = Symbol::intern(&mangled_cgu_name).as_str(); + let mangled_cgu_name = Symbol::intern(&mangled_cgu_name).as_interned_str(); let dep_node = DepNode::new(self.tcx, DepConstructor::CompileCodegenUnit(mangled_cgu_name)); diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index a11b95cb5b6..91f8beeaafb 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -535,7 +535,7 @@ impl CrateStore for cstore::CStore { .insert(local_span, (name.to_string(), data.get_span(id.index, sess))); LoadedMacro::MacroDef(ast::Item { - ident: ast::Ident::from_str(&name), + ident: ast::Ident::from_str(&name.as_str()), id: ast::DUMMY_NODE_ID, span: local_span, attrs: attrs.iter().cloned().collect(), diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 0147e8dc607..388bf1fb99a 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -40,7 +40,7 @@ use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque}; use syntax::attr; use syntax::ast::{self, Ident}; use syntax::codemap; -use syntax::symbol::{InternedString, Symbol}; +use syntax::symbol::InternedString; use syntax::ext::base::MacroKind; use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP, NO_EXPANSION}; @@ -537,12 +537,12 @@ impl<'a, 'tcx> CrateMetadata { ty::VariantDef { did: self.local_def_id(data.struct_ctor.unwrap_or(index)), - name: Symbol::intern(&self.item_name(index)), + name: self.item_name(index).as_symbol(), fields: item.children.decode(self).map(|index| { let f = self.entry(index); ty::FieldDef { did: self.local_def_id(index), - name: Symbol::intern(&self.item_name(index)), + name: self.item_name(index).as_symbol(), vis: f.visibility.decode(self) } }).collect(), @@ -730,7 +730,7 @@ impl<'a, 'tcx> CrateMetadata { if let Some(def) = self.get_def(child_index) { callback(def::Export { def, - ident: Ident::from_str(&self.item_name(child_index)), + ident: Ident::from_interned_str(self.item_name(child_index)), vis: self.get_visibility(child_index), span: self.entry(child_index).span.decode((self, sess)), is_import: false, @@ -748,7 +748,7 @@ impl<'a, 'tcx> CrateMetadata { let span = child.span.decode((self, sess)); if let (Some(def), Some(name)) = (self.get_def(child_index), def_key.disambiguated_data.data.get_opt_name()) { - let ident = Ident::from_str(&name); + let ident = Ident::from_interned_str(name); let vis = self.get_visibility(child_index); let is_import = false; callback(def::Export { def, ident, vis, span, is_import }); @@ -847,7 +847,7 @@ impl<'a, 'tcx> CrateMetadata { }; ty::AssociatedItem { - name: Symbol::intern(&name), + name: name.as_symbol(), kind, vis: item.visibility.decode(self), defaultness: container.defaultness(), @@ -914,7 +914,7 @@ impl<'a, 'tcx> CrateMetadata { self.entry(id) .children .decode(self) - .map(|index| Symbol::intern(&self.item_name(index))) + .map(|index| self.item_name(index).as_symbol()) .collect() } @@ -1106,7 +1106,7 @@ impl<'a, 'tcx> CrateMetadata { DefKey { parent: Some(CRATE_DEF_INDEX), disambiguated_data: DisambiguatedDefPathData { - data: DefPathData::MacroDef(name.as_str()), + data: DefPathData::MacroDef(name.as_interned_str()), disambiguator: 0, } } diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index c130b4f550f..562f890b4c0 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -220,7 +220,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let f = ty.fn_sig(this.hir.tcx()); if f.abi() == Abi::RustIntrinsic || f.abi() == Abi::PlatformIntrinsic { - Some(this.hir.tcx().item_name(def_id)) + Some(this.hir.tcx().item_name(def_id).as_str()) } else { None } diff --git a/src/librustc_mir/interpret/const_eval.rs b/src/librustc_mir/interpret/const_eval.rs index a25331f7279..dff9fa271ab 100644 --- a/src/librustc_mir/interpret/const_eval.rs +++ b/src/librustc_mir/interpret/const_eval.rs @@ -263,7 +263,7 @@ impl<'mir, 'tcx> super::Machine<'mir, 'tcx> for CompileTimeEvaluator { ) -> EvalResult<'tcx> { let substs = instance.substs; - let intrinsic_name = &ecx.tcx.item_name(instance.def_id())[..]; + let intrinsic_name = &ecx.tcx.item_name(instance.def_id()).as_str()[..]; match intrinsic_name { "min_align_of" => { let elem_ty = substs.type_at(0); diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs index 9e0c977a3f0..9e43bed1b63 100644 --- a/src/librustc_mir/monomorphize/item.rs +++ b/src/librustc_mir/monomorphize/item.rs @@ -76,7 +76,7 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug { MonoItem::GlobalAsm(node_id) => { let def_id = tcx.hir.local_def_id(node_id); ty::SymbolName { - name: Symbol::intern(&format!("global_asm_{:?}", def_id)).as_str() + name: Symbol::intern(&format!("global_asm_{:?}", def_id)).as_interned_str() } } } diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index f29f86af4ab..3a65cd4ea77 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -146,7 +146,7 @@ pub trait CodegenUnitExt<'tcx> { } fn work_product_id(&self) -> WorkProductId { - WorkProductId::from_cgu_name(self.name()) + WorkProductId::from_cgu_name(&self.name().as_str()) } fn items_in_deterministic_order<'a>(&self, @@ -206,9 +206,9 @@ fn fallback_cgu_name(tcx: TyCtxt) -> InternedString { const FALLBACK_CODEGEN_UNIT: &'static str = "__rustc_fallback_codegen_unit"; if tcx.sess.opts.debugging_opts.human_readable_cgu_names { - Symbol::intern(FALLBACK_CODEGEN_UNIT).as_str() + Symbol::intern(FALLBACK_CODEGEN_UNIT).as_interned_str() } else { - Symbol::intern(&CodegenUnit::mangle_name(FALLBACK_CODEGEN_UNIT)).as_str() + Symbol::intern(&CodegenUnit::mangle_name(FALLBACK_CODEGEN_UNIT)).as_interned_str() } } @@ -740,7 +740,7 @@ fn compute_codegen_unit_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } }) { cgu_name.push_str("-"); - cgu_name.push_str(&part.data.as_interned_str()); + cgu_name.push_str(&part.data.as_interned_str().as_str()); } if volatile { @@ -753,11 +753,11 @@ fn compute_codegen_unit_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, CodegenUnit::mangle_name(&cgu_name) }; - Symbol::intern(&cgu_name[..]).as_str() + Symbol::intern(&cgu_name[..]).as_interned_str() } fn numbered_codegen_unit_name(crate_name: &str, index: usize) -> InternedString { - Symbol::intern(&format!("{}{}", crate_name, index)).as_str() + Symbol::intern(&format!("{}{}", crate_name, index)).as_interned_str() } fn debug_dump<'a, 'b, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -772,7 +772,7 @@ fn debug_dump<'a, 'b, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, debug!("CodegenUnit {}:", cgu.name()); for (trans_item, linkage) in cgu.items() { - let symbol_name = trans_item.symbol_name(tcx); + let symbol_name = trans_item.symbol_name(tcx).name.as_str(); let symbol_hash_start = symbol_name.rfind('h'); let symbol_hash = symbol_hash_start.map(|i| &symbol_name[i ..]) .unwrap_or(""); diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index 31af7c21857..2bf5a49c97e 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -149,7 +149,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { self.visibility_scope_info[source_info.scope].lint_root; self.register_violations(&[UnsafetyViolation { source_info, - description: Symbol::intern("borrow of packed field").as_str(), + description: Symbol::intern("borrow of packed field").as_interned_str(), kind: UnsafetyViolationKind::BorrowPacked(lint_root) }], &[]); } @@ -214,7 +214,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { self.visibility_scope_info[source_info.scope].lint_root; self.register_violations(&[UnsafetyViolation { source_info, - description: Symbol::intern("use of extern static").as_str(), + description: Symbol::intern("use of extern static").as_interned_str(), kind: UnsafetyViolationKind::ExternStatic(lint_root) }], &[]); } @@ -231,7 +231,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { let source_info = self.source_info; self.register_violations(&[UnsafetyViolation { source_info, - description: Symbol::intern(description).as_str(), + description: Symbol::intern(description).as_interned_str(), kind: UnsafetyViolationKind::General, }], &[]); } @@ -444,7 +444,7 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { struct_span_err!( tcx.sess, source_info.span, E0133, "{} requires unsafe function or block", description) - .span_label(source_info.span, &description[..]) + .span_label(source_info.span, &description.as_str()[..]) .emit(); } UnsafetyViolationKind::ExternStatic(lint_node_id) => { @@ -452,7 +452,7 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { lint_node_id, source_info.span, &format!("{} requires unsafe function or \ - block (error E0133)", &description[..])); + block (error E0133)", &description.as_str()[..])); } UnsafetyViolationKind::BorrowPacked(lint_node_id) => { if let Some(impl_def_id) = builtin_derive_def_id(tcx, def_id) { @@ -462,7 +462,7 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) { lint_node_id, source_info.span, &format!("{} requires unsafe function or \ - block (error E0133)", &description[..])); + block (error E0133)", &description.as_str()[..])); } } } diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index ff7551ed6f4..4762c6aaa27 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -868,7 +868,7 @@ This does not pose a problem by itself because they can't be accessed directly." Abi::RustIntrinsic | Abi::PlatformIntrinsic => { assert!(!self.tcx.is_const_fn(def_id)); - match &self.tcx.item_name(def_id)[..] { + match &self.tcx.item_name(def_id).as_str()[..] { "size_of" | "min_align_of" | "type_id" => is_const_fn = Some(def_id), name if name.starts_with("simd_shuffle") => { diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index f4e2136a5a1..14ceb5f59a3 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -41,7 +41,6 @@ use syntax::ext::tt::macro_rules; use syntax::parse::token::{self, Token}; use syntax::std_inject::injected_crate_name; use syntax::symbol::keywords; -use syntax::symbol::Symbol; use syntax::visit::{self, Visitor}; use syntax_pos::{Span, DUMMY_SP}; @@ -544,14 +543,14 @@ impl<'a> Resolver<'a> { } let (name, parent) = if def_id.index == CRATE_DEF_INDEX { - (self.cstore.crate_name_untracked(def_id.krate).as_str(), None) + (self.cstore.crate_name_untracked(def_id.krate).as_interned_str(), None) } else { let def_key = self.cstore.def_key(def_id); (def_key.disambiguated_data.data.get_opt_name().unwrap(), Some(self.get_module(DefId { index: def_key.parent.unwrap(), ..def_id }))) }; - let kind = ModuleKind::Def(Def::Mod(def_id), Symbol::intern(&name)); + let kind = ModuleKind::Def(Def::Mod(def_id), name.as_symbol()); let module = self.arenas.alloc_module(ModuleData::new(parent, kind, def_id, Mark::root(), DUMMY_SP)); self.extern_module_map.insert((def_id, macros_only), module); diff --git a/src/librustc_trans/back/symbol_export.rs b/src/librustc_trans/back/symbol_export.rs index 965a34eccb8..d8520b61d91 100644 --- a/src/librustc_trans/back/symbol_export.rs +++ b/src/librustc_trans/back/symbol_export.rs @@ -132,7 +132,7 @@ fn reachable_non_generics_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }) .map(|def_id| { let export_level = if special_runtime_crate { - let name = tcx.symbol_name(Instance::mono(tcx, def_id)); + let name = tcx.symbol_name(Instance::mono(tcx, def_id)).as_str(); // We can probably do better here by just ensuring that // it has hidden visibility rather than public // visibility, as this is primarily here to ensure it's diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 2323ec3ef11..b756a6695f9 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -1037,7 +1037,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>( cgus.dedup(); for &(ref cgu_name, (linkage, _)) in cgus.iter() { output.push_str(" "); - output.push_str(&cgu_name); + output.push_str(&cgu_name.as_str()); let linkage_abbrev = match linkage { Linkage::External => "External", diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs index 5849437758a..9263d9a5f5d 100644 --- a/src/librustc_trans/callee.rs +++ b/src/librustc_trans/callee.rs @@ -52,7 +52,7 @@ pub fn get_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, return llfn; } - let sym = tcx.symbol_name(instance); + let sym = tcx.symbol_name(instance).as_str(); debug!("get_fn({:?}: {:?}) => {}", instance, fn_ty, sym); // Create a fn pointer with the substituted signature. diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs index 25ca2152b27..4a0619b2336 100644 --- a/src/librustc_trans/common.rs +++ b/src/librustc_trans/common.rs @@ -33,7 +33,7 @@ use libc::{c_uint, c_char}; use std::iter; use rustc_target::spec::abi::Abi; -use syntax::symbol::InternedString; +use syntax::symbol::LocalInternedString; use syntax_pos::{Span, DUMMY_SP}; pub use context::CodegenCx; @@ -183,7 +183,7 @@ pub fn C_u8(cx: &CodegenCx, i: u8) -> ValueRef { // This is a 'c-like' raw string, which differs from // our boxed-and-length-annotated strings. -pub fn C_cstr(cx: &CodegenCx, s: InternedString, null_terminated: bool) -> ValueRef { +pub fn C_cstr(cx: &CodegenCx, s: LocalInternedString, null_terminated: bool) -> ValueRef { unsafe { if let Some(&llval) = cx.const_cstr_cache.borrow().get(&s) { return llval; @@ -208,7 +208,7 @@ pub fn C_cstr(cx: &CodegenCx, s: InternedString, null_terminated: bool) -> Value // NB: Do not use `do_spill_noroot` to make this into a constant string, or // you will be kicked off fast isel. See issue #4352 for an example of this. -pub fn C_str_slice(cx: &CodegenCx, s: InternedString) -> ValueRef { +pub fn C_str_slice(cx: &CodegenCx, s: LocalInternedString) -> ValueRef { let len = s.len(); let cs = consts::ptrcast(C_cstr(cx, s, false), cx.layout_of(cx.tcx.mk_str()).llvm_type(cx).ptr_to()); diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs index 122b51dbbb7..405cb83ad4d 100644 --- a/src/librustc_trans/consts.rs +++ b/src/librustc_trans/consts.rs @@ -118,7 +118,7 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef { def_id); let ty = instance.ty(cx.tcx); - let sym = cx.tcx.symbol_name(instance); + let sym = cx.tcx.symbol_name(instance).as_str(); let g = if let Some(id) = cx.tcx.hir.as_local_node_id(def_id) { diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 76f8be9ee98..90b2fb4b59a 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -39,7 +39,7 @@ use std::ptr; use std::iter; use std::str; use std::sync::Arc; -use syntax::symbol::InternedString; +use syntax::symbol::LocalInternedString; use abi::Abi; /// There is one `CodegenCx` per compilation unit. Each one has its own LLVM @@ -62,7 +62,7 @@ pub struct CodegenCx<'a, 'tcx: 'a> { pub vtables: RefCell, Option>), ValueRef>>, /// Cache of constant strings, - pub const_cstr_cache: RefCell>, + pub const_cstr_cache: RefCell>, /// Reverse-direction for const ptrs cast from globals. /// Key is a ValueRef holding a *T, @@ -273,7 +273,7 @@ impl<'a, 'tcx> CodegenCx<'a, 'tcx> { let dbg_cx = if tcx.sess.opts.debuginfo != NoDebugInfo { let dctx = debuginfo::CrateDebugContext::new(llmod); debuginfo::metadata::compile_unit_metadata(tcx, - codegen_unit.name(), + &codegen_unit.name().as_str(), &dctx); Some(dctx) } else { diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index 5359e0e0405..123b9cf7931 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -1399,7 +1399,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, (discr.size(cx), discr.align(cx)); let discriminant_base_type_metadata = type_metadata(cx, discr.to_ty(cx.tcx), syntax_pos::DUMMY_SP); - let discriminant_name = get_enum_discriminant_name(cx, enum_def_id); + let discriminant_name = get_enum_discriminant_name(cx, enum_def_id).as_str(); let name = CString::new(discriminant_name.as_bytes()).unwrap(); let discriminant_type_metadata = unsafe { diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs index 706dc3dca8a..193db15303f 100644 --- a/src/librustc_trans/debuginfo/mod.rs +++ b/src/librustc_trans/debuginfo/mod.rs @@ -394,7 +394,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, substs.types().zip(names).map(|(ty, name)| { let actual_type = cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty); let actual_type_metadata = type_metadata(cx, actual_type, syntax_pos::DUMMY_SP); - let name = CString::new(name.as_bytes()).unwrap(); + let name = CString::new(name.as_str().as_bytes()).unwrap(); unsafe { llvm::LLVMRustDIBuilderCreateTemplateTypeParameter( DIB(cx), diff --git a/src/librustc_trans/debuginfo/namespace.rs b/src/librustc_trans/debuginfo/namespace.rs index 891bf649c38..51c45de9dc2 100644 --- a/src/librustc_trans/debuginfo/namespace.rs +++ b/src/librustc_trans/debuginfo/namespace.rs @@ -47,7 +47,7 @@ pub fn item_namespace(cx: &CodegenCx, def_id: DefId) -> DIScope { let namespace_name = match def_key.disambiguated_data.data { DefPathData::CrateRoot => cx.tcx.crate_name(def_id.krate).as_str(), - data => data.as_interned_str() + data => data.as_interned_str().as_str() }; let namespace_name = CString::new(namespace_name.as_bytes()).unwrap(); diff --git a/src/librustc_trans/debuginfo/type_names.rs b/src/librustc_trans/debuginfo/type_names.rs index 96ed4e88471..825fac36c93 100644 --- a/src/librustc_trans/debuginfo/type_names.rs +++ b/src/librustc_trans/debuginfo/type_names.rs @@ -190,10 +190,10 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, output.push_str(&cx.tcx.crate_name(def_id.krate).as_str()); for path_element in cx.tcx.def_path(def_id).data { output.push_str("::"); - output.push_str(&path_element.data.as_interned_str()); + output.push_str(&path_element.data.as_interned_str().as_str()); } } else { - output.push_str(&cx.tcx.item_name(def_id)); + output.push_str(&cx.tcx.item_name(def_id).as_str()); } } diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs index 103b04e6f13..49a207a2d8a 100644 --- a/src/librustc_trans/intrinsic.rs +++ b/src/librustc_trans/intrinsic.rs @@ -103,7 +103,7 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>, let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); let arg_tys = sig.inputs(); let ret_ty = sig.output(); - let name = &*tcx.item_name(def_id); + let name = &*tcx.item_name(def_id).as_str(); let llret_ty = cx.layout_of(ret_ty).llvm_type(cx); let result = PlaceRef::new_sized(llresult, fn_ty.ret.layout, fn_ty.ret.layout.align); diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index 36f03605fea..fb6a17a1c75 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -442,7 +442,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { // Handle intrinsics old trans wants Expr's for, ourselves. let intrinsic = match def { Some(ty::InstanceDef::Intrinsic(def_id)) - => Some(bx.tcx().item_name(def_id)), + => Some(bx.tcx().item_name(def_id).as_str()), _ => None }; let intrinsic = intrinsic.as_ref().map(|s| &s[..]); diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index 06d94e8d155..d19b5af2527 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -88,7 +88,7 @@ pub trait MonoItemExt<'a, 'tcx>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> { self.to_raw_string(), cx.codegen_unit.name()); - let symbol_name = self.symbol_name(cx.tcx); + let symbol_name = self.symbol_name(cx.tcx).as_str(); debug!("symbol {}", &symbol_name); diff --git a/src/librustc_trans_utils/symbol_names.rs b/src/librustc_trans_utils/symbol_names.rs index f3b7326b210..be5bff60805 100644 --- a/src/librustc_trans_utils/symbol_names.rs +++ b/src/librustc_trans_utils/symbol_names.rs @@ -229,7 +229,7 @@ fn def_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) fn symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance<'tcx>) -> ty::SymbolName { - ty::SymbolName { name: Symbol::intern(&compute_symbol_name(tcx, instance)).as_str() } + ty::SymbolName { name: Symbol::intern(&compute_symbol_name(tcx, instance)).as_interned_str() } } fn compute_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance<'tcx>) @@ -355,12 +355,12 @@ impl SymbolPathBuffer { result: String::with_capacity(64), temp_buf: String::with_capacity(16) }; - result.result.push_str(&symbol.name); + result.result.push_str(&symbol.name.as_str()); result } fn into_interned(self) -> ty::SymbolName { - ty::SymbolName { name: Symbol::intern(&self.result).as_str() } + ty::SymbolName { name: Symbol::intern(&self.result).as_interned_str() } } fn finish(mut self, hash: u64) -> String { diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 6cdce127308..93dbba6e873 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -101,7 +101,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { { let tcx = self.tcx(); let lifetime_name = |def_id| { - tcx.hir.name(tcx.hir.as_local_node_id(def_id).unwrap()).as_str() + tcx.hir.name(tcx.hir.as_local_node_id(def_id).unwrap()).as_interned_str() }; let hir_id = tcx.hir.node_to_hir_id(lifetime.id); @@ -981,7 +981,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let item_def_id = tcx.hir.local_def_id(item_id); let generics = tcx.generics_of(item_def_id); let index = generics.type_param_to_index[&tcx.hir.local_def_id(node_id)]; - tcx.mk_param(index, tcx.hir.name(node_id).as_str()) + tcx.mk_param(index, tcx.hir.name(node_id).as_interned_str()) } Def::SelfTy(_, Some(def_id)) => { // Self in impl (we know the concrete type). diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 283fbf8fecc..fcf7541a159 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -76,7 +76,7 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, /// and in libcore/intrinsics.rs pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &hir::ForeignItem) { - let param = |n| tcx.mk_param(n, Symbol::intern(&format!("P{}", n)).as_str()); + let param = |n| tcx.mk_param(n, Symbol::intern(&format!("P{}", n)).as_interned_str()); let name = it.name.as_str(); let (n_tps, inputs, output) = if name.starts_with("atomic_") { let split : Vec<&str> = name.split('_').collect(); @@ -341,7 +341,7 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &hir::ForeignItem) { let param = |n| { - let name = Symbol::intern(&format!("P{}", n)).as_str(); + let name = Symbol::intern(&format!("P{}", n)).as_interned_str(); tcx.mk_param(n, name) }; diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 787df7c6479..db859e42057 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -124,7 +124,7 @@ use syntax::attr; use syntax::codemap::{original_sp, Spanned}; use syntax::feature_gate::{GateIssue, emit_feature_err}; use syntax::ptr::P; -use syntax::symbol::{Symbol, InternedString, keywords}; +use syntax::symbol::{Symbol, LocalInternedString, keywords}; use syntax::util::lev_distance::find_best_match_for_name; use syntax_pos::{self, BytePos, Span, MultiSpan}; @@ -3172,7 +3172,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Return an hint about the closest match in field names fn suggest_field_name(variant: &'tcx ty::VariantDef, field: &Spanned, - skip: Vec) + skip: Vec) -> Option { let name = field.node.as_str(); let names = variant.fields.iter().filter_map(|field| { diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 9c4807bec2f..d0ff44c8e7e 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -655,7 +655,7 @@ fn reject_shadowing_type_parameters(tcx: TyCtxt, def_id: DefId) { // local so it should be okay to just unwrap everything. let trait_def_id = impl_params[&method_param.name]; let trait_decl_span = tcx.def_span(trait_def_id); - error_194(tcx, type_span, trait_decl_span, &method_param.name[..]); + error_194(tcx, type_span, trait_decl_span, &method_param.name.as_str()[..]); } } } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 2ebbd64cab9..1b8f2e661c3 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -244,7 +244,7 @@ fn type_param_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let param_owner_def_id = tcx.hir.local_def_id(param_owner); let generics = tcx.generics_of(param_owner_def_id); let index = generics.type_param_to_index[&def_id]; - let ty = tcx.mk_param(index, tcx.hir.ty_param_name(param_id).as_str()); + let ty = tcx.mk_param(index, tcx.hir.ty_param_name(param_id).as_interned_str()); // Don't look for bounds where the type parameter isn't in scope. let parent = if item_def_id == param_owner_def_id { @@ -842,7 +842,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, opt_self = Some(ty::TypeParameterDef { index: 0, - name: keywords::SelfType.name().as_str(), + name: keywords::SelfType.name().as_interned_str(), def_id: tcx.hir.local_def_id(param_id), has_default: false, object_lifetime_default: rl::Set1::Empty, @@ -888,7 +888,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let early_lifetimes = early_bound_lifetimes_from_generics(tcx, ast_generics); let regions = early_lifetimes.enumerate().map(|(i, l)| { ty::RegionParameterDef { - name: l.lifetime.name.name().as_str(), + name: l.lifetime.name.name().as_interned_str(), index: own_start + i as u32, def_id: tcx.hir.local_def_id(l.lifetime.id), pure_wrt_drop: l.pure_wrt_drop, @@ -918,7 +918,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty::TypeParameterDef { index: type_start + i as u32, - name: p.name.as_str(), + name: p.name.as_interned_str(), def_id: tcx.hir.local_def_id(p.id), has_default: p.default.is_some(), object_lifetime_default: @@ -937,7 +937,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // add a dummy parameter for the closure kind types.push(ty::TypeParameterDef { index: type_start, - name: Symbol::intern("").as_str(), + name: Symbol::intern("").as_interned_str(), def_id, has_default: false, object_lifetime_default: rl::Set1::Empty, @@ -948,7 +948,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // add a dummy parameter for the closure signature types.push(ty::TypeParameterDef { index: type_start + 1, - name: Symbol::intern("").as_str(), + name: Symbol::intern("").as_interned_str(), def_id, has_default: false, object_lifetime_default: rl::Set1::Empty, @@ -959,7 +959,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx.with_freevars(node_id, |fv| { types.extend(fv.iter().zip(2..).map(|(_, i)| ty::TypeParameterDef { index: type_start + i, - name: Symbol::intern("").as_str(), + name: Symbol::intern("").as_interned_str(), def_id, has_default: false, object_lifetime_default: rl::Set1::Empty, @@ -1429,7 +1429,7 @@ pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let region = tcx.mk_region(ty::ReEarlyBound(ty::EarlyBoundRegion { def_id: tcx.hir.local_def_id(param.lifetime.id), index, - name: param.lifetime.name.name().as_str(), + name: param.lifetime.name.name().as_interned_str(), })); index += 1; @@ -1443,7 +1443,7 @@ pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Collect the predicates that were written inline by the user on each // type parameter (e.g., ``). for param in ast_generics.ty_params() { - let param_ty = ty::ParamTy::new(index, param.name.as_str()).to_ty(tcx); + let param_ty = ty::ParamTy::new(index, param.name.as_interned_str()).to_ty(tcx); index += 1; let bounds = compute_bounds(&icx, diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 477b576ad21..221fc4dab72 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -224,7 +224,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { let name = if p.name == "" { hir::LifetimeName::Static } else { - hir::LifetimeName::Name(Symbol::intern(&p.name)) + hir::LifetimeName::Name(p.name.as_symbol()) }; hir::Lifetime { @@ -261,7 +261,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> { span: DUMMY_SP, def: Def::TyParam(param.def_id), segments: HirVec::from_vec(vec![ - hir::PathSegment::from_name(Symbol::intern(¶m.name)) + hir::PathSegment::from_name(param.name.as_symbol()) ]), }), )), diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index fb05cbfe32c..6623d5ab3c2 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1367,7 +1367,7 @@ impl TyParamBound { fn maybe_sized(cx: &DocContext) -> TyParamBound { let did = cx.tcx.require_lang_item(lang_items::SizedTraitLangItem); let empty = cx.tcx.intern_substs(&[]); - let path = external_path(cx, &cx.tcx.item_name(did), + let path = external_path(cx, &cx.tcx.item_name(did).as_str(), Some(did), false, vec![], empty); inline::record_extern_fqn(cx, did, TypeKind::Trait); TraitBound(PolyTrait { @@ -1474,7 +1474,7 @@ impl<'a, 'tcx> Clean for (&'a ty::TraitRef<'tcx>, Vec fn clean(&self, cx: &DocContext) -> TyParamBound { let (trait_ref, ref bounds) = *self; inline::record_extern_fqn(cx, trait_ref.def_id, TypeKind::Trait); - let path = external_path(cx, &cx.tcx.item_name(trait_ref.def_id), + let path = external_path(cx, &cx.tcx.item_name(trait_ref.def_id).as_str(), Some(trait_ref.def_id), true, bounds.clone(), trait_ref.substs); debug!("ty::TraitRef\n subst: {:?}\n", trait_ref.substs); @@ -2801,7 +2801,7 @@ impl<'tcx> Clean for Ty<'tcx> { AdtKind::Enum => TypeKind::Enum, }; inline::record_extern_fqn(cx, did, kind); - let path = external_path(cx, &cx.tcx.item_name(did), + let path = external_path(cx, &cx.tcx.item_name(did).as_str(), None, false, vec![], substs); ResolvedPath { path, @@ -2812,7 +2812,7 @@ impl<'tcx> Clean for Ty<'tcx> { } ty::TyForeign(did) => { inline::record_extern_fqn(cx, did, TypeKind::Foreign); - let path = external_path(cx, &cx.tcx.item_name(did), + let path = external_path(cx, &cx.tcx.item_name(did).as_str(), None, false, vec![], Substs::empty()); ResolvedPath { path: path, @@ -2830,7 +2830,7 @@ impl<'tcx> Clean for Ty<'tcx> { reg.clean(cx).map(|b| typarams.push(RegionBound(b))); for did in obj.auto_traits() { let empty = cx.tcx.intern_substs(&[]); - let path = external_path(cx, &cx.tcx.item_name(did), + let path = external_path(cx, &cx.tcx.item_name(did).as_str(), Some(did), false, vec![], empty); inline::record_extern_fqn(cx, did, TypeKind::Trait); let bound = TraitBound(PolyTrait { @@ -2853,7 +2853,7 @@ impl<'tcx> Clean for Ty<'tcx> { }); } - let path = external_path(cx, &cx.tcx.item_name(did), Some(did), + let path = external_path(cx, &cx.tcx.item_name(did).as_str(), Some(did), false, bindings, principal.skip_binder().substs); ResolvedPath { path, diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 556ee162c6e..4a8b1e8b1c1 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -18,6 +18,7 @@ use {Span, DUMMY_SP, GLOBALS}; use rustc_data_structures::fx::FxHashMap; use serialize::{Decodable, Decoder, Encodable, Encoder}; use std::fmt; +use std::cmp::{PartialEq, Ordering, PartialOrd, Ord}; use std::hash::{Hash, Hasher}; #[derive(Copy, Clone, Eq)] @@ -36,6 +37,11 @@ impl Ident { Ident::new(name, DUMMY_SP) } + /// Maps an interned string to an identifier with an empty syntax context. + pub fn from_interned_str(string: InternedString) -> Ident { + Ident::with_empty_ctxt(string.as_symbol()) + } + /// Maps a string to an identifier with an empty syntax context. pub fn from_str(string: &str) -> Ident { Ident::with_empty_ctxt(Symbol::intern(string)) @@ -138,14 +144,20 @@ impl Symbol { with_interner(|interner| interner.gensymed(self)) } - pub fn as_str(self) -> InternedString { + pub fn as_str(self) -> LocalInternedString { with_interner(|interner| unsafe { - InternedString { + LocalInternedString { string: ::std::mem::transmute::<&str, &str>(interner.get(self)) } }) } + pub fn as_interned_str(self) -> InternedString { + with_interner(|interner| InternedString { + symbol: interner.interned(self) + }) + } + pub fn as_u32(self) -> u32 { self.0 } @@ -365,84 +377,208 @@ fn with_interner T>(f: F) -> T { GLOBALS.with(|globals| f(&mut *globals.symbol_interner.lock())) } -/// Represents a string stored in the thread-local interner. Because the -/// interner lives for the life of the thread, this can be safely treated as an -/// immortal string, as long as it never crosses between threads. -/// -/// FIXME(pcwalton): You must be careful about what you do in the destructors -/// of objects stored in TLS, because they may run after the interner is -/// destroyed. In particular, they must not access string contents. This can -/// be fixed in the future by just leaking all strings until thread death -/// somehow. +/// Represents a string stored in the interner. Because the interner outlives any thread +/// which uses this type, we can safely treat `string` which points to interner data, +/// as an immortal string, as long as this type never crosses between threads. +// FIXME: Ensure that the interner outlives any thread which uses LocalInternedString, +// by creating a new thread right after constructing the interner #[derive(Clone, Copy, Hash, PartialOrd, Eq, Ord)] -pub struct InternedString { +pub struct LocalInternedString { string: &'static str, } -impl ::std::convert::AsRef for InternedString where str: ::std::convert::AsRef { +impl LocalInternedString { + pub fn as_interned_str(self) -> InternedString { + InternedString { + symbol: Symbol::intern(self.string) + } + } +} + +impl ::std::convert::AsRef for LocalInternedString +where + str: ::std::convert::AsRef +{ fn as_ref(&self) -> &U { self.string.as_ref() } } -impl> ::std::cmp::PartialEq for InternedString { +impl> ::std::cmp::PartialEq for LocalInternedString { fn eq(&self, other: &T) -> bool { self.string == other.deref() } } -impl ::std::cmp::PartialEq for str { - fn eq(&self, other: &InternedString) -> bool { +impl ::std::cmp::PartialEq for str { + fn eq(&self, other: &LocalInternedString) -> bool { self == other.string } } -impl<'a> ::std::cmp::PartialEq for &'a str { - fn eq(&self, other: &InternedString) -> bool { +impl<'a> ::std::cmp::PartialEq for &'a str { + fn eq(&self, other: &LocalInternedString) -> bool { *self == other.string } } -impl ::std::cmp::PartialEq for String { - fn eq(&self, other: &InternedString) -> bool { +impl ::std::cmp::PartialEq for String { + fn eq(&self, other: &LocalInternedString) -> bool { self == other.string } } -impl<'a> ::std::cmp::PartialEq for &'a String { - fn eq(&self, other: &InternedString) -> bool { +impl<'a> ::std::cmp::PartialEq for &'a String { + fn eq(&self, other: &LocalInternedString) -> bool { *self == other.string } } -impl !Send for InternedString { } +impl !Send for LocalInternedString {} +impl !Sync for LocalInternedString {} -impl ::std::ops::Deref for InternedString { +impl ::std::ops::Deref for LocalInternedString { type Target = str; fn deref(&self) -> &str { self.string } } -impl fmt::Debug for InternedString { +impl fmt::Debug for LocalInternedString { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(self.string, f) } } -impl fmt::Display for InternedString { +impl fmt::Display for LocalInternedString { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(self.string, f) } } +impl Decodable for LocalInternedString { + fn decode(d: &mut D) -> Result { + Ok(Symbol::intern(&d.read_str()?).as_str()) + } +} + +impl Encodable for LocalInternedString { + fn encode(&self, s: &mut S) -> Result<(), S::Error> { + s.emit_str(self.string) + } +} + +/// Represents a string stored in the string interner +#[derive(Clone, Copy, Eq)] +pub struct InternedString { + symbol: Symbol, +} + +impl InternedString { + pub fn with R, R>(self, f: F) -> R { + let str = with_interner(|interner| { + interner.get(self.symbol) as *const str + }); + // This is safe because the interner keeps string alive until it is dropped. + // We can access it because we know the interner is still alive since we use a + // scoped thread local to access it, and it was alive at the begining of this scope + unsafe { f(&*str) } + } + + pub fn as_symbol(self) -> Symbol { + self.symbol + } + + pub fn as_str(self) -> LocalInternedString { + self.symbol.as_str() + } +} + +impl Hash for InternedString { + fn hash(&self, state: &mut H) { + self.with(|str| str.hash(state)) + } +} + +impl PartialOrd for InternedString { + fn partial_cmp(&self, other: &InternedString) -> Option { + if self.symbol == other.symbol { + return Some(Ordering::Equal); + } + self.with(|self_str| other.with(|other_str| self_str.partial_cmp(&other_str))) + } +} + +impl Ord for InternedString { + fn cmp(&self, other: &InternedString) -> Ordering { + if self.symbol == other.symbol { + return Ordering::Equal; + } + self.with(|self_str| other.with(|other_str| self_str.cmp(&other_str))) + } +} + +impl> PartialEq for InternedString { + fn eq(&self, other: &T) -> bool { + self.with(|string| string == other.deref()) + } +} + +impl PartialEq for InternedString { + fn eq(&self, other: &InternedString) -> bool { + self.symbol == other.symbol + } +} + +impl PartialEq for str { + fn eq(&self, other: &InternedString) -> bool { + other.with(|string| self == string) + } +} + +impl<'a> PartialEq for &'a str { + fn eq(&self, other: &InternedString) -> bool { + other.with(|string| *self == string) + } +} + +impl PartialEq for String { + fn eq(&self, other: &InternedString) -> bool { + other.with(|string| self == string) + } +} + +impl<'a> PartialEq for &'a String { + fn eq(&self, other: &InternedString) -> bool { + other.with(|string| *self == string) + } +} + +impl ::std::convert::From for String { + fn from(val: InternedString) -> String { + val.as_symbol().to_string() + } +} + +impl fmt::Debug for InternedString { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.with(|str| fmt::Debug::fmt(&str, f)) + } +} + +impl fmt::Display for InternedString { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.with(|str| fmt::Display::fmt(&str, f)) + } +} + impl Decodable for InternedString { fn decode(d: &mut D) -> Result { - Ok(Symbol::intern(&d.read_str()?).as_str()) + Ok(Symbol::intern(&d.read_str()?).as_interned_str()) } } impl Encodable for InternedString { fn encode(&self, s: &mut S) -> Result<(), S::Error> { - s.emit_str(self.string) + self.with(|string| s.emit_str(string)) } } -- cgit 1.4.1-3-g733a5 From c122b3a42c5dd57682be353cb9433241f67ab9cb Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Thu, 26 Apr 2018 22:38:39 -0500 Subject: not insta-stable --- src/liballoc/lib.rs | 1 + src/liballoc/vec.rs | 1 + 2 files changed, 2 insertions(+) (limited to 'src') diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 6399be98cd5..c4950786265 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -123,6 +123,7 @@ #![feature(pointer_methods)] #![feature(inclusive_range_fields)] #![cfg_attr(stage0, feature(generic_param_attrs))] +#![feature(rustc_const_unstable)] #![cfg_attr(not(test), feature(fn_traits, i128))] #![cfg_attr(test, feature(test))] diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 1d95f76fd77..415d75664ff 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -322,6 +322,7 @@ impl Vec { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_vec_new")] pub const fn new() -> Vec { Vec { buf: RawVec::empty(), -- cgit 1.4.1-3-g733a5 From 3565556d8bb7c6a662353826cf16df166d11bce6 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 26 Apr 2018 20:50:06 -0700 Subject: Update `parking_lot` dependencies This commit updates `parking_lot` to pull in Amanieu/parking_lot#70 and... Closes #49438 --- src/Cargo.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/Cargo.lock b/src/Cargo.lock index e14b9da9713..a6f78a7e6b4 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1325,16 +1325,16 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parking_lot_core" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1755,8 +1755,8 @@ dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "ena 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-ap-serialize 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1896,8 +1896,8 @@ dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "ena 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_cratesio_shim 0.0.0", "serialize 0.0.0", "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3096,8 +3096,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum openssl-sys 0.9.28 (registry+https://github.com/rust-lang/crates.io-index)" = "0bbd90640b148b46305c1691eed6039b5c8509bed16991e3562a01eeb76902a3" "checksum ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063" "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" -"checksum parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd9d732f2de194336fb02fe11f9eed13d9e76f13f4315b4d88a14ca411750cd" -"checksum parking_lot_core 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "538ef00b7317875071d5e00f603f24d16f0b474c1a5fc0ccb8b454ca72eafa79" +"checksum parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4d05f1349491390b1730afba60bb20d55761bef489a954546b58b4b34e1e2ac" +"checksum parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4db1a8ccf734a7bce794cc19b3df06ed87ab2f3907036b693c68f56b4d4537fa" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum pest 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0fce5d8b5cc33983fc74f78ad552b5522ab41442c4ca91606e4236eb4b5ceefc" "checksum pest_derive 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ab94faafeb93f4c5e3ce81ca0e5a779529a602ad5d09ae6d21996bfb8b6a52bf" -- cgit 1.4.1-3-g733a5 From f0069b848606b3e479aa49461b58b1dce6cd5443 Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Thu, 26 Apr 2018 21:33:05 -0700 Subject: Add a ui test for an incorrect Result success type in a #[test] --- .../termination-trait-test-wrong-type.rs | 20 ++++++++++++++++++++ .../termination-trait-test-wrong-type.stderr | 14 ++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.rs create mode 100644 src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr (limited to 'src') diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.rs b/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.rs new file mode 100644 index 00000000000..1c00edee770 --- /dev/null +++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.rs @@ -0,0 +1,20 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: --test + +#![feature(termination_trait_test)] + +use std::num::ParseIntError; + +#[test] +fn can_parse_zero_as_f32() -> Result { //~ ERROR + "0".parse() +} diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr b/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr new file mode 100644 index 00000000000..8efd8a216f1 --- /dev/null +++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr @@ -0,0 +1,14 @@ +error[E0277]: `main` has invalid return type `std::result::Result` + --> $DIR/termination-trait-test-wrong-type.rs:18:1 + | +LL | / fn can_parse_zero_as_f32() -> Result { //~ ERROR +LL | | "0".parse() +LL | | } + | |_^ `main` can only return types that implement `std::process::Termination` + | + = help: the trait `std::process::Termination` is not implemented for `std::result::Result` + = note: required by `__test::test::assert_test_result` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. -- cgit 1.4.1-3-g733a5 From 4036d2be8aa7323257bcc244ba47a512f2938965 Mon Sep 17 00:00:00 2001 From: John Kåre Alsaker Date: Wed, 18 Apr 2018 04:35:40 +0200 Subject: Create a job immediately when looking in the query map and start it later --- src/librustc/ty/maps/config.rs | 14 +- src/librustc/ty/maps/mod.rs | 1 - src/librustc/ty/maps/on_disk_cache.rs | 8 +- src/librustc/ty/maps/plumbing.rs | 438 ++++++++++++++++------------------ src/librustc_metadata/cstore_impl.rs | 2 +- 5 files changed, 217 insertions(+), 246 deletions(-) (limited to 'src') diff --git a/src/librustc/ty/maps/config.rs b/src/librustc/ty/maps/config.rs index 1fd0632580c..a4c500510ae 100644 --- a/src/librustc/ty/maps/config.rs +++ b/src/librustc/ty/maps/config.rs @@ -15,18 +15,24 @@ use traits::query::{CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTy use ty::{self, ParamEnvAnd, Ty, TyCtxt}; use ty::subst::Substs; use ty::maps::queries; +use ty::maps::Query; +use ty::maps::QueryMap; use std::hash::Hash; use syntax_pos::symbol::InternedString; +use rustc_data_structures::sync::Lock; /// Query configuration and description traits. -pub trait QueryConfig { +pub trait QueryConfig<'tcx> { type Key: Eq + Hash + Clone; - type Value; + type Value: Clone; + + fn query(key: Self::Key) -> Query<'tcx>; + fn query_map<'a>(tcx: TyCtxt<'a, 'tcx, '_>) -> &'a Lock>; } -pub(super) trait QueryDescription<'tcx>: QueryConfig { +pub(super) trait QueryDescription<'tcx>: QueryConfig<'tcx> { fn describe(tcx: TyCtxt, key: Self::Key) -> String; #[inline] @@ -41,7 +47,7 @@ pub(super) trait QueryDescription<'tcx>: QueryConfig { } } -impl<'tcx, M: QueryConfig> QueryDescription<'tcx> for M { +impl<'tcx, M: QueryConfig<'tcx, Key=DefId>> QueryDescription<'tcx> for M { default fn describe(tcx: TyCtxt, def_id: DefId) -> String { if !tcx.sess.verbose() { format!("processing `{}`", tcx.item_path_str(def_id)) diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index cb929225bcd..c931f79e951 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -68,7 +68,6 @@ pub use self::plumbing::force_from_dep_node; mod job; pub use self::job::{QueryJob, QueryInfo}; -use self::job::QueryResult; mod keys; pub use self::keys::Key; diff --git a/src/librustc/ty/maps/on_disk_cache.rs b/src/librustc/ty/maps/on_disk_cache.rs index f88e33c708e..6dfa72a3cf3 100644 --- a/src/librustc/ty/maps/on_disk_cache.rs +++ b/src/librustc/ty/maps/on_disk_cache.rs @@ -239,8 +239,8 @@ impl<'sess> OnDiskCache<'sess> { encode_query_results::(tcx, enc, qri)?; // const eval is special, it only encodes successfully evaluated constants - use ty::maps::plumbing::GetCacheInternal; - for (key, entry) in const_eval::get_cache_internal(tcx).map.iter() { + use ty::maps::QueryConfig; + for (key, entry) in const_eval::query_map(tcx).borrow().map.iter() { use ty::maps::config::QueryDescription; if const_eval::cache_on_disk(key.clone()) { let entry = match *entry { @@ -1124,7 +1124,7 @@ fn encode_query_results<'enc, 'a, 'tcx, Q, E>(tcx: TyCtxt<'a, 'tcx, 'tcx>, encoder: &mut CacheEncoder<'enc, 'a, 'tcx, E>, query_result_index: &mut EncodedQueryResultIndex) -> Result<(), E::Error> - where Q: super::plumbing::GetCacheInternal<'tcx>, + where Q: super::config::QueryDescription<'tcx>, E: 'enc + TyEncoder, Q::Value: Encodable, { @@ -1133,7 +1133,7 @@ fn encode_query_results<'enc, 'a, 'tcx, Q, E>(tcx: TyCtxt<'a, 'tcx, 'tcx>, time(tcx.sess, desc, || { - for (key, entry) in Q::get_cache_internal(tcx).map.iter() { + for (key, entry) in Q::query_map(tcx).borrow().map.iter() { if Q::cache_on_disk(key.clone()) { let entry = match *entry { QueryResult::Complete(ref v) => v, diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index 1cde745d4d8..4fb12be6fb1 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -15,20 +15,26 @@ use dep_graph::{DepNodeIndex, DepNode, DepKind, DepNodeColor}; use errors::DiagnosticBuilder; use errors::Level; +use errors::Diagnostic; +use errors::FatalError; use ty::tls; use ty::{TyCtxt}; use ty::maps::Query; +use ty::maps::config::QueryConfig; use ty::maps::config::QueryDescription; -use ty::maps::job::{QueryResult, QueryInfo}; +use ty::maps::job::{QueryJob, QueryResult, QueryInfo}; use ty::item_path; +use util::common::{profq_msg, ProfileQueriesMsg}; + use rustc_data_structures::fx::{FxHashMap}; -use rustc_data_structures::sync::LockGuard; -use std::marker::PhantomData; +use rustc_data_structures::sync::{Lrc, Lock}; +use std::mem; +use std::ptr; +use std::collections::hash_map::Entry; use syntax_pos::Span; -pub(super) struct QueryMap<'tcx, D: QueryDescription<'tcx>> { - phantom: PhantomData<(D, &'tcx ())>, +pub struct QueryMap<'tcx, D: QueryConfig<'tcx> + ?Sized> { pub(super) map: FxHashMap>>, } @@ -48,18 +54,157 @@ impl QueryValue { } } -impl<'tcx, M: QueryDescription<'tcx>> QueryMap<'tcx, M> { +impl<'tcx, M: QueryConfig<'tcx>> QueryMap<'tcx, M> { pub(super) fn new() -> QueryMap<'tcx, M> { QueryMap { - phantom: PhantomData, map: FxHashMap(), } } } -pub(super) trait GetCacheInternal<'tcx>: QueryDescription<'tcx> + Sized { - fn get_cache_internal<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> LockGuard<'a, QueryMap<'tcx, Self>>; +// If enabled, send a message to the profile-queries thread +macro_rules! profq_msg { + ($tcx:expr, $msg:expr) => { + if cfg!(debug_assertions) { + if $tcx.sess.profile_queries() { + profq_msg($tcx.sess, $msg) + } + } + } +} + +// If enabled, format a key using its debug string, which can be +// expensive to compute (in terms of time). +macro_rules! profq_key { + ($tcx:expr, $key:expr) => { + if cfg!(debug_assertions) { + if $tcx.sess.profile_queries_and_keys() { + Some(format!("{:?}", $key)) + } else { None } + } else { None } + } +} + +/// A type representing the responsibility to execute the job in the `job` field. +/// This will poison the relevant query if dropped. +pub(super) struct JobOwner<'a, 'tcx: 'a, Q: QueryDescription<'tcx> + 'a> { + map: &'a Lock>, + key: Q::Key, + job: Lrc>, +} + +impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { + /// Either gets a JobOwner corresponding the the query, allowing us to + /// start executing the query, or it returns with the result of the query. + /// If the query is executing elsewhere, this will wait for it. + /// If the query panicked, this will silently panic. + pub(super) fn try_get( + tcx: TyCtxt<'a, 'tcx, '_>, + span: Span, + key: &Q::Key, + ) -> TryGetJob<'a, 'tcx, Q> { + let map = Q::query_map(tcx); + loop { + let mut lock = map.borrow_mut(); + let job = match lock.map.entry((*key).clone()) { + Entry::Occupied(entry) => { + match *entry.get() { + QueryResult::Started(ref job) => job.clone(), + QueryResult::Complete(ref value) => { + profq_msg!(tcx, ProfileQueriesMsg::CacheHit); + let result = Ok((value.value.clone(), value.index)); + return TryGetJob::JobCompleted(result); + }, + QueryResult::Poisoned => FatalError.raise(), + } + } + Entry::Vacant(entry) => { + // No job entry for this query. Return a new one to be started later + return tls::with_related_context(tcx, |icx| { + let info = QueryInfo { + span, + query: Q::query(key.clone()), + }; + let job = Lrc::new(QueryJob::new(info, icx.query.clone())); + let owner = JobOwner { + map, + job: job.clone(), + key: (*key).clone(), + }; + entry.insert(QueryResult::Started(job)); + TryGetJob::NotYetStarted(owner) + }) + } + }; + mem::drop(lock); + + if let Err(cycle) = job.await(tcx, span) { + return TryGetJob::JobCompleted(Err(cycle)); + } + } + } + + /// Completes the query by updating the query map with the `result`, + /// signals the waiter and forgets the JobOwner, so it won't poison the query + pub(super) fn complete(self, result: &Q::Value, dep_node_index: DepNodeIndex) { + // We can move out of `self` here because we `mem::forget` it below + let key = unsafe { ptr::read(&self.key) }; + let job = unsafe { ptr::read(&self.job) }; + let map = self.map; + + // Forget ourself so our destructor won't poison the query + mem::forget(self); + + let value = QueryValue::new(result.clone(), dep_node_index); + map.borrow_mut().map.insert(key, QueryResult::Complete(value)); + + job.signal_complete(); + } + + /// Executes a job by changing the ImplicitCtxt to point to the + /// new query job while it executes. It returns the diagnostics + /// captured during execution and the actual result. + pub(super) fn start<'lcx, F, R>( + &self, + tcx: TyCtxt<'_, 'tcx, 'lcx>, + compute: F) + -> (R, Vec) + where + F: for<'b> FnOnce(TyCtxt<'b, 'tcx, 'lcx>) -> R + { + // The TyCtxt stored in TLS has the same global interner lifetime + // as `tcx`, so we use `with_related_context` to relate the 'gcx lifetimes + // when accessing the ImplicitCtxt + let r = tls::with_related_context(tcx, move |icx| { + // Update the ImplicitCtxt to point to our new query job + let icx = tls::ImplicitCtxt { + tcx, + query: Some(self.job.clone()), + layout_depth: icx.layout_depth, + task: icx.task, + }; + + // Use the ImplicitCtxt while we execute the query + tls::enter_context(&icx, |icx| { + compute(icx.tcx) + }) + }); + + // Extract the diagnostic from the job + let diagnostics = mem::replace(&mut *self.job.diagnostics.lock(), Vec::new()); + + (r, diagnostics) + } +} + +impl<'a, 'tcx, Q: QueryDescription<'tcx>> Drop for JobOwner<'a, 'tcx, Q> { + fn drop(&mut self) { + // Poison the query so jobs waiting on it panic + self.map.borrow_mut().map.insert(self.key.clone(), QueryResult::Poisoned); + // Also signal the completion of the job, so waiters + // will continue execution + self.job.signal_complete(); + } } #[derive(Clone)] @@ -70,14 +215,14 @@ pub(super) struct CycleError<'tcx> { } /// The result of `try_get_lock` -pub(super) enum TryGetLock<'a, 'tcx: 'a, T, D: QueryDescription<'tcx> + 'a> { +pub(super) enum TryGetJob<'a, 'tcx: 'a, D: QueryDescription<'tcx> + 'a> { /// The query is not yet started. Contains a guard to the map eventually used to start it. - NotYetStarted(LockGuard<'a, QueryMap<'tcx, D>>), + NotYetStarted(JobOwner<'a, 'tcx, D>), /// The query was already completed. /// Returns the result of the query and its dep node index /// if it succeeded or a cycle error if it failed - JobCompleted(Result<(T, DepNodeIndex), CycleError<'tcx>>), + JobCompleted(Result<(D::Value, DepNodeIndex), CycleError<'tcx>>), } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { @@ -182,29 +327,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } -// If enabled, send a message to the profile-queries thread -macro_rules! profq_msg { - ($tcx:expr, $msg:expr) => { - if cfg!(debug_assertions) { - if $tcx.sess.profile_queries() { - profq_msg($tcx.sess, $msg) - } - } - } -} - -// If enabled, format a key using its debug string, which can be -// expensive to compute (in terms of time). -macro_rules! profq_key { - ($tcx:expr, $key:expr) => { - if cfg!(debug_assertions) { - if $tcx.sess.profile_queries_and_keys() { - Some(format!("{:?}", $key)) - } else { None } - } else { None } - } -} - macro_rules! handle_cycle_error { ([][$this: expr]) => {{ Value::from_cycle_error($this.global_tcx()) @@ -224,11 +346,7 @@ macro_rules! define_maps { [$($modifiers:tt)*] fn $name:ident: $node:ident($K:ty) -> $V:ty,)*) => { use dep_graph::DepNodeIndex; - use std::mem; - use errors::Diagnostic; - use errors::FatalError; - use rustc_data_structures::sync::{Lock, LockGuard}; - use rustc_data_structures::OnDrop; + use rustc_data_structures::sync::Lock; define_map_struct! { tcx: $tcx, @@ -303,15 +421,16 @@ macro_rules! define_maps { })* } - $(impl<$tcx> QueryConfig for queries::$name<$tcx> { + $(impl<$tcx> QueryConfig<$tcx> for queries::$name<$tcx> { type Key = $K; type Value = $V; - } - impl<$tcx> GetCacheInternal<$tcx> for queries::$name<$tcx> { - fn get_cache_internal<'a>(tcx: TyCtxt<'a, $tcx, $tcx>) - -> LockGuard<'a, QueryMap<$tcx, Self>> { - tcx.maps.$name.borrow() + fn query(key: Self::Key) -> Query<'tcx> { + Query::$name(key) + } + + fn query_map<'a>(tcx: TyCtxt<'a, $tcx, '_>) -> &'a Lock> { + &tcx.maps.$name } } @@ -324,43 +443,6 @@ macro_rules! define_maps { DepNode::new(tcx, $node(*key)) } - /// Either get the lock of the query map, allowing us to - /// start executing the query, or it returns with the result of the query. - /// If the query already executed and panicked, this will fatal error / silently panic - fn try_get_lock( - tcx: TyCtxt<'a, $tcx, 'lcx>, - span: Span, - key: &$K - ) -> TryGetLock<'a, $tcx, $V, Self> - { - loop { - let lock = tcx.maps.$name.borrow_mut(); - let job = if let Some(value) = lock.map.get(key) { - match *value { - QueryResult::Started(ref job) => Some(job.clone()), - QueryResult::Complete(ref value) => { - profq_msg!(tcx, ProfileQueriesMsg::CacheHit); - let result = Ok(((&value.value).clone(), value.index)); - return TryGetLock::JobCompleted(result); - }, - QueryResult::Poisoned => FatalError.raise(), - } - } else { - None - }; - let job = if let Some(job) = job { - job - } else { - return TryGetLock::NotYetStarted(lock); - }; - mem::drop(lock); - - if let Err(cycle) = job.await(tcx, span) { - return TryGetLock::JobCompleted(Err(cycle)); - } - } - } - fn try_get_with(tcx: TyCtxt<'a, $tcx, 'lcx>, span: Span, key: $K) @@ -378,29 +460,21 @@ macro_rules! define_maps { ) ); - /// Get the lock used to start the query or - /// return the result of the completed query - macro_rules! get_lock_or_return { - () => {{ - match Self::try_get_lock(tcx, span, &key) { - TryGetLock::NotYetStarted(lock) => lock, - TryGetLock::JobCompleted(result) => { - return result.map(|(v, index)| { - tcx.dep_graph.read_index(index); - v - }) - } - } - }} - } - - let mut lock = get_lock_or_return!(); + let job = match JobOwner::try_get(tcx, span, &key) { + TryGetJob::NotYetStarted(job) => job, + TryGetJob::JobCompleted(result) => { + return result.map(|(v, index)| { + tcx.dep_graph.read_index(index); + v + }) + } + }; // Fast path for when incr. comp. is off. `to_dep_node` is // expensive for some DepKinds. if !tcx.dep_graph.is_fully_enabled() { let null_dep_node = DepNode::new_no_params(::dep_graph::DepKind::Null); - return Self::force_with_lock(tcx, key, span, lock, null_dep_node) + return Self::force_with_job(tcx, key, job, null_dep_node) .map(|(v, _)| v); } @@ -409,48 +483,37 @@ macro_rules! define_maps { if dep_node.kind.is_anon() { profq_msg!(tcx, ProfileQueriesMsg::ProviderBegin); - let res = Self::start_job(tcx, span, key, lock, |tcx| { + let res = job.start(tcx, |tcx| { tcx.dep_graph.with_anon_task(dep_node.kind, || { Self::compute_result(tcx.global_tcx(), key) }) - })?; + }); profq_msg!(tcx, ProfileQueriesMsg::ProviderEnd); - let (((result, dep_node_index), diagnostics), job) = res; + let ((result, dep_node_index), diagnostics) = res; tcx.dep_graph.read_index(dep_node_index); tcx.on_disk_query_result_cache .store_diagnostics_for_anon_node(dep_node_index, diagnostics); - let value = QueryValue::new(Clone::clone(&result), dep_node_index); - - tcx.maps - .$name - .borrow_mut() - .map - .insert(key, QueryResult::Complete(value)); - - job.signal_complete(); + job.complete(&result, dep_node_index); return Ok(result); } if !dep_node.kind.is_input() { - // try_mark_green_and_read may force queries. So we must drop our lock here - mem::drop(lock); if let Some(dep_node_index) = tcx.try_mark_green_and_read(&dep_node) { profq_msg!(tcx, ProfileQueriesMsg::CacheHit); return Self::load_from_disk_and_cache_in_memory(tcx, key, - span, + job, dep_node_index, &dep_node) } - lock = get_lock_or_return!(); } - match Self::force_with_lock(tcx, key, span, lock, dep_node) { + match Self::force_with_job(tcx, key, job, dep_node) { Ok((result, dep_node_index)) => { tcx.dep_graph.read_index(dep_node_index); Ok(result) @@ -483,75 +546,6 @@ macro_rules! define_maps { } } - /// Creates a job for the query and updates the query map indicating that it started. - /// Then it changes ImplicitCtxt to point to the new query job while it executes. - /// If the query panics, this updates the query map to indicate so. - fn start_job(tcx: TyCtxt<'_, $tcx, 'lcx>, - span: Span, - key: $K, - mut map: LockGuard<'_, QueryMap<$tcx, Self>>, - compute: F) - -> Result<((R, Vec), Lrc>), CycleError<$tcx>> - where F: for<'b> FnOnce(TyCtxt<'b, $tcx, 'lcx>) -> R - { - let query = Query::$name(Clone::clone(&key)); - - let entry = QueryInfo { - span, - query, - }; - - // The TyCtxt stored in TLS has the same global interner lifetime - // as `tcx`, so we use `with_related_context` to relate the 'gcx lifetimes - // when accessing the ImplicitCtxt - let (r, job) = ty::tls::with_related_context(tcx, move |icx| { - let job = Lrc::new(QueryJob::new(entry, icx.query.clone())); - - // Store the job in the query map and drop the lock to allow - // others to wait it - map.map.entry(key).or_insert(QueryResult::Started(job.clone())); - mem::drop(map); - - let r = { - let on_drop = OnDrop(|| { - // Poison the query so jobs waiting on it panic - tcx.maps - .$name - .borrow_mut() - .map - .insert(key, QueryResult::Poisoned); - // Also signal the completion of the job, so waiters - // will continue execution - job.signal_complete(); - }); - - // Update the ImplicitCtxt to point to our new query job - let icx = ty::tls::ImplicitCtxt { - tcx, - query: Some(job.clone()), - layout_depth: icx.layout_depth, - task: icx.task, - }; - - // Use the ImplicitCtxt while we execute the query - let r = ty::tls::enter_context(&icx, |icx| { - compute(icx.tcx) - }); - - mem::forget(on_drop); - - r - }; - - (r, job) - }); - - // Extract the diagnostic from the job - let diagnostics: Vec<_> = mem::replace(&mut *job.diagnostics.lock(), Vec::new()); - - Ok(((r, diagnostics), job)) - } - fn compute_result(tcx: TyCtxt<'a, $tcx, 'lcx>, key: $K) -> $V { let provider = tcx.maps.providers[key.map_crate()].$name; provider(tcx.global_tcx(), key) @@ -559,7 +553,7 @@ macro_rules! define_maps { fn load_from_disk_and_cache_in_memory(tcx: TyCtxt<'a, $tcx, 'lcx>, key: $K, - span: Span, + job: JobOwner<'a, $tcx, Self>, dep_node_index: DepNodeIndex, dep_node: &DepNode) -> Result<$V, CycleError<$tcx>> @@ -589,8 +583,8 @@ macro_rules! define_maps { None }; - let (result, job) = if let Some(result) = result { - (result, None) + let result = if let Some(result) = result { + result } else { // We could not load a result from the on-disk cache, so // recompute. @@ -598,18 +592,14 @@ macro_rules! define_maps { // The diagnostics for this query have already been // promoted to the current session during // try_mark_green(), so we can ignore them here. - let ((result, _), job) = Self::start_job(tcx, - span, - key, - tcx.maps.$name.borrow_mut(), - |tcx| { + let (result, _) = job.start(tcx, |tcx| { // The dep-graph for this computation is already in // place tcx.dep_graph.with_ignore(|| { Self::compute_result(tcx, key) }) - })?; - (result, Some(job)) + }); + result }; // If -Zincremental-verify-ich is specified, re-hash results from @@ -642,15 +632,7 @@ macro_rules! define_maps { tcx.dep_graph.mark_loaded_from_cache(dep_node_index, true); } - let value = QueryValue::new(Clone::clone(&result), dep_node_index); - - tcx.maps - .$name - .borrow_mut() - .map - .insert(key, QueryResult::Complete(value)); - - job.map(|j| j.signal_complete()); + job.complete(&result, dep_node_index); Ok(result) } @@ -663,21 +645,19 @@ macro_rules! define_maps { -> Result<($V, DepNodeIndex), CycleError<$tcx>> { // We may be concurrently trying both execute and force a query // Ensure that only one of them runs the query - let lock = match Self::try_get_lock(tcx, span, &key) { - TryGetLock::NotYetStarted(lock) => lock, - TryGetLock::JobCompleted(result) => return result, + let job = match JobOwner::try_get(tcx, span, &key) { + TryGetJob::NotYetStarted(job) => job, + TryGetJob::JobCompleted(result) => return result, }; - Self::force_with_lock(tcx, - key, - span, - lock, - dep_node) + Self::force_with_job(tcx, + key, + job, + dep_node) } - fn force_with_lock(tcx: TyCtxt<'a, $tcx, 'lcx>, + fn force_with_job(tcx: TyCtxt<'a, $tcx, 'lcx>, key: $K, - span: Span, - map: LockGuard<'_, QueryMap<$tcx, Self>>, + job: JobOwner<'_, $tcx, Self>, dep_node: DepNode) -> Result<($V, DepNodeIndex), CycleError<$tcx>> { // If the following assertion triggers, it can have two reasons: @@ -692,11 +672,7 @@ macro_rules! define_maps { key, dep_node); profq_msg!(tcx, ProfileQueriesMsg::ProviderBegin); - let res = Self::start_job(tcx, - span, - key, - map, - |tcx| { + let res = job.start(tcx, |tcx| { if dep_node.kind.is_eval_always() { tcx.dep_graph.with_eval_always_task(dep_node, tcx, @@ -708,10 +684,10 @@ macro_rules! define_maps { key, Self::compute_result) } - })?; + }); profq_msg!(tcx, ProfileQueriesMsg::ProviderEnd); - let (((result, dep_node_index), diagnostics), job) = res; + let ((result, dep_node_index), diagnostics) = res; if tcx.sess.opts.debugging_opts.query_dep_graph { tcx.dep_graph.mark_loaded_from_cache(dep_node_index, false); @@ -722,17 +698,7 @@ macro_rules! define_maps { .store_diagnostics(dep_node_index, diagnostics); } - let value = QueryValue::new(Clone::clone(&result), dep_node_index); - - tcx.maps - .$name - .borrow_mut() - .map - .insert(key, QueryResult::Complete(value)); - - let job: Lrc = job; - - job.signal_complete(); + job.complete(&result, dep_node_index); Ok((result, dep_node_index)) } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index a11b95cb5b6..81812f9a1f3 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -51,7 +51,7 @@ macro_rules! provide { pub fn provide_extern<$lt>(providers: &mut Providers<$lt>) { $(fn $name<'a, $lt:$lt, T>($tcx: TyCtxt<'a, $lt, $lt>, def_id_arg: T) -> as - QueryConfig>::Value + QueryConfig<$lt>>::Value where T: IntoArgs, { #[allow(unused_variables)] -- cgit 1.4.1-3-g733a5 From 987631d3ba57f9fdfe54f3feed03127c7e6d5c5c Mon Sep 17 00:00:00 2001 From: John Kåre Alsaker Date: Thu, 19 Apr 2018 02:33:24 +0200 Subject: Move query functions out from the define_maps! macro --- src/librustc/ty/maps/config.rs | 18 +- src/librustc/ty/maps/mod.rs | 3 +- src/librustc/ty/maps/plumbing.rs | 590 ++++++++++++++++++----------------- src/librustc/ty/mod.rs | 2 +- src/librustc/ty/util.rs | 2 +- src/librustc/util/common.rs | 8 +- src/librustc_driver/profile/trace.rs | 2 +- src/librustc_mir/transform/inline.rs | 2 +- 8 files changed, 327 insertions(+), 300 deletions(-) (limited to 'src') diff --git a/src/librustc/ty/maps/config.rs b/src/librustc/ty/maps/config.rs index a4c500510ae..2f6e7ade89f 100644 --- a/src/librustc/ty/maps/config.rs +++ b/src/librustc/ty/maps/config.rs @@ -9,6 +9,7 @@ // except according to those terms. use dep_graph::SerializedDepNodeIndex; +use dep_graph::DepNode; use hir::def_id::{CrateNum, DefId, DefIndex}; use mir::interpret::{GlobalId}; use traits::query::{CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal}; @@ -19,20 +20,31 @@ use ty::maps::Query; use ty::maps::QueryMap; use std::hash::Hash; +use std::fmt::Debug; use syntax_pos::symbol::InternedString; use rustc_data_structures::sync::Lock; +use rustc_data_structures::stable_hasher::HashStable; +use ich::StableHashingContext; /// Query configuration and description traits. pub trait QueryConfig<'tcx> { - type Key: Eq + Hash + Clone; - type Value: Clone; + const NAME: &'static str; + + type Key: Eq + Hash + Clone + Debug; + type Value: Clone + for<'a> HashStable>; fn query(key: Self::Key) -> Query<'tcx>; fn query_map<'a>(tcx: TyCtxt<'a, 'tcx, '_>) -> &'a Lock>; + + fn to_dep_node(tcx: TyCtxt<'_, 'tcx, '_>, key: &Self::Key) -> DepNode; + + fn compute(tcx: TyCtxt<'_, 'tcx, '_>, key: Self::Key) -> Self::Value; + + fn handle_cycle_error(tcx: TyCtxt<'_, 'tcx, '_>) -> Self::Value; } -pub(super) trait QueryDescription<'tcx>: QueryConfig<'tcx> { +pub trait QueryDescription<'tcx>: QueryConfig<'tcx> { fn describe(tcx: TyCtxt, key: Self::Key) -> String; #[inline] diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index c931f79e951..57223a3c7b2 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -9,7 +9,6 @@ // except according to those terms. use dep_graph::{DepConstructor, DepNode}; -use errors::DiagnosticBuilder; use hir::def_id::{CrateNum, DefId, DefIndex}; use hir::def::{Def, Export}; use hir::{self, TraitCandidate, ItemLocalId, TransFnAttrs}; @@ -43,7 +42,7 @@ use ty::{self, CrateInherentImpls, ParamEnvAnd, Ty, TyCtxt}; use ty::steal::Steal; use ty::subst::Substs; use util::nodemap::{DefIdSet, DefIdMap, ItemLocalSet}; -use util::common::{profq_msg, ErrorReported, ProfileQueriesMsg}; +use util::common::{ErrorReported}; use rustc_data_structures::indexed_set::IdxSetBuf; use rustc_target::spec::PanicStrategy; diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index 4fb12be6fb1..c3f3424600c 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -25,7 +25,7 @@ use ty::maps::config::QueryDescription; use ty::maps::job::{QueryJob, QueryResult, QueryInfo}; use ty::item_path; -use util::common::{profq_msg, ProfileQueriesMsg}; +use util::common::{profq_msg, ProfileQueriesMsg, QueryMsg}; use rustc_data_structures::fx::{FxHashMap}; use rustc_data_structures::sync::{Lrc, Lock}; @@ -33,6 +33,7 @@ use std::mem; use std::ptr; use std::collections::hash_map::Entry; use syntax_pos::Span; +use syntax::codemap::DUMMY_SP; pub struct QueryMap<'tcx, D: QueryConfig<'tcx> + ?Sized> { pub(super) map: FxHashMap>>, @@ -75,14 +76,18 @@ macro_rules! profq_msg { // If enabled, format a key using its debug string, which can be // expensive to compute (in terms of time). -macro_rules! profq_key { - ($tcx:expr, $key:expr) => { - if cfg!(debug_assertions) { +macro_rules! profq_query_msg { + ($query:expr, $tcx:expr, $key:expr) => {{ + let msg = if cfg!(debug_assertions) { if $tcx.sess.profile_queries_and_keys() { Some(format!("{:?}", $key)) } else { None } - } else { None } - } + } else { None }; + QueryMsg { + query: $query, + msg, + } + }} } /// A type representing the responsibility to execute the job in the `job` field. @@ -325,6 +330,278 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } } + + fn try_get_with>( + self, + span: Span, + key: Q::Key) + -> Result> + { + debug!("ty::queries::{}::try_get_with(key={:?}, span={:?})", + Q::NAME, + key, + span); + + profq_msg!(self, + ProfileQueriesMsg::QueryBegin( + span.data(), + profq_query_msg!(Q::NAME, self, key), + ) + ); + + let job = match JobOwner::try_get(self, span, &key) { + TryGetJob::NotYetStarted(job) => job, + TryGetJob::JobCompleted(result) => { + return result.map(|(v, index)| { + self.dep_graph.read_index(index); + v + }) + } + }; + + // Fast path for when incr. comp. is off. `to_dep_node` is + // expensive for some DepKinds. + if !self.dep_graph.is_fully_enabled() { + let null_dep_node = DepNode::new_no_params(::dep_graph::DepKind::Null); + return self.force_query_with_job::(key, job, null_dep_node).map(|(v, _)| v); + } + + let dep_node = Q::to_dep_node(self, &key); + + if dep_node.kind.is_anon() { + profq_msg!(self, ProfileQueriesMsg::ProviderBegin); + + let res = job.start(self, |tcx| { + tcx.dep_graph.with_anon_task(dep_node.kind, || { + Q::compute(tcx.global_tcx(), key) + }) + }); + + profq_msg!(self, ProfileQueriesMsg::ProviderEnd); + let ((result, dep_node_index), diagnostics) = res; + + self.dep_graph.read_index(dep_node_index); + + self.on_disk_query_result_cache + .store_diagnostics_for_anon_node(dep_node_index, diagnostics); + + job.complete(&result, dep_node_index); + + return Ok(result); + } + + if !dep_node.kind.is_input() { + if let Some(dep_node_index) = self.try_mark_green_and_read(&dep_node) { + profq_msg!(self, ProfileQueriesMsg::CacheHit); + return self.load_from_disk_and_cache_in_memory::(key, + job, + dep_node_index, + &dep_node) + } + } + + match self.force_query_with_job::(key, job, dep_node) { + Ok((result, dep_node_index)) => { + self.dep_graph.read_index(dep_node_index); + Ok(result) + } + Err(e) => Err(e) + } + } + + fn load_from_disk_and_cache_in_memory>( + self, + key: Q::Key, + job: JobOwner<'a, 'gcx, Q>, + dep_node_index: DepNodeIndex, + dep_node: &DepNode + ) -> Result> + { + // Note this function can be called concurrently from the same query + // We must ensure that this is handled correctly + + debug_assert!(self.dep_graph.is_green(dep_node)); + + // First we try to load the result from the on-disk cache + let result = if Q::cache_on_disk(key.clone()) && + self.sess.opts.debugging_opts.incremental_queries { + let prev_dep_node_index = + self.dep_graph.prev_dep_node_index_of(dep_node); + let result = Q::try_load_from_disk(self.global_tcx(), + prev_dep_node_index); + + // We always expect to find a cached result for things that + // can be forced from DepNode. + debug_assert!(!dep_node.kind.can_reconstruct_query_key() || + result.is_some(), + "Missing on-disk cache entry for {:?}", + dep_node); + result + } else { + // Some things are never cached on disk. + None + }; + + let result = if let Some(result) = result { + result + } else { + // We could not load a result from the on-disk cache, so + // recompute. + + // The diagnostics for this query have already been + // promoted to the current session during + // try_mark_green(), so we can ignore them here. + let (result, _) = job.start(self, |tcx| { + // The dep-graph for this computation is already in + // place + tcx.dep_graph.with_ignore(|| { + Q::compute(tcx, key) + }) + }); + result + }; + + // If -Zincremental-verify-ich is specified, re-hash results from + // the cache and make sure that they have the expected fingerprint. + if self.sess.opts.debugging_opts.incremental_verify_ich { + use rustc_data_structures::stable_hasher::{StableHasher, HashStable}; + use ich::Fingerprint; + + assert!(Some(self.dep_graph.fingerprint_of(dep_node_index)) == + self.dep_graph.prev_fingerprint_of(dep_node), + "Fingerprint for green query instance not loaded \ + from cache: {:?}", dep_node); + + debug!("BEGIN verify_ich({:?})", dep_node); + let mut hcx = self.create_stable_hashing_context(); + let mut hasher = StableHasher::new(); + + result.hash_stable(&mut hcx, &mut hasher); + + let new_hash: Fingerprint = hasher.finish(); + debug!("END verify_ich({:?})", dep_node); + + let old_hash = self.dep_graph.fingerprint_of(dep_node_index); + + assert!(new_hash == old_hash, "Found unstable fingerprints \ + for {:?}", dep_node); + } + + if self.sess.opts.debugging_opts.query_dep_graph { + self.dep_graph.mark_loaded_from_cache(dep_node_index, true); + } + + job.complete(&result, dep_node_index); + + Ok(result) + } + + fn force_query_with_job>( + self, + key: Q::Key, + job: JobOwner<'_, 'gcx, Q>, + dep_node: DepNode) + -> Result<(Q::Value, DepNodeIndex), CycleError<'gcx>> { + // If the following assertion triggers, it can have two reasons: + // 1. Something is wrong with DepNode creation, either here or + // in DepGraph::try_mark_green() + // 2. Two distinct query keys get mapped to the same DepNode + // (see for example #48923) + assert!(!self.dep_graph.dep_node_exists(&dep_node), + "Forcing query with already existing DepNode.\n\ + - query-key: {:?}\n\ + - dep-node: {:?}", + key, dep_node); + + profq_msg!(self, ProfileQueriesMsg::ProviderBegin); + let res = job.start(self, |tcx| { + if dep_node.kind.is_eval_always() { + tcx.dep_graph.with_eval_always_task(dep_node, + tcx, + key, + Q::compute) + } else { + tcx.dep_graph.with_task(dep_node, + tcx, + key, + Q::compute) + } + }); + profq_msg!(self, ProfileQueriesMsg::ProviderEnd); + + let ((result, dep_node_index), diagnostics) = res; + + if self.sess.opts.debugging_opts.query_dep_graph { + self.dep_graph.mark_loaded_from_cache(dep_node_index, false); + } + + if dep_node.kind != ::dep_graph::DepKind::Null { + self.on_disk_query_result_cache + .store_diagnostics(dep_node_index, diagnostics); + } + + job.complete(&result, dep_node_index); + + Ok((result, dep_node_index)) + } + + /// Ensure that either this query has all green inputs or been executed. + /// Executing query::ensure(D) is considered a read of the dep-node D. + /// + /// This function is particularly useful when executing passes for their + /// side-effects -- e.g., in order to report errors for erroneous programs. + /// + /// Note: The optimization is only available during incr. comp. + pub fn ensure_query>(self, key: Q::Key) -> () { + let dep_node = Q::to_dep_node(self, &key); + + // Ensuring an "input" or anonymous query makes no sense + assert!(!dep_node.kind.is_anon()); + assert!(!dep_node.kind.is_input()); + if self.try_mark_green_and_read(&dep_node).is_none() { + // A None return from `try_mark_green_and_read` means that this is either + // a new dep node or that the dep node has already been marked red. + // Either way, we can't call `dep_graph.read()` as we don't have the + // DepNodeIndex. We must invoke the query itself. The performance cost + // this introduces should be negligible as we'll immediately hit the + // in-memory cache, or another query down the line will. + let _ = self.get_query::(DUMMY_SP, key); + } + } + + #[allow(dead_code)] + fn force_query>( + self, + key: Q::Key, + span: Span, + dep_node: DepNode + ) -> Result<(Q::Value, DepNodeIndex), CycleError<'gcx>> { + // We may be concurrently trying both execute and force a query + // Ensure that only one of them runs the query + let job = match JobOwner::try_get(self, span, &key) { + TryGetJob::NotYetStarted(job) => job, + TryGetJob::JobCompleted(result) => return result, + }; + self.force_query_with_job::(key, job, dep_node) + } + + pub fn try_get_query>( + self, + span: Span, + key: Q::Key + ) -> Result> { + match self.try_get_with::(span, key) { + Ok(e) => Ok(e), + Err(e) => Err(self.report_cycle(e)), + } + } + + pub fn get_query>(self, span: Span, key: Q::Key) -> Q::Value { + self.try_get_query::(span, key).unwrap_or_else(|mut e| { + e.emit(); + Q::handle_cycle_error(self) + }) + } } macro_rules! handle_cycle_error { @@ -332,7 +609,7 @@ macro_rules! handle_cycle_error { Value::from_cycle_error($this.global_tcx()) }}; ([fatal_cycle$(, $modifiers:ident)*][$this:expr]) => {{ - $this.tcx.sess.abort_if_errors(); + $this.sess.abort_if_errors(); unreachable!(); }}; ([$other:ident$(, $modifiers:ident)*][$($args:tt)*]) => { @@ -345,7 +622,6 @@ macro_rules! define_maps { $($(#[$attr:meta])* [$($modifiers:tt)*] fn $name:ident: $node:ident($K:ty) -> $V:ty,)*) => { - use dep_graph::DepNodeIndex; use rustc_data_structures::sync::Lock; define_map_struct! { @@ -369,12 +645,6 @@ macro_rules! define_maps { $($(#[$attr])* $name($K)),* } - #[allow(bad_style)] - #[derive(Clone, Debug, PartialEq, Eq)] - pub enum QueryMsg { - $($name(Option)),* - } - impl<$tcx> Query<$tcx> { pub fn name(&self) -> &'static str { match *self { @@ -425,6 +695,8 @@ macro_rules! define_maps { type Key = $K; type Value = $V; + const NAME: &'static str = stringify!($name); + fn query(key: Self::Key) -> Query<'tcx> { Query::$name(key) } @@ -432,96 +704,25 @@ macro_rules! define_maps { fn query_map<'a>(tcx: TyCtxt<'a, $tcx, '_>) -> &'a Lock> { &tcx.maps.$name } - } - - impl<'a, $tcx, 'lcx> queries::$name<$tcx> { #[allow(unused)] - fn to_dep_node(tcx: TyCtxt<'a, $tcx, 'lcx>, key: &$K) -> DepNode { + fn to_dep_node(tcx: TyCtxt<'_, $tcx, '_>, key: &Self::Key) -> DepNode { use dep_graph::DepConstructor::*; DepNode::new(tcx, $node(*key)) } - fn try_get_with(tcx: TyCtxt<'a, $tcx, 'lcx>, - span: Span, - key: $K) - -> Result<$V, CycleError<$tcx>> - { - debug!("ty::queries::{}::try_get_with(key={:?}, span={:?})", - stringify!($name), - key, - span); - - profq_msg!(tcx, - ProfileQueriesMsg::QueryBegin( - span.data(), - QueryMsg::$name(profq_key!(tcx, key)) - ) - ); - - let job = match JobOwner::try_get(tcx, span, &key) { - TryGetJob::NotYetStarted(job) => job, - TryGetJob::JobCompleted(result) => { - return result.map(|(v, index)| { - tcx.dep_graph.read_index(index); - v - }) - } - }; - - // Fast path for when incr. comp. is off. `to_dep_node` is - // expensive for some DepKinds. - if !tcx.dep_graph.is_fully_enabled() { - let null_dep_node = DepNode::new_no_params(::dep_graph::DepKind::Null); - return Self::force_with_job(tcx, key, job, null_dep_node) - .map(|(v, _)| v); - } - - let dep_node = Self::to_dep_node(tcx, &key); - - if dep_node.kind.is_anon() { - profq_msg!(tcx, ProfileQueriesMsg::ProviderBegin); - - let res = job.start(tcx, |tcx| { - tcx.dep_graph.with_anon_task(dep_node.kind, || { - Self::compute_result(tcx.global_tcx(), key) - }) - }); - - profq_msg!(tcx, ProfileQueriesMsg::ProviderEnd); - let ((result, dep_node_index), diagnostics) = res; - - tcx.dep_graph.read_index(dep_node_index); - - tcx.on_disk_query_result_cache - .store_diagnostics_for_anon_node(dep_node_index, diagnostics); - - job.complete(&result, dep_node_index); - - return Ok(result); - } - - if !dep_node.kind.is_input() { - if let Some(dep_node_index) = tcx.try_mark_green_and_read(&dep_node) { - profq_msg!(tcx, ProfileQueriesMsg::CacheHit); - return Self::load_from_disk_and_cache_in_memory(tcx, - key, - job, - dep_node_index, - &dep_node) - } - } + fn compute(tcx: TyCtxt<'_, 'tcx, '_>, key: Self::Key) -> Self::Value { + let provider = tcx.maps.providers[key.map_crate()].$name; + provider(tcx.global_tcx(), key) + } - match Self::force_with_job(tcx, key, job, dep_node) { - Ok((result, dep_node_index)) => { - tcx.dep_graph.read_index(dep_node_index); - Ok(result) - } - Err(e) => Err(e) - } + fn handle_cycle_error(tcx: TyCtxt<'_, 'tcx, '_>) -> Self::Value { + handle_cycle_error!([$($modifiers)*][tcx]) } + } + impl<'a, $tcx, 'lcx> queries::$name<$tcx> { /// Ensure that either this query has all green inputs or been executed. /// Executing query::ensure(D) is considered a read of the dep-node D. /// @@ -530,185 +731,7 @@ macro_rules! define_maps { /// /// Note: The optimization is only available during incr. comp. pub fn ensure(tcx: TyCtxt<'a, $tcx, 'lcx>, key: $K) -> () { - let dep_node = Self::to_dep_node(tcx, &key); - - // Ensuring an "input" or anonymous query makes no sense - assert!(!dep_node.kind.is_anon()); - assert!(!dep_node.kind.is_input()); - if tcx.try_mark_green_and_read(&dep_node).is_none() { - // A None return from `try_mark_green_and_read` means that this is either - // a new dep node or that the dep node has already been marked red. - // Either way, we can't call `dep_graph.read()` as we don't have the - // DepNodeIndex. We must invoke the query itself. The performance cost - // this introduces should be negligible as we'll immediately hit the - // in-memory cache, or another query down the line will. - let _ = tcx.$name(key); - } - } - - fn compute_result(tcx: TyCtxt<'a, $tcx, 'lcx>, key: $K) -> $V { - let provider = tcx.maps.providers[key.map_crate()].$name; - provider(tcx.global_tcx(), key) - } - - fn load_from_disk_and_cache_in_memory(tcx: TyCtxt<'a, $tcx, 'lcx>, - key: $K, - job: JobOwner<'a, $tcx, Self>, - dep_node_index: DepNodeIndex, - dep_node: &DepNode) - -> Result<$V, CycleError<$tcx>> - { - // Note this function can be called concurrently from the same query - // We must ensure that this is handled correctly - - debug_assert!(tcx.dep_graph.is_green(dep_node)); - - // First we try to load the result from the on-disk cache - let result = if Self::cache_on_disk(key) && - tcx.sess.opts.debugging_opts.incremental_queries { - let prev_dep_node_index = - tcx.dep_graph.prev_dep_node_index_of(dep_node); - let result = Self::try_load_from_disk(tcx.global_tcx(), - prev_dep_node_index); - - // We always expect to find a cached result for things that - // can be forced from DepNode. - debug_assert!(!dep_node.kind.can_reconstruct_query_key() || - result.is_some(), - "Missing on-disk cache entry for {:?}", - dep_node); - result - } else { - // Some things are never cached on disk. - None - }; - - let result = if let Some(result) = result { - result - } else { - // We could not load a result from the on-disk cache, so - // recompute. - - // The diagnostics for this query have already been - // promoted to the current session during - // try_mark_green(), so we can ignore them here. - let (result, _) = job.start(tcx, |tcx| { - // The dep-graph for this computation is already in - // place - tcx.dep_graph.with_ignore(|| { - Self::compute_result(tcx, key) - }) - }); - result - }; - - // If -Zincremental-verify-ich is specified, re-hash results from - // the cache and make sure that they have the expected fingerprint. - if tcx.sess.opts.debugging_opts.incremental_verify_ich { - use rustc_data_structures::stable_hasher::{StableHasher, HashStable}; - use ich::Fingerprint; - - assert!(Some(tcx.dep_graph.fingerprint_of(dep_node_index)) == - tcx.dep_graph.prev_fingerprint_of(dep_node), - "Fingerprint for green query instance not loaded \ - from cache: {:?}", dep_node); - - debug!("BEGIN verify_ich({:?})", dep_node); - let mut hcx = tcx.create_stable_hashing_context(); - let mut hasher = StableHasher::new(); - - result.hash_stable(&mut hcx, &mut hasher); - - let new_hash: Fingerprint = hasher.finish(); - debug!("END verify_ich({:?})", dep_node); - - let old_hash = tcx.dep_graph.fingerprint_of(dep_node_index); - - assert!(new_hash == old_hash, "Found unstable fingerprints \ - for {:?}", dep_node); - } - - if tcx.sess.opts.debugging_opts.query_dep_graph { - tcx.dep_graph.mark_loaded_from_cache(dep_node_index, true); - } - - job.complete(&result, dep_node_index); - - Ok(result) - } - - #[allow(dead_code)] - fn force(tcx: TyCtxt<'a, $tcx, 'lcx>, - key: $K, - span: Span, - dep_node: DepNode) - -> Result<($V, DepNodeIndex), CycleError<$tcx>> { - // We may be concurrently trying both execute and force a query - // Ensure that only one of them runs the query - let job = match JobOwner::try_get(tcx, span, &key) { - TryGetJob::NotYetStarted(job) => job, - TryGetJob::JobCompleted(result) => return result, - }; - Self::force_with_job(tcx, - key, - job, - dep_node) - } - - fn force_with_job(tcx: TyCtxt<'a, $tcx, 'lcx>, - key: $K, - job: JobOwner<'_, $tcx, Self>, - dep_node: DepNode) - -> Result<($V, DepNodeIndex), CycleError<$tcx>> { - // If the following assertion triggers, it can have two reasons: - // 1. Something is wrong with DepNode creation, either here or - // in DepGraph::try_mark_green() - // 2. Two distinct query keys get mapped to the same DepNode - // (see for example #48923) - assert!(!tcx.dep_graph.dep_node_exists(&dep_node), - "Forcing query with already existing DepNode.\n\ - - query-key: {:?}\n\ - - dep-node: {:?}", - key, dep_node); - - profq_msg!(tcx, ProfileQueriesMsg::ProviderBegin); - let res = job.start(tcx, |tcx| { - if dep_node.kind.is_eval_always() { - tcx.dep_graph.with_eval_always_task(dep_node, - tcx, - key, - Self::compute_result) - } else { - tcx.dep_graph.with_task(dep_node, - tcx, - key, - Self::compute_result) - } - }); - profq_msg!(tcx, ProfileQueriesMsg::ProviderEnd); - - let ((result, dep_node_index), diagnostics) = res; - - if tcx.sess.opts.debugging_opts.query_dep_graph { - tcx.dep_graph.mark_loaded_from_cache(dep_node_index, false); - } - - if dep_node.kind != ::dep_graph::DepKind::Null { - tcx.on_disk_query_result_cache - .store_diagnostics(dep_node_index, diagnostics); - } - - job.complete(&result, dep_node_index); - - Ok((result, dep_node_index)) - } - - pub fn try_get(tcx: TyCtxt<'a, $tcx, 'lcx>, span: Span, key: $K) - -> Result<$V, DiagnosticBuilder<'a>> { - match Self::try_get_with(tcx, span, key) { - Ok(e) => Ok(e), - Err(e) => Err(tcx.report_cycle(e)), - } + tcx.ensure_query::(key); } })* @@ -744,10 +767,7 @@ macro_rules! define_maps { impl<'a, $tcx, 'lcx> TyCtxtAt<'a, $tcx, 'lcx> { $($(#[$attr])* pub fn $name(self, key: $K) -> $V { - queries::$name::try_get(self.tcx, self.span, key).unwrap_or_else(|mut e| { - e.emit(); - handle_cycle_error!([$($modifiers)*][self]) - }) + self.tcx.get_query::(self.span, key) })* } @@ -838,7 +858,6 @@ macro_rules! define_provider_struct { pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, dep_node: &DepNode) -> bool { - use ty::maps::keys::Key; use hir::def_id::LOCAL_CRATE; // We must avoid ever having to call force_from_dep_node() for a @@ -881,23 +900,14 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, { use $crate::util::common::{ProfileQueriesMsg, profq_msg}; - // FIXME(eddyb) Get more valid Span's on queries. - // def_span guard is necessary to prevent a recursive loop, - // default_span calls def_span query internally. - let span = if stringify!($query) != "def_span" { - $key.default_span(tcx) - } else { - ::syntax_pos::DUMMY_SP - }; - profq_msg!(tcx, ProfileQueriesMsg::QueryBegin( - span.data(), - ::ty::maps::QueryMsg::$query(profq_key!(tcx, $key)) + DUMMY_SP.data(), + profq_query_msg!(::ty::maps::queries::$query::NAME, tcx, $key), ) ); - match ::ty::maps::queries::$query::force(tcx, $key, span, *dep_node) { + match tcx.force_query::<::ty::maps::queries::$query>($key, DUMMY_SP, *dep_node) { Ok(_) => {}, Err(e) => { tcx.report_cycle(e).emit(); diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index de043668410..050561df638 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2031,7 +2031,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { /// Due to normalization being eager, this applies even if /// the associated type is behind a pointer, e.g. issue #31299. pub fn sized_constraint(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> &'tcx [Ty<'tcx>] { - match queries::adt_sized_constraint::try_get(tcx, DUMMY_SP, self.did) { + match tcx.try_get_query::(DUMMY_SP, self.did) { Ok(tys) => tys, Err(mut bug) => { debug!("adt_sized_constraint: {:?} is recursive", self); diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index a10ca132472..4aa70e1f7e0 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -1024,7 +1024,7 @@ fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let (param_env, ty) = query.into_parts(); let needs_drop = |ty: Ty<'tcx>| -> bool { - match ty::queries::needs_drop_raw::try_get(tcx, DUMMY_SP, param_env.and(ty)) { + match tcx.try_get_query::(DUMMY_SP, param_env.and(ty)) { Ok(v) => v, Err(mut bug) => { // Cycles should be reported as an error by `check_representable`. diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index bb6aa654c29..c74e42263ef 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -25,7 +25,6 @@ use std::time::{Duration, Instant}; use std::sync::mpsc::{Sender}; use syntax_pos::{SpanData}; -use ty::maps::{QueryMsg}; use ty::TyCtxt; use dep_graph::{DepNode}; use proc_macro; @@ -77,6 +76,13 @@ pub struct ProfQDumpParams { pub dump_profq_msg_log:bool, } +#[allow(bad_style)] +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct QueryMsg { + pub query: &'static str, + pub msg: Option, +} + /// A sequence of these messages induce a trace of query-based incremental compilation. /// FIXME(matthewhammer): Determine whether we should include cycle detection here or not. #[derive(Clone,Debug)] diff --git a/src/librustc_driver/profile/trace.rs b/src/librustc_driver/profile/trace.rs index 280f3c8c796..6426286ccbc 100644 --- a/src/librustc_driver/profile/trace.rs +++ b/src/librustc_driver/profile/trace.rs @@ -10,7 +10,7 @@ use super::*; use syntax_pos::SpanData; -use rustc::ty::maps::QueryMsg; +use rustc::util::common::QueryMsg; use std::fs::File; use std::time::{Duration, Instant}; use std::collections::hash_map::HashMap; diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 2b491385d66..693df0706dc 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -126,7 +126,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { continue; } - let callee_mir = match ty::queries::optimized_mir::try_get(self.tcx, + let callee_mir = match self.tcx.try_get_query::( callsite.location.span, callsite.callee) { Ok(callee_mir) if self.should_inline(callsite, callee_mir) => { -- cgit 1.4.1-3-g733a5 From 9a5978966305fdb921982db365bf77ac22d090cf Mon Sep 17 00:00:00 2001 From: John Kåre Alsaker Date: Fri, 20 Apr 2018 09:47:26 +0200 Subject: Store query jobs and query results in separate maps to reduce memory usage --- src/librustc/ty/maps/job.rs | 5 +---- src/librustc/ty/maps/on_disk_cache.rs | 17 ++++++----------- src/librustc/ty/maps/plumbing.rs | 26 ++++++++++++++++---------- 3 files changed, 23 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/librustc/ty/maps/job.rs b/src/librustc/ty/maps/job.rs index 374406158c1..3b6af018d6b 100644 --- a/src/librustc/ty/maps/job.rs +++ b/src/librustc/ty/maps/job.rs @@ -17,13 +17,10 @@ use ty::context::TyCtxt; use errors::Diagnostic; /// Indicates the state of a query for a given key in a query map -pub(super) enum QueryResult<'tcx, T> { +pub(super) enum QueryResult<'tcx> { /// An already executing query. The query job can be used to await for its completion Started(Lrc>), - /// The query is complete and produced `T` - Complete(T), - /// The query panicked. Queries trying to wait on this will raise a fatal error / silently panic Poisoned, } diff --git a/src/librustc/ty/maps/on_disk_cache.rs b/src/librustc/ty/maps/on_disk_cache.rs index 6dfa72a3cf3..cea2a03fd53 100644 --- a/src/librustc/ty/maps/on_disk_cache.rs +++ b/src/librustc/ty/maps/on_disk_cache.rs @@ -30,7 +30,6 @@ use syntax::codemap::{CodeMap, StableFilemapId}; use syntax_pos::{BytePos, Span, DUMMY_SP, FileMap}; use syntax_pos::hygiene::{Mark, SyntaxContext, ExpnInfo}; use ty; -use ty::maps::job::QueryResult; use ty::codec::{self as ty_codec, TyDecoder, TyEncoder}; use ty::context::TyCtxt; use util::common::time; @@ -240,13 +239,11 @@ impl<'sess> OnDiskCache<'sess> { // const eval is special, it only encodes successfully evaluated constants use ty::maps::QueryConfig; - for (key, entry) in const_eval::query_map(tcx).borrow().map.iter() { + let map = const_eval::query_map(tcx).borrow(); + assert!(map.active.is_empty()); + for (key, entry) in map.results.iter() { use ty::maps::config::QueryDescription; if const_eval::cache_on_disk(key.clone()) { - let entry = match *entry { - QueryResult::Complete(ref v) => v, - _ => panic!("incomplete query"), - }; if let Ok(ref value) = entry.value { let dep_node = SerializedDepNodeIndex::new(entry.index.index()); @@ -1133,12 +1130,10 @@ fn encode_query_results<'enc, 'a, 'tcx, Q, E>(tcx: TyCtxt<'a, 'tcx, 'tcx>, time(tcx.sess, desc, || { - for (key, entry) in Q::query_map(tcx).borrow().map.iter() { + let map = Q::query_map(tcx).borrow(); + assert!(map.active.is_empty()); + for (key, entry) in map.results.iter() { if Q::cache_on_disk(key.clone()) { - let entry = match *entry { - QueryResult::Complete(ref v) => v, - _ => panic!("incomplete query"), - }; let dep_node = SerializedDepNodeIndex::new(entry.index.index()); // Record position of the cache entry diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index c3f3424600c..83305db57da 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -36,7 +36,8 @@ use syntax_pos::Span; use syntax::codemap::DUMMY_SP; pub struct QueryMap<'tcx, D: QueryConfig<'tcx> + ?Sized> { - pub(super) map: FxHashMap>>, + pub(super) results: FxHashMap>, + pub(super) active: FxHashMap>, } pub(super) struct QueryValue { @@ -58,7 +59,8 @@ impl QueryValue { impl<'tcx, M: QueryConfig<'tcx>> QueryMap<'tcx, M> { pub(super) fn new() -> QueryMap<'tcx, M> { QueryMap { - map: FxHashMap(), + results: FxHashMap(), + active: FxHashMap(), } } } @@ -111,15 +113,15 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { let map = Q::query_map(tcx); loop { let mut lock = map.borrow_mut(); - let job = match lock.map.entry((*key).clone()) { + if let Some(value) = lock.results.get(key) { + profq_msg!(tcx, ProfileQueriesMsg::CacheHit); + let result = Ok((value.value.clone(), value.index)); + return TryGetJob::JobCompleted(result); + } + let job = match lock.active.entry((*key).clone()) { Entry::Occupied(entry) => { match *entry.get() { QueryResult::Started(ref job) => job.clone(), - QueryResult::Complete(ref value) => { - profq_msg!(tcx, ProfileQueriesMsg::CacheHit); - let result = Ok((value.value.clone(), value.index)); - return TryGetJob::JobCompleted(result); - }, QueryResult::Poisoned => FatalError.raise(), } } @@ -161,7 +163,11 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { mem::forget(self); let value = QueryValue::new(result.clone(), dep_node_index); - map.borrow_mut().map.insert(key, QueryResult::Complete(value)); + { + let mut lock = map.borrow_mut(); + lock.active.remove(&key); + lock.results.insert(key, value); + } job.signal_complete(); } @@ -205,7 +211,7 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { impl<'a, 'tcx, Q: QueryDescription<'tcx>> Drop for JobOwner<'a, 'tcx, Q> { fn drop(&mut self) { // Poison the query so jobs waiting on it panic - self.map.borrow_mut().map.insert(self.key.clone(), QueryResult::Poisoned); + self.map.borrow_mut().active.insert(self.key.clone(), QueryResult::Poisoned); // Also signal the completion of the job, so waiters // will continue execution self.job.signal_complete(); -- cgit 1.4.1-3-g733a5 From f678bf0ababf77ca224c8110bd6aea5569c698da Mon Sep 17 00:00:00 2001 From: John Kåre Alsaker Date: Fri, 27 Apr 2018 12:08:54 +0200 Subject: Address comments --- src/librustc/ty/maps/config.rs | 3 +++ src/librustc/ty/maps/plumbing.rs | 12 ++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/librustc/ty/maps/config.rs b/src/librustc/ty/maps/config.rs index 2f6e7ade89f..57c8c4f34e7 100644 --- a/src/librustc/ty/maps/config.rs +++ b/src/librustc/ty/maps/config.rs @@ -35,10 +35,13 @@ pub trait QueryConfig<'tcx> { type Value: Clone + for<'a> HashStable>; fn query(key: Self::Key) -> Query<'tcx>; + + // Don't use this method to access query results, instead use the methods on TyCtxt fn query_map<'a>(tcx: TyCtxt<'a, 'tcx, '_>) -> &'a Lock>; fn to_dep_node(tcx: TyCtxt<'_, 'tcx, '_>, key: &Self::Key) -> DepNode; + // Don't use this method to compute query results, instead use the methods on TyCtxt fn compute(tcx: TyCtxt<'_, 'tcx, '_>, key: Self::Key) -> Self::Value; fn handle_cycle_error(tcx: TyCtxt<'_, 'tcx, '_>) -> Self::Value; diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index 83305db57da..37950463f74 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -186,18 +186,18 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { // The TyCtxt stored in TLS has the same global interner lifetime // as `tcx`, so we use `with_related_context` to relate the 'gcx lifetimes // when accessing the ImplicitCtxt - let r = tls::with_related_context(tcx, move |icx| { + let r = tls::with_related_context(tcx, move |current_icx| { // Update the ImplicitCtxt to point to our new query job - let icx = tls::ImplicitCtxt { + let new_icx = tls::ImplicitCtxt { tcx, query: Some(self.job.clone()), - layout_depth: icx.layout_depth, - task: icx.task, + layout_depth: current_icx.layout_depth, + task: current_icx.task, }; // Use the ImplicitCtxt while we execute the query - tls::enter_context(&icx, |icx| { - compute(icx.tcx) + tls::enter_context(&new_icx, |_| { + compute(tcx) }) }); -- cgit 1.4.1-3-g733a5 From 5f2c111165371b1e59fec9cd90e364ccf08b68ef Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Fri, 27 Apr 2018 07:20:46 +0200 Subject: Allow #[inline] on closures Fixes #49632 --- src/librustc/hir/check_attr.rs | 15 ++++++++----- src/test/compile-fail/attr-usage-inline.rs | 2 +- src/test/compile-fail/issue-31769.rs | 2 +- src/test/compile-fail/issue-43988.rs | 6 ++--- src/test/run-pass/issue-49632.rs | 17 ++++++++++++++ src/test/ui/error-codes/E0518.stderr | 8 +++---- .../feature-gate/issue-43106-gating-of-inline.rs | 10 ++++----- .../issue-43106-gating-of-inline.stderr | 26 +++++++++++----------- 8 files changed, 54 insertions(+), 32 deletions(-) create mode 100644 src/test/run-pass/issue-49632.rs (limited to 'src') diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index 956cd17f38f..19f8d15662d 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -30,6 +30,7 @@ enum Target { ForeignMod, Expression, Statement, + Closure, Other, } @@ -103,14 +104,14 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> { self.check_repr(item, target); } - /// Check if an `#[inline]` is applied to a function. + /// Check if an `#[inline]` is applied to a function or a closure. fn check_inline(&self, attr: &hir::Attribute, span: &Span, target: Target) { - if target != Target::Fn { + if target != Target::Fn && target != Target::Closure { struct_span_err!(self.tcx.sess, attr.span, E0518, - "attribute should be applied to function") - .span_label(*span, "not a function") + "attribute should be applied to function or closure") + .span_label(*span, "not a function or closure") .emit(); } } @@ -286,9 +287,13 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> { } fn check_expr_attributes(&self, expr: &hir::Expr) { + let target = match expr.node { + hir::ExprClosure(..) => Target::Closure, + _ => Target::Expression, + }; for attr in expr.attrs.iter() { if attr.check_name("inline") { - self.check_inline(attr, &expr.span, Target::Expression); + self.check_inline(attr, &expr.span, target); } if attr.check_name("repr") { self.emit_repr_error( diff --git a/src/test/compile-fail/attr-usage-inline.rs b/src/test/compile-fail/attr-usage-inline.rs index c6b9b016331..250905dbdcd 100644 --- a/src/test/compile-fail/attr-usage-inline.rs +++ b/src/test/compile-fail/attr-usage-inline.rs @@ -13,7 +13,7 @@ #[inline] fn f() {} -#[inline] //~ ERROR: attribute should be applied to function +#[inline] //~ ERROR: attribute should be applied to function or closure struct S; fn main() {} diff --git a/src/test/compile-fail/issue-31769.rs b/src/test/compile-fail/issue-31769.rs index 7f73d9076ec..2bd45deeab4 100644 --- a/src/test/compile-fail/issue-31769.rs +++ b/src/test/compile-fail/issue-31769.rs @@ -9,6 +9,6 @@ // except according to those terms. fn main() { - #[inline] struct Foo; //~ ERROR attribute should be applied to function + #[inline] struct Foo; //~ ERROR attribute should be applied to function or closure #[repr(C)] fn foo() {} //~ ERROR attribute should be applied to struct, enum or union } diff --git a/src/test/compile-fail/issue-43988.rs b/src/test/compile-fail/issue-43988.rs index ff1fdaef416..0dfa9f6f0d3 100644 --- a/src/test/compile-fail/issue-43988.rs +++ b/src/test/compile-fail/issue-43988.rs @@ -14,12 +14,12 @@ fn main() { #[inline] let _a = 4; - //~^^ ERROR attribute should be applied to function + //~^^ ERROR attribute should be applied to function or closure #[inline(XYZ)] let _b = 4; - //~^^ ERROR attribute should be applied to function + //~^^ ERROR attribute should be applied to function or closure #[repr(nothing)] let _x = 0; @@ -40,7 +40,7 @@ fn main() { #[inline(ABC)] foo(); - //~^^ ERROR attribute should be applied to function + //~^^ ERROR attribute should be applied to function or closure let _z = #[repr] 1; //~^ ERROR attribute should not be applied to an expression diff --git a/src/test/run-pass/issue-49632.rs b/src/test/run-pass/issue-49632.rs new file mode 100644 index 00000000000..8cbb7d21af7 --- /dev/null +++ b/src/test/run-pass/issue-49632.rs @@ -0,0 +1,17 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(stmt_expr_attributes)] + +pub fn main() { + let _x = #[inline(always)] || {}; + let _y = #[inline(never)] || {}; + let _z = #[inline] || {}; +} diff --git a/src/test/ui/error-codes/E0518.stderr b/src/test/ui/error-codes/E0518.stderr index d8feec99140..27d5d3645fd 100644 --- a/src/test/ui/error-codes/E0518.stderr +++ b/src/test/ui/error-codes/E0518.stderr @@ -1,19 +1,19 @@ -error[E0518]: attribute should be applied to function +error[E0518]: attribute should be applied to function or closure --> $DIR/E0518.rs:11:1 | LL | #[inline(always)] //~ ERROR: E0518 | ^^^^^^^^^^^^^^^^^ LL | struct Foo; - | ----------- not a function + | ----------- not a function or closure -error[E0518]: attribute should be applied to function +error[E0518]: attribute should be applied to function or closure --> $DIR/E0518.rs:14:1 | LL | #[inline(never)] //~ ERROR: E0518 | ^^^^^^^^^^^^^^^^ LL | / impl Foo { LL | | } - | |_- not a function + | |_- not a function or closure error: aborting due to 2 previous errors diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-inline.rs b/src/test/ui/feature-gate/issue-43106-gating-of-inline.rs index 410f960e655..b03faad988e 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-inline.rs +++ b/src/test/ui/feature-gate/issue-43106-gating-of-inline.rs @@ -19,21 +19,21 @@ #![inline = "2100"] #[inline = "2100"] -//~^ ERROR attribute should be applied to function +//~^ ERROR attribute should be applied to function or closure mod inline { mod inner { #![inline="2100"] } - //~^ ERROR attribute should be applied to function + //~^ ERROR attribute should be applied to function or closure #[inline = "2100"] fn f() { } #[inline = "2100"] struct S; - //~^ ERROR attribute should be applied to function + //~^ ERROR attribute should be applied to function or closure #[inline = "2100"] type T = S; - //~^ ERROR attribute should be applied to function + //~^ ERROR attribute should be applied to function or closure #[inline = "2100"] impl S { } - //~^ ERROR attribute should be applied to function + //~^ ERROR attribute should be applied to function or closure } fn main() {} diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr index d67d78e31a9..4d63c3f5012 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr +++ b/src/test/ui/feature-gate/issue-43106-gating-of-inline.stderr @@ -1,41 +1,41 @@ -error[E0518]: attribute should be applied to function +error[E0518]: attribute should be applied to function or closure --> $DIR/issue-43106-gating-of-inline.rs:21:1 | LL | #[inline = "2100"] | ^^^^^^^^^^^^^^^^^^ -LL | //~^ ERROR attribute should be applied to function +LL | //~^ ERROR attribute should be applied to function or closure LL | / mod inline { LL | | mod inner { #![inline="2100"] } -LL | | //~^ ERROR attribute should be applied to function +LL | | //~^ ERROR attribute should be applied to function or closure LL | | ... | -LL | | //~^ ERROR attribute should be applied to function +LL | | //~^ ERROR attribute should be applied to function or closure LL | | } - | |_- not a function + | |_- not a function or closure -error[E0518]: attribute should be applied to function +error[E0518]: attribute should be applied to function or closure --> $DIR/issue-43106-gating-of-inline.rs:24:17 | LL | mod inner { #![inline="2100"] } - | ------------^^^^^^^^^^^^^^^^^-- not a function + | ------------^^^^^^^^^^^^^^^^^-- not a function or closure -error[E0518]: attribute should be applied to function +error[E0518]: attribute should be applied to function or closure --> $DIR/issue-43106-gating-of-inline.rs:29:5 | LL | #[inline = "2100"] struct S; - | ^^^^^^^^^^^^^^^^^^ --------- not a function + | ^^^^^^^^^^^^^^^^^^ --------- not a function or closure -error[E0518]: attribute should be applied to function +error[E0518]: attribute should be applied to function or closure --> $DIR/issue-43106-gating-of-inline.rs:32:5 | LL | #[inline = "2100"] type T = S; - | ^^^^^^^^^^^^^^^^^^ ----------- not a function + | ^^^^^^^^^^^^^^^^^^ ----------- not a function or closure -error[E0518]: attribute should be applied to function +error[E0518]: attribute should be applied to function or closure --> $DIR/issue-43106-gating-of-inline.rs:35:5 | LL | #[inline = "2100"] impl S { } - | ^^^^^^^^^^^^^^^^^^ ---------- not a function + | ^^^^^^^^^^^^^^^^^^ ---------- not a function or closure error: aborting due to 5 previous errors -- cgit 1.4.1-3-g733a5 From 937f9bac5d47db0e9321a61be198d386004dabac Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Fri, 27 Apr 2018 06:27:25 -0700 Subject: mir: Run copy propagation on constant mir Now that miri is merged, this seems to Just Work! --- src/librustc_mir/transform/copy_prop.rs | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) (limited to 'src') diff --git a/src/librustc_mir/transform/copy_prop.rs b/src/librustc_mir/transform/copy_prop.rs index 95fe99a1bec..fba60c7e8dc 100644 --- a/src/librustc_mir/transform/copy_prop.rs +++ b/src/librustc_mir/transform/copy_prop.rs @@ -29,7 +29,6 @@ //! (non-mutating) use of `SRC`. These restrictions are conservative and may be relaxed in the //! future. -use rustc::hir; use rustc::mir::{Constant, Local, LocalKind, Location, Place, Mir, Operand, Rvalue, StatementKind}; use rustc::mir::visit::MutVisitor; use rustc::ty::TyCtxt; @@ -41,26 +40,8 @@ pub struct CopyPropagation; impl MirPass for CopyPropagation { fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, - source: MirSource, + _source: MirSource, mir: &mut Mir<'tcx>) { - // Don't run on constant MIR, because trans might not be able to - // evaluate the modified MIR. - // FIXME(eddyb) Remove check after miri is merged. - let id = tcx.hir.as_local_node_id(source.def_id).unwrap(); - match (tcx.hir.body_owner_kind(id), source.promoted) { - (_, Some(_)) | - (hir::BodyOwnerKind::Const, _) | - (hir::BodyOwnerKind::Static(_), _) => return, - - (hir::BodyOwnerKind::Fn, _) => { - if tcx.is_const_fn(source.def_id) { - // Don't run on const functions, as, again, trans might not be able to evaluate - // the optimized IR. - return - } - } - } - // We only run when the MIR optimization level is > 1. // This avoids a slow pass, and messing up debug info. if tcx.sess.opts.debugging_opts.mir_opt_level <= 1 { -- cgit 1.4.1-3-g733a5 From eb2582e8e16e24dc83d9e8a35bad1514812f215c Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Fri, 27 Apr 2018 06:36:46 -0700 Subject: mir: Run drop elaboration on constant MIR Seems to Just Work since miri merged. --- src/librustc_mir/transform/elaborate_drops.rs | 8 -------- 1 file changed, 8 deletions(-) (limited to 'src') diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs index f63a5ef301a..8b771fcf493 100644 --- a/src/librustc_mir/transform/elaborate_drops.rs +++ b/src/librustc_mir/transform/elaborate_drops.rs @@ -15,7 +15,6 @@ use dataflow::{on_all_children_bits, on_all_drop_children_bits}; use dataflow::{drop_flag_effects_for_location, on_lookup_result_bits}; use dataflow::MoveDataParamEnv; use dataflow::{self, do_dataflow, DebugFormatted}; -use rustc::hir; use rustc::ty::{self, TyCtxt}; use rustc::mir::*; use rustc::middle::const_val::ConstVal; @@ -42,14 +41,7 @@ impl MirPass for ElaborateDrops { { debug!("elaborate_drops({:?} @ {:?})", src, mir.span); - // Don't run on constant MIR, because trans might not be able to - // evaluate the modified MIR. - // FIXME(eddyb) Remove check after miri is merged. let id = tcx.hir.as_local_node_id(src.def_id).unwrap(); - match (tcx.hir.body_owner_kind(id), src.promoted) { - (hir::BodyOwnerKind::Fn, None) => {}, - _ => return - } let param_env = tcx.param_env(src.def_id).with_reveal_all(); let move_data = MoveData::gather_moves(mir, tcx).unwrap(); let elaborate_patch = { -- cgit 1.4.1-3-g733a5 From 1129a711a6d2b84c696cb42a7be71bf0ed236509 Mon Sep 17 00:00:00 2001 From: Nick Fitzgerald Date: Fri, 27 Apr 2018 06:42:45 -0700 Subject: mir: Deaggregate constant MIR Appears to work now that miri has merged. --- src/librustc_mir/transform/deaggregator.rs | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) (limited to 'src') diff --git a/src/librustc_mir/transform/deaggregator.rs b/src/librustc_mir/transform/deaggregator.rs index 503354ebc4f..8b2b9ef7e81 100644 --- a/src/librustc_mir/transform/deaggregator.rs +++ b/src/librustc_mir/transform/deaggregator.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc::hir; use rustc::ty::TyCtxt; use rustc::mir::*; use rustc_data_structures::indexed_vec::Idx; @@ -19,26 +18,8 @@ pub struct Deaggregator; impl MirPass for Deaggregator { fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, - source: MirSource, + _source: MirSource, mir: &mut Mir<'tcx>) { - // Don't run on constant MIR, because trans might not be able to - // evaluate the modified MIR. - // FIXME(eddyb) Remove check after miri is merged. - let id = tcx.hir.as_local_node_id(source.def_id).unwrap(); - match (tcx.hir.body_owner_kind(id), source.promoted) { - (_, Some(_)) | - (hir::BodyOwnerKind::Const, _) | - (hir::BodyOwnerKind::Static(_), _) => return, - - (hir::BodyOwnerKind::Fn, _) => { - if tcx.is_const_fn(source.def_id) { - // Don't run on const functions, as, again, trans might not be able to evaluate - // the optimized IR. - return - } - } - } - let (basic_blocks, local_decls) = mir.basic_blocks_and_local_decls_mut(); let local_decls = &*local_decls; for bb in basic_blocks { -- cgit 1.4.1-3-g733a5 From 199ee327739b12c67adef326d68164bfbf5e29c9 Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Thu, 12 Apr 2018 16:53:28 -0500 Subject: stop requiring the feature-gate to use dyn_trait --- src/libsyntax/feature_gate.rs | 9 ++------- src/test/ui/feature-gate-dyn-trait.stderr | 11 ----------- 2 files changed, 2 insertions(+), 18 deletions(-) delete mode 100644 src/test/ui/feature-gate-dyn-trait.stderr (limited to 'src') diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 120dff2dbb9..c4a0ec259b4 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -375,9 +375,6 @@ declare_features! ( // Future-proofing enums/structs with #[non_exhaustive] attribute (RFC 2008) (active, non_exhaustive, "1.22.0", Some(44109), None), - // Trait object syntax with `dyn` prefix - (active, dyn_trait, "1.22.0", Some(44662), Some(Edition::Edition2018)), - // `crate` as visibility modifier, synonymous to `pub(crate)` (active, crate_visibility_modifier, "1.23.0", Some(45388), Some(Edition::Edition2018)), @@ -592,6 +589,8 @@ declare_features! ( (accepted, cfg_target_feature, "1.27.0", Some(29717), None), // Allows #[target_feature(...)] (accepted, target_feature, "1.27.0", None, None), + // Trait object syntax with `dyn` prefix + (accepted, dyn_trait, "1.22.0", Some(44662), None), ); // If you change this, please modify src/doc/unstable-book as well. You must @@ -1657,10 +1656,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!(&self, never_type, ty.span, "The `!` type is experimental"); } - ast::TyKind::TraitObject(_, ast::TraitObjectSyntax::Dyn) => { - gate_feature_post!(&self, dyn_trait, ty.span, - "`dyn Trait` syntax is unstable"); - } _ => {} } visit::walk_ty(self, ty) diff --git a/src/test/ui/feature-gate-dyn-trait.stderr b/src/test/ui/feature-gate-dyn-trait.stderr deleted file mode 100644 index 6e6bdf1cbf0..00000000000 --- a/src/test/ui/feature-gate-dyn-trait.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0658]: `dyn Trait` syntax is unstable (see issue #44662) - --> $DIR/feature-gate-dyn-trait.rs:12:14 - | -LL | type A = Box; //~ ERROR `dyn Trait` syntax is unstable - | ^^^^^^^^^ - | - = help: add #![feature(dyn_trait)] to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. -- cgit 1.4.1-3-g733a5 From c86f1c8cc396df443e0933278c441e36302047b1 Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Thu, 12 Apr 2018 16:54:17 -0500 Subject: removed dyn_trait feature from tests --- src/test/compile-fail/impl-trait/where-allowed.rs | 4 +++- src/test/compile-fail/mir_check_cast_unsize.rs | 1 - src/test/compile-fail/trait-bounds-not-on-struct.rs | 1 - src/test/run-pass/dyn-trait.rs | 2 -- src/test/ui/impl_trait_projections.rs | 2 ++ src/test/ui/nll/ty-outlives/projection-no-regions-closure.rs | 1 - src/test/ui/nll/ty-outlives/projection-no-regions-fn.rs | 1 - src/test/ui/nll/ty-outlives/projection-one-region-closure.rs | 1 - .../ui/nll/ty-outlives/projection-one-region-trait-bound-closure.rs | 1 - .../ty-outlives/projection-one-region-trait-bound-static-closure.rs | 1 - .../ui/nll/ty-outlives/projection-two-region-trait-bound-closure.rs | 1 - .../ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.rs | 1 - .../ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs | 1 - .../ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs | 1 - src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.rs | 1 - src/test/ui/nll/ty-outlives/ty-param-fn-body.rs | 1 - src/test/ui/nll/ty-outlives/ty-param-fn.rs | 1 - 17 files changed, 5 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/test/compile-fail/impl-trait/where-allowed.rs b/src/test/compile-fail/impl-trait/where-allowed.rs index 038eacaf110..f7b331238c6 100644 --- a/src/test/compile-fail/impl-trait/where-allowed.rs +++ b/src/test/compile-fail/impl-trait/where-allowed.rs @@ -10,7 +10,9 @@ //! A simple test for testing many permutations of allowedness of //! impl Trait -#![feature(dyn_trait)] + +#![feature(conservative_impl_trait, universal_impl_trait)] + use std::fmt::Debug; // Allowed diff --git a/src/test/compile-fail/mir_check_cast_unsize.rs b/src/test/compile-fail/mir_check_cast_unsize.rs index e30bed61058..a2c840a7098 100644 --- a/src/test/compile-fail/mir_check_cast_unsize.rs +++ b/src/test/compile-fail/mir_check_cast_unsize.rs @@ -11,7 +11,6 @@ // compile-flags: -Z borrowck=mir #![allow(dead_code)] -#![feature(dyn_trait)] use std::fmt::Debug; diff --git a/src/test/compile-fail/trait-bounds-not-on-struct.rs b/src/test/compile-fail/trait-bounds-not-on-struct.rs index 0dd1a4e7d73..1b1a238a941 100644 --- a/src/test/compile-fail/trait-bounds-not-on-struct.rs +++ b/src/test/compile-fail/trait-bounds-not-on-struct.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(dyn_trait)] #![allow(bare_trait_object)] struct Foo; diff --git a/src/test/run-pass/dyn-trait.rs b/src/test/run-pass/dyn-trait.rs index 399823ec92d..01066794242 100644 --- a/src/test/run-pass/dyn-trait.rs +++ b/src/test/run-pass/dyn-trait.rs @@ -10,8 +10,6 @@ // ignore-pretty `dyn ::foo` parses differently in the current edition -#![feature(dyn_trait)] - use std::fmt::Display; static BYTE: u8 = 33; diff --git a/src/test/ui/impl_trait_projections.rs b/src/test/ui/impl_trait_projections.rs index 6a727942271..e8e25c19840 100644 --- a/src/test/ui/impl_trait_projections.rs +++ b/src/test/ui/impl_trait_projections.rs @@ -7,7 +7,9 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. + #![feature(dyn_trait)] +#![feature(conservative_impl_trait, universal_impl_trait)] use std::fmt::Debug; use std::option; diff --git a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.rs b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.rs index 7b3ed6a94fc..4767b75d89c 100644 --- a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.rs +++ b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.rs @@ -15,7 +15,6 @@ // Iterator>::Item`, to be exact). #![allow(warnings)] -#![feature(dyn_trait)] #![feature(rustc_attrs)] trait Anything { } diff --git a/src/test/ui/nll/ty-outlives/projection-no-regions-fn.rs b/src/test/ui/nll/ty-outlives/projection-no-regions-fn.rs index 32b73a51e11..dea2daf7e8e 100644 --- a/src/test/ui/nll/ty-outlives/projection-no-regions-fn.rs +++ b/src/test/ui/nll/ty-outlives/projection-no-regions-fn.rs @@ -11,7 +11,6 @@ // compile-flags:-Zborrowck=mir -Zverbose #![allow(warnings)] -#![feature(dyn_trait)] trait Anything { } diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-closure.rs b/src/test/ui/nll/ty-outlives/projection-one-region-closure.rs index cfe2880bfed..77024c4119f 100644 --- a/src/test/ui/nll/ty-outlives/projection-one-region-closure.rs +++ b/src/test/ui/nll/ty-outlives/projection-one-region-closure.rs @@ -25,7 +25,6 @@ // compile-flags:-Zborrowck=mir -Zverbose #![allow(warnings)] -#![feature(dyn_trait)] #![feature(rustc_attrs)] use std::cell::Cell; diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.rs b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.rs index 16e91f2708f..fb1009c9cc8 100644 --- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.rs +++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.rs @@ -17,7 +17,6 @@ // compile-flags:-Zborrowck=mir -Zverbose #![allow(warnings)] -#![feature(dyn_trait)] #![feature(rustc_attrs)] use std::cell::Cell; diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.rs b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.rs index 0d42636c844..1f2f40196f8 100644 --- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.rs +++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.rs @@ -16,7 +16,6 @@ // compile-pass #![allow(warnings)] -#![feature(dyn_trait)] #![feature(rustc_attrs)] use std::cell::Cell; diff --git a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.rs b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.rs index 7c8ef140a29..5307d0880d4 100644 --- a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.rs +++ b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.rs @@ -18,7 +18,6 @@ // compile-flags:-Zborrowck=mir -Zverbose #![allow(warnings)] -#![feature(dyn_trait)] #![feature(rustc_attrs)] use std::cell::Cell; diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.rs b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.rs index 80b42c29563..7ff4b484af1 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.rs +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.rs @@ -11,7 +11,6 @@ // compile-flags:-Zborrowck=mir -Zverbose #![allow(warnings)] -#![feature(dyn_trait)] #![feature(rustc_attrs)] use std::cell::Cell; diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs index 50763a1d508..b5cbd07b99c 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs @@ -11,7 +11,6 @@ // compile-flags:-Zborrowck=mir -Zverbose #![allow(warnings)] -#![feature(dyn_trait)] #![feature(rustc_attrs)] use std::fmt::Debug; diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs index b70fc2b2ec4..edaaeac080d 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs @@ -15,7 +15,6 @@ // compile-flags:-Zborrowck=mir -Zverbose #![allow(warnings)] -#![feature(dyn_trait)] #![feature(rustc_attrs)] use std::cell::Cell; diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.rs b/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.rs index babe608354f..c0c483b3957 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.rs +++ b/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.rs @@ -15,7 +15,6 @@ #![feature(nll)] #![allow(warnings)] -#![feature(dyn_trait)] use std::cell::Cell; diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn-body.rs b/src/test/ui/nll/ty-outlives/ty-param-fn-body.rs index fb4ea63f853..6226108ef19 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-fn-body.rs +++ b/src/test/ui/nll/ty-outlives/ty-param-fn-body.rs @@ -14,7 +14,6 @@ // function body. #![allow(warnings)] -#![feature(dyn_trait)] use std::cell::Cell; diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn.rs b/src/test/ui/nll/ty-outlives/ty-param-fn.rs index 42d662e1419..258d77eb2b0 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-fn.rs +++ b/src/test/ui/nll/ty-outlives/ty-param-fn.rs @@ -11,7 +11,6 @@ // compile-flags:-Zborrowck=mir #![allow(warnings)] -#![feature(dyn_trait)] use std::fmt::Debug; -- cgit 1.4.1-3-g733a5 From 0efb5677d74451787a4dbd77fce1701c52c72a68 Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Thu, 12 Apr 2018 16:55:09 -0500 Subject: dyn_trait feature-gate just for stage0 --- src/librustc/lib.rs | 2 +- src/librustc_mir/lib.rs | 2 +- src/librustc_typeck/lib.rs | 4 +++- .../rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs | 2 -- .../rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs | 2 -- src/test/ui/impl_trait_projections.rs | 1 - src/test/ui/in-band-lifetimes/impl/dyn-trait.rs | 1 - src/test/ui/raw-literal-keywords.rs | 1 - src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.rs | 2 -- src/test/ui/underscore-lifetime/dyn-trait-underscore.rs | 2 -- 10 files changed, 5 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index bb495049483..f29da5eb112 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -45,8 +45,8 @@ #![feature(const_fn)] #![feature(core_intrinsics)] #![feature(drain_filter)] -#![feature(dyn_trait)] #![feature(entry_or_default)] +#![cfg_attr(stage0, feature(dyn_trait))] #![feature(from_ref)] #![feature(fs_read_write)] #![cfg_attr(windows, feature(libc))] diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index a47b3cacc51..482fd5989f8 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -24,7 +24,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! #![feature(const_fn)] #![feature(core_intrinsics)] #![feature(decl_macro)] -#![feature(dyn_trait)] +#![cfg_attr(stage0, feature(dyn_trait))] #![feature(fs_read_write)] #![feature(macro_vis_matcher)] #![feature(exhaustive_patterns)] diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index ed0cfe38a7a..e852edc6eed 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -71,6 +71,8 @@ This API is completely unstable and subject to change. #![allow(non_camel_case_types)] +#![cfg_attr(stage0, feature(dyn_trait))] + #![feature(box_patterns)] #![feature(box_syntax)] #![feature(crate_visibility_modifier)] @@ -81,8 +83,8 @@ This API is completely unstable and subject to change. #![feature(rustc_diagnostic_macros)] #![feature(slice_patterns)] #![feature(slice_sort_by_cached_key)] -#![feature(dyn_trait)] #![feature(never_type)] +#![feature(underscore_lifetimes)] #[macro_use] extern crate log; #[macro_use] extern crate syntax; diff --git a/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs b/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs index 219eca6fd21..66a6e6afed3 100644 --- a/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs +++ b/src/test/run-fail/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs @@ -11,8 +11,6 @@ // compile-pass // failure-status: 1 -#![feature(dyn_trait)] - use std::error::Error; use std::io; diff --git a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs index 24c30a5abc2..183bb553530 100644 --- a/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs +++ b/src/test/run-pass/rfc-1937-termination-trait/termination-trait-for-box-dyn-error.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(dyn_trait)] - use std::error::Error; fn main() -> Result<(), Box> { diff --git a/src/test/ui/impl_trait_projections.rs b/src/test/ui/impl_trait_projections.rs index e8e25c19840..e8f39e169ff 100644 --- a/src/test/ui/impl_trait_projections.rs +++ b/src/test/ui/impl_trait_projections.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(dyn_trait)] #![feature(conservative_impl_trait, universal_impl_trait)] use std::fmt::Debug; diff --git a/src/test/ui/in-band-lifetimes/impl/dyn-trait.rs b/src/test/ui/in-band-lifetimes/impl/dyn-trait.rs index a504bae2e60..c27bbe77fbf 100644 --- a/src/test/ui/in-band-lifetimes/impl/dyn-trait.rs +++ b/src/test/ui/in-band-lifetimes/impl/dyn-trait.rs @@ -13,7 +13,6 @@ #![allow(warnings)] -#![feature(dyn_trait)] #![feature(in_band_lifetimes)] use std::fmt::Debug; diff --git a/src/test/ui/raw-literal-keywords.rs b/src/test/ui/raw-literal-keywords.rs index 9b28aa0b151..9bb6653d770 100644 --- a/src/test/ui/raw-literal-keywords.rs +++ b/src/test/ui/raw-literal-keywords.rs @@ -10,7 +10,6 @@ // compile-flags: -Z parse-only -#![feature(dyn_trait)] #![feature(raw_identifiers)] fn test_if() { diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.rs b/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.rs index e573ad8fc1f..6c83205d050 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.rs +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.rs @@ -13,8 +13,6 @@ // // cc #48468 -#![feature(dyn_trait)] - use std::fmt::Debug; struct Foo { diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs b/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs index 9640d346597..247492fb7b7 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.rs @@ -13,8 +13,6 @@ // // cc #48468 -#![feature(dyn_trait)] - fn a(items: &[T]) -> Box> { // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime -- cgit 1.4.1-3-g733a5 From 55a653dd359a6e5c8da7e47399310a79fd094932 Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Fri, 13 Apr 2018 17:07:33 -0500 Subject: removed linting for dyn_trait --- src/librustc/hir/lowering.rs | 16 +++++++--------- src/librustc_typeck/lib.rs | 1 - 2 files changed, 7 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 4023521147e..74fedd6bfba 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -4107,15 +4107,13 @@ impl<'a> LoweringContext<'a> { } fn maybe_lint_bare_trait(&self, span: Span, id: NodeId, is_global: bool) { - if self.sess.features_untracked().dyn_trait { - self.sess.buffer_lint_with_diagnostic( - builtin::BARE_TRAIT_OBJECT, - id, - span, - "trait objects without an explicit `dyn` are deprecated", - builtin::BuiltinLintDiagnostics::BareTraitObject(span, is_global), - ) - } + self.sess.buffer_lint_with_diagnostic( + builtin::BARE_TRAIT_OBJECT, + id, + span, + "trait objects without an explicit `dyn` are deprecated", + builtin::BuiltinLintDiagnostics::BareTraitObject(span, is_global), + ) } fn wrap_in_try_constructor( diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index e852edc6eed..1e48926f2b3 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -84,7 +84,6 @@ This API is completely unstable and subject to change. #![feature(slice_patterns)] #![feature(slice_sort_by_cached_key)] #![feature(never_type)] -#![feature(underscore_lifetimes)] #[macro_use] extern crate log; #[macro_use] extern crate syntax; -- cgit 1.4.1-3-g733a5 From 4bf35f93c9e753b413a9ff5b2a79ae5b1efbd4b8 Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Fri, 13 Apr 2018 19:21:23 -0500 Subject: updated stderr files and removed feature-gate test for dyn_trait --- src/test/ui/feature-gate-dyn-trait.rs | 14 ------- src/test/ui/impl_trait_projections.stderr | 10 ++--- .../ui/in-band-lifetimes/impl/dyn-trait.stderr | 6 +-- .../projection-no-regions-closure.stderr | 24 +++++------ .../ty-outlives/projection-no-regions-fn.stderr | 8 ++-- .../projection-one-region-closure.stderr | 34 +++++++-------- ...rojection-one-region-trait-bound-closure.stderr | 32 +++++++-------- ...on-one-region-trait-bound-static-closure.stderr | 20 ++++----- ...rojection-two-region-trait-bound-closure.stderr | 48 +++++++++++----------- ...ty-param-closure-approximate-lower-bound.stderr | 16 ++++---- ...-param-closure-outlives-from-return-type.stderr | 12 +++--- ...param-closure-outlives-from-where-clause.stderr | 24 +++++------ .../ty-param-fn-body-nll-feature.stderr | 2 +- .../ui/nll/ty-outlives/ty-param-fn-body.stderr | 4 +- src/test/ui/nll/ty-outlives/ty-param-fn.stderr | 8 ++-- src/test/ui/raw-literal-keywords.stderr | 6 +-- .../dyn-trait-underscore-in-struct.stderr | 4 +- .../dyn-trait-underscore.stderr | 8 ++-- 18 files changed, 133 insertions(+), 147 deletions(-) delete mode 100644 src/test/ui/feature-gate-dyn-trait.rs (limited to 'src') diff --git a/src/test/ui/feature-gate-dyn-trait.rs b/src/test/ui/feature-gate-dyn-trait.rs deleted file mode 100644 index 4b3803d019b..00000000000 --- a/src/test/ui/feature-gate-dyn-trait.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -trait Trait {} -type A = Box; //~ ERROR `dyn Trait` syntax is unstable - -fn main() {} diff --git a/src/test/ui/impl_trait_projections.stderr b/src/test/ui/impl_trait_projections.stderr index 9b38de614fc..f0fe1a9754a 100644 --- a/src/test/ui/impl_trait_projections.stderr +++ b/src/test/ui/impl_trait_projections.stderr @@ -1,29 +1,29 @@ error[E0667]: `impl Trait` is not allowed in path parameters - --> $DIR/impl_trait_projections.rs:23:51 + --> $DIR/impl_trait_projections.rs:24:51 | LL | fn projection_is_disallowed(x: impl Iterator) -> ::Item { | ^^^^^^^^^^^^^ error[E0667]: `impl Trait` is not allowed in path parameters - --> $DIR/impl_trait_projections.rs:30:9 + --> $DIR/impl_trait_projections.rs:31:9 | LL | -> ::Item | ^^^^^^^^^^^^^ error[E0667]: `impl Trait` is not allowed in path parameters - --> $DIR/impl_trait_projections.rs:37:27 + --> $DIR/impl_trait_projections.rs:38:27 | LL | -> <::std::ops::Range as Iterator>::Item | ^^^^^^^^^^ error[E0667]: `impl Trait` is not allowed in path parameters - --> $DIR/impl_trait_projections.rs:44:29 + --> $DIR/impl_trait_projections.rs:45:29 | LL | -> as Iterator>::Item | ^^^^^^^^^^ error[E0223]: ambiguous associated type - --> $DIR/impl_trait_projections.rs:23:50 + --> $DIR/impl_trait_projections.rs:24:50 | LL | fn projection_is_disallowed(x: impl Iterator) -> ::Item { | ^^^^^^^^^^^^^^^^^^^^^ ambiguous associated type diff --git a/src/test/ui/in-band-lifetimes/impl/dyn-trait.stderr b/src/test/ui/in-band-lifetimes/impl/dyn-trait.stderr index 9d6a318c075..201470abe67 100644 --- a/src/test/ui/in-band-lifetimes/impl/dyn-trait.stderr +++ b/src/test/ui/in-band-lifetimes/impl/dyn-trait.stderr @@ -1,11 +1,11 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements - --> $DIR/dyn-trait.rs:33:16 + --> $DIR/dyn-trait.rs:32:16 | LL | static_val(x); //~ ERROR cannot infer | ^ | -note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 32:1... - --> $DIR/dyn-trait.rs:32:1 +note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 31:1... + --> $DIR/dyn-trait.rs:31:1 | LL | fn with_dyn_debug_static<'a>(x: Box) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr index 0efbbdff12a..3689ca74adb 100644 --- a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr @@ -1,17 +1,17 @@ warning: not reporting region error due to nll - --> $DIR/projection-no-regions-closure.rs:36:31 + --> $DIR/projection-no-regions-closure.rs:35:31 | LL | with_signature(x, |mut y| Box::new(y.next())) | ^^^^^^^^^^^^^^^^^^ warning: not reporting region error due to nll - --> $DIR/projection-no-regions-closure.rs:54:31 + --> $DIR/projection-no-regions-closure.rs:53:31 | LL | with_signature(x, |mut y| Box::new(y.next())) | ^^^^^^^^^^^^^^^^^^ note: External requirements - --> $DIR/projection-no-regions-closure.rs:36:23 + --> $DIR/projection-no-regions-closure.rs:35:23 | LL | with_signature(x, |mut y| Box::new(y.next())) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -26,7 +26,7 @@ LL | with_signature(x, |mut y| Box::new(y.next())) = note: where ::Item: '_#2r error[E0309]: the associated type `::Item` may not live long enough - --> $DIR/projection-no-regions-closure.rs:36:23 + --> $DIR/projection-no-regions-closure.rs:35:23 | LL | with_signature(x, |mut y| Box::new(y.next())) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -34,7 +34,7 @@ LL | with_signature(x, |mut y| Box::new(y.next())) = help: consider adding an explicit lifetime bound `::Item: ReEarlyBound(0, 'a)`... note: No external requirements - --> $DIR/projection-no-regions-closure.rs:32:1 + --> $DIR/projection-no-regions-closure.rs:31:1 | LL | / fn no_region<'a, T>(x: Box) -> Box LL | | where @@ -51,7 +51,7 @@ LL | | } ] note: External requirements - --> $DIR/projection-no-regions-closure.rs:46:23 + --> $DIR/projection-no-regions-closure.rs:45:23 | LL | with_signature(x, |mut y| Box::new(y.next())) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -66,7 +66,7 @@ LL | with_signature(x, |mut y| Box::new(y.next())) = note: where ::Item: '_#2r note: No external requirements - --> $DIR/projection-no-regions-closure.rs:42:1 + --> $DIR/projection-no-regions-closure.rs:41:1 | LL | / fn correct_region<'a, T>(x: Box) -> Box LL | | where @@ -82,7 +82,7 @@ LL | | } ] note: External requirements - --> $DIR/projection-no-regions-closure.rs:54:23 + --> $DIR/projection-no-regions-closure.rs:53:23 | LL | with_signature(x, |mut y| Box::new(y.next())) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -98,7 +98,7 @@ LL | with_signature(x, |mut y| Box::new(y.next())) = note: where ::Item: '_#3r error[E0309]: the associated type `::Item` may not live long enough - --> $DIR/projection-no-regions-closure.rs:54:23 + --> $DIR/projection-no-regions-closure.rs:53:23 | LL | with_signature(x, |mut y| Box::new(y.next())) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -106,7 +106,7 @@ LL | with_signature(x, |mut y| Box::new(y.next())) = help: consider adding an explicit lifetime bound `::Item: ReEarlyBound(0, 'a)`... note: No external requirements - --> $DIR/projection-no-regions-closure.rs:50:1 + --> $DIR/projection-no-regions-closure.rs:49:1 | LL | / fn wrong_region<'a, 'b, T>(x: Box) -> Box LL | | where @@ -124,7 +124,7 @@ LL | | } ] note: External requirements - --> $DIR/projection-no-regions-closure.rs:65:23 + --> $DIR/projection-no-regions-closure.rs:64:23 | LL | with_signature(x, |mut y| Box::new(y.next())) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -140,7 +140,7 @@ LL | with_signature(x, |mut y| Box::new(y.next())) = note: where ::Item: '_#3r note: No external requirements - --> $DIR/projection-no-regions-closure.rs:60:1 + --> $DIR/projection-no-regions-closure.rs:59:1 | LL | / fn outlives_region<'a, 'b, T>(x: Box) -> Box LL | | where diff --git a/src/test/ui/nll/ty-outlives/projection-no-regions-fn.stderr b/src/test/ui/nll/ty-outlives/projection-no-regions-fn.stderr index b2c5f28268d..3199ec15133 100644 --- a/src/test/ui/nll/ty-outlives/projection-no-regions-fn.stderr +++ b/src/test/ui/nll/ty-outlives/projection-no-regions-fn.stderr @@ -1,17 +1,17 @@ warning: not reporting region error due to nll - --> $DIR/projection-no-regions-fn.rs:24:5 + --> $DIR/projection-no-regions-fn.rs:23:5 | LL | Box::new(x.next()) | ^^^^^^^^^^^^^^^^^^ warning: not reporting region error due to nll - --> $DIR/projection-no-regions-fn.rs:40:5 + --> $DIR/projection-no-regions-fn.rs:39:5 | LL | Box::new(x.next()) | ^^^^^^^^^^^^^^^^^^ error[E0309]: the associated type `::Item` may not live long enough - --> $DIR/projection-no-regions-fn.rs:24:5 + --> $DIR/projection-no-regions-fn.rs:23:5 | LL | Box::new(x.next()) | ^^^^^^^^^^^^^^^^^^ @@ -19,7 +19,7 @@ LL | Box::new(x.next()) = help: consider adding an explicit lifetime bound `::Item: ReEarlyBound(0, 'a)`... error[E0309]: the associated type `::Item` may not live long enough - --> $DIR/projection-no-regions-fn.rs:40:5 + --> $DIR/projection-no-regions-fn.rs:39:5 | LL | Box::new(x.next()) | ^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr index 0d5a2dc7c55..e1218830dbb 100644 --- a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr @@ -1,23 +1,23 @@ warning: not reporting region error due to nll - --> $DIR/projection-one-region-closure.rs:56:39 + --> $DIR/projection-one-region-closure.rs:55:39 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^ warning: not reporting region error due to nll - --> $DIR/projection-one-region-closure.rs:68:39 + --> $DIR/projection-one-region-closure.rs:67:39 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^ warning: not reporting region error due to nll - --> $DIR/projection-one-region-closure.rs:90:39 + --> $DIR/projection-one-region-closure.rs:89:39 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^ note: External requirements - --> $DIR/projection-one-region-closure.rs:56:29 + --> $DIR/projection-one-region-closure.rs:55:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: where '_#1r: '_#2r error[E0309]: the parameter type `T` may not live long enough - --> $DIR/projection-one-region-closure.rs:56:29 + --> $DIR/projection-one-region-closure.rs:55:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -41,13 +41,13 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:8 ~ projection_one_region_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:16), 'a))`... error: free region `ReEarlyBound(0, 'b)` does not outlive free region `ReFree(DefId(0/0:8 ~ projection_one_region_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:16), 'a))` - --> $DIR/projection-one-region-closure.rs:56:20 + --> $DIR/projection-one-region-closure.rs:55:20 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^ note: No external requirements - --> $DIR/projection-one-region-closure.rs:52:1 + --> $DIR/projection-one-region-closure.rs:51:1 | LL | / fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T) LL | | where @@ -64,7 +64,7 @@ LL | | } ] note: External requirements - --> $DIR/projection-one-region-closure.rs:68:29 + --> $DIR/projection-one-region-closure.rs:67:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -81,7 +81,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: where '_#2r: '_#3r error[E0309]: the parameter type `T` may not live long enough - --> $DIR/projection-one-region-closure.rs:68:29 + --> $DIR/projection-one-region-closure.rs:67:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -89,13 +89,13 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`... error: free region `ReEarlyBound(1, 'b)` does not outlive free region `ReEarlyBound(0, 'a)` - --> $DIR/projection-one-region-closure.rs:68:20 + --> $DIR/projection-one-region-closure.rs:67:20 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^ note: No external requirements - --> $DIR/projection-one-region-closure.rs:63:1 + --> $DIR/projection-one-region-closure.rs:62:1 | LL | / fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T) LL | | where @@ -113,7 +113,7 @@ LL | | } ] note: External requirements - --> $DIR/projection-one-region-closure.rs:90:29 + --> $DIR/projection-one-region-closure.rs:89:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -130,7 +130,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: where '_#2r: '_#3r error[E0309]: the parameter type `T` may not live long enough - --> $DIR/projection-one-region-closure.rs:90:29 + --> $DIR/projection-one-region-closure.rs:89:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -138,13 +138,13 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`... error: free region `ReEarlyBound(1, 'b)` does not outlive free region `ReEarlyBound(0, 'a)` - --> $DIR/projection-one-region-closure.rs:90:20 + --> $DIR/projection-one-region-closure.rs:89:20 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^ note: No external requirements - --> $DIR/projection-one-region-closure.rs:75:1 + --> $DIR/projection-one-region-closure.rs:74:1 | LL | / fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T) LL | | where @@ -162,7 +162,7 @@ LL | | } ] note: External requirements - --> $DIR/projection-one-region-closure.rs:103:29 + --> $DIR/projection-one-region-closure.rs:102:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -179,7 +179,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: where '_#2r: '_#3r note: No external requirements - --> $DIR/projection-one-region-closure.rs:97:1 + --> $DIR/projection-one-region-closure.rs:96:1 | LL | / fn elements_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T) LL | | where diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr index d4aca8380b4..76554e29f62 100644 --- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr @@ -1,23 +1,23 @@ warning: not reporting region error due to nll - --> $DIR/projection-one-region-trait-bound-closure.rs:48:39 + --> $DIR/projection-one-region-trait-bound-closure.rs:47:39 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^ warning: not reporting region error due to nll - --> $DIR/projection-one-region-trait-bound-closure.rs:59:39 + --> $DIR/projection-one-region-trait-bound-closure.rs:58:39 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^ warning: not reporting region error due to nll - --> $DIR/projection-one-region-trait-bound-closure.rs:80:39 + --> $DIR/projection-one-region-trait-bound-closure.rs:79:39 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^ note: External requirements - --> $DIR/projection-one-region-trait-bound-closure.rs:48:29 + --> $DIR/projection-one-region-trait-bound-closure.rs:47:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -32,13 +32,13 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: where '_#1r: '_#2r error: free region `ReEarlyBound(0, 'b)` does not outlive free region `ReFree(DefId(0/0:8 ~ projection_one_region_trait_bound_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:16), 'a))` - --> $DIR/projection-one-region-trait-bound-closure.rs:48:20 + --> $DIR/projection-one-region-trait-bound-closure.rs:47:20 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^ note: No external requirements - --> $DIR/projection-one-region-trait-bound-closure.rs:44:1 + --> $DIR/projection-one-region-trait-bound-closure.rs:43:1 | LL | / fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T) LL | | where @@ -55,7 +55,7 @@ LL | | } ] note: External requirements - --> $DIR/projection-one-region-trait-bound-closure.rs:59:29 + --> $DIR/projection-one-region-trait-bound-closure.rs:58:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -71,13 +71,13 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: where '_#2r: '_#3r error: free region `ReEarlyBound(1, 'b)` does not outlive free region `ReEarlyBound(0, 'a)` - --> $DIR/projection-one-region-trait-bound-closure.rs:59:20 + --> $DIR/projection-one-region-trait-bound-closure.rs:58:20 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^ note: No external requirements - --> $DIR/projection-one-region-trait-bound-closure.rs:54:1 + --> $DIR/projection-one-region-trait-bound-closure.rs:53:1 | LL | / fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T) LL | | where @@ -95,7 +95,7 @@ LL | | } ] note: External requirements - --> $DIR/projection-one-region-trait-bound-closure.rs:80:29 + --> $DIR/projection-one-region-trait-bound-closure.rs:79:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -111,13 +111,13 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: where '_#2r: '_#3r error: free region `ReEarlyBound(1, 'b)` does not outlive free region `ReEarlyBound(0, 'a)` - --> $DIR/projection-one-region-trait-bound-closure.rs:80:20 + --> $DIR/projection-one-region-trait-bound-closure.rs:79:20 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^ note: No external requirements - --> $DIR/projection-one-region-trait-bound-closure.rs:65:1 + --> $DIR/projection-one-region-trait-bound-closure.rs:64:1 | LL | / fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T) LL | | where @@ -135,7 +135,7 @@ LL | | } ] note: External requirements - --> $DIR/projection-one-region-trait-bound-closure.rs:91:29 + --> $DIR/projection-one-region-trait-bound-closure.rs:90:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -151,7 +151,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: where '_#2r: '_#3r note: No external requirements - --> $DIR/projection-one-region-trait-bound-closure.rs:86:1 + --> $DIR/projection-one-region-trait-bound-closure.rs:85:1 | LL | / fn elements_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T) LL | | where @@ -169,7 +169,7 @@ LL | | } ] note: External requirements - --> $DIR/projection-one-region-trait-bound-closure.rs:103:29 + --> $DIR/projection-one-region-trait-bound-closure.rs:102:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -184,7 +184,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: where '_#1r: '_#2r note: No external requirements - --> $DIR/projection-one-region-trait-bound-closure.rs:95:1 + --> $DIR/projection-one-region-trait-bound-closure.rs:94:1 | LL | / fn one_region<'a, T>(cell: Cell<&'a ()>, t: T) LL | | where diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr index 875907e6b39..136e143e80e 100644 --- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.stderr @@ -1,5 +1,5 @@ note: No external requirements - --> $DIR/projection-one-region-trait-bound-static-closure.rs:47:29 + --> $DIR/projection-one-region-trait-bound-static-closure.rs:46:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -12,7 +12,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); ] note: No external requirements - --> $DIR/projection-one-region-trait-bound-static-closure.rs:43:1 + --> $DIR/projection-one-region-trait-bound-static-closure.rs:42:1 | LL | / fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T) LL | | where @@ -28,7 +28,7 @@ LL | | } ] note: No external requirements - --> $DIR/projection-one-region-trait-bound-static-closure.rs:56:29 + --> $DIR/projection-one-region-trait-bound-static-closure.rs:55:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -42,7 +42,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); ] note: No external requirements - --> $DIR/projection-one-region-trait-bound-static-closure.rs:51:1 + --> $DIR/projection-one-region-trait-bound-static-closure.rs:50:1 | LL | / fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T) LL | | where @@ -60,7 +60,7 @@ LL | | } ] note: No external requirements - --> $DIR/projection-one-region-trait-bound-static-closure.rs:75:29 + --> $DIR/projection-one-region-trait-bound-static-closure.rs:74:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -74,7 +74,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); ] note: No external requirements - --> $DIR/projection-one-region-trait-bound-static-closure.rs:60:1 + --> $DIR/projection-one-region-trait-bound-static-closure.rs:59:1 | LL | / fn projection_outlives<'a, 'b, T>(cell: Cell<&'a ()>, t: T) LL | | where @@ -92,7 +92,7 @@ LL | | } ] note: No external requirements - --> $DIR/projection-one-region-trait-bound-static-closure.rs:84:29 + --> $DIR/projection-one-region-trait-bound-static-closure.rs:83:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -106,7 +106,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); ] note: No external requirements - --> $DIR/projection-one-region-trait-bound-static-closure.rs:79:1 + --> $DIR/projection-one-region-trait-bound-static-closure.rs:78:1 | LL | / fn elements_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T) LL | | where @@ -124,7 +124,7 @@ LL | | } ] note: No external requirements - --> $DIR/projection-one-region-trait-bound-static-closure.rs:96:29 + --> $DIR/projection-one-region-trait-bound-static-closure.rs:95:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -137,7 +137,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); ] note: No external requirements - --> $DIR/projection-one-region-trait-bound-static-closure.rs:88:1 + --> $DIR/projection-one-region-trait-bound-static-closure.rs:87:1 | LL | / fn one_region<'a, T>(cell: Cell<&'a ()>, t: T) LL | | where diff --git a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr index 7e36e467e4e..c7f45692960 100644 --- a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr @@ -1,29 +1,29 @@ warning: not reporting region error due to nll - --> $DIR/projection-two-region-trait-bound-closure.rs:49:39 + --> $DIR/projection-two-region-trait-bound-closure.rs:48:39 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^ warning: not reporting region error due to nll - --> $DIR/projection-two-region-trait-bound-closure.rs:60:39 + --> $DIR/projection-two-region-trait-bound-closure.rs:59:39 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^ warning: not reporting region error due to nll - --> $DIR/projection-two-region-trait-bound-closure.rs:81:39 + --> $DIR/projection-two-region-trait-bound-closure.rs:80:39 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^ warning: not reporting region error due to nll - --> $DIR/projection-two-region-trait-bound-closure.rs:109:39 + --> $DIR/projection-two-region-trait-bound-closure.rs:108:39 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^ note: External requirements - --> $DIR/projection-two-region-trait-bound-closure.rs:49:29 + --> $DIR/projection-two-region-trait-bound-closure.rs:48:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -39,7 +39,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: where >::AssocType: '_#3r error[E0309]: the associated type `>::AssocType` may not live long enough - --> $DIR/projection-two-region-trait-bound-closure.rs:49:29 + --> $DIR/projection-two-region-trait-bound-closure.rs:48:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -47,7 +47,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = help: consider adding an explicit lifetime bound `>::AssocType: ReFree(DefId(0/0:8 ~ projection_two_region_trait_bound_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:18), 'a))`... note: No external requirements - --> $DIR/projection-two-region-trait-bound-closure.rs:45:1 + --> $DIR/projection-two-region-trait-bound-closure.rs:44:1 | LL | / fn no_relationships_late<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T) LL | | where @@ -65,7 +65,7 @@ LL | | } ] note: External requirements - --> $DIR/projection-two-region-trait-bound-closure.rs:60:29 + --> $DIR/projection-two-region-trait-bound-closure.rs:59:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -82,7 +82,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: where >::AssocType: '_#4r error[E0309]: the associated type `>::AssocType` may not live long enough - --> $DIR/projection-two-region-trait-bound-closure.rs:60:29 + --> $DIR/projection-two-region-trait-bound-closure.rs:59:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -90,7 +90,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = help: consider adding an explicit lifetime bound `>::AssocType: ReEarlyBound(0, 'a)`... note: No external requirements - --> $DIR/projection-two-region-trait-bound-closure.rs:55:1 + --> $DIR/projection-two-region-trait-bound-closure.rs:54:1 | LL | / fn no_relationships_early<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T) LL | | where @@ -109,7 +109,7 @@ LL | | } ] note: External requirements - --> $DIR/projection-two-region-trait-bound-closure.rs:81:29 + --> $DIR/projection-two-region-trait-bound-closure.rs:80:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -126,7 +126,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: where >::AssocType: '_#4r error[E0309]: the associated type `>::AssocType` may not live long enough - --> $DIR/projection-two-region-trait-bound-closure.rs:81:29 + --> $DIR/projection-two-region-trait-bound-closure.rs:80:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -134,7 +134,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = help: consider adding an explicit lifetime bound `>::AssocType: ReEarlyBound(0, 'a)`... note: No external requirements - --> $DIR/projection-two-region-trait-bound-closure.rs:66:1 + --> $DIR/projection-two-region-trait-bound-closure.rs:65:1 | LL | / fn projection_outlives<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T) LL | | where @@ -153,7 +153,7 @@ LL | | } ] note: External requirements - --> $DIR/projection-two-region-trait-bound-closure.rs:92:29 + --> $DIR/projection-two-region-trait-bound-closure.rs:91:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -170,7 +170,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: where >::AssocType: '_#4r note: No external requirements - --> $DIR/projection-two-region-trait-bound-closure.rs:87:1 + --> $DIR/projection-two-region-trait-bound-closure.rs:86:1 | LL | / fn elements_outlive1<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T) LL | | where @@ -189,7 +189,7 @@ LL | | } ] note: External requirements - --> $DIR/projection-two-region-trait-bound-closure.rs:101:29 + --> $DIR/projection-two-region-trait-bound-closure.rs:100:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -206,7 +206,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: where >::AssocType: '_#4r note: No external requirements - --> $DIR/projection-two-region-trait-bound-closure.rs:96:1 + --> $DIR/projection-two-region-trait-bound-closure.rs:95:1 | LL | / fn elements_outlive2<'a, 'b, 'c, T>(cell: Cell<&'a ()>, t: T) LL | | where @@ -225,7 +225,7 @@ LL | | } ] note: External requirements - --> $DIR/projection-two-region-trait-bound-closure.rs:109:29 + --> $DIR/projection-two-region-trait-bound-closure.rs:108:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -240,13 +240,13 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: where >::AssocType: '_#2r error: free region `ReEarlyBound(0, 'b)` does not outlive free region `ReFree(DefId(0/0:13 ~ projection_two_region_trait_bound_closure[317d]::two_regions[0]), BrNamed(crate0:DefIndex(1:43), 'a))` - --> $DIR/projection-two-region-trait-bound-closure.rs:109:20 + --> $DIR/projection-two-region-trait-bound-closure.rs:108:20 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^ note: No external requirements - --> $DIR/projection-two-region-trait-bound-closure.rs:105:1 + --> $DIR/projection-two-region-trait-bound-closure.rs:104:1 | LL | / fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T) LL | | where @@ -263,7 +263,7 @@ LL | | } ] note: External requirements - --> $DIR/projection-two-region-trait-bound-closure.rs:120:29 + --> $DIR/projection-two-region-trait-bound-closure.rs:119:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -279,7 +279,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: where >::AssocType: '_#3r note: No external requirements - --> $DIR/projection-two-region-trait-bound-closure.rs:115:1 + --> $DIR/projection-two-region-trait-bound-closure.rs:114:1 | LL | / fn two_regions_outlive<'a, 'b, T>(cell: Cell<&'a ()>, t: T) LL | | where @@ -297,7 +297,7 @@ LL | | } ] note: External requirements - --> $DIR/projection-two-region-trait-bound-closure.rs:132:29 + --> $DIR/projection-two-region-trait-bound-closure.rs:131:29 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -312,7 +312,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: where >::AssocType: '_#2r note: No external requirements - --> $DIR/projection-two-region-trait-bound-closure.rs:124:1 + --> $DIR/projection-two-region-trait-bound-closure.rs:123:1 | LL | / fn one_region<'a, T>(cell: Cell<&'a ()>, t: T) LL | | where diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr index c8feaddff93..b4f51401a90 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr @@ -1,23 +1,23 @@ warning: not reporting region error due to nll - --> $DIR/ty-param-closure-approximate-lower-bound.rs:35:31 + --> $DIR/ty-param-closure-approximate-lower-bound.rs:34:31 | LL | twice(cell, value, |a, b| invoke(a, b)); | ^^^^^^^^^^^^ warning: not reporting region error due to nll - --> $DIR/ty-param-closure-approximate-lower-bound.rs:43:31 + --> $DIR/ty-param-closure-approximate-lower-bound.rs:42:31 | LL | twice(cell, value, |a, b| invoke(a, b)); | ^^^^^^ warning: not reporting region error due to nll - --> $DIR/ty-param-closure-approximate-lower-bound.rs:43:31 + --> $DIR/ty-param-closure-approximate-lower-bound.rs:42:31 | LL | twice(cell, value, |a, b| invoke(a, b)); | ^^^^^^^^^^^^ note: External requirements - --> $DIR/ty-param-closure-approximate-lower-bound.rs:35:24 + --> $DIR/ty-param-closure-approximate-lower-bound.rs:34:24 | LL | twice(cell, value, |a, b| invoke(a, b)); | ^^^^^^^^^^^^^^^^^^^ @@ -31,7 +31,7 @@ LL | twice(cell, value, |a, b| invoke(a, b)); = note: where T: '_#1r note: No external requirements - --> $DIR/ty-param-closure-approximate-lower-bound.rs:33:1 + --> $DIR/ty-param-closure-approximate-lower-bound.rs:32:1 | LL | / fn generic(value: T) { LL | | let cell = Cell::new(&()); @@ -47,7 +47,7 @@ LL | | } ] note: External requirements - --> $DIR/ty-param-closure-approximate-lower-bound.rs:43:24 + --> $DIR/ty-param-closure-approximate-lower-bound.rs:42:24 | LL | twice(cell, value, |a, b| invoke(a, b)); | ^^^^^^^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL | twice(cell, value, |a, b| invoke(a, b)); = note: where T: '_#1r error[E0309]: the parameter type `T` may not live long enough - --> $DIR/ty-param-closure-approximate-lower-bound.rs:43:24 + --> $DIR/ty-param-closure-approximate-lower-bound.rs:42:24 | LL | twice(cell, value, |a, b| invoke(a, b)); | ^^^^^^^^^^^^^^^^^^^ @@ -69,7 +69,7 @@ LL | twice(cell, value, |a, b| invoke(a, b)); = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:6 ~ ty_param_closure_approximate_lower_bound[317d]::generic_fail[0]), BrNamed(crate0:DefIndex(1:15), 'a))`... note: No external requirements - --> $DIR/ty-param-closure-approximate-lower-bound.rs:42:1 + --> $DIR/ty-param-closure-approximate-lower-bound.rs:41:1 | LL | / fn generic_fail<'a, T>(cell: Cell<&'a ()>, value: T) { LL | | twice(cell, value, |a, b| invoke(a, b)); diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr index 500595e0c5d..59a8a39a7b0 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr @@ -1,17 +1,17 @@ warning: not reporting region error due to nll - --> $DIR/ty-param-closure-outlives-from-return-type.rs:37:27 + --> $DIR/ty-param-closure-outlives-from-return-type.rs:36:27 | LL | with_signature(x, |y| y) | ^ warning: not reporting region error due to nll - --> $DIR/ty-param-closure-outlives-from-return-type.rs:53:5 + --> $DIR/ty-param-closure-outlives-from-return-type.rs:52:5 | LL | x | ^ note: External requirements - --> $DIR/ty-param-closure-outlives-from-return-type.rs:37:23 + --> $DIR/ty-param-closure-outlives-from-return-type.rs:36:23 | LL | with_signature(x, |y| y) | ^^^^^ @@ -26,7 +26,7 @@ LL | with_signature(x, |y| y) = note: where T: '_#2r error[E0309]: the parameter type `T` may not live long enough - --> $DIR/ty-param-closure-outlives-from-return-type.rs:37:23 + --> $DIR/ty-param-closure-outlives-from-return-type.rs:36:23 | LL | with_signature(x, |y| y) | ^^^^^ @@ -34,7 +34,7 @@ LL | with_signature(x, |y| y) = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`... note: No external requirements - --> $DIR/ty-param-closure-outlives-from-return-type.rs:26:1 + --> $DIR/ty-param-closure-outlives-from-return-type.rs:25:1 | LL | / fn no_region<'a, T>(x: Box) -> Box LL | | where @@ -51,7 +51,7 @@ LL | | } ] error[E0309]: the parameter type `T` may not live long enough - --> $DIR/ty-param-closure-outlives-from-return-type.rs:53:5 + --> $DIR/ty-param-closure-outlives-from-return-type.rs:52:5 | LL | x | ^ diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr index 4d8a66ba8e1..a53ce21b7e6 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr @@ -1,17 +1,17 @@ warning: not reporting region error due to nll - --> $DIR/ty-param-closure-outlives-from-where-clause.rs:45:9 + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:44:9 | LL | require(&x, &y) | ^^^^^^^ warning: not reporting region error due to nll - --> $DIR/ty-param-closure-outlives-from-where-clause.rs:79:9 + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:78:9 | LL | require(&x, &y) | ^^^^^^^ note: External requirements - --> $DIR/ty-param-closure-outlives-from-where-clause.rs:38:26 + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:37:26 | LL | with_signature(a, b, |x, y| { | __________________________^ @@ -32,7 +32,7 @@ LL | | }) = note: where T: '_#1r error[E0309]: the parameter type `T` may not live long enough - --> $DIR/ty-param-closure-outlives-from-where-clause.rs:38:26 + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:37:26 | LL | with_signature(a, b, |x, y| { | __________________________^ @@ -47,7 +47,7 @@ LL | | }) = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:6 ~ ty_param_closure_outlives_from_where_clause[317d]::no_region[0]), BrNamed(crate0:DefIndex(1:14), 'a))`... note: No external requirements - --> $DIR/ty-param-closure-outlives-from-where-clause.rs:37:1 + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:36:1 | LL | / fn no_region<'a, T>(a: Cell<&'a ()>, b: T) { LL | | with_signature(a, b, |x, y| { @@ -63,7 +63,7 @@ LL | | } ] note: External requirements - --> $DIR/ty-param-closure-outlives-from-where-clause.rs:55:26 + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:54:26 | LL | with_signature(a, b, |x, y| { | __________________________^ @@ -85,7 +85,7 @@ LL | | }) = note: where T: '_#2r note: No external requirements - --> $DIR/ty-param-closure-outlives-from-where-clause.rs:51:1 + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:50:1 | LL | / fn correct_region<'a, T>(a: Cell<&'a ()>, b: T) LL | | where @@ -102,7 +102,7 @@ LL | | } ] note: External requirements - --> $DIR/ty-param-closure-outlives-from-where-clause.rs:76:26 + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:75:26 | LL | with_signature(a, b, |x, y| { | __________________________^ @@ -123,7 +123,7 @@ LL | | }) = note: where T: '_#2r error[E0309]: the parameter type `T` may not live long enough - --> $DIR/ty-param-closure-outlives-from-where-clause.rs:76:26 + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:75:26 | LL | with_signature(a, b, |x, y| { | __________________________^ @@ -137,7 +137,7 @@ LL | | }) = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:8 ~ ty_param_closure_outlives_from_where_clause[317d]::wrong_region[0]), BrNamed(crate0:DefIndex(1:20), 'a))`... note: No external requirements - --> $DIR/ty-param-closure-outlives-from-where-clause.rs:72:1 + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:71:1 | LL | / fn wrong_region<'a, 'b, T>(a: Cell<&'a ()>, b: T) LL | | where @@ -154,7 +154,7 @@ LL | | } ] note: External requirements - --> $DIR/ty-param-closure-outlives-from-where-clause.rs:90:26 + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:89:26 | LL | with_signature(a, b, |x, y| { | __________________________^ @@ -174,7 +174,7 @@ LL | | }) = note: where T: '_#3r note: No external requirements - --> $DIR/ty-param-closure-outlives-from-where-clause.rs:85:1 + --> $DIR/ty-param-closure-outlives-from-where-clause.rs:84:1 | LL | / fn outlives_region<'a, 'b, T>(a: Cell<&'a ()>, b: T) LL | | where diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.stderr b/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.stderr index 1510ca61e5c..dec15f47a03 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-fn-body-nll-feature.stderr @@ -1,5 +1,5 @@ error[E0309]: the parameter type `T` may not live long enough - --> $DIR/ty-param-fn-body-nll-feature.rs:31:5 + --> $DIR/ty-param-fn-body-nll-feature.rs:30:5 | LL | outlives(cell, t) | ^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn-body.stderr b/src/test/ui/nll/ty-outlives/ty-param-fn-body.stderr index 0596861e67b..537f1223470 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-fn-body.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-fn-body.stderr @@ -1,11 +1,11 @@ warning: not reporting region error due to nll - --> $DIR/ty-param-fn-body.rs:30:5 + --> $DIR/ty-param-fn-body.rs:29:5 | LL | outlives(cell, t) | ^^^^^^^^ error[E0309]: the parameter type `T` may not live long enough - --> $DIR/ty-param-fn-body.rs:30:5 + --> $DIR/ty-param-fn-body.rs:29:5 | LL | outlives(cell, t) | ^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn.stderr b/src/test/ui/nll/ty-outlives/ty-param-fn.stderr index 0d09cac8c38..5ce50d81185 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-fn.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-fn.stderr @@ -1,17 +1,17 @@ warning: not reporting region error due to nll - --> $DIR/ty-param-fn.rs:22:5 + --> $DIR/ty-param-fn.rs:21:5 | LL | x | ^ warning: not reporting region error due to nll - --> $DIR/ty-param-fn.rs:38:5 + --> $DIR/ty-param-fn.rs:37:5 | LL | x | ^ error[E0309]: the parameter type `T` may not live long enough - --> $DIR/ty-param-fn.rs:22:5 + --> $DIR/ty-param-fn.rs:21:5 | LL | x | ^ @@ -19,7 +19,7 @@ LL | x = help: consider adding an explicit lifetime bound `T: 'a`... error[E0309]: the parameter type `T` may not live long enough - --> $DIR/ty-param-fn.rs:38:5 + --> $DIR/ty-param-fn.rs:37:5 | LL | x | ^ diff --git a/src/test/ui/raw-literal-keywords.stderr b/src/test/ui/raw-literal-keywords.stderr index 3758568323c..022f80ae8a4 100644 --- a/src/test/ui/raw-literal-keywords.stderr +++ b/src/test/ui/raw-literal-keywords.stderr @@ -1,17 +1,17 @@ error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `true` - --> $DIR/raw-literal-keywords.rs:17:10 + --> $DIR/raw-literal-keywords.rs:16:10 | LL | r#if true { } //~ ERROR found `true` | ^^^^ expected one of 8 possible tokens here error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `Test` - --> $DIR/raw-literal-keywords.rs:21:14 + --> $DIR/raw-literal-keywords.rs:20:14 | LL | r#struct Test; //~ ERROR found `Test` | ^^^^ expected one of 8 possible tokens here error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `Test` - --> $DIR/raw-literal-keywords.rs:25:13 + --> $DIR/raw-literal-keywords.rs:24:13 | LL | r#union Test; //~ ERROR found `Test` | ^^^^ expected one of 8 possible tokens here diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr index 6d777841f03..1017217828a 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr @@ -1,11 +1,11 @@ error[E0106]: missing lifetime specifier - --> $DIR/dyn-trait-underscore-in-struct.rs:21:24 + --> $DIR/dyn-trait-underscore-in-struct.rs:19:24 | LL | x: Box, //~ ERROR missing lifetime specifier | ^^ expected lifetime parameter error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound - --> $DIR/dyn-trait-underscore-in-struct.rs:21:12 + --> $DIR/dyn-trait-underscore-in-struct.rs:19:12 | LL | x: Box, //~ ERROR missing lifetime specifier | ^^^^^^^^^^^^^^ diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr index f1e59aed54a..98249d3f2b5 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr @@ -1,11 +1,11 @@ error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements - --> $DIR/dyn-trait-underscore.rs:20:20 + --> $DIR/dyn-trait-underscore.rs:18:20 | LL | Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime | ^^^^ | -note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the function body at 18:1... - --> $DIR/dyn-trait-underscore.rs:18:1 +note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the function body at 16:1... + --> $DIR/dyn-trait-underscore.rs:16:1 | LL | / fn a(items: &[T]) -> Box> { LL | | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` @@ -13,7 +13,7 @@ LL | | Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime LL | | } | |_^ note: ...so that reference does not outlive borrowed content - --> $DIR/dyn-trait-underscore.rs:20:14 + --> $DIR/dyn-trait-underscore.rs:18:14 | LL | Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime | ^^^^^ -- cgit 1.4.1-3-g733a5 From 72a8eb92b083b22c610512c9c89c6bc97660de34 Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Sun, 15 Apr 2018 09:41:10 -0500 Subject: fixed rustc version for dyn_trait --- src/libsyntax/feature_gate.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index c4a0ec259b4..6ab8a54cf96 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -590,7 +590,7 @@ declare_features! ( // Allows #[target_feature(...)] (accepted, target_feature, "1.27.0", None, None), // Trait object syntax with `dyn` prefix - (accepted, dyn_trait, "1.22.0", Some(44662), None), + (accepted, dyn_trait, "1.27.0", Some(44662), None), ); // If you change this, please modify src/doc/unstable-book as well. You must -- cgit 1.4.1-3-g733a5 From cadf251b7874cbd94198ebef95e6260c118a2fef Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Wed, 18 Apr 2018 13:33:36 -0500 Subject: removed dyn trait attribute from librustdoc --- src/librustdoc/lib.rs | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 60b713f2995..1819c7eb7d1 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -23,7 +23,6 @@ #![feature(test)] #![feature(vec_remove_item)] #![feature(entry_and_modify)] -#![feature(dyn_trait)] extern crate arena; extern crate getopts; -- cgit 1.4.1-3-g733a5 From 74412d27074a0671fc68ea651f224a97d985e813 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 27 Apr 2018 17:14:29 +0200 Subject: fix search load page failure --- src/librustdoc/html/layout.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index fd54e9bd1e0..5e93b20ea17 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -146,9 +146,9 @@ pub fn render( window.rootPath = \"{root_path}\";\ window.currentCrate = \"{krate}\";\ \ + \ \ \ - \ \ ", css_extension = if css_file_extension { -- cgit 1.4.1-3-g733a5 From b80472d84c4b5b28fd22c5ef56af181bbf544c88 Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Wed, 25 Apr 2018 10:38:15 -0500 Subject: fixed tests --- src/test/compile-fail/impl-trait/where-allowed.rs | 3 --- src/test/ui/impl_trait_projections.rs | 3 --- src/test/ui/impl_trait_projections.stderr | 10 +++++----- src/test/ui/in-band-lifetimes/impl/dyn-trait.nll.stderr | 4 ++-- .../ui/underscore-lifetime/dyn-trait-underscore.nll.stderr | 10 +++++----- 5 files changed, 12 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/test/compile-fail/impl-trait/where-allowed.rs b/src/test/compile-fail/impl-trait/where-allowed.rs index f7b331238c6..2891cd59e3e 100644 --- a/src/test/compile-fail/impl-trait/where-allowed.rs +++ b/src/test/compile-fail/impl-trait/where-allowed.rs @@ -10,9 +10,6 @@ //! A simple test for testing many permutations of allowedness of //! impl Trait - -#![feature(conservative_impl_trait, universal_impl_trait)] - use std::fmt::Debug; // Allowed diff --git a/src/test/ui/impl_trait_projections.rs b/src/test/ui/impl_trait_projections.rs index e8f39e169ff..57a0040600a 100644 --- a/src/test/ui/impl_trait_projections.rs +++ b/src/test/ui/impl_trait_projections.rs @@ -7,9 +7,6 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. - -#![feature(conservative_impl_trait, universal_impl_trait)] - use std::fmt::Debug; use std::option; diff --git a/src/test/ui/impl_trait_projections.stderr b/src/test/ui/impl_trait_projections.stderr index f0fe1a9754a..f6d58984ece 100644 --- a/src/test/ui/impl_trait_projections.stderr +++ b/src/test/ui/impl_trait_projections.stderr @@ -1,29 +1,29 @@ error[E0667]: `impl Trait` is not allowed in path parameters - --> $DIR/impl_trait_projections.rs:24:51 + --> $DIR/impl_trait_projections.rs:21:51 | LL | fn projection_is_disallowed(x: impl Iterator) -> ::Item { | ^^^^^^^^^^^^^ error[E0667]: `impl Trait` is not allowed in path parameters - --> $DIR/impl_trait_projections.rs:31:9 + --> $DIR/impl_trait_projections.rs:28:9 | LL | -> ::Item | ^^^^^^^^^^^^^ error[E0667]: `impl Trait` is not allowed in path parameters - --> $DIR/impl_trait_projections.rs:38:27 + --> $DIR/impl_trait_projections.rs:35:27 | LL | -> <::std::ops::Range as Iterator>::Item | ^^^^^^^^^^ error[E0667]: `impl Trait` is not allowed in path parameters - --> $DIR/impl_trait_projections.rs:45:29 + --> $DIR/impl_trait_projections.rs:42:29 | LL | -> as Iterator>::Item | ^^^^^^^^^^ error[E0223]: ambiguous associated type - --> $DIR/impl_trait_projections.rs:24:50 + --> $DIR/impl_trait_projections.rs:21:50 | LL | fn projection_is_disallowed(x: impl Iterator) -> ::Item { | ^^^^^^^^^^^^^^^^^^^^^ ambiguous associated type diff --git a/src/test/ui/in-band-lifetimes/impl/dyn-trait.nll.stderr b/src/test/ui/in-band-lifetimes/impl/dyn-trait.nll.stderr index ec8c4ecf102..4cf7feddd46 100644 --- a/src/test/ui/in-band-lifetimes/impl/dyn-trait.nll.stderr +++ b/src/test/ui/in-band-lifetimes/impl/dyn-trait.nll.stderr @@ -1,11 +1,11 @@ warning: not reporting region error due to nll - --> $DIR/dyn-trait.rs:33:16 + --> $DIR/dyn-trait.rs:32:16 | LL | static_val(x); //~ ERROR cannot infer | ^ error: free region `'a` does not outlive free region `'static` - --> $DIR/dyn-trait.rs:33:5 + --> $DIR/dyn-trait.rs:32:5 | LL | static_val(x); //~ ERROR cannot infer | ^^^^^^^^^^^^^ diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr index 10a03786d7b..cdc0c78e694 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr @@ -1,29 +1,29 @@ warning: not reporting region error due to nll - --> $DIR/dyn-trait-underscore.rs:20:14 + --> $DIR/dyn-trait-underscore.rs:18:14 | LL | Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime | ^^^^^ warning: not reporting region error due to nll - --> $DIR/dyn-trait-underscore.rs:20:20 + --> $DIR/dyn-trait-underscore.rs:18:20 | LL | Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime | ^^^^ warning: not reporting region error due to nll - --> $DIR/dyn-trait-underscore.rs:20:5 + --> $DIR/dyn-trait-underscore.rs:18:5 | LL | Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime | ^^^^^^^^ warning: not reporting region error due to nll - --> $DIR/dyn-trait-underscore.rs:20:5 + --> $DIR/dyn-trait-underscore.rs:18:5 | LL | Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime | ^^^^^^^^^^^^^^^^^^^^^^ error: free region `` does not outlive free region `'static` - --> $DIR/dyn-trait-underscore.rs:18:52 + --> $DIR/dyn-trait-underscore.rs:16:52 | LL | fn a(items: &[T]) -> Box> { | ____________________________________________________^ -- cgit 1.4.1-3-g733a5 From b5c7cbf2f288967f55f8155a1ded7379ee4161f0 Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Wed, 25 Apr 2018 12:55:21 -0500 Subject: rustdoc asks for dyn_trait feature in stage0 --- src/librustdoc/lib.rs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 1819c7eb7d1..00153061fd5 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -13,6 +13,8 @@ html_root_url = "https://doc.rust-lang.org/nightly/", html_playground_url = "https://play.rust-lang.org/")] +#![cfg_attr(stage0, feature(dyn_trait))] + #![feature(ascii_ctype)] #![feature(rustc_private)] #![feature(box_patterns)] -- cgit 1.4.1-3-g733a5 From 902bc0fb1afb9eeb04c541787bcef37e67bfbcbe Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Fri, 27 Apr 2018 20:41:30 +0100 Subject: Access individual fields of tuples, closures and generators on drop. --- src/librustc_mir/borrow_check/mod.rs | 40 ++++++++++++++++------ src/test/run-pass/issue-47703-tuple.rs | 21 ++++++++++++ src/test/run-pass/nll/issue-48623-closure.rs | 24 +++++++++++++ src/test/run-pass/nll/issue-48623-generator.rs | 25 ++++++++++++++ .../ui/generator/yield-while-iterating.nll.stderr | 32 ++--------------- 5 files changed, 102 insertions(+), 40 deletions(-) create mode 100644 src/test/run-pass/issue-47703-tuple.rs create mode 100644 src/test/run-pass/nll/issue-48623-closure.rs create mode 100644 src/test/run-pass/nll/issue-48623-generator.rs (limited to 'src') diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 4dd8d245d3b..5c7061abbb6 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -20,7 +20,7 @@ use rustc::ty::maps::Providers; use rustc::mir::{AssertMessage, BasicBlock, BorrowKind, Location, Place}; use rustc::mir::{Mir, Mutability, Operand, Projection, ProjectionElem, Rvalue}; use rustc::mir::{Field, Statement, StatementKind, Terminator, TerminatorKind}; -use rustc::mir::ClosureRegionRequirements; +use rustc::mir::{ClosureRegionRequirements, Local}; use rustc_data_structures::control_flow_graph::dominators::Dominators; use rustc_data_structures::fx::FxHashSet; @@ -729,6 +729,17 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { erased_drop_place_ty: ty::Ty<'gcx>, span: Span, ) { + let gcx = self.tcx.global_tcx(); + let drop_field = | + mir: &mut MirBorrowckCtxt<'cx, 'gcx, 'tcx>, + (index, field): (usize, ty::Ty<'gcx>), + | { + let field_ty = gcx.normalize_erasing_regions(mir.param_env, field); + let place = drop_place.clone().field(Field::new(index), field_ty); + + mir.visit_terminator_drop(loc, term, flow_state, &place, field_ty, span); + }; + match erased_drop_place_ty.sty { // When a struct is being dropped, we need to check // whether it has a destructor, if it does, then we can @@ -737,14 +748,24 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // destructor but `bar` does not, we will only check for // borrows of `x.foo` and not `x.bar`. See #47703. ty::TyAdt(def, substs) if def.is_struct() && !def.has_dtor(self.tcx) => { - for (index, field) in def.all_fields().enumerate() { - let gcx = self.tcx.global_tcx(); - let field_ty = field.ty(gcx, substs); - let field_ty = gcx.normalize_erasing_regions(self.param_env, field_ty); - let place = drop_place.clone().field(Field::new(index), field_ty); - - self.visit_terminator_drop(loc, term, flow_state, &place, field_ty, span); - } + def.all_fields() + .map(|field| field.ty(gcx, substs)) + .enumerate() + .for_each(|field| drop_field(self, field)); + } + // Same as above, but for tuples. + ty::TyTuple(tys) => { + tys.iter().cloned().enumerate() + .for_each(|field| drop_field(self, field)); + } + // Closures and generators also have disjoint fields, but they are only + // directly accessed in the body of the closure/generator. + ty::TyClosure(def, substs) + | ty::TyGenerator(def, substs, ..) + if *drop_place == Place::Local(Local::new(1)) && !self.mir.upvar_decls.is_empty() + => { + substs.upvar_tys(def, self.tcx).enumerate() + .for_each(|field| drop_field(self, field)); } _ => { // We have now refined the type of the value being @@ -752,7 +773,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // subfield; so check whether that field's type still // "needs drop". If so, we assume that the destructor // may access any data it likes (i.e., a Deep Write). - let gcx = self.tcx.global_tcx(); if erased_drop_place_ty.needs_drop(gcx, self.param_env) { self.access_place( ContextKind::Drop.new(loc), diff --git a/src/test/run-pass/issue-47703-tuple.rs b/src/test/run-pass/issue-47703-tuple.rs new file mode 100644 index 00000000000..4fec3efc0a0 --- /dev/null +++ b/src/test/run-pass/issue-47703-tuple.rs @@ -0,0 +1,21 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(nll)] + +struct WithDrop; + +impl Drop for WithDrop { + fn drop(&mut self) {} +} + +fn consume(x: (&mut (), WithDrop)) -> &mut () { x.0 } + +fn main() {} diff --git a/src/test/run-pass/nll/issue-48623-closure.rs b/src/test/run-pass/nll/issue-48623-closure.rs new file mode 100644 index 00000000000..08ff54a428e --- /dev/null +++ b/src/test/run-pass/nll/issue-48623-closure.rs @@ -0,0 +1,24 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(nll)] + +struct WithDrop; + +impl Drop for WithDrop { + fn drop(&mut self) {} +} + +fn reborrow_from_closure(r: &mut ()) -> &mut () { + let d = WithDrop; + (move || { d; &mut *r })() +} + +fn main() {} diff --git a/src/test/run-pass/nll/issue-48623-generator.rs b/src/test/run-pass/nll/issue-48623-generator.rs new file mode 100644 index 00000000000..524837c4ba9 --- /dev/null +++ b/src/test/run-pass/nll/issue-48623-generator.rs @@ -0,0 +1,25 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(nll)] +#![feature(generators, generator_trait)] + +struct WithDrop; + +impl Drop for WithDrop { + fn drop(&mut self) {} +} + +fn reborrow_from_generator(r: &mut ()) { + let d = WithDrop; + move || { d; yield; &mut *r }; +} + +fn main() {} diff --git a/src/test/ui/generator/yield-while-iterating.nll.stderr b/src/test/ui/generator/yield-while-iterating.nll.stderr index be4852aaf06..af79eb7ac05 100644 --- a/src/test/ui/generator/yield-while-iterating.nll.stderr +++ b/src/test/ui/generator/yield-while-iterating.nll.stderr @@ -6,20 +6,6 @@ LL | for p in &x { //~ ERROR LL | yield(); | ------- possible yield occurs here -error[E0597]: borrowed value does not live long enough - --> $DIR/yield-while-iterating.rs:50:17 - | -LL | let mut b = || { - | _________________^ -LL | | for p in &mut x { -LL | | yield p; -LL | | } -LL | | }; - | | ^ - | | | - | |_____temporary value only lives until here - | temporary value does not live long enough - error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable --> $DIR/yield-while-iterating.rs:67:20 | @@ -35,21 +21,7 @@ LL | println!("{}", x[0]); //~ ERROR LL | b.resume(); | - borrow later used here -error[E0597]: borrowed value does not live long enough - --> $DIR/yield-while-iterating.rs:62:17 - | -LL | let mut b = || { - | _________________^ -LL | | for p in &mut x { -LL | | yield p; -LL | | } -LL | | }; - | | ^ - | | | - | |_____temporary value only lives until here - | temporary value does not live long enough - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors -Some errors occurred: E0502, E0597, E0626. +Some errors occurred: E0502, E0626. For more information about an error, try `rustc --explain E0502`. -- cgit 1.4.1-3-g733a5 From 64bcbca81b25a8c7192ffa5a16c824c59aa2b0a2 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 9 Apr 2018 17:30:43 -0700 Subject: rustc_driver: Catch ICEs on the main thread too --- src/librustc_driver/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index b203f387e46..3f166daac71 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -1526,7 +1526,8 @@ pub fn in_rustc_thread(f: F) -> Result> let thread = cfg.spawn(f); thread.unwrap().join() } else { - Ok(f()) + let f = panic::AssertUnwindSafe(f); + panic::catch_unwind(f) } } -- cgit 1.4.1-3-g733a5 From 9fc2595802d37326dc25fe524149023ed46b9730 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Tue, 24 Apr 2018 00:31:13 +0900 Subject: Make `trait_of_item` return None for non associated items It have returned `Some` for constants in a trait definition, and `Instance::resolve` called `tcx.associated_item` for them, causing ICE. --- src/librustc_metadata/decoder.rs | 8 +++++++- src/test/run-pass/auxiliary/issue-48984-aux.rs | 16 ++++++++++++++++ src/test/run-pass/issue-48984.rs | 17 +++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 src/test/run-pass/auxiliary/issue-48984-aux.rs create mode 100644 src/test/run-pass/issue-48984.rs (limited to 'src') diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 0147e8dc607..07a1da42943 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -977,7 +977,13 @@ impl<'a, 'tcx> CrateMetadata { } pub fn get_trait_of_item(&self, id: DefIndex) -> Option { - self.def_key(id).parent.and_then(|parent_index| { + let def_key = self.def_key(id); + match def_key.disambiguated_data.data { + DefPathData::TypeNs(..) | DefPathData::ValueNs(..) => (), + // Not an associated item + _ => return None, + } + def_key.parent.and_then(|parent_index| { match self.entry(parent_index).kind { EntryKind::Trait(_) => Some(self.local_def_id(parent_index)), _ => None, diff --git a/src/test/run-pass/auxiliary/issue-48984-aux.rs b/src/test/run-pass/auxiliary/issue-48984-aux.rs new file mode 100644 index 00000000000..6290279701e --- /dev/null +++ b/src/test/run-pass/auxiliary/issue-48984-aux.rs @@ -0,0 +1,16 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "lib"] +#![crate_name = "issue48984aux"] + +pub trait Foo { type Item; } + +pub trait Bar: Foo { } diff --git a/src/test/run-pass/issue-48984.rs b/src/test/run-pass/issue-48984.rs new file mode 100644 index 00000000000..227ad4e58f1 --- /dev/null +++ b/src/test/run-pass/issue-48984.rs @@ -0,0 +1,17 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:issue-48984-aux.rs +extern crate issue48984aux; +use issue48984aux::Bar; + +fn do_thing() { } + +fn main() { } -- cgit 1.4.1-3-g733a5 From f756b072b3164ff17b0640dfdf367a6843f85a52 Mon Sep 17 00:00:00 2001 From: Sergio Benitez Date: Fri, 27 Apr 2018 21:32:00 -0700 Subject: Don't feature gate bang macros on 'proc_macro_path_invoc'. --- src/librustc_resolve/macros.rs | 3 ++- src/test/compile-fail/extern-macro.rs | 2 +- src/test/compile-fail/macros-nonfatal-errors.rs | 1 - src/test/compile-fail/privacy/associated-item-privacy-inherent.rs | 1 - src/test/compile-fail/privacy/associated-item-privacy-trait.rs | 1 - src/test/compile-fail/privacy/associated-item-privacy-type-binding.rs | 1 - src/test/compile-fail/private-inferred-type-3.rs | 1 - src/test/compile-fail/private-inferred-type.rs | 1 - src/test/run-pass-fulldeps/macro-quote-test.rs | 2 +- src/test/run-pass/hygiene/issue-47311.rs | 2 +- src/test/run-pass/hygiene/issue-47312.rs | 2 +- src/test/run-pass/hygiene/legacy_interaction.rs | 2 +- src/test/run-pass/hygiene/lexical.rs | 2 +- src/test/run-pass/hygiene/wrap_unhygienic_example.rs | 2 +- src/test/run-pass/hygiene/xcrate.rs | 2 +- src/test/run-pass/paths-in-macro-invocations.rs | 2 +- src/test/ui/hygiene/fields.rs | 2 +- src/test/ui/hygiene/globs.rs | 2 +- src/test/ui/hygiene/impl_items.rs | 2 +- src/test/ui/hygiene/intercrate.rs | 2 +- src/test/ui/hygiene/no_implicit_prelude.rs | 2 +- src/test/ui/hygiene/privacy.rs | 2 +- src/test/ui/hygiene/trait_items.rs | 2 +- src/test/ui/imports/macro-paths.rs | 2 +- src/test/ui/imports/shadow_builtin_macros.rs | 2 +- 25 files changed, 20 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index af1e17cd89c..e72e02933e5 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -397,7 +397,7 @@ impl<'a> Resolver<'a> { fn resolve_macro_to_def(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool) -> Result { - if path.segments.len() > 1 { + if kind != MacroKind::Bang && path.segments.len() > 1 { if !self.session.features_untracked().proc_macro_path_invoc { emit_feature_err( &self.session.parse_sess, @@ -409,6 +409,7 @@ impl<'a> Resolver<'a> { ); } } + let def = self.resolve_macro_to_def_inner(scope, path, kind, force); if def != Err(Determinacy::Undetermined) { // Do not report duplicated errors on every undetermined resolution. diff --git a/src/test/compile-fail/extern-macro.rs b/src/test/compile-fail/extern-macro.rs index 08269ce5c7e..4267103ab9a 100644 --- a/src/test/compile-fail/extern-macro.rs +++ b/src/test/compile-fail/extern-macro.rs @@ -10,7 +10,7 @@ // #41719 -#![feature(use_extern_macros, proc_macro_path_invoc)] +#![feature(use_extern_macros)] fn main() { enum Foo {} diff --git a/src/test/compile-fail/macros-nonfatal-errors.rs b/src/test/compile-fail/macros-nonfatal-errors.rs index 40412087cef..7046ee12b50 100644 --- a/src/test/compile-fail/macros-nonfatal-errors.rs +++ b/src/test/compile-fail/macros-nonfatal-errors.rs @@ -13,7 +13,6 @@ #![feature(asm)] #![feature(trace_macros, concat_idents)] -#![feature(proc_macro_path_invoc)] #[derive(Default)] //~ ERROR enum OrDeriveThis {} diff --git a/src/test/compile-fail/privacy/associated-item-privacy-inherent.rs b/src/test/compile-fail/privacy/associated-item-privacy-inherent.rs index b64829edaa2..63cb6e82c25 100644 --- a/src/test/compile-fail/privacy/associated-item-privacy-inherent.rs +++ b/src/test/compile-fail/privacy/associated-item-privacy-inherent.rs @@ -10,7 +10,6 @@ #![feature(decl_macro, associated_type_defaults)] #![allow(unused, private_in_public)] -#![feature(proc_macro_path_invoc)] mod priv_nominal { pub struct Pub; diff --git a/src/test/compile-fail/privacy/associated-item-privacy-trait.rs b/src/test/compile-fail/privacy/associated-item-privacy-trait.rs index 062dc533617..bdc0c680a92 100644 --- a/src/test/compile-fail/privacy/associated-item-privacy-trait.rs +++ b/src/test/compile-fail/privacy/associated-item-privacy-trait.rs @@ -10,7 +10,6 @@ // ignore-tidy-linelength -#![feature(proc_macro_path_invoc)] #![feature(decl_macro, associated_type_defaults)] #![allow(unused, private_in_public)] diff --git a/src/test/compile-fail/privacy/associated-item-privacy-type-binding.rs b/src/test/compile-fail/privacy/associated-item-privacy-type-binding.rs index 0dfa61a18ab..c25616c5435 100644 --- a/src/test/compile-fail/privacy/associated-item-privacy-type-binding.rs +++ b/src/test/compile-fail/privacy/associated-item-privacy-type-binding.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(proc_macro_path_invoc)] #![feature(decl_macro, associated_type_defaults)] #![allow(unused, private_in_public)] diff --git a/src/test/compile-fail/private-inferred-type-3.rs b/src/test/compile-fail/private-inferred-type-3.rs index 97d6b470d33..0c393f02323 100644 --- a/src/test/compile-fail/private-inferred-type-3.rs +++ b/src/test/compile-fail/private-inferred-type-3.rs @@ -18,7 +18,6 @@ // error-pattern:type `fn(u8) -> ext::PubTupleStruct {ext::PubTupleStruct::{{constructor}}}` is priv // error-pattern:type `for<'r> fn(&'r ext::Pub) {>::priv_method}` is private -#![feature(proc_macro_path_invoc)] #![feature(decl_macro)] extern crate private_inferred_type as ext; diff --git a/src/test/compile-fail/private-inferred-type.rs b/src/test/compile-fail/private-inferred-type.rs index dfc0107e075..5af8b063c16 100644 --- a/src/test/compile-fail/private-inferred-type.rs +++ b/src/test/compile-fail/private-inferred-type.rs @@ -11,7 +11,6 @@ #![feature(associated_consts)] #![feature(decl_macro)] #![allow(private_in_public)] -#![feature(proc_macro_path_invoc)] mod m { fn priv_fn() {} diff --git a/src/test/run-pass-fulldeps/macro-quote-test.rs b/src/test/run-pass-fulldeps/macro-quote-test.rs index 9bb8f691915..f359735d2f7 100644 --- a/src/test/run-pass-fulldeps/macro-quote-test.rs +++ b/src/test/run-pass-fulldeps/macro-quote-test.rs @@ -13,7 +13,7 @@ // aux-build:hello_macro.rs // ignore-stage1 -#![feature(proc_macro, proc_macro_path_invoc, proc_macro_non_items)] +#![feature(proc_macro, proc_macro_non_items)] extern crate hello_macro; diff --git a/src/test/run-pass/hygiene/issue-47311.rs b/src/test/run-pass/hygiene/issue-47311.rs index c4391ad0577..3b6890cdce6 100644 --- a/src/test/run-pass/hygiene/issue-47311.rs +++ b/src/test/run-pass/hygiene/issue-47311.rs @@ -10,7 +10,7 @@ // ignore-pretty pretty-printing is unhygienic -#![feature(decl_macro, proc_macro_path_invoc)] +#![feature(decl_macro)] #![allow(unused)] macro m($S:ident, $x:ident) { diff --git a/src/test/run-pass/hygiene/issue-47312.rs b/src/test/run-pass/hygiene/issue-47312.rs index 0cda0e7c7cc..5e83f3808d8 100644 --- a/src/test/run-pass/hygiene/issue-47312.rs +++ b/src/test/run-pass/hygiene/issue-47312.rs @@ -10,7 +10,7 @@ // ignore-pretty pretty-printing is unhygienic -#![feature(decl_macro, proc_macro_path_invoc)] +#![feature(decl_macro)] #![allow(unused)] mod foo { diff --git a/src/test/run-pass/hygiene/legacy_interaction.rs b/src/test/run-pass/hygiene/legacy_interaction.rs index 5395ef35882..683a15b99ae 100644 --- a/src/test/run-pass/hygiene/legacy_interaction.rs +++ b/src/test/run-pass/hygiene/legacy_interaction.rs @@ -12,7 +12,7 @@ // aux-build:legacy_interaction.rs -#![feature(decl_macro, proc_macro_path_invoc)] +#![feature(decl_macro)] #[allow(unused)] extern crate legacy_interaction; diff --git a/src/test/run-pass/hygiene/lexical.rs b/src/test/run-pass/hygiene/lexical.rs index 73deda0777e..cb02a17fec3 100644 --- a/src/test/run-pass/hygiene/lexical.rs +++ b/src/test/run-pass/hygiene/lexical.rs @@ -10,7 +10,7 @@ // ignore-pretty pretty-printing is unhygienic -#![feature(decl_macro, proc_macro_path_invoc)] +#![feature(decl_macro)] mod bar { mod baz { diff --git a/src/test/run-pass/hygiene/wrap_unhygienic_example.rs b/src/test/run-pass/hygiene/wrap_unhygienic_example.rs index 66e83eb7cac..55206950214 100644 --- a/src/test/run-pass/hygiene/wrap_unhygienic_example.rs +++ b/src/test/run-pass/hygiene/wrap_unhygienic_example.rs @@ -13,7 +13,7 @@ // aux-build:my_crate.rs // aux-build:unhygienic_example.rs -#![feature(decl_macro, proc_macro_path_invoc)] +#![feature(decl_macro)] extern crate unhygienic_example; extern crate my_crate; // (b) diff --git a/src/test/run-pass/hygiene/xcrate.rs b/src/test/run-pass/hygiene/xcrate.rs index 95d7ae6db60..6df3a34d3c8 100644 --- a/src/test/run-pass/hygiene/xcrate.rs +++ b/src/test/run-pass/hygiene/xcrate.rs @@ -12,7 +12,7 @@ // aux-build:xcrate.rs -#![feature(decl_macro, proc_macro_path_invoc)] +#![feature(decl_macro)] extern crate xcrate; diff --git a/src/test/run-pass/paths-in-macro-invocations.rs b/src/test/run-pass/paths-in-macro-invocations.rs index 2e87809a84e..69f8906778a 100644 --- a/src/test/run-pass/paths-in-macro-invocations.rs +++ b/src/test/run-pass/paths-in-macro-invocations.rs @@ -10,7 +10,7 @@ // aux-build:two_macros.rs -#![feature(use_extern_macros, proc_macro_path_invoc)] +#![feature(use_extern_macros)] extern crate two_macros; diff --git a/src/test/ui/hygiene/fields.rs b/src/test/ui/hygiene/fields.rs index ed155b28037..64217770b13 100644 --- a/src/test/ui/hygiene/fields.rs +++ b/src/test/ui/hygiene/fields.rs @@ -10,7 +10,7 @@ // ignore-pretty pretty-printing is unhygienic -#![feature(decl_macro, proc_macro_path_invoc)] +#![feature(decl_macro)] mod foo { struct S { x: u32 } diff --git a/src/test/ui/hygiene/globs.rs b/src/test/ui/hygiene/globs.rs index f3f400aafeb..7ba217061c6 100644 --- a/src/test/ui/hygiene/globs.rs +++ b/src/test/ui/hygiene/globs.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(decl_macro, proc_macro_path_invoc)] +#![feature(decl_macro)] mod foo { pub fn f() {} diff --git a/src/test/ui/hygiene/impl_items.rs b/src/test/ui/hygiene/impl_items.rs index 4f997a790e6..cdba559445d 100644 --- a/src/test/ui/hygiene/impl_items.rs +++ b/src/test/ui/hygiene/impl_items.rs @@ -10,7 +10,7 @@ // ignore-pretty pretty-printing is unhygienic -#![feature(decl_macro, proc_macro_path_invoc)] +#![feature(decl_macro)] mod foo { struct S; diff --git a/src/test/ui/hygiene/intercrate.rs b/src/test/ui/hygiene/intercrate.rs index 20ca918f026..50fc985ba34 100644 --- a/src/test/ui/hygiene/intercrate.rs +++ b/src/test/ui/hygiene/intercrate.rs @@ -14,7 +14,7 @@ // error-pattern:type `fn() -> u32 {intercrate::foo::bar::f}` is private -#![feature(decl_macro, proc_macro_path_invoc)] +#![feature(decl_macro)] extern crate intercrate; diff --git a/src/test/ui/hygiene/no_implicit_prelude.rs b/src/test/ui/hygiene/no_implicit_prelude.rs index ea6a45fba6a..c90c7b3093c 100644 --- a/src/test/ui/hygiene/no_implicit_prelude.rs +++ b/src/test/ui/hygiene/no_implicit_prelude.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(decl_macro, proc_macro_path_invoc)] +#![feature(decl_macro)] mod foo { pub macro m() { Vec::new(); ().clone() } diff --git a/src/test/ui/hygiene/privacy.rs b/src/test/ui/hygiene/privacy.rs index 8a392db92f9..987cad187d4 100644 --- a/src/test/ui/hygiene/privacy.rs +++ b/src/test/ui/hygiene/privacy.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(decl_macro, proc_macro_path_invoc)] +#![feature(decl_macro)] mod foo { fn f() {} diff --git a/src/test/ui/hygiene/trait_items.rs b/src/test/ui/hygiene/trait_items.rs index d0da6254b9b..3bd19cbc0ac 100644 --- a/src/test/ui/hygiene/trait_items.rs +++ b/src/test/ui/hygiene/trait_items.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(decl_macro, proc_macro_path_invoc)] +#![feature(decl_macro)] mod foo { pub trait T { diff --git a/src/test/ui/imports/macro-paths.rs b/src/test/ui/imports/macro-paths.rs index 51e5257be1b..e709eeee14a 100644 --- a/src/test/ui/imports/macro-paths.rs +++ b/src/test/ui/imports/macro-paths.rs @@ -10,7 +10,7 @@ // aux-build:two_macros.rs -#![feature(use_extern_macros, proc_macro_path_invoc)] +#![feature(use_extern_macros)] extern crate two_macros; diff --git a/src/test/ui/imports/shadow_builtin_macros.rs b/src/test/ui/imports/shadow_builtin_macros.rs index aad0a43be26..93de136c405 100644 --- a/src/test/ui/imports/shadow_builtin_macros.rs +++ b/src/test/ui/imports/shadow_builtin_macros.rs @@ -10,7 +10,7 @@ // aux-build:two_macros.rs -#![feature(use_extern_macros, proc_macro_path_invoc)] +#![feature(use_extern_macros)] mod foo { extern crate two_macros; -- cgit 1.4.1-3-g733a5 From 2338adf48cbb6bfcf03c5f00f48ee63014d793cd Mon Sep 17 00:00:00 2001 From: Keith Yeung Date: Wed, 28 Feb 2018 01:09:08 -0800 Subject: Allow MIR borrowck to catch unused mutable locals --- src/librustc/mir/mod.rs | 14 ++++++++++++++ src/librustc_mir/borrow_check/mod.rs | 37 +++++++++++++++++++++++++++++------- 2 files changed, 44 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index c525c4ed651..501f77547e2 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -247,6 +247,20 @@ impl<'tcx> Mir<'tcx> { }) } + /// Returns an iterator over all user-declared mutable locals. + #[inline] + pub fn mut_vars_iter<'a>(&'a self) -> impl Iterator + 'a { + (self.arg_count+1..self.local_decls.len()).filter_map(move |index| { + let local = Local::new(index); + let decl = &self.local_decls[local]; + if decl.is_user_variable && decl.mutability == Mutability::Mut { + Some(local) + } else { + None + } + }) + } + /// Returns an iterator over all function arguments. #[inline] pub fn args_iter(&self) -> impl Iterator { diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 5c7061abbb6..6cebd290b9a 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -17,10 +17,11 @@ use rustc::hir::map::definitions::DefPathData; use rustc::infer::InferCtxt; use rustc::ty::{self, ParamEnv, TyCtxt}; use rustc::ty::maps::Providers; -use rustc::mir::{AssertMessage, BasicBlock, BorrowKind, Location, Place}; -use rustc::mir::{Mir, Mutability, Operand, Projection, ProjectionElem, Rvalue}; -use rustc::mir::{Field, Statement, StatementKind, Terminator, TerminatorKind}; -use rustc::mir::{ClosureRegionRequirements, Local}; +use rustc::lint::builtin::UNUSED_MUT; +use rustc::mir::{AssertMessage, BasicBlock, BorrowKind, ClearCrossCrate, Local}; +use rustc::mir::{Location, Place, Mir, Mutability, Operand, Projection, ProjectionElem}; +use rustc::mir::{Rvalue, Field, Statement, StatementKind, Terminator, TerminatorKind}; +use rustc::mir::ClosureRegionRequirements; use rustc_data_structures::control_flow_graph::dominators::Dominators; use rustc_data_structures::fx::FxHashSet; @@ -236,7 +237,8 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( access_place_error_reported: FxHashSet(), reservation_error_reported: FxHashSet(), moved_error_reported: FxHashSet(), - nonlexical_regioncx: regioncx, + nonlexical_regioncx: opt_regioncx, + used_mut: FxHashSet(), nonlexical_cause_info: None, borrow_set, dominators, @@ -287,6 +289,9 @@ pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> { /// This field keeps track of errors reported in the checking of moved variables, /// so that we don't report report seemingly duplicate errors. moved_error_reported: FxHashSet>, + /// This field keeps track of all the local variables that are declared mut and are mutated. + /// Used for the warning issued by an unused mutable local variable. + used_mut: FxHashSet, /// Non-lexical region inference context, if NLL is enabled. This /// contains the results from region inference and lets us e.g. /// find out which CFG points are contained in each borrow region. @@ -434,6 +439,22 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx self.check_activations(location, span, flow_state); + for local in self.mir.mut_vars_iter().filter(|local| !self.used_mut.contains(local)) { + if let ClearCrossCrate::Set(ref vsi) = self.mir.visibility_scope_info { + let source_info = self.mir.local_decls[local].source_info; + let mut_span = self.tcx.sess.codemap().span_until_non_whitespace(source_info.span); + + self.tcx.struct_span_lint_node( + UNUSED_MUT, + vsi[source_info.scope].lint_root, + source_info.span, + "variable does not need to be mutable" + ) + .span_suggestion_short(mut_span, "remove this `mut`", "".to_owned()) + .emit(); + } + } + match term.kind { TerminatorKind::SwitchInt { ref discr, @@ -1594,7 +1615,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { /// /// Returns true if an error is reported, false otherwise. fn check_access_permissions( - &self, + &mut self, (place, span): (&Place<'tcx>, Span), kind: ReadOrWrite, is_local_mutation_allowed: LocalMutationIsAllowed, @@ -1631,7 +1652,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { err.emit(); }, Reservation(WriteKind::Mutate) | Write(WriteKind::Mutate) => { - + if let Place::Local(local) = *place { + self.used_mut.insert(local); + } if let Err(place_err) = self.is_mutable(place, is_local_mutation_allowed) { error_reported = true; let mut err_info = None; -- cgit 1.4.1-3-g733a5 From 3e423d05863ec7c02f6e1efebed5480a3211755e Mon Sep 17 00:00:00 2001 From: Keith Yeung Date: Thu, 1 Mar 2018 21:14:36 -0800 Subject: Disable AST unused mut check when using MIR borrowck --- src/librustc_borrowck/borrowck/mod.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 6d832d4060a..519dd574e5a 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -144,7 +144,10 @@ fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId) { check_loans::check_loans(&mut bccx, &loan_dfcx, &flowed_moves, &all_loans, body); } - unused::check(&mut bccx, body); + + if !tcx.use_mir_borrowck() { + unused::check(&mut bccx, body); + } Lrc::new(BorrowCheckResult { used_mut_nodes: bccx.used_mut_nodes.into_inner(), -- cgit 1.4.1-3-g733a5 From 5a2b590ec0d6f1de5e44c00adb6638c05da6a265 Mon Sep 17 00:00:00 2001 From: Keith Yeung Date: Fri, 2 Mar 2018 20:42:37 -0800 Subject: Track unused mutable variables across closures --- src/librustc/ich/impls_mir.rs | 5 + src/librustc/mir/mod.rs | 7 ++ src/librustc/ty/maps/mod.rs | 2 +- src/librustc_mir/borrow_check/mod.rs | 103 +++++++++++++++------ .../borrow_check/nll/type_check/mod.rs | 4 +- src/test/compile-fail/lint-unused-mut-variables.rs | 61 ++++++++---- .../borrowck/borrowck-unused-mut-locals.rs | 56 +++++++++++ 7 files changed, 189 insertions(+), 49 deletions(-) create mode 100644 src/test/run-pass/borrowck/borrowck-unused-mut-locals.rs (limited to 'src') diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs index c73f171806e..437626ff536 100644 --- a/src/librustc/ich/impls_mir.rs +++ b/src/librustc/ich/impls_mir.rs @@ -563,6 +563,11 @@ impl<'a, 'gcx> HashStable> for mir::Literal<'gcx> { impl_stable_hash_for!(struct mir::Location { block, statement_index }); +impl_stable_hash_for!(struct mir::BorrowCheckResult<'tcx> { + closure_requirements, + used_mut_upvars +}); + impl_stable_hash_for!(struct mir::ClosureRegionRequirements<'tcx> { num_external_vids, outlives_requirements diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 501f77547e2..7b6389072b7 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -21,6 +21,7 @@ use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use rustc_data_structures::control_flow_graph::dominators::{Dominators, dominators}; use rustc_data_structures::control_flow_graph::{GraphPredecessors, GraphSuccessors}; use rustc_data_structures::control_flow_graph::ControlFlowGraph; +use rustc_data_structures::small_vec::SmallVec; use rustc_serialize as serialize; use hir::def::CtorKind; use hir::def_id::DefId; @@ -2043,6 +2044,12 @@ pub struct GeneratorLayout<'tcx> { pub fields: Vec>, } +#[derive(Clone, Debug, RustcEncodable, RustcDecodable)] +pub struct BorrowCheckResult<'gcx> { + pub closure_requirements: Option>, + pub used_mut_upvars: SmallVec<[Field; 8]>, +} + /// After we borrow check a closure, we are left with various /// requirements that we have inferred between the free regions that /// appear in the closure's signature or on its field types. These diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index 57223a3c7b2..d89846a75ef 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -211,7 +211,7 @@ define_maps! { <'tcx> /// Borrow checks the function body. If this is a closure, returns /// additional requirements that the closure's creator must verify. - [] fn mir_borrowck: MirBorrowCheck(DefId) -> Option>, + [] fn mir_borrowck: MirBorrowCheck(DefId) -> mir::BorrowCheckResult<'tcx>, /// Gets a complete map from all types to their inherent impls. /// Not meant to be used directly outside of coherence. diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 6cebd290b9a..ea628cefd3e 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -18,15 +18,16 @@ use rustc::infer::InferCtxt; use rustc::ty::{self, ParamEnv, TyCtxt}; use rustc::ty::maps::Providers; use rustc::lint::builtin::UNUSED_MUT; -use rustc::mir::{AssertMessage, BasicBlock, BorrowKind, ClearCrossCrate, Local}; -use rustc::mir::{Location, Place, Mir, Mutability, Operand, Projection, ProjectionElem}; -use rustc::mir::{Rvalue, Field, Statement, StatementKind, Terminator, TerminatorKind}; -use rustc::mir::ClosureRegionRequirements; +use rustc::mir::{AssertMessage, AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind}; +use rustc::mir::{ClearCrossCrate, Local, Location, Place, Mir, Mutability, Operand}; +use rustc::mir::{Projection, ProjectionElem, Rvalue, Field, Statement, StatementKind}; +use rustc::mir::{Terminator, TerminatorKind}; use rustc_data_structures::control_flow_graph::dominators::Dominators; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::indexed_set::IdxSetBuf; use rustc_data_structures::indexed_vec::Idx; +use rustc_data_structures::small_vec::SmallVec; use std::rc::Rc; @@ -70,12 +71,15 @@ pub fn provide(providers: &mut Providers) { fn mir_borrowck<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, -) -> Option> { +) -> BorrowCheckResult<'tcx> { let input_mir = tcx.mir_validated(def_id); debug!("run query mir_borrowck: {}", tcx.item_path_str(def_id)); if !tcx.has_attr(def_id, "rustc_mir_borrowck") && !tcx.use_mir_borrowck() { - return None; + return BorrowCheckResult { + closure_requirements: None, + used_mut_upvars: SmallVec::new(), + }; } let opt_closure_req = tcx.infer_ctxt().enter(|infcx| { @@ -91,7 +95,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( infcx: &InferCtxt<'a, 'gcx, 'tcx>, input_mir: &Mir<'gcx>, def_id: DefId, -) -> Option> { +) -> BorrowCheckResult<'gcx> { let tcx = infcx.tcx; let attributes = tcx.get_attrs(def_id); let param_env = tcx.param_env(def_id); @@ -239,6 +243,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( moved_error_reported: FxHashSet(), nonlexical_regioncx: opt_regioncx, used_mut: FxHashSet(), + used_mut_upvars: SmallVec::new(), nonlexical_cause_info: None, borrow_set, dominators, @@ -254,7 +259,28 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( mbcx.analyze_results(&mut state); // entry point for DataflowResultsConsumer - opt_closure_req + debug!("mbcx.used_mut: {:?}", mbcx.used_mut); + + for local in mbcx.mir.mut_vars_iter().filter(|local| !mbcx.used_mut.contains(local)) { + if let ClearCrossCrate::Set(ref vsi) = mbcx.mir.visibility_scope_info { + let source_info = mbcx.mir.local_decls[local].source_info; + let mut_span = tcx.sess.codemap().span_until_non_whitespace(source_info.span); + + tcx.struct_span_lint_node( + UNUSED_MUT, + vsi[source_info.scope].lint_root, + source_info.span, + "variable does not need to be mutable" + ) + .span_suggestion_short(mut_span, "remove this `mut`", "".to_owned()) + .emit(); + } + } + + BorrowCheckResult { + closure_requirements: opt_closure_req, + used_mut_upvars: mbcx.used_mut_upvars, + } } #[allow(dead_code)] @@ -292,6 +318,9 @@ pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> { /// This field keeps track of all the local variables that are declared mut and are mutated. /// Used for the warning issued by an unused mutable local variable. used_mut: FxHashSet, + /// If the function we're checking is a closure, then we'll need to report back the list of + /// mutable upvars that have been used. This field keeps track of them. + used_mut_upvars: SmallVec<[Field; 8]>, /// Non-lexical region inference context, if NLL is enabled. This /// contains the results from region inference and lets us e.g. /// find out which CFG points are contained in each borrow region. @@ -439,22 +468,6 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx self.check_activations(location, span, flow_state); - for local in self.mir.mut_vars_iter().filter(|local| !self.used_mut.contains(local)) { - if let ClearCrossCrate::Set(ref vsi) = self.mir.visibility_scope_info { - let source_info = self.mir.local_decls[local].source_info; - let mut_span = self.tcx.sess.codemap().span_until_non_whitespace(source_info.span); - - self.tcx.struct_span_lint_node( - UNUSED_MUT, - vsi[source_info.scope].lint_root, - source_info.span, - "variable does not need to be mutable" - ) - .span_suggestion_short(mut_span, "remove this `mut`", "".to_owned()) - .emit(); - } - } - match term.kind { TerminatorKind::SwitchInt { ref discr, @@ -1118,9 +1131,33 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // `NullOp::Box`? } - Rvalue::Aggregate(ref _aggregate_kind, ref operands) => for operand in operands { - self.consume_operand(context, (operand, span), flow_state); - }, + Rvalue::Aggregate(ref aggregate_kind, ref operands) => { + // We need to report back the list of mutable upvars that were + // moved into the closure and subsequently used by the closure, + // in order to populate our used_mut set. + if let AggregateKind::Closure(def_id, _) = &**aggregate_kind { + let BorrowCheckResult { used_mut_upvars, .. } = self.tcx.mir_borrowck(*def_id); + for field in used_mut_upvars { + match operands[field.index()] { + Operand::Move(Place::Local(local)) => { + self.used_mut.insert(local); + } + Operand::Move(Place::Projection(ref proj)) => { + if let Some(field) = self.is_upvar_field_projection(&proj.base) { + self.used_mut_upvars.push(field); + } + } + Operand::Move(Place::Static(..)) | + Operand::Copy(..) | + Operand::Constant(..) => {} + } + } + } + + for operand in operands { + self.consume_operand(context, (operand, span), flow_state); + } + } } } @@ -1652,8 +1689,16 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { err.emit(); }, Reservation(WriteKind::Mutate) | Write(WriteKind::Mutate) => { - if let Place::Local(local) = *place { - self.used_mut.insert(local); + match place { + Place::Local(local) => { + self.used_mut.insert(*local); + } + Place::Projection(ref proj) => { + if let Some(field) = self.is_upvar_field_projection(&proj.base) { + self.used_mut_upvars.push(field); + } + } + Place::Static(..) => {} } if let Err(place_err) = self.is_mutable(place, is_local_mutation_allowed) { error_reported = true; diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 0ed95a319f7..a811b2c147e 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -1426,7 +1426,9 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { // these extra requirements are basically like where // clauses on the struct. AggregateKind::Closure(def_id, substs) => { - if let Some(closure_region_requirements) = tcx.mir_borrowck(*def_id) { + if let Some(closure_region_requirements) = + tcx.mir_borrowck(*def_id).closure_requirements + { closure_region_requirements.apply_requirements( self.infcx, self.body_id, diff --git a/src/test/compile-fail/lint-unused-mut-variables.rs b/src/test/compile-fail/lint-unused-mut-variables.rs index 3c76740d2b5..14d836074dc 100644 --- a/src/test/compile-fail/lint-unused-mut-variables.rs +++ b/src/test/compile-fail/lint-unused-mut-variables.rs @@ -8,6 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// revisions: lexical nll +#![cfg_attr(nll, feature(nll))] + // Exercise the unused_mut attribute in some positive and negative cases #![allow(unused_assignments)] @@ -18,15 +21,22 @@ fn main() { // negative cases - let mut a = 3; //~ ERROR: variable does not need to be mutable - let mut a = 2; //~ ERROR: variable does not need to be mutable - let mut b = 3; //~ ERROR: variable does not need to be mutable - let mut a = vec![3]; //~ ERROR: variable does not need to be mutable - let (mut a, b) = (1, 2); //~ ERROR: variable does not need to be mutable - let mut a; //~ ERROR: variable does not need to be mutable + let mut a = 3; //[lexical]~ ERROR: variable does not need to be mutable + //[nll]~^ ERROR: variable does not need to be mutable + let mut a = 2; //[lexical]~ ERROR: variable does not need to be mutable + //[nll]~^ ERROR: variable does not need to be mutable + let mut b = 3; //[lexical]~ ERROR: variable does not need to be mutable + //[nll]~^ ERROR: variable does not need to be mutable + let mut a = vec![3]; //[lexical]~ ERROR: variable does not need to be mutable + //[nll]~^ ERROR: variable does not need to be mutable + let (mut a, b) = (1, 2); //[lexical]~ ERROR: variable does not need to be mutable + //[nll]~^ ERROR: variable does not need to be mutable + let mut a; //[lexical]~ ERROR: variable does not need to be mutable + //[nll]~^ ERROR: variable does not need to be mutable a = 3; - let mut b; //~ ERROR: variable does not need to be mutable + let mut b; //[lexical]~ ERROR: variable does not need to be mutable + //[nll]~^ ERROR: variable does not need to be mutable if true { b = 3; } else { @@ -34,37 +44,45 @@ fn main() { } match 30 { - mut x => {} //~ ERROR: variable does not need to be mutable + mut x => {} //[lexical]~ ERROR: variable does not need to be mutable + //[nll]~^ ERROR: variable does not need to be mutable } match (30, 2) { - (mut x, 1) | //~ ERROR: variable does not need to be mutable + (mut x, 1) | //[lexical]~ ERROR: variable does not need to be mutable + //[nll]~^ ERROR: variable does not need to be mutable (mut x, 2) | (mut x, 3) => { } _ => {} } - let x = |mut y: isize| 10; //~ ERROR: variable does not need to be mutable - fn what(mut foo: isize) {} //~ ERROR: variable does not need to be mutable + let x = |mut y: isize| 10; //[lexical]~ ERROR: variable does not need to be mutable + //[nll]~^ ERROR: variable does not need to be mutable + fn what(mut foo: isize) {} //[lexical]~ ERROR: variable does not need to be mutable + //[nll]~^ ERROR: variable does not need to be mutable - let mut a = &mut 5; //~ ERROR: variable does not need to be mutable + let mut a = &mut 5; //[lexical]~ ERROR: variable does not need to be mutable + //[nll]~^ ERROR: variable does not need to be mutable *a = 4; let mut a = 5; - let mut b = (&mut a,); - *b.0 = 4; //~^ ERROR: variable does not need to be mutable + let mut b = (&mut a,); //[lexical]~ ERROR: variable does not need to be mutable + *b.0 = 4; //[nll]~^ ERROR: variable does not need to be mutable - let mut x = &mut 1; //~ ERROR: variable does not need to be mutable + let mut x = &mut 1; //[lexical]~ ERROR: variable does not need to be mutable + //[nll]~^ ERROR: variable does not need to be mutable let mut f = || { *x += 1; }; f(); fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] { - &mut arg[..] //~^ ERROR: variable does not need to be mutable + &mut arg[..] //[lexical]~^ ERROR: variable does not need to be mutable + //[nll]~^^ ERROR: variable does not need to be mutable } - let mut v : &mut Vec<()> = &mut vec![]; //~ ERROR: variable does not need to be mutable + let mut v : &mut Vec<()> = &mut vec![]; //[lexical]~ ERROR: variable does not need to be mutable + //[nll]~^ ERROR: variable does not need to be mutable v.push(()); // positive cases @@ -76,6 +94,12 @@ fn main() { callback(|| { a.push(3); }); + let mut a = Vec::new(); + callback(|| { + callback(|| { + a.push(3); + }); + }); let (mut a, b) = (1, 2); a = 34; @@ -116,5 +140,6 @@ fn foo(mut a: isize) { fn bar() { #[allow(unused_mut)] let mut a = 3; - let mut b = vec![2]; //~ ERROR: variable does not need to be mutable + let mut b = vec![2]; //[lexical]~ ERROR: variable does not need to be mutable + //[nll]~^ ERROR: variable does not need to be mutable } diff --git a/src/test/run-pass/borrowck/borrowck-unused-mut-locals.rs b/src/test/run-pass/borrowck/borrowck-unused-mut-locals.rs new file mode 100644 index 00000000000..7f1b6ed1701 --- /dev/null +++ b/src/test/run-pass/borrowck/borrowck-unused-mut-locals.rs @@ -0,0 +1,56 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(nll)] +#![deny(unused_mut)] + +#[derive(Debug)] +struct A {} + +fn init_a() -> A { + A {} +} + +#[derive(Debug)] +struct B<'a> { + ed: &'a mut A, +} + +fn init_b<'a>(ed: &'a mut A) -> B<'a> { + B { ed } +} + +#[derive(Debug)] +struct C<'a> { + pd: &'a mut B<'a>, +} + +fn init_c<'a>(pd: &'a mut B<'a>) -> C<'a> { + C { pd } +} + +#[derive(Debug)] +struct D<'a> { + sd: &'a mut C<'a>, +} + +fn init_d<'a>(sd: &'a mut C<'a>) -> D<'a> { + D { sd } +} + +fn main() { + let mut a = init_a(); + let mut b = init_b(&mut a); + let mut c = init_c(&mut b); + + let d = init_d(&mut c); + + println!("{:?}", d) +} -- cgit 1.4.1-3-g733a5 From e3b372f67d9fbfda2818febe3af914d4f4069c6d Mon Sep 17 00:00:00 2001 From: Keith Yeung Date: Mon, 12 Mar 2018 08:47:44 -0700 Subject: Only check possibly initialized values and also loop over fn args --- src/librustc/mir/mod.rs | 10 ++++++---- src/librustc_mir/borrow_check/mod.rs | 23 +++++++++++++++++++---- 2 files changed, 25 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 7b6389072b7..c26b3014e53 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -248,13 +248,15 @@ impl<'tcx> Mir<'tcx> { }) } - /// Returns an iterator over all user-declared mutable locals. + /// Returns an iterator over all user-declared mutable arguments and locals. #[inline] - pub fn mut_vars_iter<'a>(&'a self) -> impl Iterator + 'a { - (self.arg_count+1..self.local_decls.len()).filter_map(move |index| { + pub fn mut_vars_and_args_iter<'a>(&'a self) -> impl Iterator + 'a { + (1..self.local_decls.len()).filter_map(move |index| { let local = Local::new(index); let decl = &self.local_decls[local]; - if decl.is_user_variable && decl.mutability == Mutability::Mut { + if (decl.is_user_variable || index < self.arg_count + 1) + && decl.mutability == Mutability::Mut + { Some(local) } else { None diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index ea628cefd3e..60691d1179a 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -261,9 +261,17 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( debug!("mbcx.used_mut: {:?}", mbcx.used_mut); - for local in mbcx.mir.mut_vars_iter().filter(|local| !mbcx.used_mut.contains(local)) { + for local in mbcx.mir.mut_vars_and_args_iter().filter(|local| !mbcx.used_mut.contains(local)) { if let ClearCrossCrate::Set(ref vsi) = mbcx.mir.visibility_scope_info { - let source_info = mbcx.mir.local_decls[local].source_info; + let local_decl = &mbcx.mir.local_decls[local]; + + // Skip over locals that begin with an underscore + match local_decl.name { + Some(name) if name.as_str().starts_with("_") => continue, + _ => {}, + } + + let source_info = local_decl.source_info; let mut_span = tcx.sess.codemap().span_until_non_whitespace(source_info.span); tcx.struct_span_lint_node( @@ -864,7 +872,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } let mutability_error = - self.check_access_permissions(place_span, rw, is_local_mutation_allowed); + self.check_access_permissions(place_span, rw, is_local_mutation_allowed, flow_state); let conflict_error = self.check_access_for_conflict(context, place_span, sd, rw, flow_state); @@ -1656,6 +1664,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { (place, span): (&Place<'tcx>, Span), kind: ReadOrWrite, is_local_mutation_allowed: LocalMutationIsAllowed, + flow_state: &Flows<'cx, 'gcx, 'tcx>, ) -> bool { debug!( "check_access_permissions({:?}, {:?}, {:?})", @@ -1691,7 +1700,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { Reservation(WriteKind::Mutate) | Write(WriteKind::Mutate) => { match place { Place::Local(local) => { - self.used_mut.insert(*local); + // If the local may be initialized, and it is now currently being + // mutated, then it is justified to be annotated with the `mut` keyword, + // since the mutation may be a possible reassignment. + let mpi = self.move_data.rev_lookup.find_local(*local); + if flow_state.inits.contains(&mpi) { + self.used_mut.insert(*local); + } } Place::Projection(ref proj) => { if let Some(field) = self.is_upvar_field_projection(&proj.base) { -- cgit 1.4.1-3-g733a5 From 71d221f29425bf7c87fbc781fcbc5740b00d1c8f Mon Sep 17 00:00:00 2001 From: Keith Yeung Date: Fri, 16 Mar 2018 02:52:07 -0700 Subject: Determine unused mutable variables based on the 'root' place --- src/librustc_mir/borrow_check/mod.rs | 197 ++++++++++++++++++++--------------- 1 file changed, 111 insertions(+), 86 deletions(-) (limited to 'src') diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 60691d1179a..2498162d10f 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -241,7 +241,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( access_place_error_reported: FxHashSet(), reservation_error_reported: FxHashSet(), moved_error_reported: FxHashSet(), - nonlexical_regioncx: opt_regioncx, + nonlexical_regioncx: regioncx, used_mut: FxHashSet(), used_mut_upvars: SmallVec::new(), nonlexical_cause_info: None, @@ -276,7 +276,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( tcx.struct_span_lint_node( UNUSED_MUT, - vsi[source_info.scope].lint_root, + vsi[local_decl.syntactic_scope].lint_root, source_info.span, "variable does not need to be mutable" ) @@ -1366,7 +1366,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ) { debug!("check_if_reassignment_to_immutable_state({:?})", place); // determine if this path has a non-mut owner (and thus needs checking). - if let Ok(()) = self.is_mutable(place, LocalMutationIsAllowed::No) { + if let Ok(_) = self.is_mutable(place, LocalMutationIsAllowed::No) { return; } debug!( @@ -1679,27 +1679,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } } Reservation(WriteKind::MutableBorrow(BorrowKind::Mut { .. })) - | Write(WriteKind::MutableBorrow(BorrowKind::Mut { .. })) => if let Err(place_err) = - self.is_mutable(place, is_local_mutation_allowed) - { - error_reported = true; - let item_msg = self.get_default_err_msg(place); - let mut err = self.tcx - .cannot_borrow_path_as_mutable(span, &item_msg, Origin::Mir); - err.span_label(span, "cannot borrow as mutable"); - - if place != place_err { - if let Some(name) = self.describe_place(place_err) { - err.note(&format!("the value which is causing this path not to be mutable \ - is...: `{}`", name)); - } - } - - err.emit(); - }, - Reservation(WriteKind::Mutate) | Write(WriteKind::Mutate) => { - match place { - Place::Local(local) => { + | Write(WriteKind::MutableBorrow(BorrowKind::Mut { .. })) => { + match self.is_mutable(place, is_local_mutation_allowed) { + Ok(Place::Local(local)) + if is_local_mutation_allowed != LocalMutationIsAllowed::Yes => + { // If the local may be initialized, and it is now currently being // mutated, then it is justified to be annotated with the `mut` keyword, // since the mutation may be a possible reassignment. @@ -1708,77 +1692,118 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { self.used_mut.insert(*local); } } - Place::Projection(ref proj) => { + Ok(Place::Projection(ref proj)) => { if let Some(field) = self.is_upvar_field_projection(&proj.base) { self.used_mut_upvars.push(field); } } - Place::Static(..) => {} - } - if let Err(place_err) = self.is_mutable(place, is_local_mutation_allowed) { - error_reported = true; - let mut err_info = None; - match *place_err { - - Place::Projection(box Projection { - ref base, elem:ProjectionElem::Deref}) => { - match *base { - Place::Local(local) => { - let locations = self.mir.find_assignments(local); - if locations.len() > 0 { - let item_msg = if error_reported { - self.get_secondary_err_msg(base) - } else { - self.get_default_err_msg(place) - }; - let sp = self.mir.source_info(locations[0]).span; - let mut to_suggest_span = String::new(); - if let Ok(src) = - self.tcx.sess.codemap().span_to_snippet(sp) { - to_suggest_span = src[1..].to_string(); - }; - err_info = Some(( - sp, - "consider changing this to be a \ - mutable reference", - to_suggest_span, - item_msg, - self.get_primary_err_msg(base))); - } - }, - _ => {}, - } - }, - _ => {}, - } + Ok(Place::Local(_)) | + Ok(Place::Static(..)) => {} + Err(place_err) => { + error_reported = true; + let item_msg = self.get_default_err_msg(place); + let mut err = self.tcx + .cannot_borrow_path_as_mutable(span, &item_msg, Origin::Mir); + err.span_label(span, "cannot borrow as mutable"); - if let Some((err_help_span, - err_help_stmt, - to_suggest_span, - item_msg, - sec_span)) = err_info { - let mut err = self.tcx.cannot_assign(span, &item_msg, Origin::Mir); - err.span_suggestion(err_help_span, - err_help_stmt, - format!("&mut {}", to_suggest_span)); - if place != place_err { - err.span_label(span, sec_span); - } - err.emit() - } else { - let item_msg_ = self.get_default_err_msg(place); - let mut err = self.tcx.cannot_assign(span, &item_msg_, Origin::Mir); - err.span_label(span, "cannot mutate"); if place != place_err { if let Some(name) = self.describe_place(place_err) { err.note(&format!("the value which is causing this path not to be \ - mutable is...: `{}`", name)); + mutable is...: `{}`", name)); } } + err.emit(); } } } + Reservation(WriteKind::Mutate) | Write(WriteKind::Mutate) => { + match self.is_mutable(place, is_local_mutation_allowed) { + Ok(Place::Local(local)) + if is_local_mutation_allowed != LocalMutationIsAllowed::Yes => + { + // If the local may be initialized, and it is now currently being + // mutated, then it is justified to be annotated with the `mut` keyword, + // since the mutation may be a possible reassignment. + let mpi = self.move_data.rev_lookup.find_local(*local); + if flow_state.inits.contains(&mpi) { + self.used_mut.insert(*local); + } + } + Ok(Place::Projection(ref proj)) => { + if let Some(field) = self.is_upvar_field_projection(&proj.base) { + self.used_mut_upvars.push(field); + } + } + Ok(Place::Local(_)) | + Ok(Place::Static(..)) => {} + Err(place_err) => { + error_reported = true; + + let err_info = if let Place::Projection( + box Projection { + ref base, + elem: ProjectionElem::Deref + } + ) = *place_err { + if let Place::Local(local) = *base { + let locations = self.mir.find_assignments(local); + if locations.len() > 0 { + let item_msg = if error_reported { + self.get_secondary_err_msg(base) + } else { + self.get_default_err_msg(place) + }; + let sp = self.mir.source_info(locations[0]).span; + let mut to_suggest_span = String::new(); + if let Ok(src) = + self.tcx.sess.codemap().span_to_snippet(sp) { + to_suggest_span = src[1..].to_string(); + }; + Some((sp, + "consider changing this to be a \ + mutable reference", + to_suggest_span, + item_msg, + self.get_primary_err_msg(base))) + } else { + None + } + } else { + None + } + } else { + None + }; + + if let Some((err_help_span, + err_help_stmt, + to_suggest_span, + item_msg, + sec_span)) = err_info { + let mut err = self.tcx.cannot_assign(span, &item_msg, Origin::Mir); + err.span_suggestion(err_help_span, + err_help_stmt, + format!("&mut {}", to_suggest_span)); + if place != place_err { + err.span_label(span, sec_span); + } + err.emit() + } else { + let item_msg = self.get_default_err_msg(place); + let mut err = self.tcx.cannot_assign(span, &item_msg, Origin::Mir); + err.span_label(span, "cannot mutate"); + if place != place_err { + if let Some(name) = self.describe_place(place_err) { + err.note(&format!("the value which is causing this path not \ + to be mutable is...: `{}`", name)); + } + } + err.emit(); + } + } + } + } Reservation(WriteKind::Move) | Reservation(WriteKind::StorageDeadOrDrop) | Reservation(WriteKind::MutableBorrow(BorrowKind::Shared)) @@ -1810,25 +1835,25 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { &self, place: &'d Place<'tcx>, is_local_mutation_allowed: LocalMutationIsAllowed, - ) -> Result<(), &'d Place<'tcx>> { + ) -> Result<&'d Place<'tcx>, &'d Place<'tcx>> { match *place { Place::Local(local) => { let local = &self.mir.local_decls[local]; match local.mutability { Mutability::Not => match is_local_mutation_allowed { LocalMutationIsAllowed::Yes | LocalMutationIsAllowed::ExceptUpvars => { - Ok(()) + Ok(place) } LocalMutationIsAllowed::No => Err(place), }, - Mutability::Mut => Ok(()), + Mutability::Mut => Ok(place), } } Place::Static(ref static_) => if self.tcx.is_static(static_.def_id) != Some(hir::Mutability::MutMutable) { Err(place) } else { - Ok(()) + Ok(place) }, Place::Projection(ref proj) => { match proj.elem { @@ -1866,7 +1891,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { hir::MutImmutable => return Err(place), // `*mut` raw pointers are always mutable, regardless of context // The users have to check by themselve. - hir::MutMutable => return Ok(()), + hir::MutMutable => return Ok(place), } } // `Box` owns its content, so mutable if its location is mutable -- cgit 1.4.1-3-g733a5 From 180e2426c90cae9362bcc68576293da7a5bdd22a Mon Sep 17 00:00:00 2001 From: Keith Yeung Date: Tue, 20 Mar 2018 12:58:38 -0700 Subject: Return LocalMutationIsAllowed in is_mutable --- src/librustc_mir/borrow_check/mod.rs | 63 ++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 2498162d10f..9da5d1dcdcd 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -1366,7 +1366,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ) { debug!("check_if_reassignment_to_immutable_state({:?})", place); // determine if this path has a non-mut owner (and thus needs checking). - if let Ok(_) = self.is_mutable(place, LocalMutationIsAllowed::No) { + if let Ok(..) = self.is_mutable(place, LocalMutationIsAllowed::No) { return; } debug!( @@ -1681,24 +1681,23 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { Reservation(WriteKind::MutableBorrow(BorrowKind::Mut { .. })) | Write(WriteKind::MutableBorrow(BorrowKind::Mut { .. })) => { match self.is_mutable(place, is_local_mutation_allowed) { - Ok(Place::Local(local)) - if is_local_mutation_allowed != LocalMutationIsAllowed::Yes => - { - // If the local may be initialized, and it is now currently being - // mutated, then it is justified to be annotated with the `mut` keyword, - // since the mutation may be a possible reassignment. - let mpi = self.move_data.rev_lookup.find_local(*local); - if flow_state.inits.contains(&mpi) { - self.used_mut.insert(*local); + Ok((Place::Local(local), mut_allowed)) => { + if mut_allowed != LocalMutationIsAllowed::Yes { + // If the local may be initialized, and it is now currently being + // mutated, then it is justified to be annotated with the `mut` + // keyword, since the mutation may be a possible reassignment. + let mpi = self.move_data.rev_lookup.find_local(*local); + if flow_state.inits.contains(&mpi) { + self.used_mut.insert(*local); + } } } - Ok(Place::Projection(ref proj)) => { + Ok((Place::Projection(ref proj), _mut_allowed)) => { if let Some(field) = self.is_upvar_field_projection(&proj.base) { self.used_mut_upvars.push(field); } } - Ok(Place::Local(_)) | - Ok(Place::Static(..)) => {} + Ok((Place::Static(..), _mut_allowed)) => {} Err(place_err) => { error_reported = true; let item_msg = self.get_default_err_msg(place); @@ -1719,24 +1718,23 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } Reservation(WriteKind::Mutate) | Write(WriteKind::Mutate) => { match self.is_mutable(place, is_local_mutation_allowed) { - Ok(Place::Local(local)) - if is_local_mutation_allowed != LocalMutationIsAllowed::Yes => - { - // If the local may be initialized, and it is now currently being - // mutated, then it is justified to be annotated with the `mut` keyword, - // since the mutation may be a possible reassignment. - let mpi = self.move_data.rev_lookup.find_local(*local); - if flow_state.inits.contains(&mpi) { - self.used_mut.insert(*local); + Ok((Place::Local(local), mut_allowed)) => { + if mut_allowed != LocalMutationIsAllowed::Yes { + // If the local may be initialized, and it is now currently being + // mutated, then it is justified to be annotated with the `mut` + // keyword, since the mutation may be a possible reassignment. + let mpi = self.move_data.rev_lookup.find_local(*local); + if flow_state.inits.contains(&mpi) { + self.used_mut.insert(*local); + } } } - Ok(Place::Projection(ref proj)) => { + Ok((Place::Projection(ref proj), _mut_allowed)) => { if let Some(field) = self.is_upvar_field_projection(&proj.base) { self.used_mut_upvars.push(field); } } - Ok(Place::Local(_)) | - Ok(Place::Static(..)) => {} + Ok((Place::Static(..), _mut_allowed)) => {} Err(place_err) => { error_reported = true; @@ -1835,25 +1833,28 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { &self, place: &'d Place<'tcx>, is_local_mutation_allowed: LocalMutationIsAllowed, - ) -> Result<&'d Place<'tcx>, &'d Place<'tcx>> { + ) -> Result<(&'d Place<'tcx>, LocalMutationIsAllowed), &'d Place<'tcx>> { match *place { Place::Local(local) => { let local = &self.mir.local_decls[local]; match local.mutability { Mutability::Not => match is_local_mutation_allowed { - LocalMutationIsAllowed::Yes | LocalMutationIsAllowed::ExceptUpvars => { - Ok(place) + LocalMutationIsAllowed::Yes => { + Ok((place, LocalMutationIsAllowed::Yes)) + } + LocalMutationIsAllowed::ExceptUpvars => { + Ok((place, LocalMutationIsAllowed::ExceptUpvars)) } LocalMutationIsAllowed::No => Err(place), }, - Mutability::Mut => Ok(place), + Mutability::Mut => Ok((place, is_local_mutation_allowed)), } } Place::Static(ref static_) => if self.tcx.is_static(static_.def_id) != Some(hir::Mutability::MutMutable) { Err(place) } else { - Ok(place) + Ok((place, is_local_mutation_allowed)) }, Place::Projection(ref proj) => { match proj.elem { @@ -1891,7 +1892,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { hir::MutImmutable => return Err(place), // `*mut` raw pointers are always mutable, regardless of context // The users have to check by themselve. - hir::MutMutable => return Ok(place), + hir::MutMutable => return Ok((place, is_local_mutation_allowed)), } } // `Box` owns its content, so mutable if its location is mutable -- cgit 1.4.1-3-g733a5 From 8c607eaf949a0ba9c365dd00e18d948418cfe957 Mon Sep 17 00:00:00 2001 From: Keith Yeung Date: Fri, 23 Mar 2018 01:59:56 -0700 Subject: Skip implicit self argument for closures --- src/librustc_mir/borrow_check/mod.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 9da5d1dcdcd..a70c601bd1a 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -265,6 +265,11 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( if let ClearCrossCrate::Set(ref vsi) = mbcx.mir.visibility_scope_info { let local_decl = &mbcx.mir.local_decls[local]; + // Skip implicit `self` argument for closures + if local.index() == 1 && tcx.is_closure(mbcx.mir_def_id) { + continue; + } + // Skip over locals that begin with an underscore match local_decl.name { Some(name) if name.as_str().starts_with("_") => continue, @@ -1890,9 +1895,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { match tnm.mutbl { // `*const` raw pointers are not mutable hir::MutImmutable => return Err(place), - // `*mut` raw pointers are always mutable, regardless of context - // The users have to check by themselve. - hir::MutMutable => return Ok((place, is_local_mutation_allowed)), + // `*mut` raw pointers are always mutable, regardless of + // context. The users have to check by themselves. + hir::MutMutable => { + return Ok((place, is_local_mutation_allowed)); + } } } // `Box` owns its content, so mutable if its location is mutable -- cgit 1.4.1-3-g733a5 From d27e2a185411474e341b2a0baab43c27ca635357 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sat, 28 Apr 2018 15:10:42 +0200 Subject: Update clippy submodule --- src/tools/clippy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/tools/clippy b/src/tools/clippy index c5b39a5917f..1742229ebb7 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit c5b39a5917ffc0f1349b6e414fa3b874fdcf8429 +Subproject commit 1742229ebb7843a65c05ee495d8de5366fcc5567 -- cgit 1.4.1-3-g733a5 From 00bbda16a72eab1cf3418f9021329915eddb267c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 28 Apr 2018 17:21:12 +0200 Subject: Add query search order check --- src/test/rustdoc-js/alias.js | 2 ++ src/test/rustdoc-js/basic.js | 2 +- src/tools/rustdoc-js/tester.js | 18 ++++++++++++------ 3 files changed, 15 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/test/rustdoc-js/alias.js b/src/test/rustdoc-js/alias.js index a0500f24c17..93a04e31985 100644 --- a/src/test/rustdoc-js/alias.js +++ b/src/test/rustdoc-js/alias.js @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-order + const QUERY = '['; const EXPECTED = { diff --git a/src/test/rustdoc-js/basic.js b/src/test/rustdoc-js/basic.js index 863437cac91..d7ba1253eab 100644 --- a/src/test/rustdoc-js/basic.js +++ b/src/test/rustdoc-js/basic.js @@ -13,8 +13,8 @@ const QUERY = 'String'; const EXPECTED = { 'others': [ { 'path': 'std::string', 'name': 'String' }, - { 'path': 'std::ffi', 'name': 'OsString' }, { 'path': 'std::ffi', 'name': 'CString' }, + { 'path': 'std::ffi', 'name': 'OsString' }, ], 'in_args': [ { 'path': 'std::str', 'name': 'eq' }, diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js index 6992f2ba123..1c79443dedf 100644 --- a/src/tools/rustdoc-js/tester.js +++ b/src/tools/rustdoc-js/tester.js @@ -87,6 +87,7 @@ 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; return m.exports; } @@ -130,10 +131,10 @@ function lookForEntry(entry, data) { } } if (allGood === true) { - return true; + return i; } } - return false; + return null; } function main(argv) { @@ -177,6 +178,7 @@ function main(argv) { 'exports.QUERY = QUERY;exports.EXPECTED = EXPECTED;'); const expected = loadedFile.EXPECTED; const query = loadedFile.QUERY; + const ignore_order = loadedFile.ignore_order; var results = loaded.execSearch(loaded.getQuery(query), index); process.stdout.write('Checking "' + file + '" ... '); var error_text = []; @@ -189,13 +191,17 @@ function main(argv) { break; } var entry = expected[key]; - var found = false; + var prev_pos = 0; for (var i = 0; i < entry.length; ++i) { - if (lookForEntry(entry[i], results[key]) === true) { - found = true; - } else { + 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 (entry_pos < prev_pos && ignore_order === false) { + error_text.push("==> '" + JSON.stringify(entry[i]) + "' was supposed to be " + + " before '" + JSON.stringify(results[key][entry_pos]) + "'"); + } else { + prev_pos = entry_pos; } } } -- cgit 1.4.1-3-g733a5 From 69ec4aa97c23cfc316ec340d1afcaaeb4877e8ef Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Sat, 28 Apr 2018 20:35:26 +0200 Subject: Mark functions returning uninhabited types as noreturn --- src/librustc_trans/debuginfo/mod.rs | 2 +- src/librustc_trans/declare.rs | 4 ++-- src/test/codegen/noreturnflag.rs | 22 ++++++++++++++++------ 3 files changed, 19 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs index 193db15303f..30676b91620 100644 --- a/src/librustc_trans/debuginfo/mod.rs +++ b/src/librustc_trans/debuginfo/mod.rs @@ -271,7 +271,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, } None => {} }; - if sig.output().is_never() { + if cx.layout_of(sig.output()).abi == ty::layout::Abi::Uninhabited { flags = flags | DIFlags::FlagNoReturn; } diff --git a/src/librustc_trans/declare.rs b/src/librustc_trans/declare.rs index bbe4e18b18c..97721ffbf06 100644 --- a/src/librustc_trans/declare.rs +++ b/src/librustc_trans/declare.rs @@ -23,6 +23,7 @@ use llvm::{self, ValueRef}; use llvm::AttributePlace::Function; use rustc::ty::{self, Ty}; +use rustc::ty::layout::{self, LayoutOf}; use rustc::session::config::Sanitizer; use rustc_target::spec::PanicStrategy; use abi::{Abi, FnType, FnTypeExt}; @@ -133,8 +134,7 @@ pub fn declare_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, name: &str, let fty = FnType::new(cx, sig, &[]); let llfn = declare_raw_fn(cx, name, fty.llvm_cconv(), fty.llvm_type(cx)); - // FIXME(canndrew): This is_never should really be an is_uninhabited - if sig.output().is_never() { + if cx.layout_of(sig.output()).abi == layout::Abi::Uninhabited { llvm::Attribute::NoReturn.apply_llfn(Function, llfn); } diff --git a/src/test/codegen/noreturnflag.rs b/src/test/codegen/noreturnflag.rs index 24a5a4e44cb..7239223ca20 100644 --- a/src/test/codegen/noreturnflag.rs +++ b/src/test/codegen/noreturnflag.rs @@ -8,17 +8,27 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-flags: -g -C no-prepopulate-passes // ignore-tidy-linelength // min-llvm-version 4.0 -// compile-flags: -g -C no-prepopulate-passes - -// CHECK: {{.*}}DISubprogram{{.*}}name: "foo"{{.*}}DIFlagNoReturn +#![crate_type = "lib"] -fn foo() -> ! { +#[no_mangle] +pub fn foo() -> ! { +// CHECK: @foo() unnamed_addr #0 loop {} } -pub fn main() { - foo(); +pub enum EmptyEnum {} + +#[no_mangle] +pub fn bar() -> EmptyEnum { +// CHECK: @bar() unnamed_addr #0 + loop {} } + +// CHECK: attributes #0 = {{{.*}} noreturn {{.*}}} + +// CHECK: DISubprogram(name: "foo", {{.*}} DIFlagNoReturn +// CHECK: DISubprogram(name: "bar", {{.*}} DIFlagNoReturn -- cgit 1.4.1-3-g733a5 From c1bb1caa11ba30b42f62b58f74e530288779eb85 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 28 Apr 2018 14:14:21 -0700 Subject: std: Inline `DefaultResizePolicy::new` This should allow us to tighten up the [codegen][example] a bit more, avoiding a function call across object boundaries in the default optimized case. [example]: https://play.rust-lang.org/?gist=c1179088b0f8a4dcd93a9906463f993d&version=stable&mode=release --- src/libstd/collections/hash/map.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index a8c70489f44..a7eb002d5a1 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -33,6 +33,7 @@ const MIN_NONZERO_RAW_CAPACITY: usize = 32; // must be a power of two struct DefaultResizePolicy; impl DefaultResizePolicy { + #[inline] fn new() -> DefaultResizePolicy { DefaultResizePolicy } -- cgit 1.4.1-3-g733a5 From 622371153c66f9e371f587205d14040534060c18 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 23 Apr 2018 15:17:07 -0700 Subject: Add `-C target-feature` to all functions Previously the features specified to LLVM via `-C target-feature` were only reflected in the `TargetMachine` but this change *also* reflects these and the base features inside each function itself. This change matches clang and... Closes rust-lang-nursery/stdsimd#427 --- src/librustc_trans/attributes.rs | 30 ++++++++++++++++++------ src/librustc_trans/back/write.rs | 31 ++++--------------------- src/test/codegen/target-feature-on-functions.rs | 19 +++++++++++++++ 3 files changed, 47 insertions(+), 33 deletions(-) create mode 100644 src/test/codegen/target-feature-on-functions.rs (limited to 'src') diff --git a/src/librustc_trans/attributes.rs b/src/librustc_trans/attributes.rs index eb5c7396ae0..f455c19cc0b 100644 --- a/src/librustc_trans/attributes.rs +++ b/src/librustc_trans/attributes.rs @@ -14,6 +14,7 @@ use std::ffi::{CStr, CString}; use rustc::hir::{self, TransFnAttrFlags}; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::hir::itemlikevisit::ItemLikeVisitor; +use rustc::session::Session; use rustc::session::config::Sanitizer; use rustc::ty::TyCtxt; use rustc::ty::maps::Providers; @@ -104,6 +105,18 @@ pub fn set_probestack(cx: &CodegenCx, llfn: ValueRef) { cstr("probe-stack\0"), cstr("__rust_probestack\0")); } +pub fn llvm_target_features(sess: &Session) -> impl Iterator { + const RUSTC_SPECIFIC_FEATURES: &[&str] = &[ + "crt-static", + ]; + + let cmdline = sess.opts.cg.target_feature.split(',') + .filter(|f| !RUSTC_SPECIFIC_FEATURES.iter().any(|s| f.contains(s))); + sess.target.target.options.features.split(',') + .chain(cmdline) + .filter(|l| !l.is_empty()) +} + /// Composite function which sets LLVM attributes for function depending on its AST (#[attribute]) /// attributes. pub fn from_fn_attrs(cx: &CodegenCx, llfn: ValueRef, id: DefId) { @@ -131,13 +144,16 @@ pub fn from_fn_attrs(cx: &CodegenCx, llfn: ValueRef, id: DefId) { unwind(llfn, false); } - let features = - trans_fn_attrs.target_features - .iter() - .map(|f| { - let feature = &*f.as_str(); - format!("+{}", llvm_util::to_llvm_feature(cx.tcx.sess, feature)) - }) + let features = llvm_target_features(cx.tcx.sess) + .map(|s| s.to_string()) + .chain( + trans_fn_attrs.target_features + .iter() + .map(|f| { + let feature = &*f.as_str(); + format!("+{}", llvm_util::to_llvm_feature(cx.tcx.sess, feature)) + }) + ) .collect::>() .join(","); diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 613a07cd269..148e3d0025c 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use attributes; use back::bytecode::{self, RLIB_BYTECODE_EXTENSION}; use back::lto::{self, ModuleBuffer, ThinBuffer}; use back::link::{self, get_linker, remove}; @@ -111,31 +112,6 @@ pub fn write_output_file( } } -// On android, we by default compile for armv7 processors. This enables -// things like double word CAS instructions (rather than emulating them) -// which are *far* more efficient. This is obviously undesirable in some -// cases, so if any sort of target feature is specified we don't append v7 -// to the feature list. -// -// On iOS only armv7 and newer are supported. So it is useful to -// get all hardware potential via VFP3 (hardware floating point) -// and NEON (SIMD) instructions supported by LLVM. -// Note that without those flags various linking errors might -// arise as some of intrinsics are converted into function calls -// and nobody provides implementations those functions -fn target_feature(sess: &Session) -> String { - let rustc_features = [ - "crt-static", - ]; - let requested_features = sess.opts.cg.target_feature.split(','); - let llvm_features = requested_features.filter(|f| { - !rustc_features.iter().any(|s| f.contains(s)) - }); - format!("{},{}", - sess.target.target.options.features, - llvm_features.collect::>().join(",")) -} - fn get_llvm_opt_level(optimize: config::OptLevel) -> llvm::CodeGenOptLevel { match optimize { config::OptLevel::No => llvm::CodeGenOptLevel::None, @@ -203,7 +179,10 @@ pub fn target_machine_factory(sess: &Session, find_features: bool) None => &*sess.target.target.options.cpu }; let cpu = CString::new(cpu.as_bytes()).unwrap(); - let features = CString::new(target_feature(sess).as_bytes()).unwrap(); + let features = attributes::llvm_target_features(sess) + .collect::>() + .join(","); + let features = CString::new(features).unwrap(); let is_pie_binary = !find_features && is_pie_binary(sess); let trap_unreachable = sess.target.target.options.trap_unreachable; diff --git a/src/test/codegen/target-feature-on-functions.rs b/src/test/codegen/target-feature-on-functions.rs new file mode 100644 index 00000000000..e3cc2c753e5 --- /dev/null +++ b/src/test/codegen/target-feature-on-functions.rs @@ -0,0 +1,19 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// only-x86_64 +// compile-flags: -C target-feature=+avx + +#![crate_type = "lib"] + +#[no_mangle] +pub fn foo() { + // CHECK: attributes #0 = { {{.*}}"target-features"="+avx"{{.*}} } +} -- cgit 1.4.1-3-g733a5 From 0212e0230a500c3b50a6830a20c12d1db3520b99 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Sat, 28 Apr 2018 20:59:25 -0500 Subject: feature on test --- src/test/run-pass/vec-const-new.rs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/test/run-pass/vec-const-new.rs b/src/test/run-pass/vec-const-new.rs index 02d8cfdcf98..62e2a36d7cc 100644 --- a/src/test/run-pass/vec-const-new.rs +++ b/src/test/run-pass/vec-const-new.rs @@ -10,6 +10,8 @@ // Test that Vec::new() can be used for constants +#![feature(const_vec_new)] + const MY_VEC: Vec = Vec::new(); pub fn main() {} -- cgit 1.4.1-3-g733a5 From c659faba8d8a7e21eeddbf446c9101bb945e9f0c Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Sat, 10 Mar 2018 14:26:33 -0800 Subject: in which the fn-must-use codepath is prevented from panicking on closure The must-use lint needs the DefId of called functions and method receivers in order to look for a `#[must_use]` attribute, but this would ICE (!) if a called function was actually a closure (with a non-unit return value). Instead, let's be specific that we want a `Def::Fn`, rather than blithely assuming that we can get the DefId of a qpath. Supporting must-use closures doesn't seem like a priority, but could conceivably be added in the future if desired (conditional on the statement and expression attributes (#15701) story being amicable). --- src/librustc_lint/unused.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 5ec8305de78..c32e9cdce0e 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use rustc::hir::def::Def; use rustc::hir::def_id::DefId; use rustc::ty; use rustc::ty::adjustment; @@ -77,7 +78,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { hir::ExprCall(ref callee, _) => { match callee.node { hir::ExprPath(ref qpath) => { - Some(cx.tables.qpath_def(qpath, callee.hir_id)) + let def = cx.tables.qpath_def(qpath, callee.hir_id); + if let Def::Fn(_) = def { + Some(def) + } else { // `Def::Local` if it was a closure, for which we + None // do not currently support must-use linting + } }, _ => None } -- cgit 1.4.1-3-g733a5 From 3dbdccc6a9c1ead58325d415381b25c676386c34 Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Sat, 10 Mar 2018 16:23:28 -0800 Subject: stabilize `#[must_use]` for functions and must-use operators This is in the matter of RFC 1940 and tracking issue #43302. --- .../src/language-features/fn-must-use.md | 30 ---- src/liballoc/lib.rs | 2 +- src/liballoc/tests/slice.rs | 1 + src/libcore/lib.rs | 2 +- src/librustc_lint/unused.rs | 104 +++++++------- src/libstd/ffi/c_str.rs | 2 + src/libstd/sync/mpsc/select.rs | 2 + src/libsyntax/feature_gate.rs | 22 +-- .../ui/feature-gate-fn_must_use-cap-lints-allow.rs | 22 --- ...feature-gate-fn_must_use-cap-lints-allow.stderr | 8 -- src/test/ui/feature-gate-fn_must_use.rs | 31 ----- src/test/ui/feature-gate-fn_must_use.stderr | 24 ---- .../issue-43106-gating-of-builtin-attrs.rs | 1 - .../issue-43106-gating-of-builtin-attrs.stderr | 154 ++++++++++----------- src/test/ui/fn_must_use.rs | 78 +++++++++++ src/test/ui/fn_must_use.stderr | 48 +++++++ src/test/ui/lint/must-use-ops.rs | 1 - src/test/ui/lint/must-use-ops.stderr | 44 +++--- .../rfc_1940-must_use_on_functions/fn_must_use.rs | 79 ----------- .../fn_must_use.stderr | 48 ------- src/test/ui/span/gated-features-attr-spans.rs | 23 --- src/test/ui/span/gated-features-attr-spans.stderr | 18 +-- 22 files changed, 284 insertions(+), 460 deletions(-) delete mode 100644 src/doc/unstable-book/src/language-features/fn-must-use.md delete mode 100644 src/test/ui/feature-gate-fn_must_use-cap-lints-allow.rs delete mode 100644 src/test/ui/feature-gate-fn_must_use-cap-lints-allow.stderr delete mode 100644 src/test/ui/feature-gate-fn_must_use.rs delete mode 100644 src/test/ui/feature-gate-fn_must_use.stderr create mode 100644 src/test/ui/fn_must_use.rs create mode 100644 src/test/ui/fn_must_use.stderr delete mode 100644 src/test/ui/rfc_1940-must_use_on_functions/fn_must_use.rs delete mode 100644 src/test/ui/rfc_1940-must_use_on_functions/fn_must_use.stderr (limited to 'src') diff --git a/src/doc/unstable-book/src/language-features/fn-must-use.md b/src/doc/unstable-book/src/language-features/fn-must-use.md deleted file mode 100644 index 71b6cd663a0..00000000000 --- a/src/doc/unstable-book/src/language-features/fn-must-use.md +++ /dev/null @@ -1,30 +0,0 @@ -# `fn_must_use` - -The tracking issue for this feature is [#43302]. - -[#43302]: https://github.com/rust-lang/rust/issues/43302 - ------------------------- - -The `fn_must_use` feature allows functions and methods to be annotated with -`#[must_use]`, indicating that the `unused_must_use` lint should require their -return values to be used (similarly to how types annotated with `must_use`, -most notably `Result`, are linted if not used). - -## Examples - -```rust -#![feature(fn_must_use)] - -#[must_use] -fn double(x: i32) -> i32 { - 2 * x -} - -fn main() { - double(4); // warning: unused return value of `double` which must be used - - let _ = double(4); // (no warning) -} - -``` diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 021395d0c82..fa74352c23c 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -96,7 +96,7 @@ #![feature(dropck_eyepatch)] #![feature(exact_size_is_empty)] #![feature(fmt_internals)] -#![feature(fn_must_use)] +#![cfg_attr(stage0, feature(fn_must_use))] #![feature(from_ref)] #![feature(fundamental)] #![feature(lang_items)] diff --git a/src/liballoc/tests/slice.rs b/src/liballoc/tests/slice.rs index 99d9c51efc7..6fd0b33f02a 100644 --- a/src/liballoc/tests/slice.rs +++ b/src/liballoc/tests/slice.rs @@ -1282,6 +1282,7 @@ fn test_box_slice_clone() { } #[test] +#[allow(unused_must_use)] // here, we care about the side effects of `.clone()` #[cfg_attr(target_os = "emscripten", ignore)] fn test_box_slice_clone_panics() { use std::sync::Arc; diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 0e21a3327fd..f4ed24cc3a3 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -76,7 +76,6 @@ #![feature(doc_cfg)] #![feature(doc_spotlight)] #![feature(extern_types)] -#![feature(fn_must_use)] #![feature(fundamental)] #![feature(intrinsics)] #![feature(iterator_flatten)] @@ -114,6 +113,7 @@ #![cfg_attr(stage0, feature(target_feature))] #![cfg_attr(stage0, feature(cfg_target_feature))] +#![cfg_attr(stage0, feature(fn_must_use))] #[prelude_import] #[allow(unused)] diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index c32e9cdce0e..9e1b75ba336 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -73,59 +73,59 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { let mut fn_warned = false; let mut op_warned = false; - if cx.tcx.features().fn_must_use { - let maybe_def = match expr.node { - hir::ExprCall(ref callee, _) => { - match callee.node { - hir::ExprPath(ref qpath) => { - let def = cx.tables.qpath_def(qpath, callee.hir_id); - if let Def::Fn(_) = def { - Some(def) - } else { // `Def::Local` if it was a closure, for which we - None // do not currently support must-use linting - } - }, - _ => None - } - }, - hir::ExprMethodCall(..) => { - cx.tables.type_dependent_defs().get(expr.hir_id).cloned() - }, - _ => None - }; - if let Some(def) = maybe_def { - let def_id = def.def_id(); - fn_warned = check_must_use(cx, def_id, s.span, "return value of "); - } - let must_use_op = match expr.node { - // Hardcoding operators here seemed more expedient than the - // refactoring that would be needed to look up the `#[must_use]` - // attribute which does exist on the comparison trait methods - hir::ExprBinary(bin_op, ..) => { - match bin_op.node { - hir::BiEq | hir::BiLt | hir::BiLe | hir::BiNe | hir::BiGe | hir::BiGt => { - Some("comparison") - }, - hir::BiAdd | hir::BiSub | hir::BiDiv | hir::BiMul | hir::BiRem => { - Some("arithmetic operation") - }, - hir::BiAnd | hir::BiOr => { - Some("logical operation") - }, - hir::BiBitXor | hir::BiBitAnd | hir::BiBitOr | hir::BiShl | hir::BiShr => { - Some("bitwise operation") - }, - } - }, - hir::ExprUnary(..) => Some("unary operation"), - _ => None - }; - if let Some(must_use_op) = must_use_op { - cx.span_lint(UNUSED_MUST_USE, expr.span, - &format!("unused {} which must be used", must_use_op)); - op_warned = true; - } + let maybe_def = match expr.node { + hir::ExprCall(ref callee, _) => { + match callee.node { + hir::ExprPath(ref qpath) => { + let def = cx.tables.qpath_def(qpath, callee.hir_id); + if let Def::Fn(_) = def { + Some(def) + } else { // `Def::Local` if it was a closure, for which we + None // do not currently support must-use linting + } + }, + _ => None + } + }, + hir::ExprMethodCall(..) => { + cx.tables.type_dependent_defs().get(expr.hir_id).cloned() + }, + _ => None + }; + if let Some(def) = maybe_def { + let def_id = def.def_id(); + fn_warned = check_must_use(cx, def_id, s.span, "return value of "); } + let must_use_op = match expr.node { + // Hardcoding operators here seemed more expedient than the + // refactoring that would be needed to look up the `#[must_use]` + // attribute which does exist on the comparison trait methods + hir::ExprBinary(bin_op, ..) => { + match bin_op.node { + hir::BiEq | hir::BiLt | hir::BiLe | hir::BiNe | hir::BiGe | hir::BiGt => { + Some("comparison") + }, + hir::BiAdd | hir::BiSub | hir::BiDiv | hir::BiMul | hir::BiRem => { + Some("arithmetic operation") + }, + hir::BiAnd | hir::BiOr => { + Some("logical operation") + }, + hir::BiBitXor | hir::BiBitAnd | hir::BiBitOr | hir::BiShl | hir::BiShr => { + Some("bitwise operation") + }, + } + }, + hir::ExprUnary(..) => Some("unary operation"), + _ => None + }; + + if let Some(must_use_op) = must_use_op { + cx.span_lint(UNUSED_MUST_USE, expr.span, + &format!("unused {} which must be used", must_use_op)); + op_warned = true; + } + if !(ty_warned || fn_warned || op_warned) { cx.span_lint(UNUSED_RESULTS, s.span, "unused result"); } diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index c88c2bc9137..d4937c00012 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -988,6 +988,7 @@ impl CStr { /// behavior when `ptr` is used inside the `unsafe` block: /// /// ```no_run + /// # #![allow(unused_must_use)] /// use std::ffi::{CString}; /// /// let ptr = CString::new("Hello").unwrap().as_ptr(); @@ -1003,6 +1004,7 @@ impl CStr { /// To fix the problem, bind the `CString` to a local variable: /// /// ```no_run + /// # #![allow(unused_must_use)] /// use std::ffi::{CString}; /// /// let hello = CString::new("Hello").unwrap(); diff --git a/src/libstd/sync/mpsc/select.rs b/src/libstd/sync/mpsc/select.rs index a9f3cea243f..9310dad9172 100644 --- a/src/libstd/sync/mpsc/select.rs +++ b/src/libstd/sync/mpsc/select.rs @@ -518,6 +518,7 @@ mod tests { } } + #[allow(unused_must_use)] #[test] fn cloning() { let (tx1, rx1) = channel::(); @@ -540,6 +541,7 @@ mod tests { tx3.send(()).unwrap(); } + #[allow(unused_must_use)] #[test] fn cloning2() { let (tx1, rx1) = channel::(); diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index a4a83712a08..f16b1ba440a 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -369,9 +369,6 @@ declare_features! ( // #[doc(include="some-file")] (active, external_doc, "1.22.0", Some(44732), None), - // allow `#[must_use]` on functions and comparison operators (RFC 1940) - (active, fn_must_use, "1.21.0", Some(43302), None), - // Future-proofing enums/structs with #[non_exhaustive] attribute (RFC 2008) (active, non_exhaustive, "1.22.0", Some(44109), None), @@ -591,6 +588,8 @@ declare_features! ( (accepted, target_feature, "1.27.0", None, None), // Trait object syntax with `dyn` prefix (accepted, dyn_trait, "1.27.0", Some(44662), None), + // allow `#[must_use]` on functions; and, must-use operators (RFC 1940) + (accepted, fn_must_use, "1.27.0", Some(43302), None), ); // If you change this, please modify src/doc/unstable-book as well. You must @@ -1545,11 +1544,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { function may change over time, for now \ a top-level `fn main()` is required"); } - if let Some(attr) = attr::find_by_name(&i.attrs[..], "must_use") { - gate_feature_post!(&self, fn_must_use, attr.span, - "`#[must_use]` on functions is experimental", - GateStrength::Soft); - } } ast::ItemKind::Struct(..) => { @@ -1581,7 +1575,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { "trait aliases are not yet fully implemented"); } - ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, ref impl_items) => { + ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, _) => { if polarity == ast::ImplPolarity::Negative { gate_feature_post!(&self, optin_builtin_traits, i.span, @@ -1594,16 +1588,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { i.span, "specialization is unstable"); } - - for impl_item in impl_items { - if let ast::ImplItemKind::Method(..) = impl_item.node { - if let Some(attr) = attr::find_by_name(&impl_item.attrs[..], "must_use") { - gate_feature_post!(&self, fn_must_use, attr.span, - "`#[must_use]` on methods is experimental", - GateStrength::Soft); - } - } - } } ast::ItemKind::Trait(ast::IsAuto::Yes, ..) => { diff --git a/src/test/ui/feature-gate-fn_must_use-cap-lints-allow.rs b/src/test/ui/feature-gate-fn_must_use-cap-lints-allow.rs deleted file mode 100644 index 1c04199c05f..00000000000 --- a/src/test/ui/feature-gate-fn_must_use-cap-lints-allow.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// compile-flags: --cap-lints allow - -// This tests that the fn_must_use feature-gate warning respects the lint -// cap. (See discussion in Issue #44213.) - -#![feature(rustc_attrs)] - -#[must_use] // (no feature-gate warning because of the lint cap!) -fn need_to_use_it() -> bool { true } - -#[rustc_error] -fn main() {} //~ ERROR compilation successful diff --git a/src/test/ui/feature-gate-fn_must_use-cap-lints-allow.stderr b/src/test/ui/feature-gate-fn_must_use-cap-lints-allow.stderr deleted file mode 100644 index a2c1dedff38..00000000000 --- a/src/test/ui/feature-gate-fn_must_use-cap-lints-allow.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: compilation successful - --> $DIR/feature-gate-fn_must_use-cap-lints-allow.rs:22:1 - | -LL | fn main() {} //~ ERROR compilation successful - | ^^^^^^^^^^^^ - -error: aborting due to previous error - diff --git a/src/test/ui/feature-gate-fn_must_use.rs b/src/test/ui/feature-gate-fn_must_use.rs deleted file mode 100644 index 72fdcc76cf4..00000000000 --- a/src/test/ui/feature-gate-fn_must_use.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![feature(rustc_attrs)] - -struct MyStruct; - -impl MyStruct { - #[must_use] //~ WARN `#[must_use]` on methods is experimental - fn need_to_use_method() -> bool { true } -} - -#[must_use] //~ WARN `#[must_use]` on functions is experimental -fn need_to_use_it() -> bool { true } - - -// Feature gates are tidy-required to have a specially named (or -// comment-annotated) compile-fail test (which MUST fail), but for -// backwards-compatibility reasons, we want `#[must_use]` on functions to be -// compilable even if the `fn_must_use` feature is absent, thus necessitating -// the usage of `#[rustc_error]` here, pragmatically if awkwardly solving this -// dilemma until a superior solution can be devised. -#[rustc_error] -fn main() {} //~ ERROR compilation successful diff --git a/src/test/ui/feature-gate-fn_must_use.stderr b/src/test/ui/feature-gate-fn_must_use.stderr deleted file mode 100644 index 431c57abd26..00000000000 --- a/src/test/ui/feature-gate-fn_must_use.stderr +++ /dev/null @@ -1,24 +0,0 @@ -warning: `#[must_use]` on methods is experimental (see issue #43302) - --> $DIR/feature-gate-fn_must_use.rs:16:5 - | -LL | #[must_use] //~ WARN `#[must_use]` on methods is experimental - | ^^^^^^^^^^^ - | - = help: add #![feature(fn_must_use)] to the crate attributes to enable - -warning: `#[must_use]` on functions is experimental (see issue #43302) - --> $DIR/feature-gate-fn_must_use.rs:20:1 - | -LL | #[must_use] //~ WARN `#[must_use]` on functions is experimental - | ^^^^^^^^^^^ - | - = help: add #![feature(fn_must_use)] to the crate attributes to enable - -error: compilation successful - --> $DIR/feature-gate-fn_must_use.rs:31:1 - | -LL | fn main() {} //~ ERROR compilation successful - | ^^^^^^^^^^^^ - -error: aborting due to previous error - diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs index 21950402c8c..7b0c81dbab6 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs +++ b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs @@ -661,7 +661,6 @@ mod must_use { mod inner { #![must_use="1400"] } #[must_use = "1400"] fn f() { } - //~^ WARN `#[must_use]` on functions is experimental #[must_use = "1400"] struct S; diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr index 0beed627987..76ab50c9089 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr +++ b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr @@ -12,14 +12,6 @@ LL | mod inner { #![macro_escape] } | = help: consider an outer attribute, #[macro_use] mod ... -warning: `#[must_use]` on functions is experimental (see issue #43302) - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:663:5 - | -LL | #[must_use = "1400"] fn f() { } - | ^^^^^^^^^^^^^^^^^^^^ - | - = help: add #![feature(fn_must_use)] to the crate attributes to enable - warning: unknown lint: `x5400` --> $DIR/issue-43106-gating-of-builtin-attrs.rs:49:33 | @@ -799,433 +791,433 @@ LL | #[no_std = "2600"] | ^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:692:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:691:17 | LL | mod inner { #![crate_name="0900"] } | ^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:692:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:691:17 | LL | mod inner { #![crate_name="0900"] } | ^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:696:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:695:5 | LL | #[crate_name = "0900"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:696:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:695:5 | LL | #[crate_name = "0900"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:700:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:699:5 | LL | #[crate_name = "0900"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:700:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:699:5 | LL | #[crate_name = "0900"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:704:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:703:5 | LL | #[crate_name = "0900"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:704:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:703:5 | LL | #[crate_name = "0900"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:708:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:707:5 | LL | #[crate_name = "0900"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:708:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:707:5 | LL | #[crate_name = "0900"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:688:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:687:1 | LL | #[crate_name = "0900"] | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:688:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:687:1 | LL | #[crate_name = "0900"] | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:717:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:716:17 | LL | mod inner { #![crate_type="0800"] } | ^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:717:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:716:17 | LL | mod inner { #![crate_type="0800"] } | ^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:721:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:720:5 | LL | #[crate_type = "0800"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:721:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:720:5 | LL | #[crate_type = "0800"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:725:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:724:5 | LL | #[crate_type = "0800"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:725:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:724:5 | LL | #[crate_type = "0800"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:729:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:728:5 | LL | #[crate_type = "0800"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:729:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:728:5 | LL | #[crate_type = "0800"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:733:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:732:5 | LL | #[crate_type = "0800"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:733:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:732:5 | LL | #[crate_type = "0800"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:713:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:712:1 | LL | #[crate_type = "0800"] | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:713:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:712:1 | LL | #[crate_type = "0800"] | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:742:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:741:17 | LL | mod inner { #![feature(x0600)] } | ^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:742:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:741:17 | LL | mod inner { #![feature(x0600)] } | ^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:746:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:745:5 | LL | #[feature(x0600)] fn f() { } | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:746:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:745:5 | LL | #[feature(x0600)] fn f() { } | ^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:750:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:749:5 | LL | #[feature(x0600)] struct S; | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:750:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:749:5 | LL | #[feature(x0600)] struct S; | ^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:754:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:753:5 | LL | #[feature(x0600)] type T = S; | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:754:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:753:5 | LL | #[feature(x0600)] type T = S; | ^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:758:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:757:5 | LL | #[feature(x0600)] impl S { } | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:758:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:757:5 | LL | #[feature(x0600)] impl S { } | ^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:738:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:737:1 | LL | #[feature(x0600)] | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:738:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:737:1 | LL | #[feature(x0600)] | ^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:768:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:767:17 | LL | mod inner { #![no_main="0400"] } | ^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:768:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:767:17 | LL | mod inner { #![no_main="0400"] } | ^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:772:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:771:5 | LL | #[no_main = "0400"] fn f() { } | ^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:772:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:771:5 | LL | #[no_main = "0400"] fn f() { } | ^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:776:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:775:5 | LL | #[no_main = "0400"] struct S; | ^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:776:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:775:5 | LL | #[no_main = "0400"] struct S; | ^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:780:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:779:5 | LL | #[no_main = "0400"] type T = S; | ^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:780:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:779:5 | LL | #[no_main = "0400"] type T = S; | ^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:784:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:783:5 | LL | #[no_main = "0400"] impl S { } | ^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:784:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:783:5 | LL | #[no_main = "0400"] impl S { } | ^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:764:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:763:1 | LL | #[no_main = "0400"] | ^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:764:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:763:1 | LL | #[no_main = "0400"] | ^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:806:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:805:17 | LL | mod inner { #![recursion_limit="0200"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:806:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:805:17 | LL | mod inner { #![recursion_limit="0200"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:810:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:809:5 | LL | #[recursion_limit="0200"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:810:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:809:5 | LL | #[recursion_limit="0200"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:814:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:813:5 | LL | #[recursion_limit="0200"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:814:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:813:5 | LL | #[recursion_limit="0200"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:818:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:817:5 | LL | #[recursion_limit="0200"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:818:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:817:5 | LL | #[recursion_limit="0200"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:822:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:821:5 | LL | #[recursion_limit="0200"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:822:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:821:5 | LL | #[recursion_limit="0200"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:802:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:801:1 | LL | #[recursion_limit="0200"] | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:802:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:801:1 | LL | #[recursion_limit="0200"] | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:831:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:830:17 | LL | mod inner { #![type_length_limit="0100"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:831:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:830:17 | LL | mod inner { #![type_length_limit="0100"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:835:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:834:5 | LL | #[type_length_limit="0100"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:835:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:834:5 | LL | #[type_length_limit="0100"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:839:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:838:5 | LL | #[type_length_limit="0100"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:839:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:838:5 | LL | #[type_length_limit="0100"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:843:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:842:5 | LL | #[type_length_limit="0100"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:843:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:842:5 | LL | #[type_length_limit="0100"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:847:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:846:5 | LL | #[type_length_limit="0100"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:847:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:846:5 | LL | #[type_length_limit="0100"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:827:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:826:1 | LL | #[type_length_limit="0100"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:827:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:826:1 | LL | #[type_length_limit="0100"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1309,7 +1301,7 @@ LL | #![proc_macro_derive = "2500"] //~ WARN unused attribute | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: compilation successful - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:858:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:857:1 | LL | / fn main() { //~ ERROR compilation successful LL | | println!("Hello World"); diff --git a/src/test/ui/fn_must_use.rs b/src/test/ui/fn_must_use.rs new file mode 100644 index 00000000000..def23046db2 --- /dev/null +++ b/src/test/ui/fn_must_use.rs @@ -0,0 +1,78 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-pass + +#![warn(unused_must_use)] + +#[derive(PartialEq, Eq)] +struct MyStruct { + n: usize, +} + +impl MyStruct { + #[must_use] + fn need_to_use_this_method_value(&self) -> usize { + self.n + } +} + +trait EvenNature { + #[must_use = "no side effects"] + fn is_even(&self) -> bool; +} + +impl EvenNature for MyStruct { + fn is_even(&self) -> bool { + self.n % 2 == 0 + } +} + +trait Replaceable { + fn replace(&mut self, substitute: usize) -> usize; +} + +impl Replaceable for MyStruct { + // ↓ N.b.: `#[must_use]` attribute on a particular trait implementation + // method won't work; the attribute should be on the method signature in + // the trait's definition. + #[must_use] + fn replace(&mut self, substitute: usize) -> usize { + let previously = self.n; + self.n = substitute; + previously + } +} + +#[must_use = "it's important"] +fn need_to_use_this_value() -> bool { + false +} + +fn main() { + need_to_use_this_value(); //~ WARN unused return value + + let mut m = MyStruct { n: 2 }; + let n = MyStruct { n: 3 }; + + m.need_to_use_this_method_value(); //~ WARN unused return value + m.is_even(); // trait method! + //~^ WARN unused return value + + m.replace(3); // won't warn (annotation needs to be in trait definition) + + // comparison methods are `must_use` + 2.eq(&3); //~ WARN unused return value + m.eq(&n); //~ WARN unused return value + + // lint includes comparison operators + 2 == 3; //~ WARN unused comparison + m == n; //~ WARN unused comparison +} diff --git a/src/test/ui/fn_must_use.stderr b/src/test/ui/fn_must_use.stderr new file mode 100644 index 00000000000..5026dac0a94 --- /dev/null +++ b/src/test/ui/fn_must_use.stderr @@ -0,0 +1,48 @@ +warning: unused return value of `need_to_use_this_value` which must be used: it's important + --> $DIR/fn_must_use.rs:60:5 + | +LL | need_to_use_this_value(); //~ WARN unused return value + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/fn_must_use.rs:13:9 + | +LL | #![warn(unused_must_use)] + | ^^^^^^^^^^^^^^^ + +warning: unused return value of `MyStruct::need_to_use_this_method_value` which must be used + --> $DIR/fn_must_use.rs:65:5 + | +LL | m.need_to_use_this_method_value(); //~ WARN unused return value + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unused return value of `EvenNature::is_even` which must be used: no side effects + --> $DIR/fn_must_use.rs:66:5 + | +LL | m.is_even(); // trait method! + | ^^^^^^^^^^^^ + +warning: unused return value of `std::cmp::PartialEq::eq` which must be used + --> $DIR/fn_must_use.rs:72:5 + | +LL | 2.eq(&3); //~ WARN unused return value + | ^^^^^^^^^ + +warning: unused return value of `std::cmp::PartialEq::eq` which must be used + --> $DIR/fn_must_use.rs:73:5 + | +LL | m.eq(&n); //~ WARN unused return value + | ^^^^^^^^^ + +warning: unused comparison which must be used + --> $DIR/fn_must_use.rs:76:5 + | +LL | 2 == 3; //~ WARN unused comparison + | ^^^^^^ + +warning: unused comparison which must be used + --> $DIR/fn_must_use.rs:77:5 + | +LL | m == n; //~ WARN unused comparison + | ^^^^^^ + diff --git a/src/test/ui/lint/must-use-ops.rs b/src/test/ui/lint/must-use-ops.rs index 4ed82ab3b40..c0575f817c8 100644 --- a/src/test/ui/lint/must-use-ops.rs +++ b/src/test/ui/lint/must-use-ops.rs @@ -12,7 +12,6 @@ // compile-pass -#![feature(fn_must_use)] #![warn(unused_must_use)] fn main() { diff --git a/src/test/ui/lint/must-use-ops.stderr b/src/test/ui/lint/must-use-ops.stderr index f444ef09075..5703536ef48 100644 --- a/src/test/ui/lint/must-use-ops.stderr +++ b/src/test/ui/lint/must-use-ops.stderr @@ -1,131 +1,131 @@ warning: unused comparison which must be used - --> $DIR/must-use-ops.rs:23:5 + --> $DIR/must-use-ops.rs:22:5 | LL | val == 1; | ^^^^^^^^ | note: lint level defined here - --> $DIR/must-use-ops.rs:16:9 + --> $DIR/must-use-ops.rs:15:9 | LL | #![warn(unused_must_use)] | ^^^^^^^^^^^^^^^ warning: unused comparison which must be used - --> $DIR/must-use-ops.rs:24:5 + --> $DIR/must-use-ops.rs:23:5 | LL | val < 1; | ^^^^^^^ warning: unused comparison which must be used - --> $DIR/must-use-ops.rs:25:5 + --> $DIR/must-use-ops.rs:24:5 | LL | val <= 1; | ^^^^^^^^ warning: unused comparison which must be used - --> $DIR/must-use-ops.rs:26:5 + --> $DIR/must-use-ops.rs:25:5 | LL | val != 1; | ^^^^^^^^ warning: unused comparison which must be used - --> $DIR/must-use-ops.rs:27:5 + --> $DIR/must-use-ops.rs:26:5 | LL | val >= 1; | ^^^^^^^^ warning: unused comparison which must be used - --> $DIR/must-use-ops.rs:28:5 + --> $DIR/must-use-ops.rs:27:5 | LL | val > 1; | ^^^^^^^ warning: unused arithmetic operation which must be used - --> $DIR/must-use-ops.rs:31:5 + --> $DIR/must-use-ops.rs:30:5 | LL | val + 2; | ^^^^^^^ warning: unused arithmetic operation which must be used - --> $DIR/must-use-ops.rs:32:5 + --> $DIR/must-use-ops.rs:31:5 | LL | val - 2; | ^^^^^^^ warning: unused arithmetic operation which must be used - --> $DIR/must-use-ops.rs:33:5 + --> $DIR/must-use-ops.rs:32:5 | LL | val / 2; | ^^^^^^^ warning: unused arithmetic operation which must be used - --> $DIR/must-use-ops.rs:34:5 + --> $DIR/must-use-ops.rs:33:5 | LL | val * 2; | ^^^^^^^ warning: unused arithmetic operation which must be used - --> $DIR/must-use-ops.rs:35:5 + --> $DIR/must-use-ops.rs:34:5 | LL | val % 2; | ^^^^^^^ warning: unused logical operation which must be used - --> $DIR/must-use-ops.rs:38:5 + --> $DIR/must-use-ops.rs:37:5 | LL | true && true; | ^^^^^^^^^^^^ warning: unused logical operation which must be used - --> $DIR/must-use-ops.rs:39:5 + --> $DIR/must-use-ops.rs:38:5 | LL | false || true; | ^^^^^^^^^^^^^ warning: unused bitwise operation which must be used - --> $DIR/must-use-ops.rs:42:5 + --> $DIR/must-use-ops.rs:41:5 | LL | 5 ^ val; | ^^^^^^^ warning: unused bitwise operation which must be used - --> $DIR/must-use-ops.rs:43:5 + --> $DIR/must-use-ops.rs:42:5 | LL | 5 & val; | ^^^^^^^ warning: unused bitwise operation which must be used - --> $DIR/must-use-ops.rs:44:5 + --> $DIR/must-use-ops.rs:43:5 | LL | 5 | val; | ^^^^^^^ warning: unused bitwise operation which must be used - --> $DIR/must-use-ops.rs:45:5 + --> $DIR/must-use-ops.rs:44:5 | LL | 5 << val; | ^^^^^^^^ warning: unused bitwise operation which must be used - --> $DIR/must-use-ops.rs:46:5 + --> $DIR/must-use-ops.rs:45:5 | LL | 5 >> val; | ^^^^^^^^ warning: unused unary operation which must be used - --> $DIR/must-use-ops.rs:49:5 + --> $DIR/must-use-ops.rs:48:5 | LL | !val; | ^^^^ warning: unused unary operation which must be used - --> $DIR/must-use-ops.rs:50:5 + --> $DIR/must-use-ops.rs:49:5 | LL | -val; | ^^^^ warning: unused unary operation which must be used - --> $DIR/must-use-ops.rs:51:5 + --> $DIR/must-use-ops.rs:50:5 | LL | *val_pointer; | ^^^^^^^^^^^^ diff --git a/src/test/ui/rfc_1940-must_use_on_functions/fn_must_use.rs b/src/test/ui/rfc_1940-must_use_on_functions/fn_must_use.rs deleted file mode 100644 index d20ebf0b740..00000000000 --- a/src/test/ui/rfc_1940-must_use_on_functions/fn_must_use.rs +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// compile-pass - -#![feature(fn_must_use)] -#![warn(unused_must_use)] - -#[derive(PartialEq, Eq)] -struct MyStruct { - n: usize, -} - -impl MyStruct { - #[must_use] - fn need_to_use_this_method_value(&self) -> usize { - self.n - } -} - -trait EvenNature { - #[must_use = "no side effects"] - fn is_even(&self) -> bool; -} - -impl EvenNature for MyStruct { - fn is_even(&self) -> bool { - self.n % 2 == 0 - } -} - -trait Replaceable { - fn replace(&mut self, substitute: usize) -> usize; -} - -impl Replaceable for MyStruct { - // ↓ N.b.: `#[must_use]` attribute on a particular trait implementation - // method won't work; the attribute should be on the method signature in - // the trait's definition. - #[must_use] - fn replace(&mut self, substitute: usize) -> usize { - let previously = self.n; - self.n = substitute; - previously - } -} - -#[must_use = "it's important"] -fn need_to_use_this_value() -> bool { - false -} - -fn main() { - need_to_use_this_value(); //~ WARN unused return value - - let mut m = MyStruct { n: 2 }; - let n = MyStruct { n: 3 }; - - m.need_to_use_this_method_value(); //~ WARN unused return value - m.is_even(); // trait method! - //~^ WARN unused return value - - m.replace(3); // won't warn (annotation needs to be in trait definition) - - // comparison methods are `must_use` - 2.eq(&3); //~ WARN unused return value - m.eq(&n); //~ WARN unused return value - - // lint includes comparison operators - 2 == 3; //~ WARN unused comparison - m == n; //~ WARN unused comparison -} diff --git a/src/test/ui/rfc_1940-must_use_on_functions/fn_must_use.stderr b/src/test/ui/rfc_1940-must_use_on_functions/fn_must_use.stderr deleted file mode 100644 index d0a8bb525b6..00000000000 --- a/src/test/ui/rfc_1940-must_use_on_functions/fn_must_use.stderr +++ /dev/null @@ -1,48 +0,0 @@ -warning: unused return value of `need_to_use_this_value` which must be used: it's important - --> $DIR/fn_must_use.rs:61:5 - | -LL | need_to_use_this_value(); //~ WARN unused return value - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: lint level defined here - --> $DIR/fn_must_use.rs:14:9 - | -LL | #![warn(unused_must_use)] - | ^^^^^^^^^^^^^^^ - -warning: unused return value of `MyStruct::need_to_use_this_method_value` which must be used - --> $DIR/fn_must_use.rs:66:5 - | -LL | m.need_to_use_this_method_value(); //~ WARN unused return value - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: unused return value of `EvenNature::is_even` which must be used: no side effects - --> $DIR/fn_must_use.rs:67:5 - | -LL | m.is_even(); // trait method! - | ^^^^^^^^^^^^ - -warning: unused return value of `std::cmp::PartialEq::eq` which must be used - --> $DIR/fn_must_use.rs:73:5 - | -LL | 2.eq(&3); //~ WARN unused return value - | ^^^^^^^^^ - -warning: unused return value of `std::cmp::PartialEq::eq` which must be used - --> $DIR/fn_must_use.rs:74:5 - | -LL | m.eq(&n); //~ WARN unused return value - | ^^^^^^^^^ - -warning: unused comparison which must be used - --> $DIR/fn_must_use.rs:77:5 - | -LL | 2 == 3; //~ WARN unused comparison - | ^^^^^^ - -warning: unused comparison which must be used - --> $DIR/fn_must_use.rs:78:5 - | -LL | m == n; //~ WARN unused comparison - | ^^^^^^ - diff --git a/src/test/ui/span/gated-features-attr-spans.rs b/src/test/ui/span/gated-features-attr-spans.rs index 83a4c5d5dd2..eff1f98eb71 100644 --- a/src/test/ui/span/gated-features-attr-spans.rs +++ b/src/test/ui/span/gated-features-attr-spans.rs @@ -8,33 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(attr_literals)] - -#[repr(align(16))] -struct Gem { - mohs_hardness: u8, - poofed: bool, - weapon: Weapon, -} - #[repr(simd)] //~ ERROR are experimental struct Weapon { name: String, damage: u32 } -impl Gem { - #[must_use] fn summon_weapon(&self) -> Weapon { self.weapon } - //~^ WARN is experimental -} - -#[must_use] //~ WARN is experimental -fn bubble(gem: Gem) -> Result { - if gem.poofed { - Ok(gem) - } else { - Err(()) - } -} - fn main() {} diff --git a/src/test/ui/span/gated-features-attr-spans.stderr b/src/test/ui/span/gated-features-attr-spans.stderr index 179daf83c3c..a99530529fc 100644 --- a/src/test/ui/span/gated-features-attr-spans.stderr +++ b/src/test/ui/span/gated-features-attr-spans.stderr @@ -1,27 +1,11 @@ error[E0658]: SIMD types are experimental and possibly buggy (see issue #27731) - --> $DIR/gated-features-attr-spans.rs:20:1 + --> $DIR/gated-features-attr-spans.rs:11:1 | LL | #[repr(simd)] //~ ERROR are experimental | ^^^^^^^^^^^^^ | = help: add #![feature(repr_simd)] to the crate attributes to enable -warning: `#[must_use]` on methods is experimental (see issue #43302) - --> $DIR/gated-features-attr-spans.rs:27:5 - | -LL | #[must_use] fn summon_weapon(&self) -> Weapon { self.weapon } - | ^^^^^^^^^^^ - | - = help: add #![feature(fn_must_use)] to the crate attributes to enable - -warning: `#[must_use]` on functions is experimental (see issue #43302) - --> $DIR/gated-features-attr-spans.rs:31:1 - | -LL | #[must_use] //~ WARN is experimental - | ^^^^^^^^^^^ - | - = help: add #![feature(fn_must_use)] to the crate attributes to enable - error: aborting due to previous error For more information about this error, try `rustc --explain E0658`. -- cgit 1.4.1-3-g733a5 From ded06976790299c87ca3501aca23d3c74b5b0039 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 6 Apr 2018 12:35:50 -0400 Subject: Return RootPlace in is_mutable --- src/librustc_mir/borrow_check/mod.rs | 42 ++++++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index a70c601bd1a..f2b0ec58e78 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -1150,13 +1150,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // in order to populate our used_mut set. if let AggregateKind::Closure(def_id, _) = &**aggregate_kind { let BorrowCheckResult { used_mut_upvars, .. } = self.tcx.mir_borrowck(*def_id); + debug!("{:?} used_mut_upvars={:?}", def_id, used_mut_upvars); for field in used_mut_upvars { match operands[field.index()] { Operand::Move(Place::Local(local)) => { self.used_mut.insert(local); } - Operand::Move(Place::Projection(ref proj)) => { - if let Some(field) = self.is_upvar_field_projection(&proj.base) { + Operand::Move(ref place @ Place::Projection(_)) => { + if let Some(field) = self.is_upvar_field_projection(place) { self.used_mut_upvars.push(field); } } @@ -1697,8 +1698,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } } } - Ok((Place::Projection(ref proj), _mut_allowed)) => { - if let Some(field) = self.is_upvar_field_projection(&proj.base) { + Ok((Place::Projection(_), _mut_allowed)) => { + if let Some(field) = self.is_upvar_field_projection(&place) { self.used_mut_upvars.push(field); } } @@ -1734,8 +1735,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } } } - Ok((Place::Projection(ref proj), _mut_allowed)) => { - if let Some(field) = self.is_upvar_field_projection(&proj.base) { + Ok((Place::Projection(_), _mut_allowed)) => { + if let Some(field) = self.is_upvar_field_projection(&place) { self.used_mut_upvars.push(field); } } @@ -1930,7 +1931,34 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } (Mutability::Not, LocalMutationIsAllowed::Yes) | (Mutability::Mut, _) => { - self.is_mutable(&proj.base, is_local_mutation_allowed) + // Subtle: this is an upvar + // reference, so it looks like + // `self.foo` -- we want to double + // check that the context `*self` + // is mutable (i.e., this is not a + // `Fn` closure). But if that + // check succeeds, we want to + // *blame* the mutability on + // `place` (that is, + // `self.foo`). This is used to + // propagate the info about + // whether mutability declarations + // are used outwards, so that we register + // the outer variable as mutable. Otherwise a + // test like this fails to record the `mut` + // as needed: + // + // ``` + // fn foo(_f: F) { } + // fn main() { + // let var = Vec::new(); + // foo(move || { + // var.push(1); + // }); + // } + // ``` + let _ = self.is_mutable(&proj.base, is_local_mutation_allowed)?; + Ok((place, is_local_mutation_allowed)) } } } else { -- cgit 1.4.1-3-g733a5 From 0a1cb9b91422e38baf352993ad78446a29160ed8 Mon Sep 17 00:00:00 2001 From: Keith Yeung Date: Sat, 21 Apr 2018 23:41:44 -0700 Subject: Add the actual used mutable var to the set --- src/librustc_mir/borrow_check/mod.rs | 167 +++++++++++++++++++++-------------- 1 file changed, 102 insertions(+), 65 deletions(-) (limited to 'src') diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index f2b0ec58e78..3145be7df85 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -259,6 +259,31 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( mbcx.analyze_results(&mut state); // entry point for DataflowResultsConsumer + // For each non-user used mutable variable, check if it's been assigned from + // a user-declared local. If so, then put that local into the used_mut set. + // Note that this set is expected to be small - only upvars from closures + // would have a chance of erroneously adding non-user-defined mutable vars + // to the set. + let temporary_used_locals: FxHashSet = + mbcx.used_mut.iter() + .filter(|&local| !mbcx.mir.local_decls[*local].is_user_variable) + .cloned() + .collect(); + + for local in temporary_used_locals { + for location in mbcx.mir.find_assignments(local) { + for moi in &mbcx.move_data.loc_map[location] { + let mpi = &mbcx.move_data.moves[*moi].path; + let path = &mbcx.move_data.move_paths[*mpi]; + debug!("assignment of {:?} to {:?}, adding {:?} to used mutable set", + path.place, local, path.place); + if let Place::Local(user_local) = path.place { + mbcx.used_mut.insert(user_local); + } + } + } + } + debug!("mbcx.used_mut: {:?}", mbcx.used_mut); for local in mbcx.mir.mut_vars_and_args_iter().filter(|local| !mbcx.used_mut.contains(local)) { @@ -731,6 +756,11 @@ enum InitializationRequiringAction { Assignment, } +struct RootPlace<'d, 'tcx: 'd> { + place: &'d Place<'tcx>, + is_local_mutation_allowed: LocalMutationIsAllowed, +} + impl InitializationRequiringAction { fn as_noun(self) -> &'static str { match self { @@ -1687,23 +1717,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { Reservation(WriteKind::MutableBorrow(BorrowKind::Mut { .. })) | Write(WriteKind::MutableBorrow(BorrowKind::Mut { .. })) => { match self.is_mutable(place, is_local_mutation_allowed) { - Ok((Place::Local(local), mut_allowed)) => { - if mut_allowed != LocalMutationIsAllowed::Yes { - // If the local may be initialized, and it is now currently being - // mutated, then it is justified to be annotated with the `mut` - // keyword, since the mutation may be a possible reassignment. - let mpi = self.move_data.rev_lookup.find_local(*local); - if flow_state.inits.contains(&mpi) { - self.used_mut.insert(*local); - } - } - } - Ok((Place::Projection(_), _mut_allowed)) => { - if let Some(field) = self.is_upvar_field_projection(&place) { - self.used_mut_upvars.push(field); - } - } - Ok((Place::Static(..), _mut_allowed)) => {} + Ok(root_place) => self.add_used_mut(root_place, flow_state), Err(place_err) => { error_reported = true; let item_msg = self.get_default_err_msg(place); @@ -1724,55 +1738,35 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } Reservation(WriteKind::Mutate) | Write(WriteKind::Mutate) => { match self.is_mutable(place, is_local_mutation_allowed) { - Ok((Place::Local(local), mut_allowed)) => { - if mut_allowed != LocalMutationIsAllowed::Yes { - // If the local may be initialized, and it is now currently being - // mutated, then it is justified to be annotated with the `mut` - // keyword, since the mutation may be a possible reassignment. - let mpi = self.move_data.rev_lookup.find_local(*local); - if flow_state.inits.contains(&mpi) { - self.used_mut.insert(*local); - } - } - } - Ok((Place::Projection(_), _mut_allowed)) => { - if let Some(field) = self.is_upvar_field_projection(&place) { - self.used_mut_upvars.push(field); - } - } - Ok((Place::Static(..), _mut_allowed)) => {} + Ok(root_place) => self.add_used_mut(root_place, flow_state), Err(place_err) => { error_reported = true; let err_info = if let Place::Projection( box Projection { - ref base, + base: Place::Local(local), elem: ProjectionElem::Deref } ) = *place_err { - if let Place::Local(local) = *base { - let locations = self.mir.find_assignments(local); - if locations.len() > 0 { - let item_msg = if error_reported { - self.get_secondary_err_msg(base) - } else { - self.get_default_err_msg(place) - }; - let sp = self.mir.source_info(locations[0]).span; - let mut to_suggest_span = String::new(); - if let Ok(src) = - self.tcx.sess.codemap().span_to_snippet(sp) { - to_suggest_span = src[1..].to_string(); - }; - Some((sp, - "consider changing this to be a \ - mutable reference", - to_suggest_span, - item_msg, - self.get_primary_err_msg(base))) + let locations = self.mir.find_assignments(local); + if locations.len() > 0 { + let item_msg = if error_reported { + self.get_secondary_err_msg(&Place::Local(local)) } else { - None - } + self.get_default_err_msg(place) + }; + let sp = self.mir.source_info(locations[0]).span; + let mut to_suggest_span = String::new(); + if let Ok(src) = + self.tcx.sess.codemap().span_to_snippet(sp) { + to_suggest_span = src[1..].to_string(); + }; + Some((sp, + "consider changing this to be a \ + mutable reference", + to_suggest_span, + item_msg, + self.get_primary_err_msg(&Place::Local(local)))) } else { None } @@ -1834,33 +1828,76 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { error_reported } - /// Can this value be written or borrowed mutably + /// Adds the place into the used mutable variables set + fn add_used_mut<'d>( + &mut self, + root_place: RootPlace<'d, 'tcx>, + flow_state: &Flows<'cx, 'gcx, 'tcx> + ) { + match root_place { + RootPlace { + place: Place::Local(local), + is_local_mutation_allowed, + } => { + if is_local_mutation_allowed != LocalMutationIsAllowed::Yes { + // If the local may be initialized, and it is now currently being + // mutated, then it is justified to be annotated with the `mut` + // keyword, since the mutation may be a possible reassignment. + let mpi = self.move_data.rev_lookup.find_local(*local); + if flow_state.inits.contains(&mpi) { + self.used_mut.insert(*local); + } + } + } + RootPlace { + place: place @ Place::Projection(_), + is_local_mutation_allowed: _, + } => { + if let Some(field) = self.is_upvar_field_projection(&place) { + self.used_mut_upvars.push(field); + } + } + RootPlace { + place: Place::Static(..), + is_local_mutation_allowed: _, + } => {} + } + } + + /// Whether this value be written or borrowed mutably. + /// Returns the root place if the place passed in is a projection. fn is_mutable<'d>( &self, place: &'d Place<'tcx>, is_local_mutation_allowed: LocalMutationIsAllowed, - ) -> Result<(&'d Place<'tcx>, LocalMutationIsAllowed), &'d Place<'tcx>> { + ) -> Result, &'d Place<'tcx>> { match *place { Place::Local(local) => { let local = &self.mir.local_decls[local]; match local.mutability { Mutability::Not => match is_local_mutation_allowed { LocalMutationIsAllowed::Yes => { - Ok((place, LocalMutationIsAllowed::Yes)) + Ok(RootPlace { + place, + is_local_mutation_allowed: LocalMutationIsAllowed::Yes + }) } LocalMutationIsAllowed::ExceptUpvars => { - Ok((place, LocalMutationIsAllowed::ExceptUpvars)) + Ok(RootPlace { + place, + is_local_mutation_allowed: LocalMutationIsAllowed::ExceptUpvars + }) } LocalMutationIsAllowed::No => Err(place), }, - Mutability::Mut => Ok((place, is_local_mutation_allowed)), + Mutability::Mut => Ok(RootPlace { place, is_local_mutation_allowed }), } } Place::Static(ref static_) => if self.tcx.is_static(static_.def_id) != Some(hir::Mutability::MutMutable) { Err(place) } else { - Ok((place, is_local_mutation_allowed)) + Ok(RootPlace { place, is_local_mutation_allowed }) }, Place::Projection(ref proj) => { match proj.elem { @@ -1899,7 +1936,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // `*mut` raw pointers are always mutable, regardless of // context. The users have to check by themselves. hir::MutMutable => { - return Ok((place, is_local_mutation_allowed)); + return Ok(RootPlace { place, is_local_mutation_allowed }); } } } @@ -1958,7 +1995,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // } // ``` let _ = self.is_mutable(&proj.base, is_local_mutation_allowed)?; - Ok((place, is_local_mutation_allowed)) + Ok(RootPlace { place, is_local_mutation_allowed }) } } } else { -- cgit 1.4.1-3-g733a5 From 368fe37c226c6e067ba4fa93cab0bbd5b1c09e6c Mon Sep 17 00:00:00 2001 From: Pazzaz Date: Sun, 29 Apr 2018 13:45:33 +0200 Subject: Add more links in panic docs --- src/libstd/panic.rs | 51 ++++++++++++++++++++++++++++++++----------------- src/libstd/panicking.rs | 8 +++++++- 2 files changed, 40 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs index 28c178307a5..229034eb779 100644 --- a/src/libstd/panic.rs +++ b/src/libstd/panic.rs @@ -31,10 +31,14 @@ pub use core::panic::{PanicInfo, Location}; /// A marker trait which represents "panic safe" types in Rust. /// /// This trait is implemented by default for many types and behaves similarly in -/// terms of inference of implementation to the `Send` and `Sync` traits. The -/// purpose of this trait is to encode what types are safe to cross a `catch_unwind` +/// terms of inference of implementation to the [`Send`] and [`Sync`] traits. The +/// purpose of this trait is to encode what types are safe to cross a [`catch_unwind`] /// boundary with no fear of unwind safety. /// +/// [`Send`]: ../marker/trait.Send.html +/// [`Sync`]: ../marker/trait.Sync.html +/// [`catch_unwind`]: ./fn.catch_unwind.html +/// /// ## What is unwind safety? /// /// In Rust a function can "return" early if it either panics or calls a @@ -95,12 +99,13 @@ pub use core::panic::{PanicInfo, Location}; /// /// ## When should `UnwindSafe` be used? /// -/// Is not intended that most types or functions need to worry about this trait. -/// It is only used as a bound on the `catch_unwind` function and as mentioned above, -/// the lack of `unsafe` means it is mostly an advisory. The `AssertUnwindSafe` -/// wrapper struct in this module can be used to force this trait to be -/// implemented for any closed over variables passed to the `catch_unwind` function -/// (more on this below). +/// It is not intended that most types or functions need to worry about this trait. +/// It is only used as a bound on the `catch_unwind` function and as mentioned +/// above, the lack of `unsafe` means it is mostly an advisory. The +/// [`AssertUnwindSafe`] wrapper struct can be used to force this trait to be +/// implemented for any closed over variables passed to `catch_unwind`. +/// +/// [`AssertUnwindSafe`]: ./struct.AssertUnwindSafe.html #[stable(feature = "catch_unwind", since = "1.9.0")] #[rustc_on_unimplemented = "the type {Self} may not be safely transferred \ across an unwind boundary"] @@ -109,11 +114,14 @@ pub auto trait UnwindSafe {} /// A marker trait representing types where a shared reference is considered /// unwind safe. /// -/// This trait is namely not implemented by `UnsafeCell`, the root of all +/// This trait is namely not implemented by [`UnsafeCell`], the root of all /// interior mutability. /// /// This is a "helper marker trait" used to provide impl blocks for the -/// `UnwindSafe` trait, for more information see that documentation. +/// [`UnwindSafe`] trait, for more information see that documentation. +/// +/// [`UnsafeCell`]: ../cell/struct.UnsafeCell.html +/// [`UnwindSafe`]: ./trait.UnwindSafe.html #[stable(feature = "catch_unwind", since = "1.9.0")] #[rustc_on_unimplemented = "the type {Self} may contain interior mutability \ and a reference may not be safely transferrable \ @@ -122,14 +130,15 @@ pub auto trait RefUnwindSafe {} /// A simple wrapper around a type to assert that it is unwind safe. /// -/// When using `catch_unwind` it may be the case that some of the closed over +/// When using [`catch_unwind`] it may be the case that some of the closed over /// variables are not unwind safe. For example if `&mut T` is captured the /// compiler will generate a warning indicating that it is not unwind safe. It /// may not be the case, however, that this is actually a problem due to the -/// specific usage of `catch_unwind` if unwind safety is specifically taken into +/// specific usage of [`catch_unwind`] if unwind safety is specifically taken into /// account. This wrapper struct is useful for a quick and lightweight /// annotation that a variable is indeed unwind safe. /// +/// [`catch_unwind`]: ./fn.catch_unwind.html /// # Examples /// /// One way to use `AssertUnwindSafe` is to assert that the entire closure @@ -318,18 +327,22 @@ impl fmt::Debug for AssertUnwindSafe { /// panic and allowing a graceful handling of the error. /// /// It is **not** recommended to use this function for a general try/catch -/// mechanism. The `Result` type is more appropriate to use for functions that +/// mechanism. The [`Result`] type is more appropriate to use for functions that /// can fail on a regular basis. Additionally, this function is not guaranteed /// to catch all panics, see the "Notes" section below. /// -/// The closure provided is required to adhere to the `UnwindSafe` trait to ensure +/// [`Result`]: ../result/enum.Result.html +/// +/// The closure provided is required to adhere to the [`UnwindSafe`] trait to ensure /// that all captured variables are safe to cross this boundary. The purpose of /// this bound is to encode the concept of [exception safety][rfc] in the type /// system. Most usage of this function should not need to worry about this /// bound as programs are naturally unwind safe without `unsafe` code. If it -/// becomes a problem the associated `AssertUnwindSafe` wrapper type in this -/// module can be used to quickly assert that the usage here is indeed unwind -/// safe. +/// becomes a problem the [`AssertUnwindSafe`] wrapper struct can be used to quickly +/// assert that the usage here is indeed unwind safe. +/// +/// [`AssertUnwindSafe`]: ./struct.AssertUnwindSafe.html +/// [`UnwindSafe`]: ./trait.UnwindSafe.html /// /// [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1236-stabilize-catch-panic.md /// @@ -364,9 +377,11 @@ pub fn catch_unwind R + UnwindSafe, R>(f: F) -> Result { /// Triggers a panic without invoking the panic hook. /// -/// This is designed to be used in conjunction with `catch_unwind` to, for +/// This is designed to be used in conjunction with [`catch_unwind`] to, for /// example, carry a panic across a layer of C code. /// +/// [`catch_unwind`]: ./fn.catch_unwind.html +/// /// # Notes /// /// Note that panics in Rust are not always implemented via unwinding, but they diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 24eae6a4c82..403056240bf 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -76,7 +76,9 @@ static mut HOOK: Hook = Hook::Default; /// is invoked. As such, the hook will run with both the aborting and unwinding /// runtimes. The default hook prints a message to standard error and generates /// a backtrace if requested, but this behavior can be customized with the -/// `set_hook` and `take_hook` functions. +/// `set_hook` and [`take_hook`] functions. +/// +/// [`take_hook`]: ./fn.take_hook.html /// /// The hook is provided with a `PanicInfo` struct which contains information /// about the origin of the panic, including the payload passed to `panic!` and @@ -121,6 +123,10 @@ pub fn set_hook(hook: Box) { /// Unregisters the current panic hook, returning it. /// +/// *See also the function [`set_hook`].* +/// +/// [`set_hook`]: ./fn.set_hook.html +/// /// If no custom hook is registered, the default hook will be returned. /// /// # Panics -- cgit 1.4.1-3-g733a5 From 269d2790946858dd1b504c21c54a267ac63dc15a Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sun, 29 Apr 2018 10:15:40 -0700 Subject: Fix some broken links in docs. --- src/libcore/iter/iterator.rs | 2 ++ src/libcore/marker.rs | 2 ++ src/libstd/collections/hash/table.rs | 2 +- src/libstd/ffi/c_str.rs | 1 + 4 files changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index 6a77de2c986..b27bd3142e1 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -1094,6 +1094,8 @@ pub trait Iterator { /// `flatten()` a three-dimensional array the result will be /// two-dimensional and not one-dimensional. To get a one-dimensional /// structure, you have to `flatten()` again. + /// + /// [`flat_map()`]: #method.flat_map #[inline] #[unstable(feature = "iterator_flatten", issue = "48213")] fn flatten(self) -> Flatten diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index feb689dbc1f..c074adfd570 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -602,6 +602,8 @@ unsafe impl<'a, T: ?Sized> Freeze for &'a mut T {} /// `Pin` pointer. /// /// This trait is automatically implemented for almost every type. +/// +/// [`Pin`]: ../mem/struct.Pin.html #[unstable(feature = "pin", issue = "49150")] pub unsafe auto trait Unpin {} diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index 52c53dc3b12..b50652ed6b5 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -79,7 +79,7 @@ impl TaggedHashUintPtr { /// /// Essential invariants of this structure: /// -/// - if t.hashes[i] == EMPTY_BUCKET, then `Bucket::at_index(&t, i).raw` +/// - if `t.hashes[i] == EMPTY_BUCKET`, then `Bucket::at_index(&t, i).raw` /// points to 'undefined' contents. Don't read from it. This invariant is /// enforced outside this module with the `EmptyBucket`, `FullBucket`, /// and `SafeHash` types. diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index c88c2bc9137..8164f52d3c3 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -1118,6 +1118,7 @@ impl CStr { /// /// [`Cow`]: ../borrow/enum.Cow.html /// [`Borrowed`]: ../borrow/enum.Cow.html#variant.Borrowed + /// [`Owned`]: ../borrow/enum.Cow.html#variant.Owned /// [`str`]: ../primitive.str.html /// [`String`]: ../string/struct.String.html /// -- cgit 1.4.1-3-g733a5 From a815f753bc441d8eeb0f664e27c5a3d5322900e1 Mon Sep 17 00:00:00 2001 From: varkor Date: Sun, 29 Apr 2018 18:42:43 +0100 Subject: Add error when using repr(align=x) instead of repr(align(x)) --- src/libsyntax/attr.rs | 24 ++++++++++++++++++++++++ src/libsyntax/diagnostic_list.rs | 1 + 2 files changed, 25 insertions(+) (limited to 'src') diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index c68a743303a..f0557277267 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -1045,6 +1045,30 @@ pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec span_err!(diagnostic, item.span, E0589, "invalid `repr(align)` attribute: {}", literal_error); } + } else { + if let Some(meta_item) = item.meta_item() { + if meta_item.ident.name == "align" { + if let MetaItemKind::NameValue(ref value) = meta_item.node { + recognised = true; + 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, + "use parentheses instead", + format!("align({})", int)); + } + ast::LitKind::Str(s, _) => { + err.span_suggestion(item.span, + "use parentheses instead", + format!("align({})", s)); + } + _ => {} + } + err.emit(); + } + } + } } if !recognised { // Not a word we recognize diff --git a/src/libsyntax/diagnostic_list.rs b/src/libsyntax/diagnostic_list.rs index bb7988e64bc..c9cac1b1142 100644 --- a/src/libsyntax/diagnostic_list.rs +++ b/src/libsyntax/diagnostic_list.rs @@ -324,4 +324,5 @@ register_diagnostics! { E0589, // invalid `repr(align)` attribute E0629, // missing 'feature' (rustc_const_unstable) E0630, // rustc_const_unstable attribute must be paired with stable/unstable attribute + E0693, // incorrect `repr(align)` attribute format } -- cgit 1.4.1-3-g733a5 From 35fe2998c0c555c978617913771691e384670486 Mon Sep 17 00:00:00 2001 From: varkor Date: Sun, 29 Apr 2018 18:46:41 +0100 Subject: Add test for repr(align=x) --- src/test/ui/repr-align-assign.rs | 17 +++++++++++++++++ src/test/ui/repr-align-assign.stderr | 15 +++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 src/test/ui/repr-align-assign.rs create mode 100644 src/test/ui/repr-align-assign.stderr (limited to 'src') diff --git a/src/test/ui/repr-align-assign.rs b/src/test/ui/repr-align-assign.rs new file mode 100644 index 00000000000..c9780dde235 --- /dev/null +++ b/src/test/ui/repr-align-assign.rs @@ -0,0 +1,17 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[repr(align=8)] //~ ERROR incorrect `repr(align)` attribute format +struct A(u64); + +#[repr(align="8")] //~ ERROR incorrect `repr(align)` attribute format +struct B(u64); + +fn main() {} diff --git a/src/test/ui/repr-align-assign.stderr b/src/test/ui/repr-align-assign.stderr new file mode 100644 index 00000000000..1fa1263b946 --- /dev/null +++ b/src/test/ui/repr-align-assign.stderr @@ -0,0 +1,15 @@ +error[E0693]: incorrect `repr(align)` attribute format + --> $DIR/repr-align-assign.rs:11:8 + | +LL | #[repr(align=8)] //~ ERROR incorrect `repr(align)` attribute format + | ^^^^^^^ help: use parentheses instead: `align(8)` + +error[E0693]: incorrect `repr(align)` attribute format + --> $DIR/repr-align-assign.rs:14:8 + | +LL | #[repr(align="8")] //~ ERROR incorrect `repr(align)` attribute format + | ^^^^^^^^^ help: use parentheses instead: `align(8)` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0693`. -- cgit 1.4.1-3-g733a5 From e5280e452f194ea7b4066c50b7954e07cb054161 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Sun, 29 Apr 2018 17:13:49 -0500 Subject: use const trick --- src/liballoc/raw_vec.rs | 29 ++++++----------------------- src/liballoc/vec.rs | 2 +- 2 files changed, 7 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index fe18979fb51..6ca668fda59 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -54,28 +54,18 @@ pub struct RawVec { } impl RawVec { - // FIXME: this should be made `const` when `if` statements are allowed /// Like `new` but parameterized over the choice of allocator for /// the returned RawVec. - pub fn new_in(a: A) -> Self { + pub const fn new_in(a: A) -> Self { // !0 is usize::MAX. This branch should be stripped at compile time. - let cap = if mem::size_of::() == 0 { !0 } else { 0 }; + // FIXME(mark-i-m): use this line when `if`s are allowed in `const` + //let cap = if mem::size_of::() == 0 { !0 } else { 0 }; // Unique::empty() doubles as "unallocated" and "zero-sized allocation" RawVec { ptr: Unique::empty(), - cap, - a, - } - } - - // FIXME: this should removed when `new_in` can be made `const` - /// Like `empty` but parametrized over the choice of allocator for the returned `RawVec`. - pub const fn empty_in(a: A) -> Self { - // Unique::empty() doubles as "unallocated" and "zero-sized allocation" - RawVec { - ptr: Unique::empty(), - cap: 0, + // FIXME(mark-i-m): use `cap` when ifs are allowed in const + cap: [0, !0][(mem::size_of::() != 0) as usize], a, } } @@ -132,17 +122,10 @@ impl RawVec { /// RawVec with capacity 0. If T has 0 size, then it makes a /// RawVec with capacity `usize::MAX`. Useful for implementing /// delayed allocation. - pub fn new() -> Self { + pub const fn new() -> Self { Self::new_in(Global) } - // FIXME: this should removed when `new` can be made `const` - /// Create a `RawVec` with capcity 0 (on the system heap), regardless of `T`, without - /// allocating. - pub const fn empty() -> Self { - Self::empty_in(Global) - } - /// Creates a RawVec (on the system heap) with exactly the /// capacity and alignment requirements for a `[T; cap]`. This is /// equivalent to calling RawVec::new when `cap` is 0 or T is diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 415d75664ff..35d0a69a05a 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -325,7 +325,7 @@ impl Vec { #[rustc_const_unstable(feature = "const_vec_new")] pub const fn new() -> Vec { Vec { - buf: RawVec::empty(), + buf: RawVec::new(), len: 0, } } -- cgit 1.4.1-3-g733a5 From 0a6e91bdbc6368a15bd5ccc632954b8247284b6d Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 30 Apr 2018 01:13:54 +0300 Subject: Add a few more tests for proc macro feature gating --- .../proc-macro/proc-macro-gates.rs | 55 +++++++++++++++++----- 1 file changed, 42 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/test/compile-fail-fulldeps/proc-macro/proc-macro-gates.rs b/src/test/compile-fail-fulldeps/proc-macro/proc-macro-gates.rs index 0dc1c2ab2da..fff433b90ce 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/proc-macro-gates.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/proc-macro-gates.rs @@ -24,9 +24,17 @@ use foo::*; #[foo::a] //~ ERROR: paths of length greater than one fn _test() {} +fn _test_inner() { + #![a] // OK +} + #[a] //~ ERROR: custom attributes cannot be applied to modules mod _test2 {} +mod _test2_inner { + #![a] //~ ERROR: custom attributes cannot be applied to modules +} + #[a = y] //~ ERROR: must only be followed by a delimiter token fn _test3() {} @@ -36,19 +44,40 @@ fn _test4() {} #[a () = ] //~ ERROR: must only be followed by a delimiter token fn _test5() {} -fn main() { +fn attrs() { + // Statement, item + #[a] // OK + struct S; + + // Statement, macro + #[a] //~ ERROR: custom attributes cannot be applied to statements + println!(); + + // Statement, semi + #[a] //~ ERROR: custom attributes cannot be applied to statements + S; + + // Statement, local #[a] //~ ERROR: custom attributes cannot be applied to statements let _x = 2; - let _x = #[a] 2; - //~^ ERROR: custom attributes cannot be applied to expressions - - let _x: m!(u32) = 3; - //~^ ERROR: procedural macros cannot be expanded to types - if let m!(Some(_x)) = Some(3) { - //~^ ERROR: procedural macros cannot be expanded to patterns - } - let _x = m!(3); - //~^ ERROR: procedural macros cannot be expanded to expressions - m!(let _x = 3;); - //~^ ERROR: procedural macros cannot be expanded to statements + + // Expr + let _x = #[a] 2; //~ ERROR: custom attributes cannot be applied to expressions + + // Opt expr + let _x = [#[a] 2]; //~ ERROR: custom attributes cannot be applied to expressions + + // Expr macro + let _x = #[a] println!(); //~ ERROR: custom attributes cannot be applied to expressions +} + +fn main() { + let _x: m!(u32) = 3; //~ ERROR: procedural macros cannot be expanded to types + if let m!(Some(_x)) = Some(3) {} //~ ERROR: procedural macros cannot be expanded to patterns + + m!(struct S;); //~ ERROR: procedural macros cannot be expanded to statements + m!(let _x = 3;); //~ ERROR: procedural macros cannot be expanded to statements + + let _x = m!(3); //~ ERROR: procedural macros cannot be expanded to expressions + let _x = [m!(3)]; //~ ERROR: procedural macros cannot be expanded to expressions } -- cgit 1.4.1-3-g733a5 From f9f992379de4a82637ec4bf717ff42f27872bc48 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Sun, 29 Apr 2018 17:27:17 -0500 Subject: heh, logic is hard --- src/liballoc/raw_vec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index 6ca668fda59..eb25ae17511 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -65,7 +65,7 @@ impl RawVec { RawVec { ptr: Unique::empty(), // FIXME(mark-i-m): use `cap` when ifs are allowed in const - cap: [0, !0][(mem::size_of::() != 0) as usize], + cap: [0, !0][(mem::size_of::() == 0) as usize], a, } } -- cgit 1.4.1-3-g733a5 From 7232df7d5acd8a543178eccb03fe00b962b3afb1 Mon Sep 17 00:00:00 2001 From: Oliver Middleton Date: Sun, 29 Apr 2018 23:28:39 +0100 Subject: rustdoc: Fix links to constants in external crates --- src/librustdoc/clean/mod.rs | 1 + src/test/rustdoc/auxiliary/all-item-types.rs | 32 +++++++++++++ src/test/rustdoc/cross-crate-links.rs | 71 ++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+) create mode 100644 src/test/rustdoc/auxiliary/all-item-types.rs create mode 100644 src/test/rustdoc/cross-crate-links.rs (limited to 'src') diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 6623d5ab3c2..bd64ac67ac9 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -3881,6 +3881,7 @@ fn register_def(cx: &DocContext, def: Def) -> DefId { Def::Union(i) => (i, TypeKind::Union), Def::Mod(i) => (i, TypeKind::Module), Def::TyForeign(i) => (i, TypeKind::Foreign), + Def::Const(i) => (i, TypeKind::Const), Def::Static(i, _) => (i, TypeKind::Static), Def::Variant(i) => (cx.tcx.parent_def_id(i).unwrap(), TypeKind::Enum), Def::Macro(i, _) => (i, TypeKind::Macro), diff --git a/src/test/rustdoc/auxiliary/all-item-types.rs b/src/test/rustdoc/auxiliary/all-item-types.rs new file mode 100644 index 00000000000..19a0b88ce7d --- /dev/null +++ b/src/test/rustdoc/auxiliary/all-item-types.rs @@ -0,0 +1,32 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(extern_types)] + +pub mod foo_mod {} +extern "C" { + pub fn foo_ffn(); + pub static FOO_FSTATIC: FooStruct; + pub type FooFType; +} +pub fn foo_fn() {} +pub trait FooTrait {} +pub struct FooStruct; +pub enum FooEnum {} +pub union FooUnion { + x: (), +} +pub type FooType = FooStruct; +pub static FOO_STATIC: FooStruct = FooStruct; +pub const FOO_CONSTANT: FooStruct = FooStruct; +#[macro_export] +macro_rules! foo_macro { + () => (); +} diff --git a/src/test/rustdoc/cross-crate-links.rs b/src/test/rustdoc/cross-crate-links.rs new file mode 100644 index 00000000000..15a774dc935 --- /dev/null +++ b/src/test/rustdoc/cross-crate-links.rs @@ -0,0 +1,71 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:all-item-types.rs +// build-aux-docs + +#![feature(use_extern_macros)] + +#![crate_name = "foo"] + +#[macro_use] +extern crate all_item_types; + +// @has 'foo/index.html' '//a[@href="../all_item_types/foo_mod/index.html"]' 'foo_mod' +#[doc(no_inline)] +pub use all_item_types::foo_mod; + +// @has 'foo/index.html' '//a[@href="../all_item_types/fn.foo_ffn.html"]' 'foo_ffn' +#[doc(no_inline)] +pub use all_item_types::foo_ffn; + +// @has 'foo/index.html' '//a[@href="../all_item_types/static.FOO_FSTATIC.html"]' 'FOO_FSTATIC' +#[doc(no_inline)] +pub use all_item_types::FOO_FSTATIC; + +// @has 'foo/index.html' '//a[@href="../all_item_types/foreigntype.FooFType.html"]' 'FooFType' +#[doc(no_inline)] +pub use all_item_types::FooFType; + +// @has 'foo/index.html' '//a[@href="../all_item_types/fn.foo_fn.html"]' 'foo_fn' +#[doc(no_inline)] +pub use all_item_types::foo_fn; + +// @has 'foo/index.html' '//a[@href="../all_item_types/trait.FooTrait.html"]' 'FooTrait' +#[doc(no_inline)] +pub use all_item_types::FooTrait; + +// @has 'foo/index.html' '//a[@href="../all_item_types/struct.FooStruct.html"]' 'FooStruct' +#[doc(no_inline)] +pub use all_item_types::FooStruct; + +// @has 'foo/index.html' '//a[@href="../all_item_types/enum.FooEnum.html"]' 'FooEnum' +#[doc(no_inline)] +pub use all_item_types::FooEnum; + +// @has 'foo/index.html' '//a[@href="../all_item_types/union.FooUnion.html"]' 'FooUnion' +#[doc(no_inline)] +pub use all_item_types::FooUnion; + +// @has 'foo/index.html' '//a[@href="../all_item_types/type.FooType.html"]' 'FooType' +#[doc(no_inline)] +pub use all_item_types::FooType; + +// @has 'foo/index.html' '//a[@href="../all_item_types/static.FOO_STATIC.html"]' 'FOO_STATIC' +#[doc(no_inline)] +pub use all_item_types::FOO_STATIC; + +// @has 'foo/index.html' '//a[@href="../all_item_types/constant.FOO_CONSTANT.html"]' 'FOO_CONSTANT' +#[doc(no_inline)] +pub use all_item_types::FOO_CONSTANT; + +// @has 'foo/index.html' '//a[@href="../all_item_types/macro.foo_macro.html"]' 'foo_macro' +#[doc(no_inline)] +pub use all_item_types::foo_macro; -- cgit 1.4.1-3-g733a5 From f16d2ff7ec184de179f22322f1decd96f94ef8a7 Mon Sep 17 00:00:00 2001 From: Austin Bonander Date: Tue, 17 Apr 2018 23:19:21 -0700 Subject: Warn on pointless `#[derive]` in more places This fixes the regression in #49934 and ensures that unused `#[derive]`s on statements, expressions and generic type parameters survive to trip the `unused_attributes` lint. For `#[derive]` on macro invocations it has a hardcoded warning since linting occurs after expansion. This also adds regression testing for some nodes that were already warning properly. closes #49934 --- src/librustc/hir/intravisit.rs | 3 +- src/librustc_resolve/macros.rs | 4 ++- src/libsyntax/ast.rs | 2 +- src/libsyntax/ext/base.rs | 21 +++++++++++-- src/libsyntax/ext/expand.rs | 68 +++++++++++++++++++++++++++++++++++------- src/test/ui/issue-49934.rs | 52 ++++++++++++++++++++++++++++++++ src/test/ui/issue-49934.stderr | 50 +++++++++++++++++++++++++++++++ 7 files changed, 184 insertions(+), 16 deletions(-) create mode 100644 src/test/ui/issue-49934.rs create mode 100644 src/test/ui/issue-49934.stderr (limited to 'src') diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index be9f8b8dac5..3823376df73 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -404,7 +404,7 @@ pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) { // Intentionally visiting the expr first - the initialization expr // dominates the local's definition. walk_list!(visitor, visit_expr, &local.init); - + walk_list!(visitor, visit_attribute, local.attrs.iter()); visitor.visit_id(local.id); visitor.visit_pat(&local.pat); walk_list!(visitor, visit_ty, &local.ty); @@ -731,6 +731,7 @@ pub fn walk_generic_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Generi visitor.visit_name(ty_param.span, ty_param.name); walk_list!(visitor, visit_ty_param_bound, &ty_param.bounds); walk_list!(visitor, visit_ty, &ty_param.default); + walk_list!(visitor, visit_attribute, ty_param.attrs.iter()); } } } diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 0388465b485..753ce48e478 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -206,7 +206,7 @@ impl<'a> base::Resolver for Resolver<'a> { } // Resolves attribute and derive legacy macros from `#![plugin(..)]`. - fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec) + fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec, allow_derive: bool) -> Option { for i in 0..attrs.len() { let name = unwrap_or!(attrs[i].name(), continue); @@ -227,6 +227,8 @@ impl<'a> base::Resolver for Resolver<'a> { } } + if !allow_derive { return None } + // Check for legacy derives for i in 0..attrs.len() { let name = unwrap_or!(attrs[i].name(), continue); diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 91c9a1524e1..46e3e20f58e 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -821,7 +821,7 @@ impl Stmt { pub fn is_item(&self) -> bool { match self.node { - StmtKind::Local(_) => true, + StmtKind::Item(_) => true, _ => false, } } diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 0c313ab1489..3b76084f2fb 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -118,6 +118,20 @@ impl Annotatable { } } + pub fn expect_stmt(self) -> ast::Stmt { + match self { + Annotatable::Stmt(stmt) => stmt.into_inner(), + _ => panic!("expected statement"), + } + } + + pub fn expect_expr(self) -> P { + match self { + Annotatable::Expr(expr) => expr, + _ => panic!("expected expression"), + } + } + pub fn derive_allowed(&self) -> bool { match *self { Annotatable::Item(ref item) => match item.node { @@ -661,7 +675,9 @@ pub trait Resolver { fn resolve_imports(&mut self); // Resolves attribute and derive legacy macros from `#![plugin(..)]`. - fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec) -> Option; + fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec, allow_derive: bool) + -> Option; + fn resolve_invoc(&mut self, invoc: &mut Invocation, scope: Mark, force: bool) -> Result>, Determinacy>; fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool) @@ -687,7 +703,8 @@ impl Resolver for DummyResolver { fn add_builtin(&mut self, _ident: ast::Ident, _ext: Lrc) {} fn resolve_imports(&mut self) {} - fn find_legacy_attr_invoc(&mut self, _attrs: &mut Vec) -> Option { None } + fn find_legacy_attr_invoc(&mut self, _attrs: &mut Vec, _allow_derive: bool) + -> Option { None } fn resolve_invoc(&mut self, _invoc: &mut Invocation, _scope: Mark, _force: bool) -> Result>, Determinacy> { Err(Determinacy::Determined) diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 678c20402d6..ddfffe06cfd 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -143,7 +143,7 @@ impl ExpansionKind { } fn expect_from_annotatables>(self, items: I) -> Expansion { - let items = items.into_iter(); + let mut items = items.into_iter(); match self { ExpansionKind::Items => Expansion::Items(items.map(Annotatable::expect_item).collect()), @@ -153,7 +153,14 @@ impl ExpansionKind { Expansion::TraitItems(items.map(Annotatable::expect_trait_item).collect()), ExpansionKind::ForeignItems => Expansion::ForeignItems(items.map(Annotatable::expect_foreign_item).collect()), - _ => unreachable!(), + ExpansionKind::Stmts => Expansion::Stmts(items.map(Annotatable::expect_stmt).collect()), + ExpansionKind::Expr => Expansion::Expr( + items.next().expect("expected exactly one expression").expect_expr() + ), + ExpansionKind::OptExpr => + Expansion::OptExpr(items.next().map(Annotatable::expect_expr)), + ExpansionKind::Pat | ExpansionKind::Ty => + panic!("patterns and types aren't annotatable"), } } } @@ -886,14 +893,15 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { self.collect(kind, InvocationKind::Attr { attr, traits, item }) } - // If `item` is an attr invocation, remove and return the macro attribute. + /// If `item` is an attr invocation, remove and return the macro attribute and derive traits. fn classify_item(&mut self, mut item: T) -> (Option, Vec, T) where T: HasAttrs, { let (mut attr, mut traits) = (None, Vec::new()); item = item.map_attrs(|mut attrs| { - if let Some(legacy_attr_invoc) = self.cx.resolver.find_legacy_attr_invoc(&mut attrs) { + if let Some(legacy_attr_invoc) = self.cx.resolver.find_legacy_attr_invoc(&mut attrs, + true) { attr = Some(legacy_attr_invoc); return attrs; } @@ -908,6 +916,28 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { (attr, traits, item) } + /// Alternative of `classify_item()` that ignores `#[derive]` so invocations fallthrough + /// to the unused-attributes lint (making it an error on statements and expressions + /// is a breaking change) + fn classify_nonitem(&mut self, mut item: T) -> (Option, T) { + let mut attr = None; + + item = item.map_attrs(|mut attrs| { + if let Some(legacy_attr_invoc) = self.cx.resolver.find_legacy_attr_invoc(&mut attrs, + false) { + attr = Some(legacy_attr_invoc); + return attrs; + } + + if self.cx.ecfg.proc_macro_enabled() { + attr = find_attr_invoc(&mut attrs); + } + attrs + }); + + (attr, item) + } + fn configure(&mut self, node: T) -> Option { self.cfg.configure(node) } @@ -918,6 +948,13 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { let features = self.cx.ecfg.features.unwrap(); for attr in attrs.iter() { feature_gate::check_attribute(attr, self.cx.parse_sess, features); + + // macros are expanded before any lint passes so this warning has to be hardcoded + if attr.path == "derive" { + self.cx.struct_span_warn(attr.span, "`#[derive]` does nothing on macro invocations") + .note("this may become a hard error in a future release") + .emit(); + } } } @@ -938,15 +975,16 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { let mut expr = self.cfg.configure_expr(expr).into_inner(); expr.node = self.cfg.configure_expr_kind(expr.node); - let (attr, derives, expr) = self.classify_item(expr); + // ignore derives so they remain unused + let (attr, expr) = self.classify_nonitem(expr); - if attr.is_some() || !derives.is_empty() { + if attr.is_some() { // collect the invoc regardless of whether or not attributes are permitted here // expansion will eat the attribute so it won't error later attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a)); // ExpansionKind::Expr requires the macro to emit an expression - return self.collect_attr(attr, derives, Annotatable::Expr(P(expr)), ExpansionKind::Expr) + return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)), ExpansionKind::Expr) .make_expr(); } @@ -962,12 +1000,13 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { let mut expr = configure!(self, expr).into_inner(); expr.node = self.cfg.configure_expr_kind(expr.node); - let (attr, derives, expr) = self.classify_item(expr); + // ignore derives so they remain unused + let (attr, expr) = self.classify_nonitem(expr); - if attr.is_some() || !derives.is_empty() { + if attr.is_some() { attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a)); - return self.collect_attr(attr, derives, Annotatable::Expr(P(expr)), + return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)), ExpansionKind::OptExpr) .make_opt_expr(); } @@ -1001,7 +1040,14 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { // we'll expand attributes on expressions separately if !stmt.is_expr() { - let (attr, derives, stmt_) = self.classify_item(stmt); + let (attr, derives, stmt_) = if stmt.is_item() { + self.classify_item(stmt) + } else { + // ignore derives on non-item statements so it falls through + // to the unused-attributes lint + let (attr, stmt) = self.classify_nonitem(stmt); + (attr, vec![], stmt) + }; if attr.is_some() || !derives.is_empty() { return self.collect_attr(attr, derives, diff --git a/src/test/ui/issue-49934.rs b/src/test/ui/issue-49934.rs new file mode 100644 index 00000000000..3e30e7a6450 --- /dev/null +++ b/src/test/ui/issue-49934.rs @@ -0,0 +1,52 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-pass + +#![feature(stmt_expr_attributes)] +#![warn(unused_attributes)] //~ NOTE lint level defined here + +fn foo<#[derive(Debug)] T>() { //~ WARN unused attribute + match 0 { + #[derive(Debug)] //~ WARN unused attribute + _ => (), + } +} + +fn main() { + // fold_stmt (Item) + #[allow(dead_code)] + #[derive(Debug)] // should not warn + struct Foo; + + // fold_stmt (Mac) + #[derive(Debug)] + //~^ WARN `#[derive]` does nothing on macro invocations + //~| NOTE this may become a hard error in a future release + println!("Hello, world!"); + + // fold_stmt (Semi) + #[derive(Debug)] //~ WARN unused attribute + "Hello, world!"; + + // fold_stmt (Local) + #[derive(Debug)] //~ WARN unused attribute + let _ = "Hello, world!"; + + // fold_expr + let _ = #[derive(Debug)] "Hello, world!"; + //~^ WARN unused attribute + + let _ = [ + // fold_opt_expr + #[derive(Debug)] //~ WARN unused attribute + "Hello, world!" + ]; +} diff --git a/src/test/ui/issue-49934.stderr b/src/test/ui/issue-49934.stderr new file mode 100644 index 00000000000..298230b8b29 --- /dev/null +++ b/src/test/ui/issue-49934.stderr @@ -0,0 +1,50 @@ +warning: `#[derive]` does nothing on macro invocations + --> $DIR/issue-49934.rs:30:5 + | +LL | #[derive(Debug)] + | ^^^^^^^^^^^^^^^^ + | + = note: this may become a hard error in a future release + +warning: unused attribute + --> $DIR/issue-49934.rs:16:8 + | +LL | fn foo<#[derive(Debug)] T>() { //~ WARN unused attribute + | ^^^^^^^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/issue-49934.rs:14:9 + | +LL | #![warn(unused_attributes)] //~ NOTE lint level defined here + | ^^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-49934.rs:18:9 + | +LL | #[derive(Debug)] //~ WARN unused attribute + | ^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-49934.rs:36:5 + | +LL | #[derive(Debug)] //~ WARN unused attribute + | ^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-49934.rs:40:5 + | +LL | #[derive(Debug)] //~ WARN unused attribute + | ^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-49934.rs:44:13 + | +LL | let _ = #[derive(Debug)] "Hello, world!"; + | ^^^^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/issue-49934.rs:49:9 + | +LL | #[derive(Debug)] //~ WARN unused attribute + | ^^^^^^^^^^^^^^^^ + -- cgit 1.4.1-3-g733a5 From cc53db8bf9f7583b14ae3a309fb65c3cb676bd66 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 30 Apr 2018 00:40:11 +0100 Subject: Correct unused field warning on &struct match --- src/librustc/middle/liveness.rs | 28 +++++++++++++++------- ...ssue-47390-unused-variable-in-struct-pattern.rs | 12 ++++++++++ ...-47390-unused-variable-in-struct-pattern.stderr | 14 +++++++---- 3 files changed, 41 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 17c114bc3b3..bf7fecb884e 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -412,18 +412,28 @@ fn visit_local<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, local: &'tcx hir::Local) { } fn visit_arm<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, arm: &'tcx hir::Arm) { - for pat in &arm.pats { - // for struct patterns, take note of which fields used shorthand (`x` rather than `x: x`) + for mut pat in &arm.pats { + // For struct patterns, take note of which fields used shorthand + // (`x` rather than `x: x`). // - // FIXME: according to the rust-lang-nursery/rustc-guide book, `NodeId`s are to be phased - // out in favor of `HirId`s; however, we need to match the signature of `each_binding`, - // which uses `NodeIds`. + // FIXME: according to the rust-lang-nursery/rustc-guide book, `NodeId`s are to be + // phased out in favor of `HirId`s; however, we need to match the signature of + // `each_binding`, which uses `NodeIds`. let mut shorthand_field_ids = NodeSet(); - if let hir::PatKind::Struct(_, ref fields, _) = pat.node { - for field in fields { - if field.node.is_shorthand { - shorthand_field_ids.insert(field.node.pat.id); + loop { + match pat.node { + hir::PatKind::Struct(_, ref fields, _) => { + for field in fields { + if field.node.is_shorthand { + shorthand_field_ids.insert(field.node.pat.id); + } + } + break; + } + hir::PatKind::Ref(ref deref_pat, _) => { + pat = deref_pat; } + _ => break } } diff --git a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs index 18b83370355..498e7e5e6c4 100644 --- a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs +++ b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs @@ -18,6 +18,10 @@ struct SoulHistory { endless_and_singing: bool } +enum Large { + Suit { case: () } +} + fn main() { let i_think_continually = 2; let who_from_the_womb_remembered = SoulHistory { @@ -31,4 +35,12 @@ fn main() { endless_and_singing: true } = who_from_the_womb_remembered { hours_are_suns = false; } + + let bag = &Large::Suit { + case: () + }; + + match bag { + &Large::Suit { case } => {} + }; } diff --git a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr index 35fe5479406..cecda22280c 100644 --- a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr +++ b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr @@ -1,5 +1,5 @@ warning: unused variable: `i_think_continually` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:22:9 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:26:9 | LL | let i_think_continually = 2; | ^^^^^^^^^^^^^^^^^^^ help: consider using `_i_think_continually` instead @@ -12,13 +12,13 @@ LL | #![warn(unused)] // UI tests pass `-A unused` (#43896) = note: #[warn(unused_variables)] implied by #[warn(unused)] warning: unused variable: `corridors_of_light` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:29:26 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:33:26 | LL | if let SoulHistory { corridors_of_light, | ^^^^^^^^^^^^^^^^^^ help: try ignoring the field: `corridors_of_light: _` warning: variable `hours_are_suns` is assigned to, but never used - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:30:26 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:34:26 | LL | mut hours_are_suns, | ^^^^^^^^^^^^^^^^^^ @@ -26,7 +26,7 @@ LL | mut hours_are_suns, = note: consider using `_hours_are_suns` instead warning: value assigned to `hours_are_suns` is never read - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:32:9 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:36:9 | LL | hours_are_suns = false; | ^^^^^^^^^^^^^^ @@ -38,3 +38,9 @@ LL | #![warn(unused)] // UI tests pass `-A unused` (#43896) | ^^^^^^ = note: #[warn(unused_assignments)] implied by #[warn(unused)] +warning: unused variable: `case` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:44:24 + | +LL | &Large::Suit { case } => {} + | ^^^^ help: try ignoring the field: `case: _` + -- cgit 1.4.1-3-g733a5 From 8e8fe9042c86c53d90ce17cc0754505bf014d0ed Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 30 Apr 2018 00:51:02 +0100 Subject: Correct unused field warning on box struct match --- src/librustc/middle/liveness.rs | 5 +++-- .../issue-47390-unused-variable-in-struct-pattern.rs | 10 ++++++++-- ...ue-47390-unused-variable-in-struct-pattern.stderr | 20 +++++++++++++------- 3 files changed, 24 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index bf7fecb884e..b32ee2f29d2 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -430,8 +430,9 @@ fn visit_arm<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, arm: &'tcx hir::Arm) { } break; } - hir::PatKind::Ref(ref deref_pat, _) => { - pat = deref_pat; + hir::PatKind::Ref(ref inner_pat, _) | + hir::PatKind::Box(ref inner_pat) => { + pat = inner_pat; } _ => break } diff --git a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs index 498e7e5e6c4..db3c812f259 100644 --- a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs +++ b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs @@ -10,6 +10,8 @@ // compile-pass +#![feature(box_syntax)] +#![feature(box_patterns)] #![warn(unused)] // UI tests pass `-A unused` (#43896) struct SoulHistory { @@ -36,11 +38,15 @@ fn main() { hours_are_suns = false; } - let bag = &Large::Suit { + let bag = Large::Suit { case: () }; - match bag { + match &bag { &Large::Suit { case } => {} }; + + match box bag { + box Large::Suit { case } => {} + }; } diff --git a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr index cecda22280c..ce064f9c93f 100644 --- a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr +++ b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr @@ -1,24 +1,24 @@ warning: unused variable: `i_think_continually` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:26:9 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:28:9 | LL | let i_think_continually = 2; | ^^^^^^^^^^^^^^^^^^^ help: consider using `_i_think_continually` instead | note: lint level defined here - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:13:9 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:15:9 | LL | #![warn(unused)] // UI tests pass `-A unused` (#43896) | ^^^^^^ = note: #[warn(unused_variables)] implied by #[warn(unused)] warning: unused variable: `corridors_of_light` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:33:26 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:35:26 | LL | if let SoulHistory { corridors_of_light, | ^^^^^^^^^^^^^^^^^^ help: try ignoring the field: `corridors_of_light: _` warning: variable `hours_are_suns` is assigned to, but never used - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:34:26 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:36:26 | LL | mut hours_are_suns, | ^^^^^^^^^^^^^^^^^^ @@ -26,21 +26,27 @@ LL | mut hours_are_suns, = note: consider using `_hours_are_suns` instead warning: value assigned to `hours_are_suns` is never read - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:36:9 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:38:9 | LL | hours_are_suns = false; | ^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:13:9 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:15:9 | LL | #![warn(unused)] // UI tests pass `-A unused` (#43896) | ^^^^^^ = note: #[warn(unused_assignments)] implied by #[warn(unused)] warning: unused variable: `case` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:44:24 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:46:24 | LL | &Large::Suit { case } => {} | ^^^^ help: try ignoring the field: `case: _` +warning: unused variable: `case` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:50:27 + | +LL | box Large::Suit { case } => {} + | ^^^^ help: try ignoring the field: `case: _` + -- cgit 1.4.1-3-g733a5 From 2eb8343af18470d3c48a50c68dbaeb1887b42c37 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 30 Apr 2018 01:27:37 +0100 Subject: Correct unused field warning on struct match container patterns --- src/librustc/middle/liveness.rs | 29 ++++++++++++----- ...ssue-47390-unused-variable-in-struct-pattern.rs | 25 +++++++++++++++ ...-47390-unused-variable-in-struct-pattern.stderr | 36 ++++++++++++++++++---- 3 files changed, 77 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index b32ee2f29d2..d1a46f5f155 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -111,6 +111,7 @@ use ty::{self, TyCtxt}; use lint; use util::nodemap::{NodeMap, NodeSet}; +use std::collections::VecDeque; use std::{fmt, usize}; use std::io::prelude::*; use std::io; @@ -420,21 +421,35 @@ fn visit_arm<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, arm: &'tcx hir::Arm) { // phased out in favor of `HirId`s; however, we need to match the signature of // `each_binding`, which uses `NodeIds`. let mut shorthand_field_ids = NodeSet(); - loop { + let mut pats = VecDeque::new(); + pats.push_back(pat); + while let Some(pat) = pats.pop_front() { + use hir::PatKind::*; match pat.node { - hir::PatKind::Struct(_, ref fields, _) => { + Binding(_, _, _, ref inner_pat) => { + pats.extend(inner_pat.iter()); + } + Struct(_, ref fields, _) => { for field in fields { if field.node.is_shorthand { shorthand_field_ids.insert(field.node.pat.id); } } - break; } - hir::PatKind::Ref(ref inner_pat, _) | - hir::PatKind::Box(ref inner_pat) => { - pat = inner_pat; + Ref(ref inner_pat, _) | + Box(ref inner_pat) => { + pats.push_back(inner_pat); + } + TupleStruct(_, ref inner_pats, _) | + Tuple(ref inner_pats, _) => { + pats.extend(inner_pats.iter()); + } + Slice(ref pre_pats, ref inner_pat, ref post_pats) => { + pats.extend(pre_pats.iter()); + pats.extend(inner_pat.iter()); + pats.extend(post_pats.iter()); } - _ => break + _ => {} } } diff --git a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs index db3c812f259..6994a377a06 100644 --- a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs +++ b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.rs @@ -20,10 +20,13 @@ struct SoulHistory { endless_and_singing: bool } +#[derive(Clone, Copy)] enum Large { Suit { case: () } } +struct Tuple(Large, ()); + fn main() { let i_think_continually = 2; let who_from_the_womb_remembered = SoulHistory { @@ -42,11 +45,33 @@ fn main() { case: () }; + // Plain struct + match bag { + Large::Suit { case } => {} + }; + + // Referenced struct match &bag { &Large::Suit { case } => {} }; + // Boxed struct match box bag { box Large::Suit { case } => {} }; + + // Tuple with struct + match (bag,) { + (Large::Suit { case },) => {} + }; + + // Slice with struct + match [bag] { + [Large::Suit { case }] => {} + }; + + // Tuple struct with struct + match Tuple(bag, ()) { + Tuple(Large::Suit { case }, ()) => {} + }; } diff --git a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr index ce064f9c93f..7bfe2c9162e 100644 --- a/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr +++ b/src/test/ui/lint/issue-47390-unused-variable-in-struct-pattern.stderr @@ -1,5 +1,5 @@ warning: unused variable: `i_think_continually` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:28:9 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:31:9 | LL | let i_think_continually = 2; | ^^^^^^^^^^^^^^^^^^^ help: consider using `_i_think_continually` instead @@ -12,13 +12,13 @@ LL | #![warn(unused)] // UI tests pass `-A unused` (#43896) = note: #[warn(unused_variables)] implied by #[warn(unused)] warning: unused variable: `corridors_of_light` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:35:26 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:38:26 | LL | if let SoulHistory { corridors_of_light, | ^^^^^^^^^^^^^^^^^^ help: try ignoring the field: `corridors_of_light: _` warning: variable `hours_are_suns` is assigned to, but never used - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:36:26 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:39:26 | LL | mut hours_are_suns, | ^^^^^^^^^^^^^^^^^^ @@ -26,7 +26,7 @@ LL | mut hours_are_suns, = note: consider using `_hours_are_suns` instead warning: value assigned to `hours_are_suns` is never read - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:38:9 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:41:9 | LL | hours_are_suns = false; | ^^^^^^^^^^^^^^ @@ -39,14 +39,38 @@ LL | #![warn(unused)] // UI tests pass `-A unused` (#43896) = note: #[warn(unused_assignments)] implied by #[warn(unused)] warning: unused variable: `case` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:46:24 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:50:23 + | +LL | Large::Suit { case } => {} + | ^^^^ help: try ignoring the field: `case: _` + +warning: unused variable: `case` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:55:24 | LL | &Large::Suit { case } => {} | ^^^^ help: try ignoring the field: `case: _` warning: unused variable: `case` - --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:50:27 + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:60:27 | LL | box Large::Suit { case } => {} | ^^^^ help: try ignoring the field: `case: _` +warning: unused variable: `case` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:65:24 + | +LL | (Large::Suit { case },) => {} + | ^^^^ help: try ignoring the field: `case: _` + +warning: unused variable: `case` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:70:24 + | +LL | [Large::Suit { case }] => {} + | ^^^^ help: try ignoring the field: `case: _` + +warning: unused variable: `case` + --> $DIR/issue-47390-unused-variable-in-struct-pattern.rs:75:29 + | +LL | Tuple(Large::Suit { case }, ()) => {} + | ^^^^ help: try ignoring the field: `case: _` + -- cgit 1.4.1-3-g733a5 From 410e2011bd739024ff184cebd299ba4d6d96d57e Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 27 Apr 2018 11:45:34 +1200 Subject: Update Rustfmt --- src/tools/rustfmt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/tools/rustfmt b/src/tools/rustfmt index ac8ae006254..0f4ed08d0e3 160000 --- a/src/tools/rustfmt +++ b/src/tools/rustfmt @@ -1 +1 @@ -Subproject commit ac8ae0062544743aaea1719a34f299b66f2b7dc9 +Subproject commit 0f4ed08d0e3d180d66e46904126c3792f57668a9 -- cgit 1.4.1-3-g733a5 From bd4ebf28bdf6eb898971b194f5cf773c88281251 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Mon, 30 Apr 2018 07:43:22 +0200 Subject: check that #[used] is used only on statics --- src/librustc/hir/check_attr.rs | 12 ++++++++++++ src/test/compile-fail/used.rs | 28 ++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 src/test/compile-fail/used.rs (limited to 'src') diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index 19f8d15662d..cad6ff8ae9f 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -31,6 +31,7 @@ enum Target { Expression, Statement, Closure, + Static, Other, } @@ -43,6 +44,7 @@ impl Target { hir::ItemEnum(..) => Target::Enum, hir::ItemConst(..) => Target::Const, hir::ItemForeignMod(..) => Target::ForeignMod, + hir::ItemStatic(..) => Target::Static, _ => Target::Other, } } @@ -102,6 +104,7 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> { } self.check_repr(item, target); + self.check_used(item, target); } /// Check if an `#[inline]` is applied to a function or a closure. @@ -305,6 +308,15 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> { } } } + + fn check_used(&self, item: &hir::Item, target: Target) { + for attr in &item.attrs { + if attr.name().map(|name| name == "used").unwrap_or(false) && target != Target::Static { + self.tcx.sess + .span_err(attr.span, "attribute must be applied to a `static` variable"); + } + } + } } impl<'a, 'tcx> Visitor<'tcx> for CheckAttrVisitor<'a, 'tcx> { diff --git a/src/test/compile-fail/used.rs b/src/test/compile-fail/used.rs new file mode 100644 index 00000000000..f170d9c25f5 --- /dev/null +++ b/src/test/compile-fail/used.rs @@ -0,0 +1,28 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(used)] + +#[used] +static FOO: u32 = 0; // OK + +#[used] //~ ERROR attribute must be applied to a `static` variable +fn foo() {} + +#[used] //~ ERROR attribute must be applied to a `static` variable +struct Foo {} + +#[used] //~ ERROR attribute must be applied to a `static` variable +trait Bar {} + +#[used] //~ ERROR attribute must be applied to a `static` variable +impl Bar for Foo {} + +fn main() {} -- cgit 1.4.1-3-g733a5 From 989815d5670826078d9984a3515eeb68235a4687 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sat, 28 Apr 2018 07:33:34 +1000 Subject: Extend Printer::buf on demand. So that 55 entries (at 48 bytes each) don't need to be eagerly initialized on creation. This speeds up numerous rust-perf benchmark runs, by up to 3%. --- src/libsyntax/print/pp.rs | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index 5c4bf47a6db..e7bd369053c 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -247,12 +247,14 @@ pub fn mk_printer<'a>(out: Box, linewidth: usize) -> Printer<'a> { debug!("mk_printer {}", linewidth); Printer { out, - buf_len: n, + buf_max_len: n, margin: linewidth as isize, space: linewidth as isize, left: 0, right: 0, - buf: vec![BufEntry { token: Token::Eof, size: 0 }; n], + // Initialize a single entry; advance_right() will extend it on demand + // up to `buf_max_len` elements. + buf: vec![BufEntry::default()], left_total: 0, right_total: 0, scan_stack: VecDeque::new(), @@ -263,7 +265,7 @@ pub fn mk_printer<'a>(out: Box, linewidth: usize) -> Printer<'a> { pub struct Printer<'a> { out: Box, - buf_len: usize, + buf_max_len: usize, /// Width of lines we're constrained to margin: isize, /// Number of spaces left on line @@ -297,6 +299,12 @@ struct BufEntry { size: isize, } +impl Default for BufEntry { + fn default() -> Self { + BufEntry { token: Token::Eof, size: 0 } + } +} + impl<'a> Printer<'a> { pub fn last_token(&mut self) -> Token { self.buf[self.right].token.clone() @@ -322,7 +330,9 @@ impl<'a> Printer<'a> { self.right_total = 1; self.left = 0; self.right = 0; - } else { self.advance_right(); } + } else { + self.advance_right(); + } debug!("pp Begin({})/buffer Vec<{},{}>", b.offset, self.left, self.right); self.buf[self.right] = BufEntry { token: token, size: -self.right_total }; @@ -349,7 +359,9 @@ impl<'a> Printer<'a> { self.right_total = 1; self.left = 0; self.right = 0; - } else { self.advance_right(); } + } else { + self.advance_right(); + } debug!("pp Break({})/buffer Vec<{},{}>", b.offset, self.left, self.right); self.check_stack(0); @@ -408,7 +420,11 @@ impl<'a> Printer<'a> { } pub fn advance_right(&mut self) { self.right += 1; - self.right %= self.buf_len; + self.right %= self.buf_max_len; + // Extend the buf if necessary. + if self.right == self.buf.len() { + self.buf.push(BufEntry::default()); + } assert_ne!(self.right, self.left); } pub fn advance_left(&mut self) -> io::Result<()> { @@ -438,7 +454,7 @@ impl<'a> Printer<'a> { } self.left += 1; - self.left %= self.buf_len; + self.left %= self.buf_max_len; left_size = self.buf[self.left].size; } -- cgit 1.4.1-3-g733a5 From fba903a435ea6e0e3736541cb487586262835e48 Mon Sep 17 00:00:00 2001 From: kennytm Date: Fri, 6 Apr 2018 02:03:22 +0800 Subject: Make the fields of RangeInclusive private. Added new()/start()/end() methods to RangeInclusive. Changed the lowering of `..=` to use RangeInclusive::new(). --- src/liballoc/lib.rs | 2 +- src/liballoc/tests/lib.rs | 2 +- src/libcore/ops/range.rs | 60 +++++++++++++++++++++++++++++++++++++++++++- src/libcore/tests/lib.rs | 2 +- src/librustc/hir/lowering.rs | 16 +++++++++++- src/librustc_trans/lib.rs | 2 +- 6 files changed, 78 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 021395d0c82..c94fe2a2f83 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -122,7 +122,7 @@ #![feature(on_unimplemented)] #![feature(exact_chunks)] #![feature(pointer_methods)] -#![feature(inclusive_range_fields)] +#![feature(inclusive_range_methods)] #![cfg_attr(stage0, feature(generic_param_attrs))] #![cfg_attr(not(test), feature(fn_traits, i128))] diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs index 32272169307..1c8ff316e55 100644 --- a/src/liballoc/tests/lib.rs +++ b/src/liballoc/tests/lib.rs @@ -25,7 +25,7 @@ #![feature(try_reserve)] #![feature(unboxed_closures)] #![feature(exact_chunks)] -#![feature(inclusive_range_fields)] +#![feature(inclusive_range_methods)] extern crate alloc_system; extern crate core; diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs index d70f7ae66f9..c1bd1ef2d1d 100644 --- a/src/libcore/ops/range.rs +++ b/src/libcore/ops/range.rs @@ -320,7 +320,7 @@ impl> RangeTo { /// ``` /// #![feature(inclusive_range_fields)] /// -/// assert_eq!((3..=5), std::ops::RangeInclusive { start: 3, end: 5 }); +/// assert_eq!((3..=5), std::ops::RangeInclusive::new(3, 5)); /// assert_eq!(3 + 4 + 5, (3..=5).sum()); /// /// let arr = [0, 1, 2, 3]; @@ -331,14 +331,72 @@ impl> RangeTo { #[derive(Clone, PartialEq, Eq, Hash)] // not Copy -- see #27186 #[stable(feature = "inclusive_range", since = "1.26.0")] pub struct RangeInclusive { + // FIXME: The current representation follows RFC 1980, + // but it is known that LLVM is not able to optimize loops following that RFC. + // Consider adding an extra `bool` field to indicate emptiness of the range. + // See #45222 for performance test cases. + #[cfg(not(stage0))] + pub(crate) start: Idx, + #[cfg(not(stage0))] + pub(crate) end: Idx, /// The lower bound of the range (inclusive). + #[cfg(stage0)] #[unstable(feature = "inclusive_range_fields", issue = "49022")] pub start: Idx, /// The upper bound of the range (inclusive). + #[cfg(stage0)] #[unstable(feature = "inclusive_range_fields", issue = "49022")] pub end: Idx, } +impl RangeInclusive { + /// Creates a new inclusive range. Equivalent to writing `start..=end`. + /// + /// # Examples + /// + /// ``` + /// #![feature(inclusive_range_methods)] + /// use std::ops::RangeInclusive; + /// + /// assert_eq!(3..=5, RangeInclusive::new(3, 5)); + /// ``` + #[unstable(feature = "inclusive_range_methods", issue = "49022")] + #[inline] + pub fn new(start: Idx, end: Idx) -> Self { + Self { start, end } + } + + /// Returns the lower bound of the range (inclusive). + /// + /// # Examples + /// + /// ``` + /// #![feature(inclusive_range_methods)] + /// + /// assert_eq!((3..=5).start(), &3); + /// ``` + #[unstable(feature = "inclusive_range_methods", issue = "49022")] + #[inline] + pub fn start(&self) -> &Idx { + &self.start + } + + /// Returns the upper bound of the range (inclusive). + /// + /// # Examples + /// + /// ``` + /// #![feature(inclusive_range_methods)] + /// + /// assert_eq!((3..=5).end(), &5); + /// ``` + #[unstable(feature = "inclusive_range_methods", issue = "49022")] + #[inline] + pub fn end(&self) -> &Idx { + &self.end + } +} + #[stable(feature = "inclusive_range", since = "1.26.0")] impl fmt::Debug for RangeInclusive { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index e4d27717938..f6750c590b3 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -44,7 +44,7 @@ #![feature(exact_chunks)] #![cfg_attr(stage0, feature(atomic_nand))] #![feature(reverse_bits)] -#![feature(inclusive_range_fields)] +#![feature(inclusive_range_methods)] #![feature(iterator_find_map)] extern crate core; diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index e4b9fc1385d..196f7879980 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -3119,6 +3119,20 @@ impl<'a> LoweringContext<'a> { ExprKind::Index(ref el, ref er) => { hir::ExprIndex(P(self.lower_expr(el)), P(self.lower_expr(er))) } + // Desugar `..=` to `std::ops::RangeInclusive::new(, )` + ExprKind::Range(Some(ref e1), Some(ref e2), RangeLimits::Closed) => { + // FIXME: Use head_sp directly after RangeInclusive::new() is stabilized in stage0. + let span = self.allow_internal_unstable(CompilerDesugaringKind::DotFill, e.span); + let id = self.lower_node_id(e.id); + let e1 = self.lower_expr(e1); + let e2 = self.lower_expr(e2); + let ty_path = P(self.std_path(span, &["ops", "RangeInclusive"], false)); + let ty = self.ty_path(id, span, hir::QPath::Resolved(None, ty_path)); + let new_seg = P(hir::PathSegment::from_name(Symbol::intern("new"))); + let new_path = hir::QPath::TypeRelative(ty, new_seg); + let new = P(self.expr(span, hir::ExprPath(new_path), ThinVec::new())); + hir::ExprCall(new, hir_vec![e1, e2]) + } ExprKind::Range(ref e1, ref e2, lims) => { use syntax::ast::RangeLimits::*; @@ -3128,7 +3142,7 @@ impl<'a> LoweringContext<'a> { (&None, &Some(..), HalfOpen) => "RangeTo", (&Some(..), &Some(..), HalfOpen) => "Range", (&None, &Some(..), Closed) => "RangeToInclusive", - (&Some(..), &Some(..), Closed) => "RangeInclusive", + (&Some(..), &Some(..), Closed) => unreachable!(), (_, &None, Closed) => self.diagnostic() .span_fatal(e.span, "inclusive range with no end") .raise(), diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 96a10e8b99d..9259fef279f 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -29,7 +29,7 @@ #![feature(rustc_diagnostic_macros)] #![feature(slice_sort_by_cached_key)] #![feature(optin_builtin_traits)] -#![feature(inclusive_range_fields)] +#![feature(inclusive_range_methods)] use rustc::dep_graph::WorkProduct; use syntax_pos::symbol::Symbol; -- cgit 1.4.1-3-g733a5 From 21941c8129da7b37f5df687e3862a5b331c04f83 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 30 Apr 2018 17:04:42 +0200 Subject: Update Cargo to 2018-04-28 122fd5be5201913d42e219e132d6569493583bca --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/tools/cargo b/src/tools/cargo index 0a1add2d868..122fd5be520 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 0a1add2d8689ad12a86f6c32d0a5cd0393dc5d80 +Subproject commit 122fd5be5201913d42e219e132d6569493583bca -- cgit 1.4.1-3-g733a5 From 21c2b714056f5c6fee634b87f3f4c05ac1a85bec Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 24 Apr 2018 14:17:05 +0200 Subject: Remove unused error variants --- src/librustc/ich/impls_const_math.rs | 5 ----- src/librustc/middle/const_val.rs | 5 +---- src/librustc_const_math/err.rs | 22 ---------------------- 3 files changed, 1 insertion(+), 31 deletions(-) (limited to 'src') diff --git a/src/librustc/ich/impls_const_math.rs b/src/librustc/ich/impls_const_math.rs index 5f3ff461c0c..afa28ae319c 100644 --- a/src/librustc/ich/impls_const_math.rs +++ b/src/librustc/ich/impls_const_math.rs @@ -17,16 +17,11 @@ impl_stable_hash_for!(struct ::rustc_const_math::ConstFloat { }); impl_stable_hash_for!(enum ::rustc_const_math::ConstMathErr { - NotInRange, CmpBetweenUnequalTypes, UnequalTypes(op), Overflow(op), - ShiftNegative, DivisionByZero, RemainderByZero, - UnsignedNegation, - ULitOutOfRange(int_ty), - LitOutOfRange(int_ty) }); impl_stable_hash_for!(enum ::rustc_const_math::Op { diff --git a/src/librustc/middle/const_val.rs b/src/librustc/middle/const_val.rs index 19a7576b7ce..8a2126e356f 100644 --- a/src/librustc/middle/const_val.rs +++ b/src/librustc/middle/const_val.rs @@ -78,10 +78,7 @@ pub struct FrameInfo { impl<'tcx> From for ErrKind<'tcx> { fn from(err: ConstMathErr) -> ErrKind<'tcx> { - match err { - ConstMathErr::UnsignedNegation => ErrKind::TypeckError, - _ => ErrKind::Math(err) - } + ErrKind::Math(err) } } diff --git a/src/librustc_const_math/err.rs b/src/librustc_const_math/err.rs index bd0a332436e..dee8813e86f 100644 --- a/src/librustc_const_math/err.rs +++ b/src/librustc_const_math/err.rs @@ -8,20 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use syntax::ast; - #[derive(Debug, PartialEq, Eq, Clone, RustcEncodable, RustcDecodable)] pub enum ConstMathErr { - NotInRange, CmpBetweenUnequalTypes, UnequalTypes(Op), Overflow(Op), - ShiftNegative, DivisionByZero, RemainderByZero, - UnsignedNegation, - ULitOutOfRange(ast::UintTy), - LitOutOfRange(ast::IntTy), } pub use self::ConstMathErr::*; @@ -44,7 +37,6 @@ impl ConstMathErr { pub fn description(&self) -> &'static str { use self::Op::*; match *self { - NotInRange => "inferred value out of range", CmpBetweenUnequalTypes => "compared two values of different types", UnequalTypes(Add) => "tried to add two values of different types", UnequalTypes(Sub) => "tried to subtract two values of different types", @@ -66,22 +58,8 @@ impl ConstMathErr { Overflow(Shr) => "attempt to shift right with overflow", Overflow(Shl) => "attempt to shift left with overflow", Overflow(_) => unreachable!(), - ShiftNegative => "attempt to shift by a negative amount", DivisionByZero => "attempt to divide by zero", RemainderByZero => "attempt to calculate the remainder with a divisor of zero", - UnsignedNegation => "unary negation of unsigned integer", - ULitOutOfRange(ast::UintTy::U8) => "literal out of range for u8", - ULitOutOfRange(ast::UintTy::U16) => "literal out of range for u16", - ULitOutOfRange(ast::UintTy::U32) => "literal out of range for u32", - ULitOutOfRange(ast::UintTy::U64) => "literal out of range for u64", - ULitOutOfRange(ast::UintTy::U128) => "literal out of range for u128", - ULitOutOfRange(ast::UintTy::Usize) => "literal out of range for usize", - LitOutOfRange(ast::IntTy::I8) => "literal out of range for i8", - LitOutOfRange(ast::IntTy::I16) => "literal out of range for i16", - LitOutOfRange(ast::IntTy::I32) => "literal out of range for i32", - LitOutOfRange(ast::IntTy::I64) => "literal out of range for i64", - LitOutOfRange(ast::IntTy::I128) => "literal out of range for i128", - LitOutOfRange(ast::IntTy::Isize) => "literal out of range for isize", } } } -- cgit 1.4.1-3-g733a5 From 7def638e42b70ee204cc84458b3d3775bbeba055 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 24 Apr 2018 14:36:16 +0200 Subject: Comment typo --- src/librustc_apfloat/ppc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/librustc_apfloat/ppc.rs b/src/librustc_apfloat/ppc.rs index dec88eb62cc..e662088e82f 100644 --- a/src/librustc_apfloat/ppc.rs +++ b/src/librustc_apfloat/ppc.rs @@ -20,7 +20,7 @@ use std::ops::Neg; pub struct DoubleFloat(F, F); pub type DoubleDouble = DoubleFloat; -// These are legacy semantics for the Fallback, inaccrurate implementation of +// These are legacy semantics for the Fallback, inaccurate implementation of // IBM double-double, if the accurate DoubleDouble doesn't handle the // operation. It's equivalent to having an IEEE number with consecutive 106 // bits of mantissa and 11 bits of exponent. -- cgit 1.4.1-3-g733a5 From 7d982fdcf439799efbcc9f0cfcda99fa87b07460 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 24 Apr 2018 14:42:30 +0200 Subject: Implement `PartialCmp` for `ConstFloat` --- src/librustc/ich/impls_const_math.rs | 1 - src/librustc_const_math/err.rs | 2 -- src/librustc_const_math/float.rs | 14 ++++++++++---- src/librustc_mir/hair/pattern/mod.rs | 3 +-- src/librustc_mir/interpret/operator.rs | 12 ++++++------ 5 files changed, 17 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/librustc/ich/impls_const_math.rs b/src/librustc/ich/impls_const_math.rs index afa28ae319c..387a6d5f35c 100644 --- a/src/librustc/ich/impls_const_math.rs +++ b/src/librustc/ich/impls_const_math.rs @@ -17,7 +17,6 @@ impl_stable_hash_for!(struct ::rustc_const_math::ConstFloat { }); impl_stable_hash_for!(enum ::rustc_const_math::ConstMathErr { - CmpBetweenUnequalTypes, UnequalTypes(op), Overflow(op), DivisionByZero, diff --git a/src/librustc_const_math/err.rs b/src/librustc_const_math/err.rs index dee8813e86f..5d442ee7b97 100644 --- a/src/librustc_const_math/err.rs +++ b/src/librustc_const_math/err.rs @@ -10,7 +10,6 @@ #[derive(Debug, PartialEq, Eq, Clone, RustcEncodable, RustcDecodable)] pub enum ConstMathErr { - CmpBetweenUnequalTypes, UnequalTypes(Op), Overflow(Op), DivisionByZero, @@ -37,7 +36,6 @@ impl ConstMathErr { pub fn description(&self) -> &'static str { use self::Op::*; match *self { - CmpBetweenUnequalTypes => "compared two values of different types", UnequalTypes(Add) => "tried to add two values of different types", UnequalTypes(Sub) => "tried to subtract two values of different types", UnequalTypes(Mul) => "tried to multiply two values of different types", diff --git a/src/librustc_const_math/float.rs b/src/librustc_const_math/float.rs index 9d820ea8cbe..61e9b34f06a 100644 --- a/src/librustc_const_math/float.rs +++ b/src/librustc_const_math/float.rs @@ -31,6 +31,12 @@ pub struct ConstFloat { pub bits: u128, } +impl PartialOrd for ConstFloat { + fn partial_cmp(&self, other: &Self) -> Option { + self.try_cmp(*other) + } +} + impl ConstFloat { /// Description of the type, not the value pub fn description(&self) -> &'static str { @@ -38,22 +44,22 @@ impl ConstFloat { } /// Compares the values if they are of the same type - pub fn try_cmp(self, rhs: Self) -> Result { + fn try_cmp(self, rhs: Self) -> Option { match (self.ty, rhs.ty) { (ast::FloatTy::F64, ast::FloatTy::F64) => { let a = Double::from_bits(self.bits); let b = Double::from_bits(rhs.bits); // This is pretty bad but it is the existing behavior. - Ok(a.partial_cmp(&b).unwrap_or(Ordering::Greater)) + Some(a.partial_cmp(&b).unwrap_or(Ordering::Greater)) } (ast::FloatTy::F32, ast::FloatTy::F32) => { let a = Single::from_bits(self.bits); let b = Single::from_bits(rhs.bits); - Ok(a.partial_cmp(&b).unwrap_or(Ordering::Greater)) + Some(a.partial_cmp(&b).unwrap_or(Ordering::Greater)) } - _ => Err(CmpBetweenUnequalTypes), + _ => None, } } diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index c2da8c11d87..776b24a8648 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -1069,8 +1069,7 @@ pub fn compare_const_vals<'a, 'tcx>( bits: b, ty, }; - // FIXME(oli-obk): report cmp errors? - l.try_cmp(r).ok() + l.partial_cmp(&r) }, ty::TyInt(_) => { let a = interpret::sign_extend(tcx, a, ty).expect("layout error for TyInt"); diff --git a/src/librustc_mir/interpret/operator.rs b/src/librustc_mir/interpret/operator.rs index dfc0c4a824a..0c748f818cc 100644 --- a/src/librustc_mir/interpret/operator.rs +++ b/src/librustc_mir/interpret/operator.rs @@ -135,12 +135,12 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { ty, }; match op { - Eq => PrimVal::from_bool(l.try_cmp(r).unwrap() == Ordering::Equal), - Ne => PrimVal::from_bool(l.try_cmp(r).unwrap() != Ordering::Equal), - Lt => PrimVal::from_bool(l.try_cmp(r).unwrap() == Ordering::Less), - Le => PrimVal::from_bool(l.try_cmp(r).unwrap() != Ordering::Greater), - Gt => PrimVal::from_bool(l.try_cmp(r).unwrap() == Ordering::Greater), - Ge => PrimVal::from_bool(l.try_cmp(r).unwrap() != Ordering::Less), + Eq => PrimVal::from_bool(l.partial_cmp(&r).unwrap() == Ordering::Equal), + Ne => PrimVal::from_bool(l.partial_cmp(&r).unwrap() != Ordering::Equal), + Lt => PrimVal::from_bool(l.partial_cmp(&r).unwrap() == Ordering::Less), + Le => PrimVal::from_bool(l.partial_cmp(&r).unwrap() != Ordering::Greater), + Gt => PrimVal::from_bool(l.partial_cmp(&r).unwrap() == Ordering::Greater), + Ge => PrimVal::from_bool(l.partial_cmp(&r).unwrap() != Ordering::Less), Add => PrimVal::Bytes((l + r).unwrap().bits), Sub => PrimVal::Bytes((l - r).unwrap().bits), Mul => PrimVal::Bytes((l * r).unwrap().bits), -- cgit 1.4.1-3-g733a5 From 0aa6e039d013e2c3800884a19e53e3f6c927a0e8 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 24 Apr 2018 14:55:34 +0200 Subject: Remove the `UnequalTypes` error variant --- src/librustc/ich/impls_const_math.rs | 1 - src/librustc_const_math/err.rs | 12 ------------ src/librustc_const_math/float.rs | 10 ++++------ 3 files changed, 4 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/librustc/ich/impls_const_math.rs b/src/librustc/ich/impls_const_math.rs index 387a6d5f35c..494fa49b53d 100644 --- a/src/librustc/ich/impls_const_math.rs +++ b/src/librustc/ich/impls_const_math.rs @@ -17,7 +17,6 @@ impl_stable_hash_for!(struct ::rustc_const_math::ConstFloat { }); impl_stable_hash_for!(enum ::rustc_const_math::ConstMathErr { - UnequalTypes(op), Overflow(op), DivisionByZero, RemainderByZero, diff --git a/src/librustc_const_math/err.rs b/src/librustc_const_math/err.rs index 5d442ee7b97..94a51c23a5e 100644 --- a/src/librustc_const_math/err.rs +++ b/src/librustc_const_math/err.rs @@ -10,7 +10,6 @@ #[derive(Debug, PartialEq, Eq, Clone, RustcEncodable, RustcDecodable)] pub enum ConstMathErr { - UnequalTypes(Op), Overflow(Op), DivisionByZero, RemainderByZero, @@ -36,17 +35,6 @@ impl ConstMathErr { pub fn description(&self) -> &'static str { use self::Op::*; match *self { - UnequalTypes(Add) => "tried to add two values of different types", - UnequalTypes(Sub) => "tried to subtract two values of different types", - UnequalTypes(Mul) => "tried to multiply two values of different types", - UnequalTypes(Div) => "tried to divide two values of different types", - UnequalTypes(Rem) => { - "tried to calculate the remainder of two values of different types" - }, - UnequalTypes(BitAnd) => "tried to bitand two values of different types", - UnequalTypes(BitOr) => "tried to bitor two values of different types", - UnequalTypes(BitXor) => "tried to xor two values of different types", - UnequalTypes(_) => unreachable!(), Overflow(Add) => "attempt to add with overflow", Overflow(Sub) => "attempt to subtract with overflow", Overflow(Mul) => "attempt to multiply with overflow", diff --git a/src/librustc_const_math/float.rs b/src/librustc_const_math/float.rs index 61e9b34f06a..35cfe466c8a 100644 --- a/src/librustc_const_math/float.rs +++ b/src/librustc_const_math/float.rs @@ -16,8 +16,6 @@ use syntax::ast; use rustc_apfloat::{Float, FloatConvert, Status}; use rustc_apfloat::ieee::{Single, Double}; -use super::err::*; - // Note that equality for `ConstFloat` means that the it is the same // constant, not that the rust values are equal. In particular, `NaN // == NaN` (at least if it's the same NaN; distinct encodings for NaN @@ -172,8 +170,8 @@ impl ::std::fmt::Debug for ConstFloat { macro_rules! derive_binop { ($op:ident, $func:ident) => { impl ::std::ops::$op for ConstFloat { - type Output = Result; - fn $func(self, rhs: Self) -> Result { + type Output = Option; + fn $func(self, rhs: Self) -> Option { let bits = match (self.ty, rhs.ty) { (ast::FloatTy::F32, ast::FloatTy::F32) =>{ let a = Single::from_bits(self.bits); @@ -185,9 +183,9 @@ macro_rules! derive_binop { let b = Double::from_bits(rhs.bits); a.$func(b).value.to_bits() } - _ => return Err(UnequalTypes(Op::$op)), + _ => return None, }; - Ok(ConstFloat { bits, ty: self.ty }) + Some(ConstFloat { bits, ty: self.ty }) } } } -- cgit 1.4.1-3-g733a5 From d1d8d999ba577ae03576403aa9124204dd630f63 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 24 Apr 2018 15:09:09 +0200 Subject: Remove unused const error variant --- src/librustc/ich/impls_ty.rs | 3 --- src/librustc/middle/const_val.rs | 9 --------- src/librustc/ty/structural_impls.rs | 1 - 3 files changed, 13 deletions(-) (limited to 'src') diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 5ab8d6eb7b3..f4d20f4c31a 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -505,9 +505,6 @@ for ::middle::const_val::ErrKind<'gcx> { len.hash_stable(hcx, hasher); index.hash_stable(hcx, hasher); } - Math(ref const_math_err) => { - const_math_err.hash_stable(hcx, hasher); - } LayoutError(ref layout_error) => { layout_error.hash_stable(hcx, hasher); } diff --git a/src/librustc/middle/const_val.rs b/src/librustc/middle/const_val.rs index 8a2126e356f..0ecab50dda2 100644 --- a/src/librustc/middle/const_val.rs +++ b/src/librustc/middle/const_val.rs @@ -11,7 +11,6 @@ use hir::def_id::DefId; use ty::{self, TyCtxt, layout}; use ty::subst::Substs; -use rustc_const_math::*; use mir::interpret::{Value, PrimVal}; use errors::DiagnosticBuilder; @@ -62,7 +61,6 @@ pub enum ErrKind<'tcx> { UnimplementedConstVal(&'static str), IndexOutOfBounds { len: u64, index: u64 }, - Math(ConstMathErr), LayoutError(layout::LayoutError<'tcx>), TypeckError, @@ -76,12 +74,6 @@ pub struct FrameInfo { pub location: String, } -impl<'tcx> From for ErrKind<'tcx> { - fn from(err: ConstMathErr) -> ErrKind<'tcx> { - ErrKind::Math(err) - } -} - #[derive(Clone, Debug)] pub enum ConstEvalErrDescription<'a, 'tcx: 'a> { Simple(Cow<'a, str>), @@ -119,7 +111,6 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> { len, index) } - Math(ref err) => Simple(err.description().into_cow()), LayoutError(ref err) => Simple(err.to_string().into_cow()), TypeckError => simple!("type-checking failed"), diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 9b20fce6673..f81617a3795 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -585,7 +585,6 @@ impl<'a, 'tcx> Lift<'tcx> for const_val::ErrKind<'a> { NonConstPath => NonConstPath, UnimplementedConstVal(s) => UnimplementedConstVal(s), IndexOutOfBounds { len, index } => IndexOutOfBounds { len, index }, - Math(ref e) => Math(e.clone()), LayoutError(ref e) => { return tcx.lift(e).map(LayoutError) -- cgit 1.4.1-3-g733a5 From a9366aa874a29467014c2eef96234455509aa438 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 24 Apr 2018 15:35:58 +0200 Subject: Remove unused const math ops --- src/librustc/ich/impls_const_math.rs | 3 --- src/librustc_const_math/err.rs | 4 ---- 2 files changed, 7 deletions(-) (limited to 'src') diff --git a/src/librustc/ich/impls_const_math.rs b/src/librustc/ich/impls_const_math.rs index 494fa49b53d..3c1205a6784 100644 --- a/src/librustc/ich/impls_const_math.rs +++ b/src/librustc/ich/impls_const_math.rs @@ -31,7 +31,4 @@ impl_stable_hash_for!(enum ::rustc_const_math::Op { Shr, Shl, Neg, - BitAnd, - BitOr, - BitXor }); diff --git a/src/librustc_const_math/err.rs b/src/librustc_const_math/err.rs index 94a51c23a5e..552932993ec 100644 --- a/src/librustc_const_math/err.rs +++ b/src/librustc_const_math/err.rs @@ -26,9 +26,6 @@ pub enum Op { Shr, Shl, Neg, - BitAnd, - BitOr, - BitXor, } impl ConstMathErr { @@ -43,7 +40,6 @@ impl ConstMathErr { Overflow(Neg) => "attempt to negate with overflow", Overflow(Shr) => "attempt to shift right with overflow", Overflow(Shl) => "attempt to shift left with overflow", - Overflow(_) => unreachable!(), DivisionByZero => "attempt to divide by zero", RemainderByZero => "attempt to calculate the remainder with a divisor of zero", } -- cgit 1.4.1-3-g733a5 From f45d0f3783ec2a03a34712392d9d5e42067690dc Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 24 Apr 2018 15:36:25 +0200 Subject: Removed unused dependencies on rustc_const_math --- src/librustc_passes/Cargo.toml | 1 - src/librustc_passes/lib.rs | 1 - src/librustc_typeck/Cargo.toml | 1 - src/librustc_typeck/lib.rs | 1 - src/librustdoc/lib.rs | 1 - 5 files changed, 5 deletions(-) (limited to 'src') diff --git a/src/librustc_passes/Cargo.toml b/src/librustc_passes/Cargo.toml index 4bab24ae139..2babb93eedb 100644 --- a/src/librustc_passes/Cargo.toml +++ b/src/librustc_passes/Cargo.toml @@ -12,7 +12,6 @@ crate-type = ["dylib"] log = "0.4" rustc = { path = "../librustc" } rustc_mir = { path = "../librustc_mir"} -rustc_const_math = { path = "../librustc_const_math" } rustc_data_structures = { path = "../librustc_data_structures" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index e65c9de8df1..b6b5edc0940 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -23,7 +23,6 @@ #[macro_use] extern crate rustc; extern crate rustc_mir; -extern crate rustc_const_math; extern crate rustc_data_structures; #[macro_use] diff --git a/src/librustc_typeck/Cargo.toml b/src/librustc_typeck/Cargo.toml index 70c13e9b7d6..c426533779c 100644 --- a/src/librustc_typeck/Cargo.toml +++ b/src/librustc_typeck/Cargo.toml @@ -15,7 +15,6 @@ syntax = { path = "../libsyntax" } arena = { path = "../libarena" } fmt_macros = { path = "../libfmt_macros" } rustc = { path = "../librustc" } -rustc_const_math = { path = "../librustc_const_math" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_platform_intrinsics = { path = "../librustc_platform_intrinsics" } rustc_target = { path = "../librustc_target" } diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 958960d3a36..350b53a406b 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -92,7 +92,6 @@ extern crate syntax_pos; extern crate arena; #[macro_use] extern crate rustc; extern crate rustc_platform_intrinsics as intrinsics; -extern crate rustc_const_math; extern crate rustc_data_structures; extern crate rustc_errors as errors; extern crate rustc_target; diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 8efb51bccd8..059d4169895 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -31,7 +31,6 @@ extern crate getopts; extern crate env_logger; extern crate rustc; extern crate rustc_data_structures; -extern crate rustc_const_math; extern crate rustc_trans_utils; extern crate rustc_driver; extern crate rustc_resolve; -- cgit 1.4.1-3-g733a5 From 40b118cf4767413f7676c97296c222167604485b Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 25 Apr 2018 15:26:12 +0200 Subject: Remove ConstFloat --- src/librustc/ich/impls_const_math.rs | 5 - src/librustc/mir/mod.rs | 9 +- src/librustc_const_math/float.rs | 217 --------------------------------- src/librustc_const_math/lib.rs | 5 - src/librustc_mir/hair/cx/mod.rs | 24 +--- src/librustc_mir/hair/pattern/mod.rs | 66 ++++++---- src/librustc_mir/interpret/cast.rs | 9 +- src/librustc_mir/interpret/operator.rs | 54 ++++---- src/librustc_trans/mir/rvalue.rs | 5 +- 9 files changed, 85 insertions(+), 309 deletions(-) delete mode 100644 src/librustc_const_math/float.rs (limited to 'src') diff --git a/src/librustc/ich/impls_const_math.rs b/src/librustc/ich/impls_const_math.rs index 3c1205a6784..bbc43987c99 100644 --- a/src/librustc/ich/impls_const_math.rs +++ b/src/librustc/ich/impls_const_math.rs @@ -11,11 +11,6 @@ //! This module contains `HashStable` implementations for various data types //! from `rustc_const_math` in no particular order. -impl_stable_hash_for!(struct ::rustc_const_math::ConstFloat { - ty, - bits -}); - impl_stable_hash_for!(enum ::rustc_const_math::ConstMathErr { Overflow(op), DivisionByZero, diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index c26b3014e53..d1e515b2c77 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -43,6 +43,8 @@ use std::vec::IntoIter; use syntax::ast::{self, Name}; use syntax::symbol::InternedString; use syntax_pos::{Span, DUMMY_SP}; +use rustc_apfloat::ieee::{Single, Double}; +use rustc_apfloat::Float; mod cache; pub mod tcx; @@ -1915,12 +1917,13 @@ fn fmt_const_val(fmt: &mut W, const_val: &ty::Const) -> fmt::Result { pub fn print_miri_value(value: Value, ty: Ty, f: &mut W) -> fmt::Result { use ty::TypeVariants::*; - use rustc_const_math::ConstFloat; match (value, &ty.sty) { (Value::ByVal(PrimVal::Bytes(0)), &TyBool) => write!(f, "false"), (Value::ByVal(PrimVal::Bytes(1)), &TyBool) => write!(f, "true"), - (Value::ByVal(PrimVal::Bytes(bits)), &TyFloat(fty)) => - write!(f, "{}", ConstFloat { bits, ty: fty }), + (Value::ByVal(PrimVal::Bytes(bits)), &TyFloat(ast::FloatTy::F32)) => + write!(f, "{}", Single::from_bits(bits)), + (Value::ByVal(PrimVal::Bytes(bits)), &TyFloat(ast::FloatTy::F64)) => + write!(f, "{}", Double::from_bits(bits)), (Value::ByVal(PrimVal::Bytes(n)), &TyUint(ui)) => write!(f, "{:?}{}", n, ui), (Value::ByVal(PrimVal::Bytes(n)), &TyInt(i)) => write!(f, "{:?}{}", n as i128, i), (Value::ByVal(PrimVal::Bytes(n)), &TyChar) => diff --git a/src/librustc_const_math/float.rs b/src/librustc_const_math/float.rs deleted file mode 100644 index 35cfe466c8a..00000000000 --- a/src/librustc_const_math/float.rs +++ /dev/null @@ -1,217 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use std::cmp::Ordering; -use std::num::ParseFloatError; - -use syntax::ast; - -use rustc_apfloat::{Float, FloatConvert, Status}; -use rustc_apfloat::ieee::{Single, Double}; - -// Note that equality for `ConstFloat` means that the it is the same -// constant, not that the rust values are equal. In particular, `NaN -// == NaN` (at least if it's the same NaN; distinct encodings for NaN -// are considering unequal). -#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] -pub struct ConstFloat { - pub ty: ast::FloatTy, - - // This is a bit inefficient but it makes conversions below more - // ergonomic, and all of this will go away once `miri` is merged. - pub bits: u128, -} - -impl PartialOrd for ConstFloat { - fn partial_cmp(&self, other: &Self) -> Option { - self.try_cmp(*other) - } -} - -impl ConstFloat { - /// Description of the type, not the value - pub fn description(&self) -> &'static str { - self.ty.ty_to_string() - } - - /// Compares the values if they are of the same type - fn try_cmp(self, rhs: Self) -> Option { - match (self.ty, rhs.ty) { - (ast::FloatTy::F64, ast::FloatTy::F64) => { - let a = Double::from_bits(self.bits); - let b = Double::from_bits(rhs.bits); - // This is pretty bad but it is the existing behavior. - Some(a.partial_cmp(&b).unwrap_or(Ordering::Greater)) - } - - (ast::FloatTy::F32, ast::FloatTy::F32) => { - let a = Single::from_bits(self.bits); - let b = Single::from_bits(rhs.bits); - Some(a.partial_cmp(&b).unwrap_or(Ordering::Greater)) - } - - _ => None, - } - } - - pub fn from_i128(input: i128, ty: ast::FloatTy) -> Self { - let bits = match ty { - ast::FloatTy::F32 => Single::from_i128(input).value.to_bits(), - ast::FloatTy::F64 => Double::from_i128(input).value.to_bits() - }; - ConstFloat { bits, ty } - } - - pub fn from_u128(input: u128, ty: ast::FloatTy) -> Self { - let bits = match ty { - ast::FloatTy::F32 => Single::from_u128(input).value.to_bits(), - ast::FloatTy::F64 => Double::from_u128(input).value.to_bits() - }; - ConstFloat { bits, ty } - } - - pub fn from_str(num: &str, ty: ast::FloatTy) -> Result { - let bits = match ty { - ast::FloatTy::F32 => { - let rust_bits = num.parse::()?.to_bits() as u128; - let apfloat = num.parse::().unwrap_or_else(|e| { - panic!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e); - }); - let apfloat_bits = apfloat.to_bits(); - assert!(rust_bits == apfloat_bits, - "apfloat::ieee::Single gave different result for `{}`: \ - {}({:#x}) vs Rust's {}({:#x})", - num, apfloat, apfloat_bits, - Single::from_bits(rust_bits), rust_bits); - apfloat_bits - } - ast::FloatTy::F64 => { - let rust_bits = num.parse::()?.to_bits() as u128; - let apfloat = num.parse::().unwrap_or_else(|e| { - panic!("apfloat::ieee::Double failed to parse `{}`: {:?}", num, e); - }); - let apfloat_bits = apfloat.to_bits(); - assert!(rust_bits == apfloat_bits, - "apfloat::ieee::Double gave different result for `{}`: \ - {}({:#x}) vs Rust's {}({:#x})", - num, apfloat, apfloat_bits, - Double::from_bits(rust_bits), rust_bits); - apfloat_bits - } - }; - Ok(ConstFloat { bits, ty }) - } - - pub fn to_i128(self, width: usize) -> Option { - assert!(width <= 128); - let r = match self.ty { - ast::FloatTy::F32 => Single::from_bits(self.bits).to_i128(width), - ast::FloatTy::F64 => Double::from_bits(self.bits).to_i128(width) - }; - if r.status.intersects(Status::INVALID_OP) { - None - } else { - Some(r.value) - } - } - - pub fn to_u128(self, width: usize) -> Option { - assert!(width <= 128); - let r = match self.ty { - ast::FloatTy::F32 => Single::from_bits(self.bits).to_u128(width), - ast::FloatTy::F64 => Double::from_bits(self.bits).to_u128(width) - }; - if r.status.intersects(Status::INVALID_OP) { - None - } else { - Some(r.value) - } - } - - pub fn convert(self, to: ast::FloatTy) -> Self { - let bits = match (self.ty, to) { - (ast::FloatTy::F32, ast::FloatTy::F32) | - (ast::FloatTy::F64, ast::FloatTy::F64) => return self, - - (ast::FloatTy::F32, ast::FloatTy::F64) => { - Double::to_bits(Single::from_bits(self.bits).convert(&mut false).value) - } - (ast::FloatTy::F64, ast::FloatTy::F32) => { - Single::to_bits(Double::from_bits(self.bits).convert(&mut false).value) - } - }; - ConstFloat { bits, ty: to } - } -} - -impl ::std::fmt::Display for ConstFloat { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { - match self.ty { - ast::FloatTy::F32 => write!(fmt, "{:#}", Single::from_bits(self.bits))?, - ast::FloatTy::F64 => write!(fmt, "{:#}", Double::from_bits(self.bits))?, - } - write!(fmt, "{}", self.ty) - } -} - -impl ::std::fmt::Debug for ConstFloat { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { - ::std::fmt::Display::fmt(self, fmt) - } -} - -macro_rules! derive_binop { - ($op:ident, $func:ident) => { - impl ::std::ops::$op for ConstFloat { - type Output = Option; - fn $func(self, rhs: Self) -> Option { - let bits = match (self.ty, rhs.ty) { - (ast::FloatTy::F32, ast::FloatTy::F32) =>{ - let a = Single::from_bits(self.bits); - let b = Single::from_bits(rhs.bits); - a.$func(b).value.to_bits() - } - (ast::FloatTy::F64, ast::FloatTy::F64) => { - let a = Double::from_bits(self.bits); - let b = Double::from_bits(rhs.bits); - a.$func(b).value.to_bits() - } - _ => return None, - }; - Some(ConstFloat { bits, ty: self.ty }) - } - } - } -} - -derive_binop!(Add, add); -derive_binop!(Sub, sub); -derive_binop!(Mul, mul); -derive_binop!(Div, div); -derive_binop!(Rem, rem); - -impl ::std::ops::Neg for ConstFloat { - type Output = Self; - fn neg(self) -> Self { - let bits = match self.ty { - ast::FloatTy::F32 => (-Single::from_bits(self.bits)).to_bits(), - ast::FloatTy::F64 => (-Double::from_bits(self.bits)).to_bits(), - }; - ConstFloat { bits, ty: self.ty } - } -} - -/// This is `f32::MAX + (0.5 ULP)` as an integer. Numbers greater or equal to this -/// are rounded to infinity when converted to `f32`. -/// -/// NB: Computed as maximum significand with an extra 1 bit added (for the half ULP) -/// shifted by the maximum exponent (accounting for normalization). -pub const MAX_F32_PLUS_HALF_ULP: u128 = ((1 << (Single::PRECISION + 1)) - 1) - << (Single::MAX_EXP - Single::PRECISION as i16); diff --git a/src/librustc_const_math/lib.rs b/src/librustc_const_math/lib.rs index 499c330be1d..08996b892f9 100644 --- a/src/librustc_const_math/lib.rs +++ b/src/librustc_const_math/lib.rs @@ -18,14 +18,9 @@ html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] -extern crate rustc_apfloat; - -extern crate syntax; extern crate serialize as rustc_serialize; // used by deriving -mod float; mod err; -pub use float::*; pub use err::{ConstMathErr, Op}; diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index e6aa2d3abb7..ff5c8084591 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -30,9 +30,9 @@ use syntax::ast::{self, LitKind}; use syntax::attr; use syntax::symbol::Symbol; use rustc::hir; -use rustc_const_math::ConstFloat; use rustc_data_structures::sync::Lrc; use rustc::mir::interpret::{Value, PrimVal}; +use hair::pattern::parse_float; #[derive(Clone)] pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { @@ -170,14 +170,6 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { neg: bool, ) -> Literal<'tcx> { trace!("const_eval_literal: {:#?}, {:?}, {:?}, {:?}", lit, ty, sp, neg); - let tcx = self.tcx.global_tcx(); - - let parse_float = |num: &str, fty| -> ConstFloat { - ConstFloat::from_str(num, fty).unwrap_or_else(|_| { - // FIXME(#31407) this is only necessary because float parsing is buggy - tcx.sess.span_fatal(sp, "could not evaluate float literal (see issue #31407)"); - }) - }; let clamp = |n| { let size = self.integer_bit_width(ty); @@ -214,12 +206,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { LitKind::Int(n, _) => Value::ByVal(PrimVal::Bytes(clamp(n))), LitKind::Float(n, fty) => { let n = n.as_str(); - let mut f = parse_float(&n, fty); - if neg { - f = -f; - } - let bits = f.bits; - Value::ByVal(PrimVal::Bytes(bits)) + parse_float(&n, fty, neg).expect("apfloat parsing failed") } LitKind::FloatUnsuffixed(n) => { let fty = match ty.sty { @@ -227,12 +214,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { _ => bug!() }; let n = n.as_str(); - let mut f = parse_float(&n, fty); - if neg { - f = -f; - } - let bits = f.bits; - Value::ByVal(PrimVal::Bytes(bits)) + parse_float(&n, fty, neg).expect("apfloat parsing failed") } LitKind::Bool(b) => Value::ByVal(PrimVal::Bytes(b as u128)), LitKind::Char(c) => Value::ByVal(PrimVal::Bytes(c as u128)), diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 776b24a8648..590cc77c46d 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -28,7 +28,6 @@ use rustc::hir::def::{Def, CtorKind}; use rustc::hir::pat_util::EnumerateAndAdjustIterator; use rustc_data_structures::indexed_vec::Idx; -use rustc_const_math::ConstFloat; use std::cmp::Ordering; use std::fmt; @@ -1053,22 +1052,21 @@ pub fn compare_const_vals<'a, 'tcx>( b: &ConstVal, ty: Ty<'tcx>, ) -> Option { - use rustc_const_math::ConstFloat; trace!("compare_const_vals: {:?}, {:?}", a, b); use rustc::mir::interpret::{Value, PrimVal}; match (a, b) { (&ConstVal::Value(Value::ByVal(PrimVal::Bytes(a))), &ConstVal::Value(Value::ByVal(PrimVal::Bytes(b)))) => { + use ::rustc_apfloat::Float; match ty.sty { - ty::TyFloat(ty) => { - let l = ConstFloat { - bits: a, - ty, - }; - let r = ConstFloat { - bits: b, - ty, - }; + ty::TyFloat(ast::FloatTy::F32) => { + let l = ::rustc_apfloat::ieee::Single::from_bits(a); + let r = ::rustc_apfloat::ieee::Single::from_bits(b); + l.partial_cmp(&r) + }, + ty::TyFloat(ast::FloatTy::F64) => { + let l = ::rustc_apfloat::ieee::Double::from_bits(a); + let r = ::rustc_apfloat::ieee::Double::from_bits(b); l.partial_cmp(&r) }, ty::TyInt(_) => { @@ -1148,12 +1146,7 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind, }, LitKind::Float(n, fty) => { let n = n.as_str(); - let mut f = parse_float(&n, fty)?; - if neg { - f = -f; - } - let bits = f.bits; - Value::ByVal(PrimVal::Bytes(bits)) + parse_float(&n, fty, neg).map_err(|_| ())? } LitKind::FloatUnsuffixed(n) => { let fty = match ty.sty { @@ -1161,12 +1154,7 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind, _ => bug!() }; let n = n.as_str(); - let mut f = parse_float(&n, fty)?; - if neg { - f = -f; - } - let bits = f.bits; - Value::ByVal(PrimVal::Bytes(bits)) + parse_float(&n, fty, neg).map_err(|_| ())? } LitKind::Bool(b) => Value::ByVal(PrimVal::Bytes(b as u128)), LitKind::Char(c) => Value::ByVal(PrimVal::Bytes(c as u128)), @@ -1174,7 +1162,33 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind, Ok(ConstVal::Value(lit)) } -fn parse_float<'tcx>(num: &str, fty: ast::FloatTy) - -> Result { - ConstFloat::from_str(num, fty).map_err(|_| ()) +pub fn parse_float( + num: &str, + fty: ast::FloatTy, + neg: bool, +) -> Result { + use rustc_apfloat::ieee::{Single, Double}; + use rustc_apfloat::Float; + let bits = match fty { + ast::FloatTy::F32 => { + let mut f = num.parse::().map_err(|e| { + format!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e) + })?; + if neg { + f = -f; + } + f.to_bits() + } + ast::FloatTy::F64 => { + let mut f = num.parse::().map_err(|e| { + format!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e) + })?; + if neg { + f = -f; + } + f.to_bits() + } + }; + + Ok(Value::ByVal(PrimVal::Bytes(bits))) } diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index e654142d216..002b5eb187d 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -2,10 +2,9 @@ use rustc::ty::Ty; use rustc::ty::layout::LayoutOf; use syntax::ast::{FloatTy, IntTy, UintTy}; -use rustc_const_math::ConstFloat; +use rustc_apfloat::ieee::{Single, Double}; use super::{EvalContext, Machine}; use rustc::mir::interpret::{PrimVal, EvalResult, MemoryPointer, PointerArithmetic}; -use rustc_apfloat::ieee::{Single, Double}; use rustc_apfloat::Float; impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { @@ -50,8 +49,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { Ok(PrimVal::Bytes(v)) } - TyFloat(fty) if signed => Ok(PrimVal::Bytes(ConstFloat::from_i128(v as i128, fty).bits)), - TyFloat(fty) => Ok(PrimVal::Bytes(ConstFloat::from_u128(v, fty).bits)), + TyFloat(FloatTy::F32) if signed => Ok(PrimVal::Bytes(Single::from_i128(v as i128).value.to_bits())), + TyFloat(FloatTy::F64) if signed => Ok(PrimVal::Bytes(Double::from_i128(v as i128).value.to_bits())), + TyFloat(FloatTy::F32) => Ok(PrimVal::Bytes(Single::from_u128(v).value.to_bits())), + TyFloat(FloatTy::F64) => Ok(PrimVal::Bytes(Double::from_u128(v).value.to_bits())), TyChar if v as u8 as u128 == v => Ok(PrimVal::Bytes(v)), TyChar => err!(InvalidChar(v)), diff --git a/src/librustc_mir/interpret/operator.rs b/src/librustc_mir/interpret/operator.rs index 0c748f818cc..5a815e0dc67 100644 --- a/src/librustc_mir/interpret/operator.rs +++ b/src/librustc_mir/interpret/operator.rs @@ -1,9 +1,10 @@ use rustc::mir; use rustc::ty::{self, Ty}; -use rustc_const_math::ConstFloat; use syntax::ast::FloatTy; use std::cmp::Ordering; use rustc::ty::layout::LayoutOf; +use rustc_apfloat::ieee::{Double, Single}; +use rustc_apfloat::Float; use super::{EvalContext, Place, Machine, ValTy}; @@ -125,31 +126,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { return err!(Unimplemented(msg)); } - let float_op = |op, l, r, ty| { - let l = ConstFloat { - bits: l, - ty, - }; - let r = ConstFloat { - bits: r, - ty, - }; - match op { - Eq => PrimVal::from_bool(l.partial_cmp(&r).unwrap() == Ordering::Equal), - Ne => PrimVal::from_bool(l.partial_cmp(&r).unwrap() != Ordering::Equal), - Lt => PrimVal::from_bool(l.partial_cmp(&r).unwrap() == Ordering::Less), - Le => PrimVal::from_bool(l.partial_cmp(&r).unwrap() != Ordering::Greater), - Gt => PrimVal::from_bool(l.partial_cmp(&r).unwrap() == Ordering::Greater), - Ge => PrimVal::from_bool(l.partial_cmp(&r).unwrap() != Ordering::Less), - Add => PrimVal::Bytes((l + r).unwrap().bits), - Sub => PrimVal::Bytes((l - r).unwrap().bits), - Mul => PrimVal::Bytes((l * r).unwrap().bits), - Div => PrimVal::Bytes((l / r).unwrap().bits), - Rem => PrimVal::Bytes((l % r).unwrap().bits), - _ => bug!("invalid float op: `{:?}`", op), - } - }; - if left_layout.abi.is_signed() { let op: Option bool> = match bin_op { Lt => Some(i128::lt), @@ -199,7 +175,31 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { } if let ty::TyFloat(fty) = left_ty.sty { - return Ok((float_op(bin_op, l, r, fty), false)); + macro_rules! float_math { + ($ty:path) => {{ + let l = <$ty>::from_bits(l); + let r = <$ty>::from_bits(r); + let val = match bin_op { + Eq => PrimVal::from_bool(l.partial_cmp(&r).unwrap_or(Ordering::Greater) == Ordering::Equal), + Ne => PrimVal::from_bool(l.partial_cmp(&r).unwrap_or(Ordering::Greater) != Ordering::Equal), + Lt => PrimVal::from_bool(l.partial_cmp(&r).unwrap_or(Ordering::Greater) == Ordering::Less), + Le => PrimVal::from_bool(l.partial_cmp(&r).unwrap_or(Ordering::Greater) != Ordering::Greater), + Gt => PrimVal::from_bool(l.partial_cmp(&r).unwrap_or(Ordering::Greater) == Ordering::Greater), + Ge => PrimVal::from_bool(l.partial_cmp(&r).unwrap_or(Ordering::Greater) != Ordering::Less), + Add => PrimVal::Bytes((l + r).value.to_bits()), + Sub => PrimVal::Bytes((l - r).value.to_bits()), + Mul => PrimVal::Bytes((l * r).value.to_bits()), + Div => PrimVal::Bytes((l / r).value.to_bits()), + Rem => PrimVal::Bytes((l % r).value.to_bits()), + _ => bug!("invalid float op: `{:?}`", bin_op), + }; + return Ok((val, false)); + }}; + } + match fty { + FloatTy::F32 => float_math!(Single), + FloatTy::F64 => float_math!(Double), + } } // only ints left diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index 79e906ca975..6e16590bf35 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -15,7 +15,6 @@ use rustc::ty::layout::{self, LayoutOf}; use rustc::mir; use rustc::middle::lang_items::ExchangeMallocFnLangItem; use rustc_apfloat::{ieee, Float, Status, Round}; -use rustc_const_math::MAX_F32_PLUS_HALF_ULP; use std::{u128, i128}; use base; @@ -805,6 +804,10 @@ fn cast_int_to_float(bx: &Builder, if is_u128_to_f32 { // All inputs greater or equal to (f32::MAX + 0.5 ULP) are rounded to infinity, // and for everything else LLVM's uitofp works just fine. + use rustc_apfloat::ieee::Single; + use rustc_apfloat::Float; + const MAX_F32_PLUS_HALF_ULP: u128 = ((1 << (Single::PRECISION + 1)) - 1) + << (Single::MAX_EXP - Single::PRECISION as i16); let max = C_uint_big(int_ty, MAX_F32_PLUS_HALF_ULP); let overflow = bx.icmp(llvm::IntUGE, x, max); let infinity_bits = C_u32(bx.cx, ieee::Single::INFINITY.to_bits() as u32); -- cgit 1.4.1-3-g733a5 From cf103e56bd0bfdc3ef7202ba774a1981adb36a46 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 26 Apr 2018 10:39:04 +0200 Subject: Reintroduce the float parsing error --- src/librustc_mir/hair/cx/mod.rs | 13 +++++++++---- src/librustc_mir/hair/pattern/mod.rs | 26 ++++++++++++++------------ 2 files changed, 23 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index ff5c8084591..5890ea5c9d0 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -171,6 +171,13 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { ) -> Literal<'tcx> { trace!("const_eval_literal: {:#?}, {:?}, {:?}, {:?}", lit, ty, sp, neg); + let parse_float = |num, fty| -> Value { + parse_float(num, fty, neg).unwrap_or_else(|_| { + // FIXME(#31407) this is only necessary because float parsing is buggy + self.tcx.sess.span_fatal(sp, "could not evaluate float literal (see issue #31407)"); + }) + }; + let clamp = |n| { let size = self.integer_bit_width(ty); trace!("clamp {} with size {} and amt {}", n, size, 128 - size); @@ -205,16 +212,14 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { }, LitKind::Int(n, _) => Value::ByVal(PrimVal::Bytes(clamp(n))), LitKind::Float(n, fty) => { - let n = n.as_str(); - parse_float(&n, fty, neg).expect("apfloat parsing failed") + parse_float(n, fty) } LitKind::FloatUnsuffixed(n) => { let fty = match ty.sty { ty::TyFloat(fty) => fty, _ => bug!() }; - let n = n.as_str(); - parse_float(&n, fty, neg).expect("apfloat parsing failed") + parse_float(n, fty) } LitKind::Bool(b) => Value::ByVal(PrimVal::Bytes(b as u128)), LitKind::Char(c) => Value::ByVal(PrimVal::Bytes(c as u128)), diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 590cc77c46d..619b4596b42 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -34,6 +34,7 @@ use std::fmt; use syntax::ast; use syntax::ptr::P; use syntax_pos::Span; +use syntax_pos::symbol::Symbol; #[derive(Clone, Debug)] pub enum PatternError { @@ -1145,16 +1146,14 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind, Value::ByVal(PrimVal::Bytes(n)) }, LitKind::Float(n, fty) => { - let n = n.as_str(); - parse_float(&n, fty, neg).map_err(|_| ())? + parse_float(n, fty, neg)? } LitKind::FloatUnsuffixed(n) => { let fty = match ty.sty { ty::TyFloat(fty) => fty, _ => bug!() }; - let n = n.as_str(); - parse_float(&n, fty, neg).map_err(|_| ())? + parse_float(n, fty, neg)? } LitKind::Bool(b) => Value::ByVal(PrimVal::Bytes(b as u128)), LitKind::Char(c) => Value::ByVal(PrimVal::Bytes(c as u128)), @@ -1163,26 +1162,29 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind, } pub fn parse_float( - num: &str, + num: Symbol, fty: ast::FloatTy, neg: bool, -) -> Result { +) -> Result { + let num = num.as_str(); use rustc_apfloat::ieee::{Single, Double}; use rustc_apfloat::Float; let bits = match fty { ast::FloatTy::F32 => { - let mut f = num.parse::().map_err(|e| { - format!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e) - })?; + num.parse::().map_err(|_| ())?; + let mut f = num.parse::().unwrap_or_else(|e| { + panic!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e) + }); if neg { f = -f; } f.to_bits() } ast::FloatTy::F64 => { - let mut f = num.parse::().map_err(|e| { - format!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e) - })?; + num.parse::().map_err(|_| ())?; + let mut f = num.parse::().unwrap_or_else(|e| { + panic!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e) + }); if neg { f = -f; } -- cgit 1.4.1-3-g733a5 From 671b2a596439566b6614d2a7dd25643fc947c721 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 26 Apr 2018 11:37:03 +0200 Subject: Remove the `rustc_const_math` crate --- src/librustc/Cargo.toml | 1 - src/librustc/ich/impls_const_math.rs | 29 -------------------- src/librustc/ich/impls_ty.rs | 17 ++++++++++++ src/librustc/ich/mod.rs | 1 - src/librustc/lib.rs | 1 - src/librustc/mir/interpret/error.rs | 39 +++++++++++++++++++++++++- src/librustc/mir/interpret/mod.rs | 2 +- src/librustc/mir/mod.rs | 3 +- src/librustc_const_math/Cargo.toml | 14 ---------- src/librustc_const_math/err.rs | 47 -------------------------------- src/librustc_const_math/lib.rs | 26 ------------------ src/librustc_mir/Cargo.toml | 1 - src/librustc_mir/build/expr/as_rvalue.rs | 3 +- src/librustc_mir/lib.rs | 2 -- src/librustc_trans/Cargo.toml | 1 - src/librustc_trans/lib.rs | 1 - src/librustc_trans/mir/block.rs | 4 +-- 17 files changed, 60 insertions(+), 132 deletions(-) delete mode 100644 src/librustc/ich/impls_const_math.rs delete mode 100644 src/librustc_const_math/Cargo.toml delete mode 100644 src/librustc_const_math/err.rs delete mode 100644 src/librustc_const_math/lib.rs (limited to 'src') diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml index 357ebb89fb6..af108188ce0 100644 --- a/src/librustc/Cargo.toml +++ b/src/librustc/Cargo.toml @@ -19,7 +19,6 @@ log = { version = "0.4", features = ["release_max_level_info", "std"] } proc_macro = { path = "../libproc_macro" } rustc_apfloat = { path = "../librustc_apfloat" } rustc_target = { path = "../librustc_target" } -rustc_const_math = { path = "../librustc_const_math" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_errors = { path = "../librustc_errors" } serialize = { path = "../libserialize" } diff --git a/src/librustc/ich/impls_const_math.rs b/src/librustc/ich/impls_const_math.rs deleted file mode 100644 index bbc43987c99..00000000000 --- a/src/librustc/ich/impls_const_math.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! This module contains `HashStable` implementations for various data types -//! from `rustc_const_math` in no particular order. - -impl_stable_hash_for!(enum ::rustc_const_math::ConstMathErr { - Overflow(op), - DivisionByZero, - RemainderByZero, -}); - -impl_stable_hash_for!(enum ::rustc_const_math::Op { - Add, - Sub, - Mul, - Div, - Rem, - Shr, - Shl, - Neg, -}); diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index f4d20f4c31a..92a8ee28168 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -669,6 +669,23 @@ for ::mir::interpret::EvalError<'gcx> { } } +impl_stable_hash_for!(enum mir::interpret::ConstMathErr { + Overflow(op), + DivisionByZero, + RemainderByZero, +}); + +impl_stable_hash_for!(enum mir::interpret::Op { + Add, + Sub, + Mul, + Div, + Rem, + Shr, + Shl, + Neg, +}); + impl_stable_hash_for!(enum mir::interpret::Lock { NoLock, WriteLock(dl), diff --git a/src/librustc/ich/mod.rs b/src/librustc/ich/mod.rs index 1b77a2e7c82..a0c6bbbb239 100644 --- a/src/librustc/ich/mod.rs +++ b/src/librustc/ich/mod.rs @@ -18,7 +18,6 @@ mod fingerprint; mod caching_codemap_view; mod hcx; -mod impls_const_math; mod impls_cstore; mod impls_hir; mod impls_mir; diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 24892dfcc8f..9c06c9055fb 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -85,7 +85,6 @@ extern crate libc; extern crate rustc_target; #[macro_use] extern crate rustc_data_structures; extern crate serialize; -extern crate rustc_const_math; extern crate rustc_errors as errors; #[macro_use] extern crate log; #[macro_use] extern crate syntax; diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index b919f4d15a8..fff555a8976 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -8,7 +8,6 @@ use super::{ MemoryPointer, Lock, AccessKind }; -use rustc_const_math::ConstMathErr; use syntax::codemap::Span; use backtrace::Backtrace; @@ -304,3 +303,41 @@ impl<'tcx> fmt::Display for EvalError<'tcx> { } } } + +#[derive(Debug, PartialEq, Eq, Clone, RustcEncodable, RustcDecodable)] +pub enum ConstMathErr { + Overflow(Op), + DivisionByZero, + RemainderByZero, +} +pub use self::ConstMathErr::*; + +#[derive(Debug, PartialEq, Eq, Clone, RustcEncodable, RustcDecodable)] +pub enum Op { + Add, + Sub, + Mul, + Div, + Rem, + Shr, + Shl, + Neg, +} + +impl ConstMathErr { + pub fn description(&self) -> &'static str { + use self::Op::*; + match *self { + Overflow(Add) => "attempt to add with overflow", + Overflow(Sub) => "attempt to subtract with overflow", + Overflow(Mul) => "attempt to multiply with overflow", + Overflow(Div) => "attempt to divide with overflow", + Overflow(Rem) => "attempt to calculate the remainder with overflow", + Overflow(Neg) => "attempt to negate with overflow", + Overflow(Shr) => "attempt to shift right with overflow", + Overflow(Shl) => "attempt to shift left with overflow", + DivisionByZero => "attempt to divide by zero", + RemainderByZero => "attempt to calculate the remainder with a divisor of zero", + } + } +} diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs index c9eed0e4a28..fe29222e883 100644 --- a/src/librustc/mir/interpret/mod.rs +++ b/src/librustc/mir/interpret/mod.rs @@ -8,7 +8,7 @@ macro_rules! err { mod error; mod value; -pub use self::error::{EvalError, EvalResult, EvalErrorKind}; +pub use self::error::{EvalError, EvalResult, EvalErrorKind, Op, ConstMathErr}; pub use self::value::{PrimVal, PrimValKind, Value, Pointer}; diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index d1e515b2c77..3c4b9ae3351 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -15,7 +15,6 @@ use graphviz::IntoCow; use middle::const_val::ConstVal; use middle::region; -use rustc_const_math::ConstMathErr; use rustc_data_structures::sync::{Lrc}; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use rustc_data_structures::control_flow_graph::dominators::{Dominators, dominators}; @@ -26,7 +25,7 @@ use rustc_serialize as serialize; use hir::def::CtorKind; use hir::def_id::DefId; use mir::visit::MirVisitable; -use mir::interpret::{Value, PrimVal}; +use mir::interpret::{Value, PrimVal, ConstMathErr}; use ty::subst::{Subst, Substs}; use ty::{self, AdtDef, CanonicalTy, ClosureSubsts, Region, Ty, TyCtxt, GeneratorInterior}; use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; diff --git a/src/librustc_const_math/Cargo.toml b/src/librustc_const_math/Cargo.toml deleted file mode 100644 index 41310ede3e0..00000000000 --- a/src/librustc_const_math/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -authors = ["The Rust Project Developers"] -name = "rustc_const_math" -version = "0.0.0" - -[lib] -name = "rustc_const_math" -path = "lib.rs" -crate-type = ["dylib"] - -[dependencies] -rustc_apfloat = { path = "../librustc_apfloat" } -serialize = { path = "../libserialize" } -syntax = { path = "../libsyntax" } diff --git a/src/librustc_const_math/err.rs b/src/librustc_const_math/err.rs deleted file mode 100644 index 552932993ec..00000000000 --- a/src/librustc_const_math/err.rs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[derive(Debug, PartialEq, Eq, Clone, RustcEncodable, RustcDecodable)] -pub enum ConstMathErr { - Overflow(Op), - DivisionByZero, - RemainderByZero, -} -pub use self::ConstMathErr::*; - -#[derive(Debug, PartialEq, Eq, Clone, RustcEncodable, RustcDecodable)] -pub enum Op { - Add, - Sub, - Mul, - Div, - Rem, - Shr, - Shl, - Neg, -} - -impl ConstMathErr { - pub fn description(&self) -> &'static str { - use self::Op::*; - match *self { - Overflow(Add) => "attempt to add with overflow", - Overflow(Sub) => "attempt to subtract with overflow", - Overflow(Mul) => "attempt to multiply with overflow", - Overflow(Div) => "attempt to divide with overflow", - Overflow(Rem) => "attempt to calculate the remainder with overflow", - Overflow(Neg) => "attempt to negate with overflow", - Overflow(Shr) => "attempt to shift right with overflow", - Overflow(Shl) => "attempt to shift left with overflow", - DivisionByZero => "attempt to divide by zero", - RemainderByZero => "attempt to calculate the remainder with a divisor of zero", - } - } -} diff --git a/src/librustc_const_math/lib.rs b/src/librustc_const_math/lib.rs deleted file mode 100644 index 08996b892f9..00000000000 --- a/src/librustc_const_math/lib.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Rusty Mathematics -//! -//! # Note -//! -//! This API is completely unstable and subject to change. - -#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", - html_favicon_url = "https://doc.rust-lang.org/favicon.ico", - html_root_url = "https://doc.rust-lang.org/nightly/")] - - -extern crate serialize as rustc_serialize; // used by deriving - -mod err; - -pub use err::{ConstMathErr, Op}; diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml index a1b348774b1..62964745b6f 100644 --- a/src/librustc_mir/Cargo.toml +++ b/src/librustc_mir/Cargo.toml @@ -16,7 +16,6 @@ log = "0.4" log_settings = "0.1.1" rustc = { path = "../librustc" } rustc_target = { path = "../librustc_target" } -rustc_const_math = { path = "../librustc_const_math" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_errors = { path = "../librustc_errors" } serialize = { path = "../libserialize" } diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index b7f402f61a9..a3798f3ed4c 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -10,7 +10,6 @@ //! See docs in build/expr/mod.rs -use rustc_const_math::{ConstMathErr, Op}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexed_vec::Idx; @@ -21,7 +20,7 @@ use rustc::middle::const_val::ConstVal; use rustc::middle::region; use rustc::ty::{self, Ty}; use rustc::mir::*; -use rustc::mir::interpret::{Value, PrimVal}; +use rustc::mir::interpret::{Value, PrimVal, ConstMathErr, Op}; use syntax_pos::Span; impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index 75b7a10097d..97d1fb0a698 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -50,8 +50,6 @@ extern crate rustc_errors; extern crate syntax; extern crate syntax_pos; extern crate rustc_target; -extern crate rustc_const_math; -extern crate core; // for NonZero extern crate log_settings; extern crate rustc_apfloat; extern crate byteorder; diff --git a/src/librustc_trans/Cargo.toml b/src/librustc_trans/Cargo.toml index 32432d6cc83..a4dd02e97b2 100644 --- a/src/librustc_trans/Cargo.toml +++ b/src/librustc_trans/Cargo.toml @@ -21,7 +21,6 @@ rustc-demangle = "0.1.4" rustc_allocator = { path = "../librustc_allocator" } rustc_apfloat = { path = "../librustc_apfloat" } rustc_target = { path = "../librustc_target" } -rustc_const_math = { path = "../librustc_const_math" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_errors = { path = "../librustc_errors" } rustc_incremental = { path = "../librustc_incremental" } diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 96a10e8b99d..306f4179e4f 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -43,7 +43,6 @@ extern crate rustc_mir; extern crate rustc_allocator; extern crate rustc_apfloat; extern crate rustc_target; -extern crate rustc_const_math; #[macro_use] extern crate rustc_data_structures; extern crate rustc_demangle; extern crate rustc_incremental; diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index e5fdc26eeaf..7c854ef04b7 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -311,8 +311,8 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { // checked operation, just a comparison with the minimum // value, so we have to check for the assert message. if !bx.cx.check_overflow { - use rustc_const_math::ConstMathErr::Overflow; - use rustc_const_math::Op::Neg; + use rustc::mir::interpret::ConstMathErr::Overflow; + use rustc::mir::interpret::Op::Neg; if let mir::AssertMessage::Math(Overflow(Neg)) = *msg { const_cond = Some(expected); -- cgit 1.4.1-3-g733a5 From cefcf0548ec06cfdd00de4d02ee9c1b0c6cfe6fa Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 26 Apr 2018 14:52:59 +0200 Subject: Merge ConstMathError into EvalErrorKind --- src/librustc/ich/impls_ty.rs | 42 +++++++--------- src/librustc/mir/interpret/error.rs | 72 ++++++++-------------------- src/librustc/mir/interpret/mod.rs | 12 ++--- src/librustc/mir/mod.rs | 8 ++-- src/librustc/ty/layout.rs | 2 +- src/librustc/ty/structural_impls.rs | 6 ++- src/librustc_mir/build/expr/as_rvalue.rs | 23 +++------ src/librustc_mir/interpret/eval_context.rs | 2 +- src/librustc_mir/interpret/operator.rs | 2 +- src/librustc_mir/interpret/terminator/mod.rs | 4 +- src/librustc_mir/transform/const_prop.rs | 2 +- src/librustc_trans/mir/block.rs | 5 +- 12 files changed, 65 insertions(+), 115 deletions(-) (limited to 'src') diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 92a8ee28168..a5447a3145a 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -525,16 +525,26 @@ impl_stable_hash_for!(struct ty::GenericPredicates<'tcx> { predicates }); + impl<'a, 'gcx> HashStable> for ::mir::interpret::EvalError<'gcx> { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { + self.kind.hash_stable(hcx, hasher) + } +} + +impl<'a, 'gcx> HashStable> +for ::mir::interpret::EvalErrorKind<'gcx> { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { use mir::interpret::EvalErrorKind::*; - mem::discriminant(&self.kind).hash_stable(hcx, hasher); + mem::discriminant(&self).hash_stable(hcx, hasher); - match self.kind { + match *self { DanglingPointerDeref | DoubleFree | InvalidMemoryAccess | @@ -565,8 +575,10 @@ for ::mir::interpret::EvalError<'gcx> { TypeckError | DerefFunctionPointer | ExecuteMemory | - ReferencedConstant | - OverflowingMath => {} + OverflowNeg | + RemainderByZero | + DivisionByZero | + ReferencedConstant => {} MachineError(ref err) => err.hash_stable(hcx, hasher), FunctionPointerTyMismatch(a, b) => { a.hash_stable(hcx, hasher); @@ -590,10 +602,6 @@ for ::mir::interpret::EvalError<'gcx> { a.hash_stable(hcx, hasher); b.hash_stable(hcx, hasher) }, - Math(sp, ref err) => { - sp.hash_stable(hcx, hasher); - err.hash_stable(hcx, hasher) - }, Intrinsic(ref s) => s.hash_stable(hcx, hasher), InvalidChar(c) => c.hash_stable(hcx, hasher), AbiViolation(ref s) => s.hash_stable(hcx, hasher), @@ -665,27 +673,11 @@ for ::mir::interpret::EvalError<'gcx> { Layout(lay) => lay.hash_stable(hcx, hasher), HeapAllocNonPowerOfTwoAlignment(n) => n.hash_stable(hcx, hasher), PathNotFound(ref v) => v.hash_stable(hcx, hasher), + Overflow(op) => op.hash_stable(hcx, hasher), } } } -impl_stable_hash_for!(enum mir::interpret::ConstMathErr { - Overflow(op), - DivisionByZero, - RemainderByZero, -}); - -impl_stable_hash_for!(enum mir::interpret::Op { - Add, - Sub, - Mul, - Div, - Rem, - Shr, - Shl, - Neg, -}); - impl_stable_hash_for!(enum mir::interpret::Lock { NoLock, WriteLock(dl), diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index fff555a8976..022b82841bc 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -1,4 +1,3 @@ -use std::error::Error; use std::{fmt, env}; use mir; @@ -30,7 +29,7 @@ impl<'tcx> From> for EvalError<'tcx> { } } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, RustcEncodable, RustcDecodable)] pub enum EvalErrorKind<'tcx> { /// This variant is used by machines to signal their own errors that do not /// match an existing variant @@ -60,9 +59,11 @@ pub enum EvalErrorKind<'tcx> { DerefFunctionPointer, ExecuteMemory, ArrayIndexOutOfBounds(Span, u64, u64), - Math(Span, ConstMathErr), + Overflow(mir::BinOp), + OverflowNeg, + DivisionByZero, + RemainderByZero, Intrinsic(String), - OverflowingMath, InvalidChar(u128), StackFrameLimitReached, OutOfTls, @@ -124,10 +125,10 @@ pub enum EvalErrorKind<'tcx> { pub type EvalResult<'tcx, T = ()> = Result>; -impl<'tcx> Error for EvalError<'tcx> { - fn description(&self) -> &str { +impl<'tcx> EvalErrorKind<'tcx> { + pub fn description(&self) -> &str { use self::EvalErrorKind::*; - match self.kind { + match *self { MachineError(ref inner) => inner, FunctionPointerTyMismatch(..) => "tried to call a function through a function pointer of a different type", @@ -176,12 +177,8 @@ impl<'tcx> Error for EvalError<'tcx> { "tried to treat a memory pointer as a function pointer", ArrayIndexOutOfBounds(..) => "array index out of bounds", - Math(..) => - "mathematical operation failed", Intrinsic(..) => "intrinsic failed", - OverflowingMath => - "attempted to do overflowing math", NoMirFor(..) => "mir not found", InvalidChar(..) => @@ -239,6 +236,17 @@ impl<'tcx> Error for EvalError<'tcx> { "encountered constants with type errors, stopping evaluation", ReferencedConstant => "referenced constant has errors", + Overflow(mir::BinOp::Add) => "attempt to add with overflow", + Overflow(mir::BinOp::Sub) => "attempt to subtract with overflow", + Overflow(mir::BinOp::Mul) => "attempt to multiply with overflow", + Overflow(mir::BinOp::Div) => "attempt to divide with overflow", + Overflow(mir::BinOp::Rem) => "attempt to calculate the remainder with overflow", + OverflowNeg => "attempt to negate with overflow", + Overflow(mir::BinOp::Shr) => "attempt to shift right with overflow", + Overflow(mir::BinOp::Shl) => "attempt to shift left with overflow", + Overflow(op) => bug!("{:?} cannot overflow", op), + DivisionByZero => "attempt to divide by zero", + RemainderByZero => "attempt to calculate the remainder with a divisor of zero", } } } @@ -280,8 +288,6 @@ impl<'tcx> fmt::Display for EvalError<'tcx> { write!(f, "tried to reallocate memory from {} to {}", old, new), DeallocatedWrongMemoryKind(ref old, ref new) => write!(f, "tried to deallocate {} memory but gave {} as the kind", old, new), - Math(_, ref err) => - write!(f, "{}", err.description()), Intrinsic(ref err) => write!(f, "{}", err), InvalidChar(c) => @@ -299,45 +305,7 @@ impl<'tcx> fmt::Display for EvalError<'tcx> { write!(f, "{}", inner), IncorrectAllocationInformation(size, size2, align, align2) => write!(f, "incorrect alloc info: expected size {} and align {}, got size {} and align {}", size, align, size2, align2), - _ => write!(f, "{}", self.description()), - } - } -} - -#[derive(Debug, PartialEq, Eq, Clone, RustcEncodable, RustcDecodable)] -pub enum ConstMathErr { - Overflow(Op), - DivisionByZero, - RemainderByZero, -} -pub use self::ConstMathErr::*; - -#[derive(Debug, PartialEq, Eq, Clone, RustcEncodable, RustcDecodable)] -pub enum Op { - Add, - Sub, - Mul, - Div, - Rem, - Shr, - Shl, - Neg, -} - -impl ConstMathErr { - pub fn description(&self) -> &'static str { - use self::Op::*; - match *self { - Overflow(Add) => "attempt to add with overflow", - Overflow(Sub) => "attempt to subtract with overflow", - Overflow(Mul) => "attempt to multiply with overflow", - Overflow(Div) => "attempt to divide with overflow", - Overflow(Rem) => "attempt to calculate the remainder with overflow", - Overflow(Neg) => "attempt to negate with overflow", - Overflow(Shr) => "attempt to shift right with overflow", - Overflow(Shl) => "attempt to shift left with overflow", - DivisionByZero => "attempt to divide by zero", - RemainderByZero => "attempt to calculate the remainder with a divisor of zero", + _ => write!(f, "{}", self.kind.description()), } } } diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs index fe29222e883..a521caf4fda 100644 --- a/src/librustc/mir/interpret/mod.rs +++ b/src/librustc/mir/interpret/mod.rs @@ -8,7 +8,7 @@ macro_rules! err { mod error; mod value; -pub use self::error::{EvalError, EvalResult, EvalErrorKind, Op, ConstMathErr}; +pub use self::error::{EvalError, EvalResult, EvalErrorKind}; pub use self::value::{PrimVal, PrimValKind, Value, Pointer}; @@ -23,7 +23,7 @@ use std::iter; use syntax::ast::Mutability; use rustc_serialize::{Encoder, Decoder, Decodable, Encodable}; -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)] pub enum Lock { NoLock, WriteLock(DynamicLifetime), @@ -31,13 +31,13 @@ pub enum Lock { ReadLock(Vec), } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub struct DynamicLifetime { pub frame: usize, pub region: Option, // "None" indicates "until the function ends" } -#[derive(Copy, Clone, Debug, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)] pub enum AccessKind { Read, Write, @@ -88,12 +88,12 @@ pub trait PointerArithmetic: layout::HasDataLayout { fn signed_offset<'tcx>(self, val: u64, i: i64) -> EvalResult<'tcx, u64> { let (res, over) = self.overflowing_signed_offset(val, i as i128); - if over { err!(OverflowingMath) } else { Ok(res) } + if over { err!(Overflow(mir::BinOp::Add)) } else { Ok(res) } } fn offset<'tcx>(self, val: u64, i: u64) -> EvalResult<'tcx, u64> { let (res, over) = self.overflowing_offset(val, i); - if over { err!(OverflowingMath) } else { Ok(res) } + if over { err!(Overflow(mir::BinOp::Add)) } else { Ok(res) } } fn wrapping_signed_offset(self, val: u64, i: i64) -> u64 { diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 3c4b9ae3351..0b56dbda42c 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -25,7 +25,7 @@ use rustc_serialize as serialize; use hir::def::CtorKind; use hir::def_id::DefId; use mir::visit::MirVisitable; -use mir::interpret::{Value, PrimVal, ConstMathErr}; +use mir::interpret::{Value, PrimVal, EvalErrorKind}; use ty::subst::{Subst, Substs}; use ty::{self, AdtDef, CanonicalTy, ClosureSubsts, Region, Ty, TyCtxt, GeneratorInterior}; use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; @@ -1211,7 +1211,7 @@ pub enum AssertMessage<'tcx> { len: Operand<'tcx>, index: Operand<'tcx> }, - Math(ConstMathErr), + Math(EvalErrorKind<'tcx>), GeneratorResumedAfterReturn, GeneratorResumedAfterPanic, } @@ -1920,9 +1920,9 @@ pub fn print_miri_value(value: Value, ty: Ty, f: &mut W) -> fmt::Resul (Value::ByVal(PrimVal::Bytes(0)), &TyBool) => write!(f, "false"), (Value::ByVal(PrimVal::Bytes(1)), &TyBool) => write!(f, "true"), (Value::ByVal(PrimVal::Bytes(bits)), &TyFloat(ast::FloatTy::F32)) => - write!(f, "{}", Single::from_bits(bits)), + write!(f, "{}f32", Single::from_bits(bits)), (Value::ByVal(PrimVal::Bytes(bits)), &TyFloat(ast::FloatTy::F64)) => - write!(f, "{}", Double::from_bits(bits)), + write!(f, "{}f64", Double::from_bits(bits)), (Value::ByVal(PrimVal::Bytes(n)), &TyUint(ui)) => write!(f, "{:?}{}", n, ui), (Value::ByVal(PrimVal::Bytes(n)), &TyInt(i)) => write!(f, "{:?}{}", n as i128, i), (Value::ByVal(PrimVal::Bytes(n)), &TyChar) => diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 55137e28911..92cea61bae5 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -149,7 +149,7 @@ pub const FAT_PTR_ADDR: usize = 0; /// - For a slice, this is the length. pub const FAT_PTR_EXTRA: usize = 1; -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)] pub enum LayoutError<'tcx> { Unknown(Ty<'tcx>), SizeOverflow(Ty<'tcx>) diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index f81617a3795..bae91d064a5 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -505,9 +505,7 @@ impl<'a, 'tcx> Lift<'tcx> for interpret::EvalError<'a> { DerefFunctionPointer => DerefFunctionPointer, ExecuteMemory => ExecuteMemory, ArrayIndexOutOfBounds(sp, a, b) => ArrayIndexOutOfBounds(sp, a, b), - Math(sp, ref err) => Math(sp, err.clone()), Intrinsic(ref s) => Intrinsic(s.clone()), - OverflowingMath => OverflowingMath, InvalidChar(c) => InvalidChar(c), StackFrameLimitReached => StackFrameLimitReached, OutOfTls => OutOfTls, @@ -568,6 +566,10 @@ impl<'a, 'tcx> Lift<'tcx> for interpret::EvalError<'a> { UnimplementedTraitSelection => UnimplementedTraitSelection, TypeckError => TypeckError, ReferencedConstant => ReferencedConstant, + OverflowNeg => OverflowNeg, + Overflow(op) => Overflow(op), + DivisionByZero => DivisionByZero, + RemainderByZero => RemainderByZero, }; Some(interpret::EvalError { kind: kind, diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index a3798f3ed4c..33c80ab22a3 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -20,7 +20,7 @@ use rustc::middle::const_val::ConstVal; use rustc::middle::region; use rustc::ty::{self, Ty}; use rustc::mir::*; -use rustc::mir::interpret::{Value, PrimVal, ConstMathErr, Op}; +use rustc::mir::interpret::{Value, PrimVal, EvalErrorKind}; use syntax_pos::Span; impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { @@ -85,7 +85,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { this.cfg.push_assign(block, source_info, &is_min, Rvalue::BinaryOp(BinOp::Eq, arg.to_copy(), minval)); - let err = ConstMathErr::Overflow(Op::Neg); + let err = EvalErrorKind::OverflowNeg; block = this.assert(block, Operand::Move(is_min), false, AssertMessage::Math(err), expr_span); } @@ -310,16 +310,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let val = result_value.clone().field(val_fld, ty); let of = result_value.field(of_fld, bool_ty); - let err = ConstMathErr::Overflow(match op { - BinOp::Add => Op::Add, - BinOp::Sub => Op::Sub, - BinOp::Mul => Op::Mul, - BinOp::Shl => Op::Shl, - BinOp::Shr => Op::Shr, - _ => { - bug!("MIR build_binary_op: {:?} is not checkable", op) - } - }); + let err = EvalErrorKind::Overflow(op); block = self.assert(block, Operand::Move(of), false, AssertMessage::Math(err), span); @@ -331,11 +322,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // and 2. there are two possible failure cases, divide-by-zero and overflow. let (zero_err, overflow_err) = if op == BinOp::Div { - (ConstMathErr::DivisionByZero, - ConstMathErr::Overflow(Op::Div)) + (EvalErrorKind::DivisionByZero, + EvalErrorKind::Overflow(op)) } else { - (ConstMathErr::RemainderByZero, - ConstMathErr::Overflow(Op::Rem)) + (EvalErrorKind::RemainderByZero, + EvalErrorKind::Overflow(op)) }; // Check for / 0 diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index f6e9994b5da..d055c979d11 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -513,7 +513,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M // it emits in debug mode) is performance, but it doesn't cost us any performance in miri. // If, however, the compiler ever starts transforming unchecked intrinsics into unchecked binops, // we have to go back to just ignoring the overflow here. - return err!(OverflowingMath); + return err!(Overflow(bin_op)); } } diff --git a/src/librustc_mir/interpret/operator.rs b/src/librustc_mir/interpret/operator.rs index 5a815e0dc67..6e7a37c2228 100644 --- a/src/librustc_mir/interpret/operator.rs +++ b/src/librustc_mir/interpret/operator.rs @@ -269,7 +269,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { (Neg, ty::TyFloat(FloatTy::F32)) => Single::to_bits(-Single::from_bits(bytes)), (Neg, ty::TyFloat(FloatTy::F64)) => Double::to_bits(-Double::from_bits(bytes)), - (Neg, _) if bytes == (1 << (size - 1)) => return err!(OverflowingMath), + (Neg, _) if bytes == (1 << (size - 1)) => return err!(OverflowNeg), (Neg, _) => (-(bytes as i128)) as u128, }; diff --git a/src/librustc_mir/interpret/terminator/mod.rs b/src/librustc_mir/interpret/terminator/mod.rs index aa80ee7af18..4f0e97f6e1a 100644 --- a/src/librustc_mir/interpret/terminator/mod.rs +++ b/src/librustc_mir/interpret/terminator/mod.rs @@ -160,9 +160,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { .to_u64()?; err!(ArrayIndexOutOfBounds(span, len, index)) } - Math(ref err) => { - err!(Math(terminator.source_info.span, err.clone())) - } + Math(ref err) => Err(err.clone().into()), GeneratorResumedAfterReturn | GeneratorResumedAfterPanic => unimplemented!(), }; diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 47b2f430bc7..192ab6e17e7 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -328,7 +328,7 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> { } else { if overflow { use rustc::mir::interpret::EvalErrorKind; - let mut err = EvalErrorKind::OverflowingMath.into(); + let mut err = EvalErrorKind::Overflow(op).into(); ecx.report(&mut err, false, Some(span)); return None; } diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index 7c854ef04b7..32cb6c72d58 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -311,10 +311,9 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { // checked operation, just a comparison with the minimum // value, so we have to check for the assert message. if !bx.cx.check_overflow { - use rustc::mir::interpret::ConstMathErr::Overflow; - use rustc::mir::interpret::Op::Neg; + use rustc::mir::interpret::EvalErrorKind::OverflowNeg; - if let mir::AssertMessage::Math(Overflow(Neg)) = *msg { + if let mir::AssertMessage::Math(OverflowNeg) = *msg { const_cond = Some(expected); } } -- cgit 1.4.1-3-g733a5 From 5f46e5cc7e9fbe433fe40d013c19d8d641e7edc0 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 26 Apr 2018 15:02:54 +0200 Subject: Update ui test output --- src/test/ui/const-eval/promoted_errors.stderr | 12 ++++++------ src/test/ui/error-codes/E0080.stderr | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/test/ui/const-eval/promoted_errors.stderr b/src/test/ui/const-eval/promoted_errors.stderr index a5db8cc9083..59dcc2bac42 100644 --- a/src/test/ui/const-eval/promoted_errors.stderr +++ b/src/test/ui/const-eval/promoted_errors.stderr @@ -2,7 +2,7 @@ warning: constant evaluation error --> $DIR/promoted_errors.rs:14:20 | LL | println!("{}", 0u32 - 1); - | ^^^^^^^^ attempted to do overflowing math + | ^^^^^^^^ attempt to subtract with overflow | = note: #[warn(const_err)] on by default @@ -10,13 +10,13 @@ warning: constant evaluation error --> $DIR/promoted_errors.rs:14:20 | LL | println!("{}", 0u32 - 1); - | ^^^^^^^^ attempted to do overflowing math + | ^^^^^^^^ attempt to subtract with overflow warning: constant evaluation error --> $DIR/promoted_errors.rs:17:14 | LL | let _x = 0u32 - 1; - | ^^^^^^^^ attempted to do overflowing math + | ^^^^^^^^ attempt to subtract with overflow warning: attempt to divide by zero --> $DIR/promoted_errors.rs:19:20 @@ -28,7 +28,7 @@ warning: constant evaluation error --> $DIR/promoted_errors.rs:19:20 | LL | println!("{}", 1/(1-1)); - | ^^^^^^^ attempted to do overflowing math + | ^^^^^^^ attempt to divide with overflow warning: attempt to divide by zero --> $DIR/promoted_errors.rs:22:14 @@ -40,11 +40,11 @@ warning: constant evaluation error --> $DIR/promoted_errors.rs:22:14 | LL | let _x = 1/(1-1); - | ^^^^^^^ attempted to do overflowing math + | ^^^^^^^ attempt to divide with overflow warning: constant evaluation error --> $DIR/promoted_errors.rs:25:20 | LL | println!("{}", 1/(false as u32)); - | ^^^^^^^^^^^^^^^^ attempted to do overflowing math + | ^^^^^^^^^^^^^^^^ attempt to divide with overflow diff --git a/src/test/ui/error-codes/E0080.stderr b/src/test/ui/error-codes/E0080.stderr index 500e0e83a55..56c23f080cc 100644 --- a/src/test/ui/error-codes/E0080.stderr +++ b/src/test/ui/error-codes/E0080.stderr @@ -24,7 +24,7 @@ warning: constant evaluation error --> $DIR/E0080.rs:14:9 | LL | Y = (1 / 0) //~ ERROR E0080 - | ^^^^^^^ attempted to do overflowing math + | ^^^^^^^ attempt to divide with overflow error[E0080]: constant evaluation error --> $DIR/E0080.rs:14:9 -- cgit 1.4.1-3-g733a5 From 01158eaec6fc53ac6d3655dc31fde9d55aac15e9 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 27 Apr 2018 15:21:31 +0200 Subject: Unify MIR assert messages and const eval errors --- src/librustc/ich/impls_mir.rs | 21 ------------ src/librustc/ich/impls_ty.rs | 13 ++++---- src/librustc/mir/interpret/error.rs | 39 ++++++++++++++-------- src/librustc/mir/interpret/mod.rs | 2 +- src/librustc/mir/mod.rs | 37 ++++---------------- src/librustc/mir/visit.rs | 14 +++----- src/librustc/ty/structural_impls.rs | 23 +++++++++---- src/librustc_mir/borrow_check/mod.rs | 22 +++++------- .../borrow_check/nll/type_check/mod.rs | 3 +- src/librustc_mir/build/expr/as_place.rs | 3 +- src/librustc_mir/build/expr/as_rvalue.rs | 9 +++-- src/librustc_mir/interpret/terminator/mod.rs | 9 ++--- src/librustc_mir/transform/const_prop.rs | 12 ++++--- src/librustc_mir/transform/generator.rs | 9 +++-- src/librustc_passes/mir_stats.rs | 13 +++++--- src/librustc_trans/mir/block.rs | 29 +++------------- 16 files changed, 111 insertions(+), 147 deletions(-) (limited to 'src') diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs index 437626ff536..33f43e53394 100644 --- a/src/librustc/ich/impls_mir.rs +++ b/src/librustc/ich/impls_mir.rs @@ -227,27 +227,6 @@ for mir::TerminatorKind<'gcx> { } } -impl<'a, 'gcx> HashStable> -for mir::AssertMessage<'gcx> { - fn hash_stable(&self, - hcx: &mut StableHashingContext<'a>, - hasher: &mut StableHasher) { - mem::discriminant(self).hash_stable(hcx, hasher); - - match *self { - mir::AssertMessage::BoundsCheck { ref len, ref index } => { - len.hash_stable(hcx, hasher); - index.hash_stable(hcx, hasher); - } - mir::AssertMessage::Math(ref const_math_err) => { - const_math_err.hash_stable(hcx, hasher); - } - mir::AssertMessage::GeneratorResumedAfterReturn => (), - mir::AssertMessage::GeneratorResumedAfterPanic => (), - } - } -} - impl_stable_hash_for!(struct mir::Statement<'tcx> { source_info, kind }); impl<'a, 'gcx> HashStable> diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index a5447a3145a..a40d8e09277 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -535,8 +535,8 @@ for ::mir::interpret::EvalError<'gcx> { } } -impl<'a, 'gcx> HashStable> -for ::mir::interpret::EvalErrorKind<'gcx> { +impl<'a, 'gcx, O: HashStable>> HashStable> +for ::mir::interpret::EvalErrorKind<'gcx, O> { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { @@ -578,6 +578,8 @@ for ::mir::interpret::EvalErrorKind<'gcx> { OverflowNeg | RemainderByZero | DivisionByZero | + GeneratorResumedAfterReturn | + GeneratorResumedAfterPanic | ReferencedConstant => {} MachineError(ref err) => err.hash_stable(hcx, hasher), FunctionPointerTyMismatch(a, b) => { @@ -597,10 +599,9 @@ for ::mir::interpret::EvalErrorKind<'gcx> { }, InvalidBoolOp(bop) => bop.hash_stable(hcx, hasher), Unimplemented(ref s) => s.hash_stable(hcx, hasher), - ArrayIndexOutOfBounds(sp, a, b) => { - sp.hash_stable(hcx, hasher); - a.hash_stable(hcx, hasher); - b.hash_stable(hcx, hasher) + BoundsCheck { ref len, ref index } => { + len.hash_stable(hcx, hasher); + index.hash_stable(hcx, hasher) }, Intrinsic(ref s) => s.hash_stable(hcx, hasher), InvalidChar(c) => c.hash_stable(hcx, hasher), diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index 022b82841bc..1e1d50c3fc0 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -7,17 +7,16 @@ use super::{ MemoryPointer, Lock, AccessKind }; -use syntax::codemap::Span; use backtrace::Backtrace; #[derive(Debug, Clone)] pub struct EvalError<'tcx> { - pub kind: EvalErrorKind<'tcx>, + pub kind: EvalErrorKind<'tcx, u64>, pub backtrace: Option, } -impl<'tcx> From> for EvalError<'tcx> { - fn from(kind: EvalErrorKind<'tcx>) -> Self { +impl<'tcx> From> for EvalError<'tcx> { + fn from(kind: EvalErrorKind<'tcx, u64>) -> Self { let backtrace = match env::var("MIRI_BACKTRACE") { Ok(ref val) if !val.is_empty() => Some(Backtrace::new_unresolved()), _ => None @@ -29,8 +28,10 @@ impl<'tcx> From> for EvalError<'tcx> { } } -#[derive(Debug, Clone, RustcEncodable, RustcDecodable)] -pub enum EvalErrorKind<'tcx> { +pub type AssertMessage<'tcx> = EvalErrorKind<'tcx, mir::Operand<'tcx>>; + +#[derive(Clone, RustcEncodable, RustcDecodable)] +pub enum EvalErrorKind<'tcx, O> { /// This variant is used by machines to signal their own errors that do not /// match an existing variant MachineError(String), @@ -58,7 +59,7 @@ pub enum EvalErrorKind<'tcx> { Unimplemented(String), DerefFunctionPointer, ExecuteMemory, - ArrayIndexOutOfBounds(Span, u64, u64), + BoundsCheck { len: O, index: O }, Overflow(mir::BinOp), OverflowNeg, DivisionByZero, @@ -121,11 +122,13 @@ pub enum EvalErrorKind<'tcx> { /// Cannot compute this constant because it depends on another one /// which already produced an error ReferencedConstant, + GeneratorResumedAfterReturn, + GeneratorResumedAfterPanic, } pub type EvalResult<'tcx, T = ()> = Result>; -impl<'tcx> EvalErrorKind<'tcx> { +impl<'tcx, O> EvalErrorKind<'tcx, O> { pub fn description(&self) -> &str { use self::EvalErrorKind::*; match *self { @@ -175,7 +178,7 @@ impl<'tcx> EvalErrorKind<'tcx> { "tried to dereference a function pointer", ExecuteMemory => "tried to treat a memory pointer as a function pointer", - ArrayIndexOutOfBounds(..) => + BoundsCheck{..} => "array index out of bounds", Intrinsic(..) => "intrinsic failed", @@ -228,7 +231,7 @@ impl<'tcx> EvalErrorKind<'tcx> { "the evaluated program panicked", ReadFromReturnPointer => "tried to read from the return pointer", - EvalErrorKind::PathNotFound(_) => + PathNotFound(_) => "a path could not be resolved, maybe the crate is not loaded", UnimplementedTraitSelection => "there were unresolved type arguments during trait selection", @@ -247,14 +250,22 @@ impl<'tcx> EvalErrorKind<'tcx> { Overflow(op) => bug!("{:?} cannot overflow", op), DivisionByZero => "attempt to divide by zero", RemainderByZero => "attempt to calculate the remainder with a divisor of zero", + GeneratorResumedAfterReturn => "generator resumed after completion", + GeneratorResumedAfterPanic => "generator resumed after panicking", } } } impl<'tcx> fmt::Display for EvalError<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{:?}", self.kind) + } +} + +impl<'tcx, O: fmt::Debug> fmt::Debug for EvalErrorKind<'tcx, O> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use self::EvalErrorKind::*; - match self.kind { + match *self { PointerOutOfBounds { ptr, access, allocation_size } => { write!(f, "{} at offset {}, outside bounds of allocation {} which has size {}", if access { "memory access" } else { "pointer computed" }, @@ -282,8 +293,8 @@ impl<'tcx> fmt::Display for EvalError<'tcx> { NoMirFor(ref func) => write!(f, "no mir for `{}`", func), FunctionPointerTyMismatch(sig, got) => write!(f, "tried to call a function with sig {} through a function pointer of type {}", sig, got), - ArrayIndexOutOfBounds(span, len, index) => - write!(f, "index out of bounds: the len is {} but the index is {} at {:?}", len, index, span), + BoundsCheck { ref len, ref index } => + write!(f, "index out of bounds: the len is {:?} but the index is {:?}", len, index), ReallocatedWrongMemoryKind(ref old, ref new) => write!(f, "tried to reallocate memory from {} to {}", old, new), DeallocatedWrongMemoryKind(ref old, ref new) => @@ -305,7 +316,7 @@ impl<'tcx> fmt::Display for EvalError<'tcx> { write!(f, "{}", inner), IncorrectAllocationInformation(size, size2, align, align2) => write!(f, "incorrect alloc info: expected size {} and align {}, got size {} and align {}", size, align, size2, align2), - _ => write!(f, "{}", self.kind.description()), + _ => write!(f, "{}", self.description()), } } } diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs index a521caf4fda..546c7a920d5 100644 --- a/src/librustc/mir/interpret/mod.rs +++ b/src/librustc/mir/interpret/mod.rs @@ -8,7 +8,7 @@ macro_rules! err { mod error; mod value; -pub use self::error::{EvalError, EvalResult, EvalErrorKind}; +pub use self::error::{EvalError, EvalResult, EvalErrorKind, AssertMessage}; pub use self::value::{PrimVal, PrimValKind, Value, Pointer}; diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 0b56dbda42c..c62fe0372df 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -45,6 +45,8 @@ use syntax_pos::{Span, DUMMY_SP}; use rustc_apfloat::ieee::{Single, Double}; use rustc_apfloat::Float; +pub use mir::interpret::AssertMessage; + mod cache; pub mod tcx; pub mod visit; @@ -1132,23 +1134,7 @@ impl<'tcx> TerminatorKind<'tcx> { write!(fmt, "!")?; } write!(fmt, "{:?}, ", cond)?; - - match *msg { - AssertMessage::BoundsCheck { ref len, ref index } => { - write!(fmt, "{:?}, {:?}, {:?}", - "index out of bounds: the len is {} but the index is {}", - len, index)?; - } - AssertMessage::Math(ref err) => { - write!(fmt, "{:?}", err.description())?; - } - AssertMessage::GeneratorResumedAfterReturn => { - write!(fmt, "{:?}", "generator resumed after completion")?; - } - AssertMessage::GeneratorResumedAfterPanic => { - write!(fmt, "{:?}", "generator resumed after panicking")?; - } - } + write!(fmt, "{:?}", msg)?; write!(fmt, ")") }, @@ -1205,17 +1191,6 @@ impl<'tcx> TerminatorKind<'tcx> { } } -#[derive(Clone, Debug, RustcEncodable, RustcDecodable)] -pub enum AssertMessage<'tcx> { - BoundsCheck { - len: Operand<'tcx>, - index: Operand<'tcx> - }, - Math(EvalErrorKind<'tcx>), - GeneratorResumedAfterReturn, - GeneratorResumedAfterPanic, -} - /////////////////////////////////////////////////////////////////////////// // Statements @@ -2281,8 +2256,8 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { } }, Assert { ref cond, expected, ref msg, target, cleanup } => { - let msg = if let AssertMessage::BoundsCheck { ref len, ref index } = *msg { - AssertMessage::BoundsCheck { + let msg = if let EvalErrorKind::BoundsCheck { ref len, ref index } = *msg { + EvalErrorKind::BoundsCheck { len: len.fold_with(folder), index: index.fold_with(folder), } @@ -2331,7 +2306,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { }, Assert { ref cond, ref msg, .. } => { if cond.visit_with(visitor) { - if let AssertMessage::BoundsCheck { ref len, ref index } = *msg { + if let EvalErrorKind::BoundsCheck { ref len, ref index } = *msg { len.visit_with(visitor) || index.visit_with(visitor) } else { false diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index a3fdb6f73ab..59b6f369754 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -511,17 +511,13 @@ macro_rules! make_mir_visitor { fn super_assert_message(&mut self, msg: & $($mutability)* AssertMessage<'tcx>, location: Location) { - match *msg { - AssertMessage::BoundsCheck { + use mir::interpret::EvalErrorKind::*; + if let BoundsCheck { ref $($mutability)* len, ref $($mutability)* index - } => { - self.visit_operand(len, location); - self.visit_operand(index, location); - } - AssertMessage::Math(_) => {}, - AssertMessage::GeneratorResumedAfterReturn => {}, - AssertMessage::GeneratorResumedAfterPanic => {}, + } = *msg { + self.visit_operand(len, location); + self.visit_operand(index, location); } } diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index bae91d064a5..d4ed6c60e0e 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -473,9 +473,19 @@ impl<'a, 'tcx> Lift<'tcx> for ConstEvalErr<'a> { impl<'a, 'tcx> Lift<'tcx> for interpret::EvalError<'a> { type Lifted = interpret::EvalError<'tcx>; + fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { + Some(interpret::EvalError { + kind: tcx.lift(&self.kind)?, + backtrace: self.backtrace.clone(), + }) + } +} + +impl<'a, 'tcx, O: Lift<'tcx>> Lift<'tcx> for interpret::EvalErrorKind<'a, O> { + type Lifted = interpret::EvalErrorKind<'tcx, >::Lifted>; fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { use ::mir::interpret::EvalErrorKind::*; - let kind = match self.kind { + Some(match *self { MachineError(ref err) => MachineError(err.clone()), FunctionPointerTyMismatch(a, b) => FunctionPointerTyMismatch( tcx.lift(&a)?, @@ -504,7 +514,10 @@ impl<'a, 'tcx> Lift<'tcx> for interpret::EvalError<'a> { Unimplemented(ref s) => Unimplemented(s.clone()), DerefFunctionPointer => DerefFunctionPointer, ExecuteMemory => ExecuteMemory, - ArrayIndexOutOfBounds(sp, a, b) => ArrayIndexOutOfBounds(sp, a, b), + BoundsCheck { ref len, ref index } => BoundsCheck { + len: tcx.lift(len)?, + index: tcx.lift(index)?, + }, Intrinsic(ref s) => Intrinsic(s.clone()), InvalidChar(c) => InvalidChar(c), StackFrameLimitReached => StackFrameLimitReached, @@ -570,10 +583,8 @@ impl<'a, 'tcx> Lift<'tcx> for interpret::EvalError<'a> { Overflow(op) => Overflow(op), DivisionByZero => DivisionByZero, RemainderByZero => RemainderByZero, - }; - Some(interpret::EvalError { - kind: kind, - backtrace: self.backtrace.clone(), + GeneratorResumedAfterReturn => GeneratorResumedAfterReturn, + GeneratorResumedAfterPanic => GeneratorResumedAfterPanic, }) } } diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 3145be7df85..7e1c20dff6a 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -18,7 +18,7 @@ use rustc::infer::InferCtxt; use rustc::ty::{self, ParamEnv, TyCtxt}; use rustc::ty::maps::Providers; use rustc::lint::builtin::UNUSED_MUT; -use rustc::mir::{AssertMessage, AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind}; +use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind}; use rustc::mir::{ClearCrossCrate, Local, Location, Place, Mir, Mutability, Operand}; use rustc::mir::{Projection, ProjectionElem, Rvalue, Field, Statement, StatementKind}; use rustc::mir::{Terminator, TerminatorKind}; @@ -586,18 +586,14 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx cleanup: _, } => { self.consume_operand(ContextKind::Assert.new(loc), (cond, span), flow_state); - match *msg { - AssertMessage::BoundsCheck { ref len, ref index } => { - self.consume_operand(ContextKind::Assert.new(loc), (len, span), flow_state); - self.consume_operand( - ContextKind::Assert.new(loc), - (index, span), - flow_state, - ); - } - AssertMessage::Math(_ /*const_math_err*/) => {} - AssertMessage::GeneratorResumedAfterReturn => {} - AssertMessage::GeneratorResumedAfterPanic => {} + use rustc::mir::interpret::EvalErrorKind::BoundsCheck; + if let BoundsCheck { ref len, ref index } = *msg { + self.consume_operand(ContextKind::Assert.new(loc), (len, span), flow_state); + self.consume_operand( + ContextKind::Assert.new(loc), + (index, span), + flow_state, + ); } } diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index a811b2c147e..a21b9196bad 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -22,6 +22,7 @@ use rustc::infer::region_constraints::{GenericKind, RegionConstraintData}; use rustc::infer::{InferCtxt, InferOk, InferResult, LateBoundRegionConversionTime, UnitResult}; use rustc::mir::tcx::PlaceTy; use rustc::mir::visit::{PlaceContext, Visitor}; +use rustc::mir::interpret::EvalErrorKind::BoundsCheck; use rustc::mir::*; use rustc::traits::query::NoSolution; use rustc::traits::{self, Normalized, TraitEngine}; @@ -928,7 +929,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { span_mirbug!(self, term, "bad Assert ({:?}, not bool", cond_ty); } - if let AssertMessage::BoundsCheck { ref len, ref index } = *msg { + if let BoundsCheck { ref len, ref index } = *msg { if len.ty(mir, tcx) != tcx.types.usize { span_mirbug!(self, len, "bounds-check length non-usize {:?}", len) } diff --git a/src/librustc_mir/build/expr/as_place.rs b/src/librustc_mir/build/expr/as_place.rs index 9e217908511..19ec13324d6 100644 --- a/src/librustc_mir/build/expr/as_place.rs +++ b/src/librustc_mir/build/expr/as_place.rs @@ -14,6 +14,7 @@ use build::{BlockAnd, BlockAndExtension, Builder}; use build::expr::category::Category; use hair::*; use rustc::mir::*; +use rustc::mir::interpret::EvalErrorKind::BoundsCheck; use rustc_data_structures::indexed_vec::Idx; @@ -73,7 +74,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { Operand::Copy(Place::Local(idx)), Operand::Copy(len.clone()))); - let msg = AssertMessage::BoundsCheck { + let msg = BoundsCheck { len: Operand::Move(len), index: Operand::Copy(Place::Local(idx)) }; diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 33c80ab22a3..9e96fdf8214 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -85,9 +85,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { this.cfg.push_assign(block, source_info, &is_min, Rvalue::BinaryOp(BinOp::Eq, arg.to_copy(), minval)); - let err = EvalErrorKind::OverflowNeg; block = this.assert(block, Operand::Move(is_min), false, - AssertMessage::Math(err), expr_span); + EvalErrorKind::OverflowNeg, expr_span); } block.and(Rvalue::UnaryOp(op, arg)) } @@ -313,7 +312,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let err = EvalErrorKind::Overflow(op); block = self.assert(block, Operand::Move(of), false, - AssertMessage::Math(err), span); + err, span); block.and(Rvalue::Use(Operand::Move(val))) } else { @@ -336,7 +335,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { Rvalue::BinaryOp(BinOp::Eq, rhs.to_copy(), zero)); block = self.assert(block, Operand::Move(is_zero), false, - AssertMessage::Math(zero_err), span); + zero_err, span); // We only need to check for the overflow in one case: // MIN / -1, and only for signed values. @@ -361,7 +360,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { Rvalue::BinaryOp(BinOp::BitAnd, is_neg_1, is_min)); block = self.assert(block, Operand::Move(of), false, - AssertMessage::Math(overflow_err), span); + overflow_err, span); } } diff --git a/src/librustc_mir/interpret/terminator/mod.rs b/src/librustc_mir/interpret/terminator/mod.rs index 4f0e97f6e1a..b630725b0d2 100644 --- a/src/librustc_mir/interpret/terminator/mod.rs +++ b/src/librustc_mir/interpret/terminator/mod.rs @@ -148,21 +148,22 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { if expected == cond_val { self.goto_block(target); } else { - use rustc::mir::AssertMessage::*; + use rustc::mir::interpret::EvalErrorKind::*; return match *msg { BoundsCheck { ref len, ref index } => { - let span = terminator.source_info.span; let len = self.eval_operand_to_primval(len) .expect("can't eval len") .to_u64()?; let index = self.eval_operand_to_primval(index) .expect("can't eval index") .to_u64()?; - err!(ArrayIndexOutOfBounds(span, len, index)) + err!(BoundsCheck { len, index }) } - Math(ref err) => Err(err.clone().into()), + Overflow(op) => Err(Overflow(op).into()), + OverflowNeg => Err(OverflowNeg.into()), GeneratorResumedAfterReturn | GeneratorResumedAfterPanic => unimplemented!(), + _ => bug!(), }; } } diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 192ab6e17e7..e1db216b6bb 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -478,12 +478,12 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> { .hir .as_local_node_id(self.source.def_id) .expect("some part of a failing const eval must be local"); - use rustc::mir::AssertMessage::*; + use rustc::mir::interpret::EvalErrorKind::*; let msg = match msg { - // Need proper const propagator for these - GeneratorResumedAfterReturn | - GeneratorResumedAfterPanic => return, - Math(ref err) => err.description().to_owned(), + Overflow(_) | + OverflowNeg | + DivisionByZero | + RemainderByZero => msg.description().to_owned(), BoundsCheck { ref len, ref index } => { let len = self.eval_operand(len).expect("len must be const"); let len = match len.0 { @@ -504,6 +504,8 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> { index, ) }, + // Need proper const propagator for these + _ => return, }; self.tcx.lint_node( ::rustc::lint::builtin::CONST_ERR, diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 0ff73569433..36735586e81 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -738,12 +738,17 @@ fn create_generator_resume_function<'a, 'tcx>( let mut cases = create_cases(mir, &transform, |point| Some(point.resume)); + use rustc::mir::interpret::EvalErrorKind::{ + GeneratorResumedAfterPanic, + GeneratorResumedAfterReturn, + }; + // Jump to the entry point on the 0 state cases.insert(0, (0, BasicBlock::new(0))); // Panic when resumed on the returned (1) state - cases.insert(1, (1, insert_panic_block(tcx, mir, AssertMessage::GeneratorResumedAfterReturn))); + cases.insert(1, (1, insert_panic_block(tcx, mir, GeneratorResumedAfterReturn))); // Panic when resumed on the poisoned (2) state - cases.insert(2, (2, insert_panic_block(tcx, mir, AssertMessage::GeneratorResumedAfterPanic))); + cases.insert(2, (2, insert_panic_block(tcx, mir, GeneratorResumedAfterPanic))); insert_switch(tcx, mir, cases, &transform, TerminatorKind::Unreachable); diff --git a/src/librustc_passes/mir_stats.rs b/src/librustc_passes/mir_stats.rs index a4e056c6b58..45c6e89321d 100644 --- a/src/librustc_passes/mir_stats.rs +++ b/src/librustc_passes/mir_stats.rs @@ -18,6 +18,7 @@ use rustc::mir::{Place, PlaceElem, PlaceProjection}; use rustc::mir::{Mir, Operand, ProjectionElem}; use rustc::mir::{Rvalue, SourceInfo, Statement, StatementKind}; use rustc::mir::{Terminator, TerminatorKind, VisibilityScope, VisibilityScopeData}; +use rustc::mir::interpret::EvalErrorKind; use rustc::mir::visit as mir_visit; use rustc::ty::{self, ClosureSubsts, TyCtxt}; use rustc::util::nodemap::{FxHashMap}; @@ -133,14 +134,18 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> { location: Location) { self.record("AssertMessage", msg); self.record(match *msg { - AssertMessage::BoundsCheck { .. } => "AssertMessage::BoundsCheck", - AssertMessage::Math(..) => "AssertMessage::Math", - AssertMessage::GeneratorResumedAfterReturn => { + EvalErrorKind::BoundsCheck { .. } => "AssertMessage::BoundsCheck", + EvalErrorKind::Overflow(..) => "AssertMessage::Overflow", + EvalErrorKind::OverflowNeg => "AssertMessage::OverflowNeg", + EvalErrorKind::DivisionByZero => "AssertMessage::DivisionByZero", + EvalErrorKind::RemainderByZero => "AssertMessage::RemainderByZero", + EvalErrorKind::GeneratorResumedAfterReturn => { "AssertMessage::GeneratorResumedAfterReturn" } - AssertMessage::GeneratorResumedAfterPanic => { + EvalErrorKind::GeneratorResumedAfterPanic => { "AssertMessage::GeneratorResumedAfterPanic" } + _ => bug!(), }, msg); self.super_assert_message(msg, location); } diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs index 32cb6c72d58..b666c2b2115 100644 --- a/src/librustc_trans/mir/block.rs +++ b/src/librustc_trans/mir/block.rs @@ -13,6 +13,7 @@ use rustc::middle::lang_items; use rustc::ty::{self, Ty, TypeFoldable}; use rustc::ty::layout::{self, LayoutOf}; use rustc::mir; +use rustc::mir::interpret::EvalErrorKind; use abi::{Abi, ArgType, ArgTypeExt, FnType, FnTypeExt, LlvmType, PassMode}; use base; use callee; @@ -311,9 +312,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { // checked operation, just a comparison with the minimum // value, so we have to check for the assert message. if !bx.cx.check_overflow { - use rustc::mir::interpret::EvalErrorKind::OverflowNeg; - - if let mir::AssertMessage::Math(OverflowNeg) = *msg { + if let mir::interpret::EvalErrorKind::OverflowNeg = *msg { const_cond = Some(expected); } } @@ -353,7 +352,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { // Put together the arguments to the panic entry point. let (lang_item, args) = match *msg { - mir::AssertMessage::BoundsCheck { ref len, ref index } => { + EvalErrorKind::BoundsCheck { ref len, ref index } => { let len = self.trans_operand(&mut bx, len).immediate(); let index = self.trans_operand(&mut bx, index).immediate(); @@ -365,26 +364,8 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { (lang_items::PanicBoundsCheckFnLangItem, vec![file_line_col, index, len]) } - mir::AssertMessage::Math(ref err) => { - let msg_str = Symbol::intern(err.description()).as_str(); - let msg_str = C_str_slice(bx.cx, msg_str); - let msg_file_line_col = C_struct(bx.cx, - &[msg_str, filename, line, col], - false); - let msg_file_line_col = consts::addr_of(bx.cx, - msg_file_line_col, - align, - "panic_loc"); - (lang_items::PanicFnLangItem, - vec![msg_file_line_col]) - } - mir::AssertMessage::GeneratorResumedAfterReturn | - mir::AssertMessage::GeneratorResumedAfterPanic => { - let str = if let mir::AssertMessage::GeneratorResumedAfterReturn = *msg { - "generator resumed after completion" - } else { - "generator resumed after panicking" - }; + _ => { + let str = msg.description(); let msg_str = Symbol::intern(str).as_str(); let msg_str = C_str_slice(bx.cx, msg_str); let msg_file_line_col = C_struct(bx.cx, -- cgit 1.4.1-3-g733a5 From 1f3cb926a24897d6524920bb38618b4b6ee17aa7 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 27 Apr 2018 15:21:42 +0200 Subject: Update Cargo.lock --- src/Cargo.lock | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'src') diff --git a/src/Cargo.lock b/src/Cargo.lock index a6f78a7e6b4..940ca1aace0 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1728,7 +1728,6 @@ dependencies = [ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "proc_macro 0.0.0", "rustc_apfloat 0.0.0", - "rustc_const_math 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", "rustc_target 0.0.0", @@ -1872,15 +1871,6 @@ dependencies = [ "syntax_pos 0.0.0", ] -[[package]] -name = "rustc_const_math" -version = "0.0.0" -dependencies = [ - "rustc_apfloat 0.0.0", - "serialize 0.0.0", - "syntax 0.0.0", -] - [[package]] name = "rustc_cratesio_shim" version = "0.0.0" @@ -2026,7 +2016,6 @@ dependencies = [ "log_settings 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_apfloat 0.0.0", - "rustc_const_math 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", "rustc_target 0.0.0", @@ -2053,7 +2042,6 @@ version = "0.0.0" dependencies = [ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", - "rustc_const_math 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", "rustc_mir 0.0.0", @@ -2154,7 +2142,6 @@ dependencies = [ "rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_allocator 0.0.0", "rustc_apfloat 0.0.0", - "rustc_const_math 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", "rustc_incremental 0.0.0", @@ -2205,7 +2192,6 @@ dependencies = [ "fmt_macros 0.0.0", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", - "rustc_const_math 0.0.0", "rustc_data_structures 0.0.0", "rustc_errors 0.0.0", "rustc_platform_intrinsics 0.0.0", -- cgit 1.4.1-3-g733a5 From f66367daccd2352d14730e472e8dfdef244aec63 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Sat, 28 Apr 2018 13:35:35 +0200 Subject: Improve div by zero const eval errors --- src/librustc/mir/mod.rs | 2 +- src/librustc_mir/interpret/operator.rs | 6 ++++-- src/librustc_mir/interpret/terminator/mod.rs | 2 ++ src/test/ui/const-eval/index_out_of_bound.stderr | 2 +- src/test/ui/const-eval/promoted_errors.stderr | 6 +++--- src/test/ui/error-codes/E0080.rs | 1 - src/test/ui/error-codes/E0080.stderr | 2 +- 7 files changed, 12 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index c62fe0372df..624f8ed789c 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1134,7 +1134,7 @@ impl<'tcx> TerminatorKind<'tcx> { write!(fmt, "!")?; } write!(fmt, "{:?}, ", cond)?; - write!(fmt, "{:?}", msg)?; + write!(fmt, "\"{:?}\"", msg)?; write!(fmt, ")") }, diff --git a/src/librustc_mir/interpret/operator.rs b/src/librustc_mir/interpret/operator.rs index 6e7a37c2228..ef6deab0477 100644 --- a/src/librustc_mir/interpret/operator.rs +++ b/src/librustc_mir/interpret/operator.rs @@ -140,7 +140,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { return Ok((PrimVal::from_bool(op(&l, &r)), false)); } let op: Option (i128, bool)> = match bin_op { - Rem | Div if r == 0 => return Ok((PrimVal::Bytes(l), true)), + Div if r == 0 => return err!(DivisionByZero), + Rem if r == 0 => return err!(RemainderByZero), Div => Some(i128::overflowing_div), Rem => Some(i128::overflowing_rem), Add => Some(i128::overflowing_add), @@ -221,7 +222,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { Add => u128::overflowing_add, Sub => u128::overflowing_sub, Mul => u128::overflowing_mul, - Rem | Div if r == 0 => return Ok((PrimVal::Bytes(l), true)), + Div if r == 0 => return err!(DivisionByZero), + Rem if r == 0 => return err!(RemainderByZero), Div => u128::overflowing_div, Rem => u128::overflowing_rem, _ => bug!(), diff --git a/src/librustc_mir/interpret/terminator/mod.rs b/src/librustc_mir/interpret/terminator/mod.rs index b630725b0d2..0e0d91f4724 100644 --- a/src/librustc_mir/interpret/terminator/mod.rs +++ b/src/librustc_mir/interpret/terminator/mod.rs @@ -161,6 +161,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { } Overflow(op) => Err(Overflow(op).into()), OverflowNeg => Err(OverflowNeg.into()), + DivisionByZero => Err(DivisionByZero.into()), + RemainderByZero => Err(RemainderByZero.into()), GeneratorResumedAfterReturn | GeneratorResumedAfterPanic => unimplemented!(), _ => bug!(), diff --git a/src/test/ui/const-eval/index_out_of_bound.stderr b/src/test/ui/const-eval/index_out_of_bound.stderr index 793e0a7ace8..d16231c72b9 100644 --- a/src/test/ui/const-eval/index_out_of_bound.stderr +++ b/src/test/ui/const-eval/index_out_of_bound.stderr @@ -2,7 +2,7 @@ error[E0080]: constant evaluation error --> $DIR/index_out_of_bound.rs:11:19 | LL | static FOO: i32 = [][0]; - | ^^^^^ index out of bounds: the len is 0 but the index is 0 at $DIR/index_out_of_bound.rs:11:19: 11:24 + | ^^^^^ index out of bounds: the len is 0 but the index is 0 error: aborting due to previous error diff --git a/src/test/ui/const-eval/promoted_errors.stderr b/src/test/ui/const-eval/promoted_errors.stderr index 59dcc2bac42..7761f192fdb 100644 --- a/src/test/ui/const-eval/promoted_errors.stderr +++ b/src/test/ui/const-eval/promoted_errors.stderr @@ -28,7 +28,7 @@ warning: constant evaluation error --> $DIR/promoted_errors.rs:19:20 | LL | println!("{}", 1/(1-1)); - | ^^^^^^^ attempt to divide with overflow + | ^^^^^^^ attempt to divide by zero warning: attempt to divide by zero --> $DIR/promoted_errors.rs:22:14 @@ -40,11 +40,11 @@ warning: constant evaluation error --> $DIR/promoted_errors.rs:22:14 | LL | let _x = 1/(1-1); - | ^^^^^^^ attempt to divide with overflow + | ^^^^^^^ attempt to divide by zero warning: constant evaluation error --> $DIR/promoted_errors.rs:25:20 | LL | println!("{}", 1/(false as u32)); - | ^^^^^^^^^^^^^^^^ attempt to divide with overflow + | ^^^^^^^^^^^^^^^^ attempt to divide by zero diff --git a/src/test/ui/error-codes/E0080.rs b/src/test/ui/error-codes/E0080.rs index c8e42571128..7f3e6eaad9b 100644 --- a/src/test/ui/error-codes/E0080.rs +++ b/src/test/ui/error-codes/E0080.rs @@ -15,7 +15,6 @@ enum Enum { //~| const_err //~| const_err //~| const_err - //~| divide by zero } fn main() { diff --git a/src/test/ui/error-codes/E0080.stderr b/src/test/ui/error-codes/E0080.stderr index 56c23f080cc..5e401bd6c79 100644 --- a/src/test/ui/error-codes/E0080.stderr +++ b/src/test/ui/error-codes/E0080.stderr @@ -24,7 +24,7 @@ warning: constant evaluation error --> $DIR/E0080.rs:14:9 | LL | Y = (1 / 0) //~ ERROR E0080 - | ^^^^^^^ attempt to divide with overflow + | ^^^^^^^ attempt to divide by zero error[E0080]: constant evaluation error --> $DIR/E0080.rs:14:9 -- cgit 1.4.1-3-g733a5 From 2e59e467a0e4dbcf6a6e7ba2e443ebc2fde88e11 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 4 Apr 2018 17:17:23 -0400 Subject: remove some (apparently) dead code --- src/librustc/ty/fold.rs | 9 --------- src/librustc/ty/sty.rs | 7 ------- 2 files changed, 16 deletions(-) (limited to 'src') diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 650ac4e6f6d..3d0f2de57bf 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -111,15 +111,6 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { self.has_type_flags(TypeFlags::HAS_FREE_REGIONS) } - fn is_normalized_for_trans(&self) -> bool { - !self.has_type_flags(TypeFlags::HAS_RE_INFER | - TypeFlags::HAS_FREE_REGIONS | - TypeFlags::HAS_TY_INFER | - TypeFlags::HAS_PARAMS | - TypeFlags::HAS_NORMALIZABLE_PROJECTION | - TypeFlags::HAS_TY_ERR | - TypeFlags::HAS_SELF) - } /// Indicates whether this value references only 'global' /// types/lifetimes that are the same regardless of what fn we are /// in. This is used for caching. Errs on the side of returning diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index e9c1e87676b..936dbb1ccb8 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1171,13 +1171,6 @@ impl RegionKind { } } - pub fn needs_infer(&self) -> bool { - match *self { - ty::ReVar(..) | ty::ReSkolemized(..) => true, - _ => false - } - } - pub fn escapes_depth(&self, depth: u32) -> bool { match *self { ty::ReLateBound(debruijn, _) => debruijn.depth > depth, -- cgit 1.4.1-3-g733a5 From c916ee8511339dd231d90d7fe6be2cc6995284b9 Mon Sep 17 00:00:00 2001 From: kennytm Date: Fri, 6 Apr 2018 05:21:47 +0800 Subject: Removed direct field usage of RangeInclusive in rustc itself. --- src/libcore/lib.rs | 1 + src/libcore/ops/range.rs | 2 +- src/libcore/tests/ops.rs | 8 +++--- src/librustc/lib.rs | 2 +- src/librustc/ty/layout.rs | 44 ++++++++++++++---------------- src/librustc_mir/interpret/eval_context.rs | 6 ++-- src/librustc_mir/lib.rs | 2 +- src/librustc_target/abi/mod.rs | 4 +-- src/librustc_target/lib.rs | 2 +- src/librustc_trans/abi.rs | 4 +-- src/librustc_trans/debuginfo/metadata.rs | 2 +- src/librustc_trans/mir/place.rs | 12 ++++---- src/librustc_trans/mir/rvalue.rs | 4 +-- 13 files changed, 45 insertions(+), 48 deletions(-) (limited to 'src') diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 0e21a3327fd..5a6e0050835 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -103,6 +103,7 @@ #![feature(untagged_unions)] #![feature(unwind_attributes)] #![feature(doc_alias)] +#![feature(inclusive_range_methods)] #![cfg_attr(not(stage0), feature(mmx_target_feature))] #![cfg_attr(not(stage0), feature(tbm_target_feature))] diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs index c1bd1ef2d1d..59ee40fdda4 100644 --- a/src/libcore/ops/range.rs +++ b/src/libcore/ops/range.rs @@ -318,7 +318,7 @@ impl> RangeTo { /// # Examples /// /// ``` -/// #![feature(inclusive_range_fields)] +/// #![feature(inclusive_range_methods)] /// /// assert_eq!((3..=5), std::ops::RangeInclusive::new(3, 5)); /// assert_eq!(3 + 4 + 5, (3..=5).sum()); diff --git a/src/libcore/tests/ops.rs b/src/libcore/tests/ops.rs index bed08f86d72..d66193b1687 100644 --- a/src/libcore/tests/ops.rs +++ b/src/libcore/tests/ops.rs @@ -50,21 +50,21 @@ fn test_full_range() { #[test] fn test_range_inclusive() { - let mut r = RangeInclusive { start: 1i8, end: 2 }; + let mut r = RangeInclusive::new(1i8, 2); assert_eq!(r.next(), Some(1)); assert_eq!(r.next(), Some(2)); assert_eq!(r.next(), None); - r = RangeInclusive { start: 127i8, end: 127 }; + r = RangeInclusive::new(127i8, 127); assert_eq!(r.next(), Some(127)); assert_eq!(r.next(), None); - r = RangeInclusive { start: -128i8, end: -128 }; + r = RangeInclusive::new(-128i8, -128); assert_eq!(r.next_back(), Some(-128)); assert_eq!(r.next_back(), None); // degenerate - r = RangeInclusive { start: 1, end: -1 }; + r = RangeInclusive::new(1, -1); assert_eq!(r.size_hint(), (0, Some(0))); assert_eq!(r.next(), None); } diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 24892dfcc8f..9dc9fb1144e 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -69,7 +69,7 @@ #![feature(trusted_len)] #![feature(catch_expr)] #![feature(test)] -#![feature(inclusive_range_fields)] +#![feature(inclusive_range_methods)] #![recursion_limit="512"] diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 55137e28911..47b52cacd56 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -19,7 +19,6 @@ use std::cmp; use std::fmt; use std::i128; use std::mem; -use std::ops::RangeInclusive; use ich::StableHashingContext; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, @@ -492,7 +491,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { ty::TyFloat(FloatTy::F64) => scalar(F64), ty::TyFnPtr(_) => { let mut ptr = scalar_unit(Pointer); - ptr.valid_range.start = 1; + ptr.valid_range = 1..=*ptr.valid_range.end(); tcx.intern_layout(LayoutDetails::scalar(self, ptr)) } @@ -506,7 +505,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { ty::TyRawPtr(ty::TypeAndMut { ty: pointee, .. }) => { let mut data_ptr = scalar_unit(Pointer); if !ty.is_unsafe_ptr() { - data_ptr.valid_range.start = 1; + data_ptr.valid_range = 1..=*data_ptr.valid_range.end(); } let pointee = tcx.normalize_erasing_regions(param_env, pointee); @@ -524,7 +523,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { } ty::TyDynamic(..) => { let mut vtable = scalar_unit(Pointer); - vtable.valid_range.start = 1; + vtable.valid_range = 1..=*vtable.valid_range.end(); vtable } _ => return Err(LayoutError::Unknown(unsized_part)) @@ -751,8 +750,8 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { match st.abi { Abi::Scalar(ref mut scalar) | Abi::ScalarPair(ref mut scalar, _) => { - if scalar.valid_range.start == 0 { - scalar.valid_range.start = 1; + if *scalar.valid_range.start() == 0 { + scalar.valid_range = 1..=*scalar.valid_range.end(); } } _ => {} @@ -788,18 +787,15 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { } } } - if niche_variants.start > v { - niche_variants.start = v; - } - niche_variants.end = v; + niche_variants = *niche_variants.start().min(&v)..=v; } - if niche_variants.start > niche_variants.end { + if niche_variants.start() > niche_variants.end() { dataful_variant = None; } if let Some(i) = dataful_variant { - let count = (niche_variants.end - niche_variants.start + 1) as u128; + let count = (niche_variants.end() - niche_variants.start() + 1) as u128; for (field_index, &field) in variants[i].iter().enumerate() { let (offset, niche, niche_start) = match self.find_niche(field, count)? { @@ -1659,10 +1655,10 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { let max_value = !0u128 >> (128 - bits); // Find out how many values are outside the valid range. - let niches = if v.start <= v.end { - v.start + (max_value - v.end) + let niches = if v.start() <= v.end() { + v.start() + (max_value - v.end()) } else { - v.start - v.end - 1 + v.start() - v.end() - 1 }; // Give up if we can't fit `count` consecutive niches. @@ -1670,11 +1666,11 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { return None; } - let niche_start = v.end.wrapping_add(1) & max_value; - let niche_end = v.end.wrapping_add(count) & max_value; + let niche_start = v.end().wrapping_add(1) & max_value; + let niche_end = v.end().wrapping_add(count) & max_value; Some((offset, Scalar { value, - valid_range: v.start..=niche_end + valid_range: *v.start()..=niche_end }, niche_start)) }; @@ -1744,14 +1740,14 @@ impl<'a> HashStable> for Variants { } NicheFilling { dataful_variant, - niche_variants: RangeInclusive { start, end }, + ref niche_variants, ref niche, niche_start, ref variants, } => { dataful_variant.hash_stable(hcx, hasher); - start.hash_stable(hcx, hasher); - end.hash_stable(hcx, hasher); + niche_variants.start().hash_stable(hcx, hasher); + niche_variants.end().hash_stable(hcx, hasher); niche.hash_stable(hcx, hasher); niche_start.hash_stable(hcx, hasher); variants.hash_stable(hcx, hasher); @@ -1814,10 +1810,10 @@ impl<'a> HashStable> for Scalar { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - let Scalar { value, valid_range: RangeInclusive { start, end } } = *self; + let Scalar { value, ref valid_range } = *self; value.hash_stable(hcx, hasher); - start.hash_stable(hcx, hasher); - end.hash_stable(hcx, hasher); + valid_range.start().hash_stable(hcx, hasher); + valid_range.end().hash_stable(hcx, hasher); } } diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index f6e9994b5da..c8cebf8328d 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -917,8 +917,8 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M niche_start, .. } => { - let variants_start = niche_variants.start as u128; - let variants_end = niche_variants.end as u128; + let variants_start = *niche_variants.start() as u128; + let variants_end = *niche_variants.end() as u128; match raw_discr { PrimVal::Ptr(_) => { assert!(niche_start == 0); @@ -984,7 +984,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M if variant_index != dataful_variant { let (niche_dest, niche) = self.place_field(dest, mir::Field::new(0), layout)?; - let niche_value = ((variant_index - niche_variants.start) as u128) + let niche_value = ((variant_index - niche_variants.start()) as u128) .wrapping_add(niche_start); self.write_primval(niche_dest, PrimVal::Bytes(niche_value), niche.ty)?; } diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index 75b7a10097d..a6dc4c74f36 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -31,7 +31,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! #![feature(range_contains)] #![feature(rustc_diagnostic_macros)] #![feature(nonzero)] -#![feature(inclusive_range_fields)] +#![feature(inclusive_range_methods)] #![feature(crate_visibility_modifier)] #![feature(never_type)] #![cfg_attr(stage0, feature(try_trait))] diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index 346e5667a7b..f73085196f4 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -555,8 +555,8 @@ impl Scalar { let bits = self.value.size(cx).bits(); assert!(bits <= 128); let mask = !0u128 >> (128 - bits); - let start = self.valid_range.start; - let end = self.valid_range.end; + let start = *self.valid_range.start(); + let end = *self.valid_range.end(); assert_eq!(start, start & mask); assert_eq!(end, end & mask); start..(end.wrapping_add(1) & mask) diff --git a/src/librustc_target/lib.rs b/src/librustc_target/lib.rs index 927d5c7e15a..45f2ee13bbd 100644 --- a/src/librustc_target/lib.rs +++ b/src/librustc_target/lib.rs @@ -29,7 +29,7 @@ #![feature(const_fn)] #![feature(fs_read_write)] #![feature(inclusive_range)] -#![feature(inclusive_range_fields)] +#![feature(inclusive_range_methods)] #![feature(slice_patterns)] #[macro_use] diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs index 1d0d7ec601f..1838dae049a 100644 --- a/src/librustc_trans/abi.rs +++ b/src/librustc_trans/abi.rs @@ -388,8 +388,8 @@ impl<'a, 'tcx> FnTypeExt<'a, 'tcx> for FnType<'tcx, Ty<'tcx>> { return; } - if scalar.valid_range.start < scalar.valid_range.end { - if scalar.valid_range.start > 0 { + if scalar.valid_range.start() < scalar.valid_range.end() { + if *scalar.valid_range.start() > 0 { attrs.set(ArgAttribute::NonNull); } } diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index 123b9cf7931..2fc6c9d4433 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -1236,7 +1236,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> { self.layout, self.layout.fields.offset(0), self.layout.field(cx, 0).size); - name.push_str(&adt.variants[niche_variants.start].name.as_str()); + name.push_str(&adt.variants[*niche_variants.start()].name.as_str()); // Create the (singleton) list of descriptions of union members. vec![ diff --git a/src/librustc_trans/mir/place.rs b/src/librustc_trans/mir/place.rs index 8532c0b149d..79859aee64d 100644 --- a/src/librustc_trans/mir/place.rs +++ b/src/librustc_trans/mir/place.rs @@ -99,7 +99,7 @@ impl<'a, 'tcx> PlaceRef<'tcx> { bx.range_metadata(load, range); } } - layout::Pointer if vr.start < vr.end && !vr.contains(&0) => { + layout::Pointer if vr.start() < vr.end() && !vr.contains(&0) => { bx.nonnull_metadata(load); } _ => {} @@ -287,7 +287,7 @@ impl<'a, 'tcx> PlaceRef<'tcx> { .. } => { let niche_llty = discr.layout.immediate_llvm_type(bx.cx); - if niche_variants.start == niche_variants.end { + if niche_variants.start() == niche_variants.end() { // FIXME(eddyb) Check the actual primitive type here. let niche_llval = if niche_start == 0 { // HACK(eddyb) Using `C_null` as it works on all types. @@ -296,13 +296,13 @@ impl<'a, 'tcx> PlaceRef<'tcx> { C_uint_big(niche_llty, niche_start) }; bx.select(bx.icmp(llvm::IntEQ, lldiscr, niche_llval), - C_uint(cast_to, niche_variants.start as u64), + C_uint(cast_to, *niche_variants.start() as u64), C_uint(cast_to, dataful_variant as u64)) } else { // Rebase from niche values to discriminant values. - let delta = niche_start.wrapping_sub(niche_variants.start as u128); + let delta = niche_start.wrapping_sub(*niche_variants.start() as u128); let lldiscr = bx.sub(lldiscr, C_uint_big(niche_llty, delta)); - let lldiscr_max = C_uint(niche_llty, niche_variants.end as u64); + let lldiscr_max = C_uint(niche_llty, *niche_variants.end() as u64); bx.select(bx.icmp(llvm::IntULE, lldiscr, lldiscr_max), bx.intcast(lldiscr, cast_to, false), C_uint(cast_to, dataful_variant as u64)) @@ -352,7 +352,7 @@ impl<'a, 'tcx> PlaceRef<'tcx> { let niche = self.project_field(bx, 0); let niche_llty = niche.layout.immediate_llvm_type(bx.cx); - let niche_value = ((variant_index - niche_variants.start) as u128) + let niche_value = ((variant_index - *niche_variants.start()) as u128) .wrapping_add(niche_start); // FIXME(eddyb) Check the actual primitive type here. let niche_llval = if niche_value == 0 { diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index 79e906ca975..4fa54dc276d 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -301,7 +301,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { if let layout::Int(_, s) = scalar.value { signed = s; - if scalar.valid_range.end > scalar.valid_range.start { + if scalar.valid_range.end() > scalar.valid_range.start() { // We want `table[e as usize]` to not // have bound checks, and this is the most // convenient place to put the `assume`. @@ -309,7 +309,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { base::call_assume(&bx, bx.icmp( llvm::IntULE, llval, - C_uint_big(ll_t_in, scalar.valid_range.end) + C_uint_big(ll_t_in, *scalar.valid_range.end()) )); } } -- cgit 1.4.1-3-g733a5 From f70b2ebd08f47c504681ca5f62c3ccdacdd69763 Mon Sep 17 00:00:00 2001 From: kennytm Date: Sat, 7 Apr 2018 14:19:34 +0800 Subject: new() should be const; start()/end() after iteration is unspecified. --- src/libcore/ops/range.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs index 59ee40fdda4..b01a769eda7 100644 --- a/src/libcore/ops/range.rs +++ b/src/libcore/ops/range.rs @@ -362,12 +362,20 @@ impl RangeInclusive { /// ``` #[unstable(feature = "inclusive_range_methods", issue = "49022")] #[inline] - pub fn new(start: Idx, end: Idx) -> Self { + pub const fn new(start: Idx, end: Idx) -> Self { Self { start, end } } /// Returns the lower bound of the range (inclusive). /// + /// When using an inclusive range for iteration, the values of `start()` and + /// [`end()`] are unspecified after the iteration ended. To determine + /// whether the inclusive range is empty, use the [`is_empty()`] method + /// instead of comparing `start() > end()`. + /// + /// [`end()`]: #method.end + /// [`is_empty()`]: #method.is_empty + /// /// # Examples /// /// ``` @@ -383,6 +391,14 @@ impl RangeInclusive { /// Returns the upper bound of the range (inclusive). /// + /// When using an inclusive range for iteration, the values of [`start()`] + /// and `end()` are unspecified after the iteration ended. To determine + /// whether the inclusive range is empty, use the [`is_empty()`] method + /// instead of comparing `start() > end()`. + /// + /// [`start()`]: #method.start + /// [`is_empty()`]: #method.is_empty + /// /// # Examples /// /// ``` -- cgit 1.4.1-3-g733a5 From 69400751ab4ae903244aff95e088df8fcefe409c Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 4 Apr 2018 17:21:50 -0400 Subject: make needs_infer specific to inference variables Notably, excluding ReSkolemized --- src/librustc/traits/project.rs | 2 +- src/librustc/traits/query/normalize.rs | 2 +- src/librustc/ty/context.rs | 11 +++++++---- src/librustc/ty/fold.rs | 3 +++ src/librustc/ty/mod.rs | 6 +++++- src/librustc/ty/sty.rs | 1 - src/librustc_typeck/check/method/probe.rs | 5 ++++- src/librustc_typeck/check/writeback.rs | 4 ++-- 8 files changed, 23 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 0c35e20324c..1f1fdfafe33 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -409,7 +409,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a, if let ConstVal::Unevaluated(def_id, substs) = constant.val { let tcx = self.selcx.tcx().global_tcx(); if let Some(param_env) = self.tcx().lift_to_global(&self.param_env) { - if substs.needs_infer() { + if substs.needs_infer() || substs.has_skol() { let identity_substs = Substs::identity_for_item(tcx, def_id); let instance = ty::Instance::resolve(tcx, param_env, def_id, identity_substs); if let Some(instance) = instance { diff --git a/src/librustc/traits/query/normalize.rs b/src/librustc/traits/query/normalize.rs index 5e0a4ca3305..f074e061653 100644 --- a/src/librustc/traits/query/normalize.rs +++ b/src/librustc/traits/query/normalize.rs @@ -196,7 +196,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx if let ConstVal::Unevaluated(def_id, substs) = constant.val { let tcx = self.infcx.tcx.global_tcx(); if let Some(param_env) = self.tcx().lift_to_global(&self.param_env) { - if substs.needs_infer() { + if substs.needs_infer() || substs.has_skol() { let identity_substs = Substs::identity_for_item(tcx, def_id); let instance = ty::Instance::resolve(tcx, param_env, def_id, identity_substs); if let Some(instance) = instance { diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index c28fcfe8805..1f95bbfa9ac 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -2119,7 +2119,7 @@ macro_rules! intern_method { $alloc_method:ident, $alloc_to_key:expr, $alloc_to_ret:expr, - $needs_infer:expr) -> $ty:ty) => { + $keep_in_local_tcx:expr) -> $ty:ty) => { impl<'a, 'gcx, $lt_tcx> TyCtxt<'a, 'gcx, $lt_tcx> { pub fn $method(self, v: $alloc) -> &$lt_tcx $ty { { @@ -2137,7 +2137,7 @@ macro_rules! intern_method { // HACK(eddyb) Depend on flags being accurate to // determine that all contents are in the global tcx. // See comments on Lift for why we can't use that. - if !($needs_infer)(&v) { + if !($keep_in_local_tcx)(&v) { if !self.is_global() { let v = unsafe { mem::transmute(v) @@ -2165,7 +2165,7 @@ macro_rules! intern_method { } macro_rules! direct_interners { - ($lt_tcx:tt, $($name:ident: $method:ident($needs_infer:expr) -> $ty:ty),+) => { + ($lt_tcx:tt, $($name:ident: $method:ident($keep_in_local_tcx:expr) -> $ty:ty),+) => { $(impl<$lt_tcx> PartialEq for Interned<$lt_tcx, $ty> { fn eq(&self, other: &Self) -> bool { self.0 == other.0 @@ -2180,7 +2180,10 @@ macro_rules! direct_interners { } } - intern_method!($lt_tcx, $name: $method($ty, alloc, |x| x, |x| x, $needs_infer) -> $ty);)+ + intern_method!( + $lt_tcx, + $name: $method($ty, alloc, |x| x, |x| x, $keep_in_local_tcx) -> $ty + );)+ } } diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 3d0f2de57bf..1793b5e1edb 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -91,6 +91,9 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { fn needs_infer(&self) -> bool { self.has_type_flags(TypeFlags::HAS_TY_INFER | TypeFlags::HAS_RE_INFER) } + fn has_skol(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_RE_SKOL) + } fn needs_subst(&self) -> bool { self.has_type_flags(TypeFlags::NEEDS_SUBST) } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 5a121d3edbe..4fdc247686f 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1476,7 +1476,11 @@ impl<'tcx> ParamEnv<'tcx> { } Reveal::All => { - if value.needs_infer() || value.has_param_types() || value.has_self_ty() { + if value.has_skol() + || value.needs_infer() + || value.has_param_types() + || value.has_self_ty() + { ParamEnvAnd { param_env: self, value, diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 936dbb1ccb8..8348df38fb9 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1199,7 +1199,6 @@ impl RegionKind { } ty::ReSkolemized(..) => { flags = flags | TypeFlags::HAS_FREE_REGIONS; - flags = flags | TypeFlags::HAS_RE_INFER; flags = flags | TypeFlags::HAS_RE_SKOL; flags = flags | TypeFlags::KEEP_IN_LOCAL_TCX; } diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 476ae680973..907c80f0daf 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -1485,7 +1485,10 @@ impl<'tcx> Candidate<'tcx> { // inference variables or other artifacts. This // means they are safe to put into the // `WhereClausePick`. - assert!(!trait_ref.skip_binder().substs.needs_infer()); + assert!( + !trait_ref.skip_binder().substs.needs_infer() + && !trait_ref.skip_binder().substs.has_skol() + ); WhereClausePick(trait_ref.clone()) } diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 6e0d7dd8508..802e5375b6b 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -107,7 +107,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { fn write_ty_to_tables(&mut self, hir_id: hir::HirId, ty: Ty<'gcx>) { debug!("write_ty_to_tables({:?}, {:?})", hir_id, ty); - assert!(!ty.needs_infer()); + assert!(!ty.needs_infer() && !ty.has_skol()); self.tables.node_types_mut().insert(hir_id, ty); } @@ -431,7 +431,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { if let Some(substs) = self.fcx.tables.borrow().node_substs_opt(hir_id) { let substs = self.resolve(&substs, &span); debug!("write_substs_to_tcx({:?}, {:?})", hir_id, substs); - assert!(!substs.needs_infer()); + assert!(!substs.needs_infer() && !substs.has_skol()); self.tables.node_substs_mut().insert(hir_id, substs); } } -- cgit 1.4.1-3-g733a5 From 149ab1bc39c148fc48394df1ba328c3a5eeca8d8 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 4 Apr 2018 18:24:17 -0400 Subject: put ReSkolemized into the global tcx --- src/librustc/ty/context.rs | 7 +------ src/librustc/ty/sty.rs | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 1f95bbfa9ac..ce4439e7c54 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -2192,12 +2192,7 @@ pub fn keep_local<'tcx, T: ty::TypeFoldable<'tcx>>(x: &T) -> bool { } direct_interners!('tcx, - region: mk_region(|r| { - match r { - &ty::ReVar(_) | &ty::ReSkolemized(..) => true, - _ => false - } - }) -> RegionKind, + region: mk_region(|r: &RegionKind| r.keep_in_local_tcx()) -> RegionKind, const_: mk_const(|c: &Const| keep_local(&c.ty) || keep_local(&c.val)) -> Const<'tcx> ); diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 8348df38fb9..0d655562214 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1188,19 +1188,29 @@ impl RegionKind { } } + pub fn keep_in_local_tcx(&self) -> bool { + if let ty::ReVar(..) = self { + true + } else { + false + } + } + pub fn type_flags(&self) -> TypeFlags { let mut flags = TypeFlags::empty(); + if self.keep_in_local_tcx() { + flags = flags | TypeFlags::KEEP_IN_LOCAL_TCX; + } + match *self { ty::ReVar(..) => { flags = flags | TypeFlags::HAS_FREE_REGIONS; flags = flags | TypeFlags::HAS_RE_INFER; - flags = flags | TypeFlags::KEEP_IN_LOCAL_TCX; } ty::ReSkolemized(..) => { flags = flags | TypeFlags::HAS_FREE_REGIONS; flags = flags | TypeFlags::HAS_RE_SKOL; - flags = flags | TypeFlags::KEEP_IN_LOCAL_TCX; } ty::ReLateBound(..) => { } ty::ReEarlyBound(..) => { -- cgit 1.4.1-3-g733a5 From 135ee85abac2ffbff2f55725fccea5fbc3be9f38 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 30 Apr 2018 22:32:17 +0200 Subject: Rename "show type declaration" to "show declaration" --- src/librustdoc/html/static/main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index bcad2eb19f5..6d80145b29c 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -1996,7 +1996,7 @@ if (e.parentNode.id === "main") { var otherMessage; if (hasClass(e, "type-decl")) { - otherMessage = ' Show type declaration'; + otherMessage = ' Show declaration'; } e.parentNode.insertBefore(createToggle(otherMessage), e); if (otherMessage && getCurrentValue('rustdoc-item-declarations') !== "false") { -- cgit 1.4.1-3-g733a5 From 428ef191e0ff3a26bb571efcdc6d7221c2ded07b Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 30 Apr 2018 02:20:14 +0300 Subject: resolve (cleanup): Get rid of `Option` in `PerNS` --- src/librustc_resolve/build_reduced_graph.rs | 8 ++++++-- src/librustc_resolve/lib.rs | 21 +++++++++------------ 2 files changed, 15 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 14ceb5f59a3..f4a5ace69dd 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -17,7 +17,7 @@ use macros::{InvocationData, LegacyScope}; use resolve_imports::ImportDirective; use resolve_imports::ImportDirectiveSubclass::{self, GlobImport, SingleImport}; use {Module, ModuleData, ModuleKind, NameBinding, NameBindingKind, ToNameBinding}; -use {Resolver, ResolverArenas}; +use {PerNS, Resolver, ResolverArenas}; use Namespace::{self, TypeNS, ValueNS, MacroNS}; use {resolve_error, resolve_struct_error, ResolutionError}; @@ -175,7 +175,11 @@ impl<'a> Resolver<'a> { let subclass = SingleImport { target: ident, source, - result: self.per_ns(|_, _| Cell::new(Err(Undetermined))), + result: PerNS { + type_ns: Cell::new(Err(Undetermined)), + value_ns: Cell::new(Err(Undetermined)), + macro_ns: Cell::new(Err(Undetermined)), + }, type_ns_only, }; self.add_import_directive( diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 127331152c1..cb8c38b92b5 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -700,7 +700,7 @@ pub enum Namespace { pub struct PerNS { value_ns: T, type_ns: T, - macro_ns: Option, + macro_ns: T, } impl ::std::ops::Index for PerNS { @@ -709,7 +709,7 @@ impl ::std::ops::Index for PerNS { match ns { ValueNS => &self.value_ns, TypeNS => &self.type_ns, - MacroNS => self.macro_ns.as_ref().unwrap(), + MacroNS => &self.macro_ns, } } } @@ -719,7 +719,7 @@ impl ::std::ops::IndexMut for PerNS { match ns { ValueNS => &mut self.value_ns, TypeNS => &mut self.type_ns, - MacroNS => self.macro_ns.as_mut().unwrap(), + MacroNS => &mut self.macro_ns, } } } @@ -1726,7 +1726,7 @@ impl<'a> Resolver<'a> { ribs: PerNS { value_ns: vec![Rib::new(ModuleRibKind(graph_root))], type_ns: vec![Rib::new(ModuleRibKind(graph_root))], - macro_ns: Some(vec![Rib::new(ModuleRibKind(graph_root))]), + macro_ns: vec![Rib::new(ModuleRibKind(graph_root))], }, label_ribs: Vec::new(), @@ -1806,14 +1806,11 @@ impl<'a> Resolver<'a> { } /// Runs the function on each namespace. - fn per_ns T>(&mut self, mut f: F) -> PerNS { - PerNS { - type_ns: f(self, TypeNS), - value_ns: f(self, ValueNS), - macro_ns: match self.use_extern_macros { - true => Some(f(self, MacroNS)), - false => None, - }, + fn per_ns(&mut self, mut f: F) { + f(self, TypeNS); + f(self, ValueNS); + if self.use_extern_macros { + f(self, MacroNS); } } -- cgit 1.4.1-3-g733a5 From d5e31158a204aaa8ddc46bd8b9f44a4770db5c4d Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 1 May 2018 03:12:36 +0300 Subject: Better support for import resolution in 3 namespaces --- src/librustc_resolve/resolve_imports.rs | 80 ++++++++++++++++++++++++--------- src/test/ui/issue-50187.rs | 49 ++++++++++++++++++++ 2 files changed, 107 insertions(+), 22 deletions(-) create mode 100644 src/test/ui/issue-50187.rs (limited to 'src') diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index e2a7f5668d2..17aa510b565 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -33,7 +33,7 @@ use syntax::util::lev_distance::find_best_match_for_name; use syntax_pos::Span; use std::cell::{Cell, RefCell}; -use std::mem; +use std::{mem, ptr}; /// Contains data for specific types of import directives. #[derive(Clone, Debug)] @@ -89,6 +89,8 @@ enum SingleImports<'a> { None, /// Only the given single import can define the name in the namespace. MaybeOne(&'a ImportDirective<'a>), + /// Only one of these two single imports can define the name in the namespace. + MaybeTwo(&'a ImportDirective<'a>, &'a ImportDirective<'a>), /// At least one single import will define the name in the namespace. AtLeastOne, } @@ -101,21 +103,28 @@ impl<'a> Default for SingleImports<'a> { } impl<'a> SingleImports<'a> { - fn add_directive(&mut self, directive: &'a ImportDirective<'a>) { + fn add_directive(&mut self, directive: &'a ImportDirective<'a>, use_extern_macros: bool) { match *self { SingleImports::None => *self = SingleImports::MaybeOne(directive), - // If two single imports can define the name in the namespace, we can assume that at - // least one of them will define it since otherwise both would have to define only one - // namespace, leading to a duplicate error. - SingleImports::MaybeOne(_) => *self = SingleImports::AtLeastOne, + SingleImports::MaybeOne(directive_one) => *self = if use_extern_macros { + SingleImports::MaybeTwo(directive_one, directive) + } else { + SingleImports::AtLeastOne + }, + // If three single imports can define the name in the namespace, we can assume that at + // least one of them will define it since otherwise we'd get duplicate errors in one of + // other namespaces. + SingleImports::MaybeTwo(..) => *self = SingleImports::AtLeastOne, SingleImports::AtLeastOne => {} }; } - fn directive_failed(&mut self) { + fn directive_failed(&mut self, dir: &'a ImportDirective<'a>) { match *self { SingleImports::None => unreachable!(), SingleImports::MaybeOne(_) => *self = SingleImports::None, + SingleImports::MaybeTwo(dir1, dir2) => + *self = SingleImports::MaybeOne(if ptr::eq(dir1, dir) { dir1 } else { dir2 }), SingleImports::AtLeastOne => {} } } @@ -199,23 +208,50 @@ impl<'a> Resolver<'a> { } // Check if a single import can still define the name. + let resolve_single_import = |this: &mut Self, directive: &'a ImportDirective<'a>| { + let module = match directive.imported_module.get() { + Some(module) => module, + None => return false, + }; + let ident = match directive.subclass { + SingleImport { source, .. } => source, + _ => unreachable!(), + }; + match this.resolve_ident_in_module(module, ident, ns, false, false, path_span) { + Err(Determined) => {} + _ => return false, + } + true + }; match resolution.single_imports { SingleImports::AtLeastOne => return Err(Undetermined), - SingleImports::MaybeOne(directive) if self.is_accessible(directive.vis.get()) => { - let module = match directive.imported_module.get() { - Some(module) => module, - None => return Err(Undetermined), - }; - let ident = match directive.subclass { - SingleImport { source, .. } => source, - _ => unreachable!(), - }; - match self.resolve_ident_in_module(module, ident, ns, false, false, path_span) { - Err(Determined) => {} - _ => return Err(Undetermined), + SingleImports::MaybeOne(directive) => { + let accessible = self.is_accessible(directive.vis.get()); + if accessible { + if !resolve_single_import(self, directive) { + return Err(Undetermined) + } + } + } + SingleImports::MaybeTwo(directive1, directive2) => { + let accessible1 = self.is_accessible(directive1.vis.get()); + let accessible2 = self.is_accessible(directive2.vis.get()); + if accessible1 && accessible2 { + if !resolve_single_import(self, directive1) && + !resolve_single_import(self, directive2) { + return Err(Undetermined) + } + } else if accessible1 { + if !resolve_single_import(self, directive1) { + return Err(Undetermined) + } + } else { + if !resolve_single_import(self, directive2) { + return Err(Undetermined) + } } } - SingleImports::MaybeOne(_) | SingleImports::None => {}, + SingleImports::None => {}, } let no_unresolved_invocations = @@ -281,7 +317,7 @@ impl<'a> Resolver<'a> { SingleImport { target, .. } => { self.per_ns(|this, ns| { let mut resolution = this.resolution(current_module, target, ns).borrow_mut(); - resolution.single_imports.add_directive(directive); + resolution.single_imports.add_directive(directive, this.use_extern_macros); }); } // We don't add prelude imports to the globs since they only affect lexical scopes, @@ -575,7 +611,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { Err(Undetermined) => indeterminate = true, Err(Determined) => { this.update_resolution(parent, target, ns, |_, resolution| { - resolution.single_imports.directive_failed() + resolution.single_imports.directive_failed(directive) }); } Ok(binding) if !binding.is_importable() => { diff --git a/src/test/ui/issue-50187.rs b/src/test/ui/issue-50187.rs new file mode 100644 index 00000000000..87acf106393 --- /dev/null +++ b/src/test/ui/issue-50187.rs @@ -0,0 +1,49 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-pass + +#![feature(use_extern_macros, decl_macro)] + +mod type_ns { + pub type A = u8; +} +mod value_ns { + pub const A: u8 = 0; +} +mod macro_ns { + pub macro A() {} +} + +mod merge2 { + pub use type_ns::A; + pub use value_ns::A; +} +mod merge3 { + pub use type_ns::A; + pub use value_ns::A; + pub use macro_ns::A; +} + +mod use2 { + pub use merge2::A; +} +mod use3 { + pub use merge3::A; +} + +fn main() { + type B2 = use2::A; + let a2 = use2::A; + + type B3 = use3::A; + let a3 = use3::A; + use3::A!(); +} -- cgit 1.4.1-3-g733a5 From aad9840ad49c56830384e87bc8bd87fd0199dc44 Mon Sep 17 00:00:00 2001 From: John Kåre Alsaker Date: Tue, 20 Mar 2018 01:18:08 +0100 Subject: Set opt-level to 3 --- src/Cargo.toml | 8 -------- 1 file changed, 8 deletions(-) (limited to 'src') diff --git a/src/Cargo.toml b/src/Cargo.toml index 814c054c51e..35858ee2868 100644 --- a/src/Cargo.toml +++ b/src/Cargo.toml @@ -40,14 +40,6 @@ members = [ "tools/rls/test_data/workspace_symbol", ] -# Curiously, compiletest will segfault if compiled with opt-level=3 on 64-bit -# MSVC when running the compile-fail test suite when a should-fail test panics. -# But hey if this is removed and it gets past the bots, sounds good to me. -[profile.release] -opt-level = 2 -[profile.bench] -opt-level = 2 - # These options are controlled from our rustc wrapper script, so turn them off # here and have them controlled elsewhere. [profile.dev] -- cgit 1.4.1-3-g733a5 From 5b800c231f45fcd823a3e958bb942cd620ceb3e0 Mon Sep 17 00:00:00 2001 From: Björn Steinbrink Date: Wed, 3 Jan 2018 10:29:27 +0100 Subject: Don't force-enable frame pointers when generating debug info We apparently used to generate bad/incomplete debug info causing debuggers not to find symbols of stack allocated variables. This was somehow worked around by having frame pointers. With the current codegen, this seems no longer necessary, so we can remove the code that force-enables frame pointers whenever debug info is requested. Since certain situations, like profiling code profit from having frame pointers, we add a -Cforce-frame-pointers flag to always enable frame pointers. Fixes #11906 --- src/librustc/session/config.rs | 6 ++++++ src/librustc/session/mod.rs | 2 +- src/librustc_trans/attributes.rs | 2 -- src/test/codegen/force-frame-pointers.rs | 16 ++++++++++++++++ 4 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 src/test/codegen/force-frame-pointers.rs (limited to 'src') diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 06922d986b3..023be789222 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1053,6 +1053,8 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, 2 = full debug info with variable and type information"), opt_level: Option = (None, parse_opt_string, [TRACKED], "optimize with possible levels 0-3, s, or z"), + force_frame_pointers: bool = (false, parse_bool, [TRACKED], + "force frame pointers to be used"), debug_assertions: Option = (None, parse_opt_bool, [TRACKED], "explicitly enable the cfg(debug_assertions) directive"), inline_threshold: Option = (None, parse_opt_uint, [TRACKED], @@ -2965,6 +2967,10 @@ mod tests { opts.cg.debuginfo = Some(0xba5eba11); assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + opts = reference.clone(); + opts.cg.force_frame_pointers = true; + assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); + opts = reference.clone(); opts.cg.debug_assertions = Some(true); assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 37a6b2e79f7..45b7e2d1740 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -20,7 +20,7 @@ use lint::builtin::BuiltinLintDiagnostics; use middle::allocator::AllocatorKind; use middle::dependency_format; use session::search_paths::PathKind; -use session::config::{DebugInfoLevel, OutputType}; +use session::config::{OutputType}; use ty::tls; use util::nodemap::{FxHashSet}; use util::common::{duration_to_secs_str, ErrorReported}; diff --git a/src/librustc_trans/attributes.rs b/src/librustc_trans/attributes.rs index f455c19cc0b..5baed57092d 100644 --- a/src/librustc_trans/attributes.rs +++ b/src/librustc_trans/attributes.rs @@ -69,8 +69,6 @@ pub fn naked(val: ValueRef, is_naked: bool) { } pub fn set_frame_pointer_elimination(cx: &CodegenCx, llfn: ValueRef) { - // FIXME: #11906: Omitting frame pointers breaks retrieving the value of a - // parameter. if cx.sess().must_not_eliminate_frame_pointers() { llvm::AddFunctionAttrStringValue( llfn, llvm::AttributePlace::Function, diff --git a/src/test/codegen/force-frame-pointers.rs b/src/test/codegen/force-frame-pointers.rs new file mode 100644 index 00000000000..d40406a0476 --- /dev/null +++ b/src/test/codegen/force-frame-pointers.rs @@ -0,0 +1,16 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +// +// compile-flags: -C no-prepopulate-passes -C force-frame-pointers + +#![crate_type="lib"] + +// CHECK: attributes #{{.*}} "no-frame-pointer-elim"="true" +pub fn foo() {} -- cgit 1.4.1-3-g733a5 From 09d2db4e963c6696f7c22386b6791e419ad75cfb Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Tue, 6 Mar 2018 20:27:19 +0200 Subject: Rework force-frame-pointer This reworks the force-frame-pointer PR to explicitly only consider the value of the flag if it is provided, and use a target default otherwise. Something that was tried but not kept was renaming the flag to `frame-pointer`, because for flag `frame-pointer=no`, there is no guarante, that LLVM will elide *all* the frame pointers; oposite of what the literal reading of the flag would suggest. --- src/librustc/session/config.rs | 6 +++--- src/librustc/session/mod.rs | 7 +++++-- src/test/codegen/force-frame-pointers.rs | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 023be789222..59b40e9e2dc 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1053,8 +1053,8 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, 2 = full debug info with variable and type information"), opt_level: Option = (None, parse_opt_string, [TRACKED], "optimize with possible levels 0-3, s, or z"), - force_frame_pointers: bool = (false, parse_bool, [TRACKED], - "force frame pointers to be used"), + force_frame_pointers: Option = (None, parse_opt_bool, [TRACKED], + "force use of the frame pointers"), debug_assertions: Option = (None, parse_opt_bool, [TRACKED], "explicitly enable the cfg(debug_assertions) directive"), inline_threshold: Option = (None, parse_opt_uint, [TRACKED], @@ -2968,7 +2968,7 @@ mod tests { assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); opts = reference.clone(); - opts.cg.force_frame_pointers = true; + opts.cg.force_frame_pointers = Some(false); assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash()); opts = reference.clone(); diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 45b7e2d1740..2ab72ba20bf 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -658,8 +658,11 @@ impl Session { } pub fn must_not_eliminate_frame_pointers(&self) -> bool { - self.opts.debuginfo != DebugInfoLevel::NoDebugInfo - || !self.target.target.options.eliminate_frame_pointer + if let Some(x) = self.opts.cg.force_frame_pointers { + x + } else { + !self.target.target.options.eliminate_frame_pointer + } } /// Returns the symbol name for the registrar function, diff --git a/src/test/codegen/force-frame-pointers.rs b/src/test/codegen/force-frame-pointers.rs index d40406a0476..f70e3667198 100644 --- a/src/test/codegen/force-frame-pointers.rs +++ b/src/test/codegen/force-frame-pointers.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. // -// compile-flags: -C no-prepopulate-passes -C force-frame-pointers +// compile-flags: -C no-prepopulate-passes -C force-frame-pointers=y #![crate_type="lib"] -- cgit 1.4.1-3-g733a5 From 969449f236bf8fe47b5bc90d4f02a3db00a80643 Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Sat, 24 Mar 2018 21:54:21 +0200 Subject: Don’t eliminate frame pointers on apple by default MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/librustc_target/spec/apple_ios_base.rs | 1 + src/librustc_target/spec/i686_apple_darwin.rs | 1 + 2 files changed, 2 insertions(+) (limited to 'src') diff --git a/src/librustc_target/spec/apple_ios_base.rs b/src/librustc_target/spec/apple_ios_base.rs index acbbab313fe..46bb01e7c42 100644 --- a/src/librustc_target/spec/apple_ios_base.rs +++ b/src/librustc_target/spec/apple_ios_base.rs @@ -98,6 +98,7 @@ pub fn opts(arch: Arch) -> Result { executables: true, pre_link_args, has_elf_tls: false, + eliminate_frame_pointer: false, // The following line is a workaround for jemalloc 4.5 being broken on // ios. jemalloc 5.0 is supposed to fix this. // see https://github.com/rust-lang/rust/issues/45262 diff --git a/src/librustc_target/spec/i686_apple_darwin.rs b/src/librustc_target/spec/i686_apple_darwin.rs index 06ea1e4649b..d17789dfcc0 100644 --- a/src/librustc_target/spec/i686_apple_darwin.rs +++ b/src/librustc_target/spec/i686_apple_darwin.rs @@ -16,6 +16,7 @@ pub fn target() -> TargetResult { base.max_atomic_width = Some(64); base.pre_link_args.insert(LinkerFlavor::Gcc, vec!["-m32".to_string()]); base.stack_probes = true; + base.eliminate_frame_pointer = false; Ok(Target { llvm_target: "i686-apple-darwin".to_string(), -- cgit 1.4.1-3-g733a5 From 7ec045219040876730693543e6cca53120a3236b Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Wed, 18 Apr 2018 20:48:34 +0300 Subject: Force frame pointers for the backtrace test --- src/test/run-pass/backtrace-debuginfo.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/test/run-pass/backtrace-debuginfo.rs b/src/test/run-pass/backtrace-debuginfo.rs index 2b82a894363..7bcb4e5ec2d 100644 --- a/src/test/run-pass/backtrace-debuginfo.rs +++ b/src/test/run-pass/backtrace-debuginfo.rs @@ -16,6 +16,7 @@ // "enable" to 0 instead. // compile-flags:-g -Cllvm-args=-enable-tail-merge=0 -Cllvm-args=-opt-bisect-limit=0 +// compile-flags:-Cforce-frame-pointers=yes // ignore-pretty issue #37195 // ignore-cloudabi spawning processes is not supported // ignore-emscripten spawning processes is not supported -- cgit 1.4.1-3-g733a5 From a78028d742e80002feca0be67a5f4f8ce183c82b Mon Sep 17 00:00:00 2001 From: kennytm Date: Tue, 1 May 2018 16:52:03 +0800 Subject: Clarify wordings of the `unstable_name_collision` lint. Stabilizing an inherent method may cause change in behavior instead of inference error. Updated to use the wording from [varkor's comment]. Closes #50232. [varkor's comment]: https://github.com/rust-lang/rust/issues/50232#issuecomment-384678097 --- src/librustc/lint/mod.rs | 2 +- src/test/ui/inference_unstable.rs | 2 +- src/test/ui/inference_unstable.stderr | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 0d4fd99995f..d6c6f9dc0f6 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -507,7 +507,7 @@ pub fn struct_lint_level<'a>(sess: &'a Session, let explanation = if lint_id == LintId::of(::lint::builtin::UNSTABLE_NAME_COLLISION) { "once this method is added to the standard library, \ - there will be ambiguity here, which will cause a hard error!" + the ambiguity may cause an error or change in behavior!" .to_owned() } else if let Some(edition) = future_incompatible.edition { format!("{} in the {} edition!", STANDARD_MESSAGE, edition) diff --git a/src/test/ui/inference_unstable.rs b/src/test/ui/inference_unstable.rs index 816c443a06c..5a70dffd4c8 100644 --- a/src/test/ui/inference_unstable.rs +++ b/src/test/ui/inference_unstable.rs @@ -25,5 +25,5 @@ use inference_unstable_itertools::IpuItertools; fn main() { assert_eq!('x'.ipu_flatten(), 1); //~^ WARN a method with this name may be added to the standard library in the future - //~^^ WARN once this method is added to the standard library, there will be ambiguity here + //~^^ WARN once this method is added to the standard library, the ambiguity may cause an error } diff --git a/src/test/ui/inference_unstable.stderr b/src/test/ui/inference_unstable.stderr index 9c614d659d3..a217bc57b36 100644 --- a/src/test/ui/inference_unstable.stderr +++ b/src/test/ui/inference_unstable.stderr @@ -5,7 +5,7 @@ LL | assert_eq!('x'.ipu_flatten(), 1); | ^^^^^^^^^^^ | = note: #[warn(unstable_name_collision)] on by default - = warning: once this method is added to the standard library, there will be ambiguity here, which will cause a hard error! + = warning: once this method is added to the standard library, the ambiguity may cause an error or change in behavior! = note: for more information, see issue #48919 = help: call with fully qualified syntax `inference_unstable_itertools::IpuItertools::ipu_flatten(...)` to keep using the current method = note: add #![feature(ipu_flatten)] to the crate attributes to enable `inference_unstable_iterator::IpuIterator::ipu_flatten` -- cgit 1.4.1-3-g733a5 From f0f26b875a1ae3c5d7aad4ce865bf311169cc2a9 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 27 Apr 2018 14:02:09 +0300 Subject: rustc: return impl Iterator from Terminator(Kind)::successors(_mut). --- src/librustc/mir/cache.rs | 2 +- src/librustc/mir/mod.rs | 128 +++++++++++---------- src/librustc/mir/traversal.rs | 16 +-- .../borrow_check/nll/explain_borrow/mod.rs | 1 - .../borrow_check/nll/region_infer/dfs.rs | 1 - src/librustc_mir/dataflow/graphviz.rs | 6 +- src/librustc_mir/transform/inline.rs | 2 +- .../transform/remove_noop_landing_pads.rs | 2 +- src/librustc_mir/transform/simplify.rs | 10 +- src/librustc_mir/util/graphviz.rs | 2 +- src/librustc_mir/util/liveness.rs | 2 +- src/librustc_trans/mir/analyze.rs | 2 +- 12 files changed, 85 insertions(+), 89 deletions(-) (limited to 'src') diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs index 1ed5a22257c..41ba526b73f 100644 --- a/src/librustc/mir/cache.rs +++ b/src/librustc/mir/cache.rs @@ -68,7 +68,7 @@ fn calculate_predecessors(mir: &Mir) -> IndexVec> { let mut result = IndexVec::from_elem(vec![], mir.basic_blocks()); for (bb, data) in mir.basic_blocks().iter_enumerated() { if let Some(ref term) = data.terminator { - for &tgt in term.successors().iter() { + for &tgt in term.successors() { result[tgt].push(bb); } } diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index c26b3014e53..f1bb7ccbd4c 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -37,7 +37,7 @@ use hir::{self, InlineAsm}; use std::borrow::{Cow}; use rustc_data_structures::sync::ReadGuard; use std::fmt::{self, Debug, Formatter, Write}; -use std::{iter, mem, u32}; +use std::{iter, mem, option, u32}; use std::ops::{Index, IndexMut}; use std::vec::IntoIter; use syntax::ast::{self, Name}; @@ -859,12 +859,17 @@ pub enum TerminatorKind<'tcx> { }, } +pub type Successors<'a> = + iter::Chain, slice::Iter<'a, BasicBlock>>; +pub type SuccessorsMut<'a> = + iter::Chain, slice::IterMut<'a, BasicBlock>>; + impl<'tcx> Terminator<'tcx> { - pub fn successors(&self) -> Cow<[BasicBlock]> { + pub fn successors(&self) -> Successors { self.kind.successors() } - pub fn successors_mut(&mut self) -> Vec<&mut BasicBlock> { + pub fn successors_mut(&mut self) -> SuccessorsMut { self.kind.successors_mut() } @@ -885,72 +890,71 @@ impl<'tcx> TerminatorKind<'tcx> { } } - pub fn successors(&self) -> Cow<[BasicBlock]> { + pub fn successors(&self) -> Successors { use self::TerminatorKind::*; match *self { - Goto { target: ref b } => slice::from_ref(b).into_cow(), - SwitchInt { targets: ref b, .. } => b[..].into_cow(), - Resume | Abort | GeneratorDrop => (&[]).into_cow(), - Return => (&[]).into_cow(), - Unreachable => (&[]).into_cow(), - Call { destination: Some((_, t)), cleanup: Some(c), .. } => vec![t, c].into_cow(), - Call { destination: Some((_, ref t)), cleanup: None, .. } => - slice::from_ref(t).into_cow(), - Call { destination: None, cleanup: Some(ref c), .. } => slice::from_ref(c).into_cow(), - Call { destination: None, cleanup: None, .. } => (&[]).into_cow(), - Yield { resume: t, drop: Some(c), .. } => vec![t, c].into_cow(), - Yield { resume: ref t, drop: None, .. } => slice::from_ref(t).into_cow(), - DropAndReplace { target, unwind: Some(unwind), .. } | - Drop { target, unwind: Some(unwind), .. } => { - vec![target, unwind].into_cow() + Resume | Abort | GeneratorDrop | Return | Unreachable | + Call { destination: None, cleanup: None, .. } => { + None.into_iter().chain(&[]) + } + Goto { target: ref t } | + Call { destination: None, cleanup: Some(ref t), .. } | + Call { destination: Some((_, ref t)), cleanup: None, .. } | + Yield { resume: ref t, drop: None, .. } | + DropAndReplace { target: ref t, unwind: None, .. } | + Drop { target: ref t, unwind: None, .. } | + Assert { target: ref t, cleanup: None, .. } | + FalseUnwind { real_target: ref t, unwind: None } => { + Some(t).into_iter().chain(&[]) } - DropAndReplace { ref target, unwind: None, .. } | - Drop { ref target, unwind: None, .. } => { - slice::from_ref(target).into_cow() + Call { destination: Some((_, ref t)), cleanup: Some(ref u), .. } | + Yield { resume: ref t, drop: Some(ref u), .. } | + DropAndReplace { target: ref t, unwind: Some(ref u), .. } | + Drop { target: ref t, unwind: Some(ref u), .. } | + Assert { target: ref t, cleanup: Some(ref u), .. } | + FalseUnwind { real_target: ref t, unwind: Some(ref u) } => { + Some(t).into_iter().chain(slice::from_ref(u)) + } + SwitchInt { ref targets, .. } => { + None.into_iter().chain(&targets[..]) } - Assert { target, cleanup: Some(unwind), .. } => vec![target, unwind].into_cow(), - Assert { ref target, .. } => slice::from_ref(target).into_cow(), FalseEdges { ref real_target, ref imaginary_targets } => { - let mut s = vec![*real_target]; - s.extend_from_slice(imaginary_targets); - s.into_cow() + Some(real_target).into_iter().chain(&imaginary_targets[..]) } - FalseUnwind { real_target: t, unwind: Some(u) } => vec![t, u].into_cow(), - FalseUnwind { real_target: ref t, unwind: None } => slice::from_ref(t).into_cow(), } } - // FIXME: no mootable cow. I’m honestly not sure what a “cow” between `&mut [BasicBlock]` and - // `Vec<&mut BasicBlock>` would look like in the first place. - pub fn successors_mut(&mut self) -> Vec<&mut BasicBlock> { + pub fn successors_mut(&mut self) -> SuccessorsMut { use self::TerminatorKind::*; match *self { - Goto { target: ref mut b } => vec![b], - SwitchInt { targets: ref mut b, .. } => b.iter_mut().collect(), - Resume | Abort | GeneratorDrop => Vec::new(), - Return => Vec::new(), - Unreachable => Vec::new(), - Call { destination: Some((_, ref mut t)), cleanup: Some(ref mut c), .. } => vec![t, c], - Call { destination: Some((_, ref mut t)), cleanup: None, .. } => vec![t], - Call { destination: None, cleanup: Some(ref mut c), .. } => vec![c], - Call { destination: None, cleanup: None, .. } => vec![], - Yield { resume: ref mut t, drop: Some(ref mut c), .. } => vec![t, c], - Yield { resume: ref mut t, drop: None, .. } => vec![t], - DropAndReplace { ref mut target, unwind: Some(ref mut unwind), .. } | - Drop { ref mut target, unwind: Some(ref mut unwind), .. } => vec![target, unwind], - DropAndReplace { ref mut target, unwind: None, .. } | - Drop { ref mut target, unwind: None, .. } => { - vec![target] + Resume | Abort | GeneratorDrop | Return | Unreachable | + Call { destination: None, cleanup: None, .. } => { + None.into_iter().chain(&mut []) + } + Goto { target: ref mut t } | + Call { destination: None, cleanup: Some(ref mut t), .. } | + Call { destination: Some((_, ref mut t)), cleanup: None, .. } | + Yield { resume: ref mut t, drop: None, .. } | + DropAndReplace { target: ref mut t, unwind: None, .. } | + Drop { target: ref mut t, unwind: None, .. } | + Assert { target: ref mut t, cleanup: None, .. } | + FalseUnwind { real_target: ref mut t, unwind: None } => { + Some(t).into_iter().chain(&mut []) + } + Call { destination: Some((_, ref mut t)), cleanup: Some(ref mut u), .. } | + Yield { resume: ref mut t, drop: Some(ref mut u), .. } | + DropAndReplace { target: ref mut t, unwind: Some(ref mut u), .. } | + Drop { target: ref mut t, unwind: Some(ref mut u), .. } | + Assert { target: ref mut t, cleanup: Some(ref mut u), .. } | + FalseUnwind { real_target: ref mut t, unwind: Some(ref mut u) } => { + Some(t).into_iter().chain(slice::from_ref_mut(u)) + } + SwitchInt { ref mut targets, .. } => { + None.into_iter().chain(&mut targets[..]) } - Assert { ref mut target, cleanup: Some(ref mut unwind), .. } => vec![target, unwind], - Assert { ref mut target, .. } => vec![target], FalseEdges { ref mut real_target, ref mut imaginary_targets } => { - let mut s = vec![real_target]; - s.extend(imaginary_targets.iter_mut()); - s + Some(real_target).into_iter().chain(&mut imaginary_targets[..]) } - FalseUnwind { real_target: ref mut t, unwind: Some(ref mut u) } => vec![t, u], - FalseUnwind { ref mut real_target, unwind: None } => vec![real_target], } } @@ -1070,18 +1074,18 @@ impl<'tcx> BasicBlockData<'tcx> { impl<'tcx> Debug for TerminatorKind<'tcx> { fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { self.fmt_head(fmt)?; - let successors = self.successors(); + let successor_count = self.successors().count(); let labels = self.fmt_successor_labels(); - assert_eq!(successors.len(), labels.len()); + assert_eq!(successor_count, labels.len()); - match successors.len() { + match successor_count { 0 => Ok(()), - 1 => write!(fmt, " -> {:?}", successors[0]), + 1 => write!(fmt, " -> {:?}", self.successors().nth(0).unwrap()), _ => { write!(fmt, " -> [")?; - for (i, target) in successors.iter().enumerate() { + for (i, target) in self.successors().enumerate() { if i > 0 { write!(fmt, ", ")?; } @@ -1969,7 +1973,7 @@ impl<'tcx> ControlFlowGraph for Mir<'tcx> { fn successors<'graph>(&'graph self, node: Self::Node) -> >::Iter { - self.basic_blocks[node].terminator().successors().into_owned().into_iter() + self.basic_blocks[node].terminator().successors().cloned() } } @@ -1980,7 +1984,7 @@ impl<'a, 'b> GraphPredecessors<'b> for Mir<'a> { impl<'a, 'b> GraphSuccessors<'b> for Mir<'a> { type Item = BasicBlock; - type Iter = IntoIter; + type Iter = iter::Cloned>; } #[derive(Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)] diff --git a/src/librustc/mir/traversal.rs b/src/librustc/mir/traversal.rs index 666ca5eabe8..92888ed99e4 100644 --- a/src/librustc/mir/traversal.rs +++ b/src/librustc/mir/traversal.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::vec; - use rustc_data_structures::bitvec::BitVector; use rustc_data_structures::indexed_vec::Idx; @@ -67,7 +65,7 @@ impl<'a, 'tcx> Iterator for Preorder<'a, 'tcx> { let data = &self.mir[idx]; if let Some(ref term) = data.terminator { - for &succ in term.successors().iter() { + for &succ in term.successors() { self.worklist.push(succ); } } @@ -110,7 +108,7 @@ impl<'a, 'tcx> ExactSizeIterator for Preorder<'a, 'tcx> {} pub struct Postorder<'a, 'tcx: 'a> { mir: &'a Mir<'tcx>, visited: BitVector, - visit_stack: Vec<(BasicBlock, vec::IntoIter)> + visit_stack: Vec<(BasicBlock, Successors<'a>)> } impl<'a, 'tcx> Postorder<'a, 'tcx> { @@ -126,10 +124,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> { if let Some(ref term) = data.terminator { po.visited.insert(root.index()); - - let succs = term.successors().into_owned().into_iter(); - - po.visit_stack.push((root, succs)); + po.visit_stack.push((root, term.successors())); po.traverse_successor(); } @@ -186,7 +181,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> { // two iterations yield `C` and finally `A` for a final traversal of [E, D, B, C, A] loop { let bb = if let Some(&mut (_, ref mut iter)) = self.visit_stack.last_mut() { - if let Some(bb) = iter.next() { + if let Some(&bb) = iter.next() { bb } else { break; @@ -197,8 +192,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> { if self.visited.insert(bb.index()) { if let Some(ref term) = self.mir[bb].terminator { - let succs = term.successors().into_owned().into_iter(); - self.visit_stack.push((bb, succs)); + self.visit_stack.push((bb, term.successors())); } } } diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs index d5e11a312ec..56e388a5b60 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -193,7 +193,6 @@ impl<'gcx, 'tcx> UseFinder<'gcx, 'tcx> { block_data .terminator() .successors() - .iter() .map(|&basic_block| Location { statement_index: 0, block: basic_block, diff --git a/src/librustc_mir/borrow_check/nll/region_infer/dfs.rs b/src/librustc_mir/borrow_check/nll/region_infer/dfs.rs index 4fcd3118f91..f68394d6149 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/dfs.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/dfs.rs @@ -95,7 +95,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { block_data .terminator() .successors() - .iter() .map(|&basic_block| Location { statement_index: 0, block: basic_block, diff --git a/src/librustc_mir/dataflow/graphviz.rs b/src/librustc_mir/dataflow/graphviz.rs index 07585c08f6a..9096ac1444c 100644 --- a/src/librustc_mir/dataflow/graphviz.rs +++ b/src/librustc_mir/dataflow/graphviz.rs @@ -73,8 +73,8 @@ pub type Node = BasicBlock; pub struct Edge { source: BasicBlock, index: usize } fn outgoing(mir: &Mir, bb: BasicBlock) -> Vec { - let succ_len = mir[bb].terminator().successors().len(); - (0..succ_len).map(|index| Edge { source: bb, index: index}).collect() + mir[bb].terminator().successors().enumerate() + .map(|(index, _)| Edge { source: bb, index: index}).collect() } impl<'a, 'tcx, MWF, P> dot::Labeller<'a> for Graph<'a, 'tcx, MWF, P> @@ -285,6 +285,6 @@ impl<'a, 'tcx, MWF, P> dot::GraphWalk<'a> for Graph<'a, 'tcx, MWF, P> fn target(&self, edge: &Edge) -> Node { let mir = self.mbcx.mir(); - mir[edge.source].terminator().successors()[edge.index] + *mir[edge.source].terminator().successors().nth(edge.index).unwrap() } } diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 2e2f8494146..ee6d42b1fe5 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -330,7 +330,7 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> { } if !is_drop { - for &succ in &term.successors()[..] { + for &succ in term.successors() { work_list.push(succ); } } diff --git a/src/librustc_mir/transform/remove_noop_landing_pads.rs b/src/librustc_mir/transform/remove_noop_landing_pads.rs index 6d365012525..bcc8fef18f0 100644 --- a/src/librustc_mir/transform/remove_noop_landing_pads.rs +++ b/src/librustc_mir/transform/remove_noop_landing_pads.rs @@ -78,7 +78,7 @@ impl RemoveNoopLandingPads { TerminatorKind::SwitchInt { .. } | TerminatorKind::FalseEdges { .. } | TerminatorKind::FalseUnwind { .. } => { - terminator.successors().iter().all(|succ| { + terminator.successors().all(|succ| { nop_landing_pads.contains(succ.index()) }) }, diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index 2c6ed1f19b7..691fdd130e5 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -91,7 +91,7 @@ impl<'a, 'tcx: 'a> CfgSimplifier<'a, 'tcx> { for (_, data) in traversal::preorder(mir) { if let Some(ref term) = data.terminator { - for &tgt in term.successors().iter() { + for &tgt in term.successors() { pred_count[tgt] += 1; } } @@ -219,10 +219,10 @@ impl<'a, 'tcx: 'a> CfgSimplifier<'a, 'tcx> { }; let first_succ = { - let successors = terminator.successors(); - if let Some(&first_succ) = terminator.successors().get(0) { - if successors.iter().all(|s| *s == first_succ) { - self.pred_count[first_succ] -= (successors.len()-1) as u32; + if let Some(&first_succ) = terminator.successors().nth(0) { + if terminator.successors().all(|s| *s == first_succ) { + let count = terminator.successors().count(); + self.pred_count[first_succ] -= (count - 1) as u32; first_succ } else { return false diff --git a/src/librustc_mir/util/graphviz.rs b/src/librustc_mir/util/graphviz.rs index 85b66c29be1..22e2b1b0b09 100644 --- a/src/librustc_mir/util/graphviz.rs +++ b/src/librustc_mir/util/graphviz.rs @@ -125,7 +125,7 @@ fn write_edges(source: BasicBlock, mir: &Mir, w: &mut W) -> io::Result let terminator = mir[source].terminator(); let labels = terminator.kind.fmt_successor_labels(); - for (&target, label) in terminator.successors().iter().zip(labels) { + for (&target, label) in terminator.successors().zip(labels) { writeln!(w, r#" {} -> {} [label="{}"];"#, node(source), node(target), label)?; } diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index 42ddabddd2d..cfb1a2cd28b 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -138,7 +138,7 @@ pub fn liveness_of_locals<'tcx>(mir: &Mir<'tcx>, mode: LivenessMode) -> Liveness for b in mir.basic_blocks().indices().rev() { // outs[b] = ∪ {ins of successors} bits.clear(); - for &successor in mir.basic_blocks()[b].terminator().successors().into_iter() { + for &successor in mir.basic_blocks()[b].terminator().successors() { bits.union(&ins[successor]); } outs[b].clone_from(&bits); diff --git a/src/librustc_trans/mir/analyze.rs b/src/librustc_trans/mir/analyze.rs index 0fe7163da7a..9e5298eb736 100644 --- a/src/librustc_trans/mir/analyze.rs +++ b/src/librustc_trans/mir/analyze.rs @@ -322,7 +322,7 @@ pub fn cleanup_kinds<'a, 'tcx>(mir: &mir::Mir<'tcx>) -> IndexVec Date: Tue, 1 May 2018 12:26:58 +0200 Subject: Merge adjacent write! invocations --- src/librustc/mir/mod.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'src') diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 624f8ed789c..3bbec3915dd 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1133,10 +1133,7 @@ impl<'tcx> TerminatorKind<'tcx> { if !expected { write!(fmt, "!")?; } - write!(fmt, "{:?}, ", cond)?; - write!(fmt, "\"{:?}\"", msg)?; - - write!(fmt, ")") + write!(fmt, "{:?}, \"{:?}\")", cond, msg) }, FalseEdges { .. } => write!(fmt, "falseEdges"), FalseUnwind { .. } => write!(fmt, "falseUnwind"), -- cgit 1.4.1-3-g733a5 From 94c5d38f0b5c85e2171dfe7b9ec36954d17f5fe0 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 1 May 2018 10:01:02 +1000 Subject: Use two vectors in nearest_common_ancestor. When looking at any scope in scope chain A, we only need to look for matches among scopes previously seen in scope chain B, and vice versa. This halves the number of "seen before?" comparisons, speeding up some runs of style-servo, clap-rs, and syn by 1--2%. --- src/librustc/middle/region.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 5f4efbeeaa8..bfc9ff6660d 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -690,21 +690,22 @@ impl<'tcx> ScopeTree { // the start. So this algorithm is faster. let mut ma = Some(scope_a); let mut mb = Some(scope_b); - let mut seen: SmallVec<[Scope; 32]> = SmallVec::new(); + let mut seen_a: SmallVec<[Scope; 32]> = SmallVec::new(); + let mut seen_b: SmallVec<[Scope; 32]> = SmallVec::new(); loop { if let Some(a) = ma { - if seen.iter().position(|s| *s == a).is_some() { + if seen_b.iter().position(|s| *s == a).is_some() { return a; } - seen.push(a); + seen_a.push(a); ma = self.parent_map.get(&a).map(|s| *s); } if let Some(b) = mb { - if seen.iter().position(|s| *s == b).is_some() { + if seen_a.iter().position(|s| *s == b).is_some() { return b; } - seen.push(b); + seen_b.push(b); mb = self.parent_map.get(&b).map(|s| *s); } -- cgit 1.4.1-3-g733a5 From 300b6bb41784d63b04bf621a3290fe1c247f873f Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 15 Apr 2018 16:59:00 +0300 Subject: Remove `macro_reexport` It's subsumed by `feature(use_extern_macros)` and `pub use` --- src/librustc_resolve/build_reduced_graph.rs | 29 +- src/librustc_resolve/diagnostics.rs | 73 +--- src/librustdoc/visit_ast.rs | 15 +- src/libstd/lib.rs | 16 +- src/libsyntax/feature_gate.rs | 11 +- .../compile-fail-fulldeps/gated-macro-reexports.rs | 21 - .../compile-fail/auxiliary/macro_non_reexport_2.rs | 19 - .../compile-fail/auxiliary/macro_reexport_1.rs | 15 - .../compile-fail/macro-no-implicit-reexport.rs | 20 - .../compile-fail/macro-reexport-malformed-1.rs | 16 - .../compile-fail/macro-reexport-malformed-2.rs | 16 - .../compile-fail/macro-reexport-malformed-3.rs | 16 - .../macro-reexport-not-locally-visible.rs | 22 - src/test/compile-fail/macro-reexport-undef.rs | 21 - .../proc-macro/auxiliary/derive-reexport.rs | 16 - .../run-pass-fulldeps/proc-macro/use-reexport.rs | 21 - src/test/run-pass/auxiliary/macro_reexport_1.rs | 15 - src/test/run-pass/auxiliary/macro_reexport_2.rs | 16 - .../run-pass/auxiliary/macro_reexport_2_no_use.rs | 16 - .../run-pass/macro-reexport-no-intermediate-use.rs | 19 - src/test/run-pass/macro-reexport.rs | 19 - src/test/rustdoc/pub-use-extern-macros.rs | 11 +- .../issue-43106-gating-of-builtin-attrs.rs | 20 - .../issue-43106-gating-of-builtin-attrs.stderr | 460 ++++++++++----------- src/test/ui/macro-reexport-removed.rs | 18 + src/test/ui/macro-reexport-removed.stderr | 18 + 26 files changed, 267 insertions(+), 692 deletions(-) delete mode 100644 src/test/compile-fail-fulldeps/gated-macro-reexports.rs delete mode 100644 src/test/compile-fail/auxiliary/macro_non_reexport_2.rs delete mode 100644 src/test/compile-fail/auxiliary/macro_reexport_1.rs delete mode 100644 src/test/compile-fail/macro-no-implicit-reexport.rs delete mode 100644 src/test/compile-fail/macro-reexport-malformed-1.rs delete mode 100644 src/test/compile-fail/macro-reexport-malformed-2.rs delete mode 100644 src/test/compile-fail/macro-reexport-malformed-3.rs delete mode 100644 src/test/compile-fail/macro-reexport-not-locally-visible.rs delete mode 100644 src/test/compile-fail/macro-reexport-undef.rs delete mode 100644 src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-reexport.rs delete mode 100644 src/test/run-pass-fulldeps/proc-macro/use-reexport.rs delete mode 100644 src/test/run-pass/auxiliary/macro_reexport_1.rs delete mode 100644 src/test/run-pass/auxiliary/macro_reexport_2.rs delete mode 100644 src/test/run-pass/auxiliary/macro_reexport_2_no_use.rs delete mode 100644 src/test/run-pass/macro-reexport-no-intermediate-use.rs delete mode 100644 src/test/run-pass/macro-reexport.rs create mode 100644 src/test/ui/macro-reexport-removed.rs create mode 100644 src/test/ui/macro-reexport-removed.stderr (limited to 'src') diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 14ceb5f59a3..e5e6c22c7a2 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -71,7 +71,6 @@ impl<'a> ToNameBinding<'a> for (Def, ty::Visibility, Span, Mark) { struct LegacyMacroImports { import_all: Option, imports: Vec<(Name, Span)>, - reexports: Vec<(Name, Span)>, } impl<'a> Resolver<'a> { @@ -621,7 +620,7 @@ impl<'a> Resolver<'a> { let legacy_imports = self.legacy_macro_imports(&item.attrs); let mut used = legacy_imports != LegacyMacroImports::default(); - // `#[macro_use]` and `#[macro_reexport]` are only allowed at the crate root. + // `#[macro_use]` is only allowed at the crate root. if self.current_module.parent.is_some() && used { span_err!(self.session, item.span, E0468, "an `extern crate` loading macros must be at the crate root"); @@ -669,17 +668,6 @@ impl<'a> Resolver<'a> { } } } - for (name, span) in legacy_imports.reexports { - self.cstore.export_macros_untracked(module.def_id().unwrap().krate); - let ident = Ident::with_empty_ctxt(name); - let result = self.resolve_ident_in_module(module, ident, MacroNS, false, false, span); - if let Ok(binding) = result { - let (def, vis) = (binding.def(), binding.vis); - self.macro_exports.push(Export { ident, def, vis, span, is_import: true }); - } else { - span_err!(self.session, span, E0470, "re-exported macro not found"); - } - } used } @@ -721,21 +709,6 @@ impl<'a> Resolver<'a> { }, None => imports.import_all = Some(attr.span), } - } else if attr.check_name("macro_reexport") { - let bad_macro_reexport = |this: &mut Self, span| { - span_err!(this.session, span, E0467, "bad macro re-export"); - }; - if let Some(names) = attr.meta_item_list() { - for attr in names { - if let Some(word) = attr.word() { - imports.reexports.push((word.ident.name, attr.span())); - } else { - bad_macro_reexport(self, attr.span()); - } - } - } else { - bad_macro_reexport(self, attr.span()); - } } } imports diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index a0fc5533f8e..232a32deb86 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -1395,35 +1395,6 @@ If you would like to import all exported macros, write `macro_use` with no arguments. "##, -E0467: r##" -Macro re-export declarations were empty or malformed. - -Erroneous code examples: - -```compile_fail,E0467 -#[macro_reexport] // error: no macros listed for export -extern crate core as macros_for_good; - -#[macro_reexport(fun_macro = "foo")] // error: not a macro identifier -extern crate core as other_macros_for_good; -``` - -This is a syntax error at the level of attribute declarations. - -Currently, `macro_reexport` requires at least one macro name to be listed. -Unlike `macro_use`, listing no names does not re-export all macros from the -given crate. - -Decide which macros you would like to export and list them properly. - -These are proper re-export declarations: - -```ignore (cannot-doctest-multicrate-project) -#[macro_reexport(some_macro, another_macro)] -extern crate macros_for_good; -``` -"##, - E0468: r##" A non-root module attempts to import macros from another crate. @@ -1496,48 +1467,6 @@ extern crate some_crate; //ok! ``` "##, -E0470: r##" -A macro listed for re-export was not found. - -Erroneous code example: - -```compile_fail,E0470 -#[macro_reexport(drink, be_merry)] -extern crate alloc; - -fn main() { - // ... -} -``` - -Either the listed macro is not contained in the imported crate, or it is not -exported from the given crate. - -This could be caused by a typo. Did you misspell the macro's name? - -Double-check the names of the macros listed for re-export, and that the crate -in question exports them. - -A working version: - -```ignore (cannot-doctest-multicrate-project) -// In some_crate crate: -#[macro_export] -macro_rules! eat { - ... -} - -#[macro_export] -macro_rules! drink { - ... -} - -// In your_crate: -#[macro_reexport(eat, drink)] -extern crate some_crate; -``` -"##, - E0530: r##" A binding shadowed something it shouldn't. @@ -1715,6 +1644,8 @@ register_diagnostics! { // E0421, merged into 531 E0531, // unresolved pattern path kind `name` // E0427, merged into 530 +// E0467, removed +// E0470, removed E0573, E0574, E0575, diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 967c50e62db..6db02cc6cc1 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -49,7 +49,6 @@ pub struct RustdocVisitor<'a, 'tcx: 'a, 'rcx: 'a> { inlining: bool, /// Is the current module and all of its parents public? inside_public_path: bool, - reexported_macros: FxHashSet, exact_paths: Option>>, } @@ -66,7 +65,6 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> { view_item_stack: stack, inlining: false, inside_public_path: true, - reexported_macros: FxHashSet(), exact_paths: Some(FxHashMap()), cstore, } @@ -221,7 +219,7 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> { if let Some(exports) = self.cx.tcx.module_exports(def_id) { for export in exports.iter().filter(|e| e.vis == Visibility::Public) { if let Def::Macro(def_id, ..) = export.def { - if def_id.krate == LOCAL_CRATE || self.reexported_macros.contains(&def_id) { + if def_id.krate == LOCAL_CRATE { continue // These are `krate.exported_macros`, handled in `self.visit()`. } @@ -298,17 +296,6 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> { let is_no_inline = use_attrs.lists("doc").has_word("no_inline") || use_attrs.lists("doc").has_word("hidden"); - // Memoize the non-inlined `pub use`'d macros so we don't push an extra - // declaration in `visit_mod_contents()` - if !def_did.is_local() { - if let Def::Macro(did, _) = def { - if please_inline { return true } - debug!("memoizing non-inlined macro export: {:?}", def); - self.reexported_macros.insert(did); - return false; - } - } - // For cross-crate impl inlining we need to know whether items are // reachable in documentation - a previously nonreachable item can be // made reachable by cross-crate inlining which we're checking here. diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 41992193135..c6ee5b57be2 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -273,7 +273,6 @@ #![feature(libc)] #![feature(link_args)] #![feature(linkage)] -#![feature(macro_reexport)] #![feature(macro_vis_matcher)] #![feature(needs_panic_runtime)] #![feature(never_type)] @@ -313,6 +312,7 @@ #![feature(unboxed_closures)] #![feature(untagged_unions)] #![feature(unwind_attributes)] +#![feature(use_extern_macros)] #![feature(vec_push_all)] #![feature(doc_cfg)] #![feature(doc_masked)] @@ -347,15 +347,13 @@ use prelude::v1::*; #[cfg(test)] extern crate test; #[cfg(test)] extern crate rand; -// We want to re-export a few macros from core but libcore has already been -// imported by the compiler (via our #[no_std] attribute) In this case we just -// add a new crate name so we can attach the re-exports to it. -#[macro_reexport(assert_eq, assert_ne, debug_assert, debug_assert_eq, - debug_assert_ne, unreachable, unimplemented, write, writeln, try)] -extern crate core as __core; +// Re-export a few macros from core +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::{assert_eq, assert_ne, debug_assert, debug_assert_eq, debug_assert_ne}; +#[stable(feature = "rust1", since = "1.0.0")] +pub use core::{unreachable, unimplemented, write, writeln, try}; #[macro_use] -#[macro_reexport(vec, format)] extern crate alloc as alloc_crate; extern crate alloc_system; #[doc(masked)] @@ -450,6 +448,8 @@ pub use alloc_crate::borrow; #[stable(feature = "rust1", since = "1.0.0")] pub use alloc_crate::fmt; #[stable(feature = "rust1", since = "1.0.0")] +pub use alloc_crate::format; +#[stable(feature = "rust1", since = "1.0.0")] pub use alloc_crate::slice; #[stable(feature = "rust1", since = "1.0.0")] pub use alloc_crate::str; diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index f16b1ba440a..e373013b3f9 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -162,9 +162,6 @@ declare_features! ( // OIBIT specific features (active, optin_builtin_traits, "1.0.0", Some(13231), None), - // macro re-export needs more discussion and stabilization - (active, macro_reexport, "1.0.0", Some(29638), None), - // Allows use of #[staged_api] // rustc internal (active, staged_api, "1.0.0", None, None), @@ -484,6 +481,8 @@ declare_features! ( (removed, simd, "1.0.0", Some(27731), None), // Merged into `slice_patterns` (removed, advanced_slice_patterns, "1.0.0", Some(23121), None), + // Subsumed by `use` + (removed, macro_reexport, "1.0.0", Some(29638), None), ); declare_features! ( @@ -673,7 +672,6 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG ("forbid", Normal, Ungated), ("deny", Normal, Ungated), - ("macro_reexport", Normal, Ungated), ("macro_use", Normal, Ungated), ("macro_export", Normal, Ungated), ("plugin_registrar", Normal, Ungated), @@ -1516,11 +1514,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!(&self, underscore_imports, i.span, "renaming extern crates with `_` is unstable"); } - if let Some(attr) = attr::find_by_name(&i.attrs[..], "macro_reexport") { - gate_feature_post!(&self, macro_reexport, attr.span, - "macros re-exports are experimental \ - and possibly buggy"); - } } ast::ItemKind::ForeignMod(ref foreign_module) => { diff --git a/src/test/compile-fail-fulldeps/gated-macro-reexports.rs b/src/test/compile-fail-fulldeps/gated-macro-reexports.rs deleted file mode 100644 index 8b448e401bd..00000000000 --- a/src/test/compile-fail-fulldeps/gated-macro-reexports.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test that macro re-exports item are gated by `macro_reexport` feature gate. - -// aux-build:macro_reexport_1.rs -// gate-test-macro_reexport - -#![crate_type = "dylib"] - -#[macro_reexport(reexported)] -//~^ ERROR macros re-exports are experimental and possibly buggy -#[macro_use] #[no_link] -extern crate macro_reexport_1; diff --git a/src/test/compile-fail/auxiliary/macro_non_reexport_2.rs b/src/test/compile-fail/auxiliary/macro_non_reexport_2.rs deleted file mode 100644 index 910fcd2e367..00000000000 --- a/src/test/compile-fail/auxiliary/macro_non_reexport_2.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![crate_type = "dylib"] - -// Since we load a serialized macro with all its attributes, accidentally -// re-exporting a `#[macro_export] macro_rules!` is something of a concern! -// -// We avoid it at the moment only because of the order in which we do things. - -#[macro_use] #[no_link] -extern crate macro_reexport_1; diff --git a/src/test/compile-fail/auxiliary/macro_reexport_1.rs b/src/test/compile-fail/auxiliary/macro_reexport_1.rs deleted file mode 100644 index aaeccc6e898..00000000000 --- a/src/test/compile-fail/auxiliary/macro_reexport_1.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![crate_type = "dylib"] -#[macro_export] -macro_rules! reexported { - () => ( 3 ) -} diff --git a/src/test/compile-fail/macro-no-implicit-reexport.rs b/src/test/compile-fail/macro-no-implicit-reexport.rs deleted file mode 100644 index 07467e06eb2..00000000000 --- a/src/test/compile-fail/macro-no-implicit-reexport.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// aux-build:macro_reexport_1.rs -// aux-build:macro_non_reexport_2.rs - -#[macro_use] #[no_link] -extern crate macro_non_reexport_2; - -fn main() { - assert_eq!(reexported!(), 3); - //~^ ERROR cannot find macro `reexported!` in this scope -} diff --git a/src/test/compile-fail/macro-reexport-malformed-1.rs b/src/test/compile-fail/macro-reexport-malformed-1.rs deleted file mode 100644 index 36a6fce00a1..00000000000 --- a/src/test/compile-fail/macro-reexport-malformed-1.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![no_std] -#![feature(macro_reexport)] - -#[allow(unused_extern_crates)] -#[macro_reexport] //~ ERROR bad macro re-export -extern crate std; diff --git a/src/test/compile-fail/macro-reexport-malformed-2.rs b/src/test/compile-fail/macro-reexport-malformed-2.rs deleted file mode 100644 index 5f741d010de..00000000000 --- a/src/test/compile-fail/macro-reexport-malformed-2.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![no_std] -#![feature(macro_reexport)] - -#[allow(unused_extern_crates)] -#[macro_reexport="foo"] //~ ERROR bad macro re-export -extern crate std; diff --git a/src/test/compile-fail/macro-reexport-malformed-3.rs b/src/test/compile-fail/macro-reexport-malformed-3.rs deleted file mode 100644 index 1a7e3b918cd..00000000000 --- a/src/test/compile-fail/macro-reexport-malformed-3.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![no_std] -#![feature(macro_reexport)] - -#[allow(unused_extern_crates)] -#[macro_reexport(foo="bar")] //~ ERROR bad macro re-export -extern crate std; diff --git a/src/test/compile-fail/macro-reexport-not-locally-visible.rs b/src/test/compile-fail/macro-reexport-not-locally-visible.rs deleted file mode 100644 index 54a74b0e134..00000000000 --- a/src/test/compile-fail/macro-reexport-not-locally-visible.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// aux-build:macro_reexport_1.rs - -#![feature(macro_reexport)] - -#[macro_reexport(reexported)] -#[no_link] -extern crate macro_reexport_1; - -fn main() { - assert_eq!(reexported!(), 3); - //~^ ERROR cannot find macro -} diff --git a/src/test/compile-fail/macro-reexport-undef.rs b/src/test/compile-fail/macro-reexport-undef.rs deleted file mode 100644 index 50ac89e49e0..00000000000 --- a/src/test/compile-fail/macro-reexport-undef.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// aux-build:two_macros.rs - -#![feature(macro_reexport)] - -#[macro_use(macro_two)] -#[macro_reexport(no_way)] //~ ERROR re-exported macro not found -extern crate two_macros; - -pub fn main() { - macro_two!(); -} diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-reexport.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-reexport.rs deleted file mode 100644 index cfaf913216a..00000000000 --- a/src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-reexport.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// ignore-test not a test, auxiliary - -#![feature(macro_reexport)] - -#[macro_reexport(A)] -extern crate derive_a; diff --git a/src/test/run-pass-fulldeps/proc-macro/use-reexport.rs b/src/test/run-pass-fulldeps/proc-macro/use-reexport.rs deleted file mode 100644 index 03dfeb1f5c9..00000000000 --- a/src/test/run-pass-fulldeps/proc-macro/use-reexport.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// aux-build:derive-a.rs -// aux-build:derive-reexport.rs -// ignore-stage1 - -#[macro_use] -extern crate derive_reexport; - -#[derive(Debug, PartialEq, A, Eq, Copy, Clone)] -struct A; - -fn main() {} diff --git a/src/test/run-pass/auxiliary/macro_reexport_1.rs b/src/test/run-pass/auxiliary/macro_reexport_1.rs deleted file mode 100644 index aaeccc6e898..00000000000 --- a/src/test/run-pass/auxiliary/macro_reexport_1.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![crate_type = "dylib"] -#[macro_export] -macro_rules! reexported { - () => ( 3 ) -} diff --git a/src/test/run-pass/auxiliary/macro_reexport_2.rs b/src/test/run-pass/auxiliary/macro_reexport_2.rs deleted file mode 100644 index 3918be88d86..00000000000 --- a/src/test/run-pass/auxiliary/macro_reexport_2.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![crate_type = "dylib"] -#![feature(macro_reexport)] - -#[macro_reexport(reexported)] -#[macro_use] #[no_link] -extern crate macro_reexport_1; diff --git a/src/test/run-pass/auxiliary/macro_reexport_2_no_use.rs b/src/test/run-pass/auxiliary/macro_reexport_2_no_use.rs deleted file mode 100644 index 1d3dc26b0b4..00000000000 --- a/src/test/run-pass/auxiliary/macro_reexport_2_no_use.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![crate_type = "dylib"] -#![feature(macro_reexport)] - -#[macro_reexport(reexported)] -#[no_link] -extern crate macro_reexport_1; diff --git a/src/test/run-pass/macro-reexport-no-intermediate-use.rs b/src/test/run-pass/macro-reexport-no-intermediate-use.rs deleted file mode 100644 index de7df1ec021..00000000000 --- a/src/test/run-pass/macro-reexport-no-intermediate-use.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// aux-build:macro_reexport_1.rs -// aux-build:macro_reexport_2_no_use.rs - -#[macro_use] #[no_link] -extern crate macro_reexport_2_no_use; - -fn main() { - assert_eq!(reexported!(), 3_usize); -} diff --git a/src/test/run-pass/macro-reexport.rs b/src/test/run-pass/macro-reexport.rs deleted file mode 100644 index b8926eca9e9..00000000000 --- a/src/test/run-pass/macro-reexport.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// aux-build:macro_reexport_1.rs -// aux-build:macro_reexport_2.rs - -#[macro_use] #[no_link] -extern crate macro_reexport_2; - -fn main() { - assert_eq!(reexported!(), 3_usize); -} diff --git a/src/test/rustdoc/pub-use-extern-macros.rs b/src/test/rustdoc/pub-use-extern-macros.rs index 3f8f6f9544e..57d54585d84 100644 --- a/src/test/rustdoc/pub-use-extern-macros.rs +++ b/src/test/rustdoc/pub-use-extern-macros.rs @@ -10,14 +10,11 @@ // aux-build:pub-use-extern-macros.rs -#![feature(use_extern_macros, macro_reexport)] +#![feature(use_extern_macros)] -// @has pub_use_extern_macros/macro.foo.html -// @!has pub_use_extern_macros/index.html 'pub use macros::foo;' -#[macro_reexport(foo)] extern crate macros; +extern crate macros; -// @has pub_use_extern_macros/index.html 'pub use macros::bar;' -// @!has pub_use_extern_macros/macro.bar.html +// @has pub_use_extern_macros/macro.bar.html pub use macros::bar; // @has pub_use_extern_macros/macro.baz.html @@ -25,7 +22,7 @@ pub use macros::bar; #[doc(inline)] pub use macros::baz; -// @!has pub_use_extern_macros/macro.quux.html +// @has pub_use_extern_macros/macro.quux.html // @!has pub_use_extern_macros/index.html 'pub use macros::quux;' #[doc(hidden)] pub use macros::quux; diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs index 7b0c81dbab6..76fb09f27be 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs +++ b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs @@ -50,7 +50,6 @@ #![allow (x5300)] //~ WARN unknown lint: `x5300` #![forbid (x5200)] //~ WARN unknown lint: `x5200` #![deny (x5100)] //~ WARN unknown lint: `x5100` -#![macro_reexport = "5000"] //~ WARN unused attribute #![macro_use] // (allowed if no argument; see issue-43160-gating-of-macro_use.rs) #![macro_export = "4800"] //~ WARN unused attribute #![plugin_registrar = "4700"] //~ WARN unused attribute @@ -186,25 +185,6 @@ mod deny { //~^ WARN unknown lint: `x5100` } -#[macro_reexport = "5000"] -//~^ WARN unused attribute -mod macro_reexport { - mod inner { #![macro_reexport="5000"] } - //~^ WARN unused attribute - - #[macro_reexport = "5000"] fn f() { } - //~^ WARN unused attribute - - #[macro_reexport = "5000"] struct S; - //~^ WARN unused attribute - - #[macro_reexport = "5000"] type T = S; - //~^ WARN unused attribute - - #[macro_reexport = "5000"] impl S { } - //~^ WARN unused attribute -} - #[macro_use] mod macro_use { mod inner { #![macro_use] } diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr index 76ab50c9089..7a94c1f0351 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr +++ b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr @@ -1,17 +1,25 @@ warning: macro_escape is a deprecated synonym for macro_use - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:513:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:493:1 | LL | #[macro_escape] | ^^^^^^^^^^^^^^^ warning: macro_escape is a deprecated synonym for macro_use - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:516:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:496:17 | LL | mod inner { #![macro_escape] } | ^^^^^^^^^^^^^^^^ | = help: consider an outer attribute, #[macro_use] mod ... +warning: `#[must_use]` on functions is experimental (see issue #43302) + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:643:5 + | +LL | #[must_use = "1400"] fn f() { } + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(fn_must_use)] to the crate attributes to enable + warning: unknown lint: `x5400` --> $DIR/issue-43106-gating-of-builtin-attrs.rs:49:33 | @@ -43,154 +51,154 @@ LL | #![deny (x5100)] //~ WARN unknown lint: `x5100` | ^^^^^ warning: unknown lint: `x5400` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:113:8 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:112:8 | LL | #[warn(x5400)] | ^^^^^ warning: unknown lint: `x5400` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:116:25 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:115:25 | LL | mod inner { #![warn(x5400)] } | ^^^^^ warning: unknown lint: `x5400` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:119:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:118:12 | LL | #[warn(x5400)] fn f() { } | ^^^^^ warning: unknown lint: `x5400` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:122:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:121:12 | LL | #[warn(x5400)] struct S; | ^^^^^ warning: unknown lint: `x5400` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:125:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:124:12 | LL | #[warn(x5400)] type T = S; | ^^^^^ warning: unknown lint: `x5400` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:128:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:127:12 | LL | #[warn(x5400)] impl S { } | ^^^^^ warning: unknown lint: `x5300` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:132:9 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:131:9 | LL | #[allow(x5300)] | ^^^^^ warning: unknown lint: `x5300` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:135:26 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:134:26 | LL | mod inner { #![allow(x5300)] } | ^^^^^ warning: unknown lint: `x5300` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:138:13 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:137:13 | LL | #[allow(x5300)] fn f() { } | ^^^^^ warning: unknown lint: `x5300` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:141:13 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:140:13 | LL | #[allow(x5300)] struct S; | ^^^^^ warning: unknown lint: `x5300` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:144:13 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:143:13 | LL | #[allow(x5300)] type T = S; | ^^^^^ warning: unknown lint: `x5300` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:147:13 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:146:13 | LL | #[allow(x5300)] impl S { } | ^^^^^ warning: unknown lint: `x5200` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:151:10 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:150:10 | LL | #[forbid(x5200)] | ^^^^^ warning: unknown lint: `x5200` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:154:27 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:153:27 | LL | mod inner { #![forbid(x5200)] } | ^^^^^ warning: unknown lint: `x5200` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:157:14 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:156:14 | LL | #[forbid(x5200)] fn f() { } | ^^^^^ warning: unknown lint: `x5200` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:160:14 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:159:14 | LL | #[forbid(x5200)] struct S; | ^^^^^ warning: unknown lint: `x5200` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:163:14 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:162:14 | LL | #[forbid(x5200)] type T = S; | ^^^^^ warning: unknown lint: `x5200` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:166:14 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:165:14 | LL | #[forbid(x5200)] impl S { } | ^^^^^ warning: unknown lint: `x5100` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:170:8 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:169:8 | LL | #[deny(x5100)] | ^^^^^ warning: unknown lint: `x5100` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:173:25 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:172:25 | LL | mod inner { #![deny(x5100)] } | ^^^^^ warning: unknown lint: `x5100` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:176:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:175:12 | LL | #[deny(x5100)] fn f() { } | ^^^^^ warning: unknown lint: `x5100` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:179:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:178:12 | LL | #[deny(x5100)] struct S; | ^^^^^ warning: unknown lint: `x5100` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:182:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:181:12 | LL | #[deny(x5100)] type T = S; | ^^^^^ warning: unknown lint: `x5100` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:185:12 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:184:12 | LL | #[deny(x5100)] impl S { } | ^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:192:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:192:5 | -LL | mod inner { #![macro_reexport="5000"] } - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[macro_use] fn f() { } + | ^^^^^^^^^^^^ | note: lint level defined here --> $DIR/issue-43106-gating-of-builtin-attrs.rs:44:9 @@ -201,311 +209,275 @@ LL | #![warn(unused_attributes, unknown_lints)] warning: unused attribute --> $DIR/issue-43106-gating-of-builtin-attrs.rs:195:5 | -LL | #[macro_reexport = "5000"] fn f() { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:198:5 - | -LL | #[macro_reexport = "5000"] struct S; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:201:5 - | -LL | #[macro_reexport = "5000"] type T = S; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:204:5 - | -LL | #[macro_reexport = "5000"] impl S { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:189:1 - | -LL | #[macro_reexport = "5000"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:212:5 - | -LL | #[macro_use] fn f() { } - | ^^^^^^^^^^^^ - -warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:215:5 - | LL | #[macro_use] struct S; | ^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:218:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:198:5 | LL | #[macro_use] type T = S; | ^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:221:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:201:5 | LL | #[macro_use] impl S { } | ^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:228:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:208:17 | LL | mod inner { #![macro_export="4800"] } | ^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:231:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:211:5 | LL | #[macro_export = "4800"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:234:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:214:5 | LL | #[macro_export = "4800"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:237:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:217:5 | LL | #[macro_export = "4800"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:240:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:220:5 | LL | #[macro_export = "4800"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:225:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:205:1 | LL | #[macro_export = "4800"] | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:247:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:227:17 | LL | mod inner { #![plugin_registrar="4700"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:252:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:232:5 | LL | #[plugin_registrar = "4700"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:255:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:235:5 | LL | #[plugin_registrar = "4700"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:258:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:238:5 | LL | #[plugin_registrar = "4700"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:244:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:224:1 | LL | #[plugin_registrar = "4700"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:265:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:245:17 | LL | mod inner { #![main="4300"] } | ^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:270:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:250:5 | LL | #[main = "4400"] struct S; | ^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:273:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:253:5 | LL | #[main = "4400"] type T = S; | ^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:276:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:256:5 | LL | #[main = "4400"] impl S { } | ^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:262:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:242:1 | LL | #[main = "4400"] | ^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:283:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:263:17 | LL | mod inner { #![start="4300"] } | ^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:288:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:268:5 | LL | #[start = "4300"] struct S; | ^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:291:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:271:5 | LL | #[start = "4300"] type T = S; | ^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:294:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:274:5 | LL | #[start = "4300"] impl S { } | ^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:280:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:260:1 | LL | #[start = "4300"] | ^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:333:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:313:17 | LL | mod inner { #![repr="3900"] } | ^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:336:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:316:5 | LL | #[repr = "3900"] fn f() { } | ^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:341:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:321:5 | LL | #[repr = "3900"] type T = S; | ^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:344:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:324:5 | LL | #[repr = "3900"] impl S { } | ^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:330:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:310:1 | LL | #[repr = "3900"] | ^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:352:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:332:5 | LL | #[path = "3800"] fn f() { } | ^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:355:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:335:5 | LL | #[path = "3800"] struct S; | ^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:358:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:338:5 | LL | #[path = "3800"] type T = S; | ^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:361:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:341:5 | LL | #[path = "3800"] impl S { } | ^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:368:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:348:17 | LL | mod inner { #![abi="3700"] } | ^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:371:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:351:5 | LL | #[abi = "3700"] fn f() { } | ^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:374:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:354:5 | LL | #[abi = "3700"] struct S; | ^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:377:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:357:5 | LL | #[abi = "3700"] type T = S; | ^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:380:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:360:5 | LL | #[abi = "3700"] impl S { } | ^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:365:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:345:1 | LL | #[abi = "3700"] | ^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:387:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:367:17 | LL | mod inner { #![automatically_derived="3600"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:390:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:370:5 | LL | #[automatically_derived = "3600"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:393:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:373:5 | LL | #[automatically_derived = "3600"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:396:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:376:5 | LL | #[automatically_derived = "3600"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:399:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:379:5 | LL | #[automatically_derived = "3600"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:384:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:364:1 | LL | #[automatically_derived = "3600"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: function is marked #[no_mangle], but not exported - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:407:27 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:387:27 | LL | #[no_mangle = "3500"] fn f() { } | -^^^^^^^^^ @@ -515,793 +487,787 @@ LL | #[no_mangle = "3500"] fn f() { } = note: #[warn(private_no_mangle_fns)] on by default warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:420:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:400:17 | LL | mod inner { #![no_link="3400"] } | ^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:423:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:403:5 | LL | #[no_link = "3400"] fn f() { } | ^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:426:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:406:5 | LL | #[no_link = "3400"] struct S; | ^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:429:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:409:5 | LL | #[no_link = "3400"]type T = S; | ^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:432:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:412:5 | LL | #[no_link = "3400"] impl S { } | ^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:417:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:397:1 | LL | #[no_link = "3400"] | ^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:439:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:419:17 | LL | mod inner { #![should_panic="3200"] } | ^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:442:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:422:5 | LL | #[should_panic = "3200"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:445:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:425:5 | LL | #[should_panic = "3200"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:448:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:428:5 | LL | #[should_panic = "3200"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:451:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:431:5 | LL | #[should_panic = "3200"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:436:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:416:1 | LL | #[should_panic = "3200"] | ^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:458:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:438:17 | LL | mod inner { #![ignore="3100"] } | ^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:461:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:441:5 | LL | #[ignore = "3100"] fn f() { } | ^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:464:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:444:5 | LL | #[ignore = "3100"] struct S; | ^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:467:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:447:5 | LL | #[ignore = "3100"] type T = S; | ^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:470:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:450:5 | LL | #[ignore = "3100"] impl S { } | ^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:455:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:435:1 | LL | #[ignore = "3100"] | ^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:477:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:457:17 | LL | mod inner { #![no_implicit_prelude="3000"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:480:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:460:5 | LL | #[no_implicit_prelude = "3000"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:483:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:463:5 | LL | #[no_implicit_prelude = "3000"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:486:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:466:5 | LL | #[no_implicit_prelude = "3000"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:489:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:469:5 | LL | #[no_implicit_prelude = "3000"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:474:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:454:1 | LL | #[no_implicit_prelude = "3000"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:496:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:476:17 | LL | mod inner { #![reexport_test_harness_main="2900"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:499:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:479:5 | LL | #[reexport_test_harness_main = "2900"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:502:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:482:5 | LL | #[reexport_test_harness_main = "2900"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:505:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:485:5 | LL | #[reexport_test_harness_main = "2900"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:508:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:488:5 | LL | #[reexport_test_harness_main = "2900"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:493:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:473:1 | LL | #[reexport_test_harness_main = "2900"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:519:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:499:5 | LL | #[macro_escape] fn f() { } | ^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:522:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:502:5 | LL | #[macro_escape] struct S; | ^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:525:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:505:5 | LL | #[macro_escape] type T = S; | ^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:528:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:508:5 | LL | #[macro_escape] impl S { } | ^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:536:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:516:17 | LL | mod inner { #![no_std="2600"] } | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:536:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:516:17 | LL | mod inner { #![no_std="2600"] } | ^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:540:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:520:5 | LL | #[no_std = "2600"] fn f() { } | ^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:540:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:520:5 | LL | #[no_std = "2600"] fn f() { } | ^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:544:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:524:5 | LL | #[no_std = "2600"] struct S; | ^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:544:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:524:5 | LL | #[no_std = "2600"] struct S; | ^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:548:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:528:5 | LL | #[no_std = "2600"] type T = S; | ^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:548:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:528:5 | LL | #[no_std = "2600"] type T = S; | ^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:552:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:532:5 | LL | #[no_std = "2600"] impl S { } | ^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:552:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:532:5 | LL | #[no_std = "2600"] impl S { } | ^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:532:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:512:1 | LL | #[no_std = "2600"] | ^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:532:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:512:1 | LL | #[no_std = "2600"] | ^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:691:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:672:17 | LL | mod inner { #![crate_name="0900"] } | ^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:691:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:672:17 | LL | mod inner { #![crate_name="0900"] } | ^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:695:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:676:5 | LL | #[crate_name = "0900"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:695:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:676:5 | LL | #[crate_name = "0900"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:699:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:680:5 | LL | #[crate_name = "0900"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:699:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:680:5 | LL | #[crate_name = "0900"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:703:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:684:5 | LL | #[crate_name = "0900"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:703:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:684:5 | LL | #[crate_name = "0900"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:707:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:688:5 | LL | #[crate_name = "0900"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:707:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:688:5 | LL | #[crate_name = "0900"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:687:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:668:1 | LL | #[crate_name = "0900"] | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:687:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:668:1 | LL | #[crate_name = "0900"] | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:716:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:697:17 | LL | mod inner { #![crate_type="0800"] } | ^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:716:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:697:17 | LL | mod inner { #![crate_type="0800"] } | ^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:720:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:701:5 | LL | #[crate_type = "0800"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:720:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:701:5 | LL | #[crate_type = "0800"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:724:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:705:5 | LL | #[crate_type = "0800"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:724:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:705:5 | LL | #[crate_type = "0800"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:728:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:709:5 | LL | #[crate_type = "0800"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:728:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:709:5 | LL | #[crate_type = "0800"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:732:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:713:5 | LL | #[crate_type = "0800"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:732:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:713:5 | LL | #[crate_type = "0800"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:712:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:693:1 | LL | #[crate_type = "0800"] | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:712:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:693:1 | LL | #[crate_type = "0800"] | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:741:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:722:17 | LL | mod inner { #![feature(x0600)] } | ^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:741:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:722:17 | LL | mod inner { #![feature(x0600)] } | ^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:745:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:726:5 | LL | #[feature(x0600)] fn f() { } | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:745:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:726:5 | LL | #[feature(x0600)] fn f() { } | ^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:749:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:730:5 | LL | #[feature(x0600)] struct S; | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:749:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:730:5 | LL | #[feature(x0600)] struct S; | ^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:753:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:734:5 | LL | #[feature(x0600)] type T = S; | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:753:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:734:5 | LL | #[feature(x0600)] type T = S; | ^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:757:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:738:5 | LL | #[feature(x0600)] impl S { } | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:757:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:738:5 | LL | #[feature(x0600)] impl S { } | ^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:737:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:718:1 | LL | #[feature(x0600)] | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:737:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:718:1 | LL | #[feature(x0600)] | ^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:767:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:748:17 | LL | mod inner { #![no_main="0400"] } | ^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:767:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:748:17 | LL | mod inner { #![no_main="0400"] } | ^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:771:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:752:5 | LL | #[no_main = "0400"] fn f() { } | ^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:771:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:752:5 | LL | #[no_main = "0400"] fn f() { } | ^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:775:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:756:5 | LL | #[no_main = "0400"] struct S; | ^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:775:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:756:5 | LL | #[no_main = "0400"] struct S; | ^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:779:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:760:5 | LL | #[no_main = "0400"] type T = S; | ^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:779:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:760:5 | LL | #[no_main = "0400"] type T = S; | ^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:783:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:764:5 | LL | #[no_main = "0400"] impl S { } | ^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:783:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:764:5 | LL | #[no_main = "0400"] impl S { } | ^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:763:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:744:1 | LL | #[no_main = "0400"] | ^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:763:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:744:1 | LL | #[no_main = "0400"] | ^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:805:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:786:17 | LL | mod inner { #![recursion_limit="0200"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:805:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:786:17 | LL | mod inner { #![recursion_limit="0200"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:809:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:790:5 | LL | #[recursion_limit="0200"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:809:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:790:5 | LL | #[recursion_limit="0200"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:813:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:794:5 | LL | #[recursion_limit="0200"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:813:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:794:5 | LL | #[recursion_limit="0200"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:817:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:798:5 | LL | #[recursion_limit="0200"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:817:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:798:5 | LL | #[recursion_limit="0200"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:821:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:802:5 | LL | #[recursion_limit="0200"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:821:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:802:5 | LL | #[recursion_limit="0200"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:801:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:782:1 | LL | #[recursion_limit="0200"] | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:801:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:782:1 | LL | #[recursion_limit="0200"] | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:830:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:811:17 | LL | mod inner { #![type_length_limit="0100"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:830:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:811:17 | LL | mod inner { #![type_length_limit="0100"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:834:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:815:5 | LL | #[type_length_limit="0100"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:834:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:815:5 | LL | #[type_length_limit="0100"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:838:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:819:5 | LL | #[type_length_limit="0100"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:838:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:819:5 | LL | #[type_length_limit="0100"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:842:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:823:5 | LL | #[type_length_limit="0100"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:842:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:823:5 | LL | #[type_length_limit="0100"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:846:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:827:5 | LL | #[type_length_limit="0100"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:846:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:827:5 | LL | #[type_length_limit="0100"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:826:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:807:1 | LL | #[type_length_limit="0100"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:826:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:807:1 | LL | #[type_length_limit="0100"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:53:1 - | -LL | #![macro_reexport = "5000"] //~ WARN unused attribute - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:55:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:54:1 | LL | #![macro_export = "4800"] //~ WARN unused attribute | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:56:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:55:1 | LL | #![plugin_registrar = "4700"] //~ WARN unused attribute | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:59:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:58:1 | LL | #![main = "x4400"] //~ WARN unused attribute | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:60:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:59:1 | LL | #![start = "x4300"] //~ WARN unused attribute | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:63:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:62:1 | LL | #![repr = "3900"] //~ WARN unused attribute | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:64:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:63:1 | LL | #![path = "3800"] //~ WARN unused attribute | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:65:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:64:1 | LL | #![abi = "3700"] //~ WARN unused attribute | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:66:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:65:1 | LL | #![automatically_derived = "3600"] //~ WARN unused attribute | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:68:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:67:1 | LL | #![no_link = "3400"] //~ WARN unused attribute | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:70:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:69:1 | LL | #![should_panic = "3200"] //~ WARN unused attribute | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:71:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:70:1 | LL | #![ignore = "3100"] //~ WARN unused attribute | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:77:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:76:1 | LL | #![proc_macro_derive = "2500"] //~ WARN unused attribute | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: compilation successful - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:857:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:838:1 | LL | / fn main() { //~ ERROR compilation successful LL | | println!("Hello World"); diff --git a/src/test/ui/macro-reexport-removed.rs b/src/test/ui/macro-reexport-removed.rs new file mode 100644 index 00000000000..bab583da37b --- /dev/null +++ b/src/test/ui/macro-reexport-removed.rs @@ -0,0 +1,18 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:two_macros.rs + +#![feature(macro_reexport)] //~ ERROR feature has been removed + +#[macro_reexport(macro_one)] //~ ERROR attribute `macro_reexport` is currently unknown +extern crate two_macros; + +fn main() {} diff --git a/src/test/ui/macro-reexport-removed.stderr b/src/test/ui/macro-reexport-removed.stderr new file mode 100644 index 00000000000..4d262e96081 --- /dev/null +++ b/src/test/ui/macro-reexport-removed.stderr @@ -0,0 +1,18 @@ +error[E0557]: feature has been removed + --> $DIR/macro-reexport-removed.rs:13:12 + | +LL | #![feature(macro_reexport)] //~ ERROR feature has been removed + | ^^^^^^^^^^^^^^ + +error[E0658]: The attribute `macro_reexport` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642) + --> $DIR/macro-reexport-removed.rs:15:1 + | +LL | #[macro_reexport(macro_one)] //~ ERROR attribute `macro_reexport` is currently unknown + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: aborting due to 2 previous errors + +Some errors occurred: E0557, E0658. +For more information about an error, try `rustc --explain E0557`. -- cgit 1.4.1-3-g733a5 From d98100b9679609516c9cbf67eac3ec35e0e5d5fc Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 29 Apr 2018 17:58:51 +0300 Subject: Give removal reasons to removed features --- src/libsyntax/feature_gate.rs | 76 ++++++++++++++++--------------- src/test/ui/macro-reexport-removed.stderr | 6 +++ 2 files changed, 46 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index e373013b3f9..4d4d1e10535 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -90,24 +90,24 @@ macro_rules! declare_features { } }; - ($((removed, $feature: ident, $ver: expr, $issue: expr, None),)+) => { + ($((removed, $feature: ident, $ver: expr, $issue: expr, None, $reason: expr),)+) => { /// Represents unstable features which have since been removed (it was once Active) - const REMOVED_FEATURES: &'static [(&'static str, &'static str, Option)] = &[ - $((stringify!($feature), $ver, $issue)),+ + const REMOVED_FEATURES: &[(&str, &str, Option, Option<&str>)] = &[ + $((stringify!($feature), $ver, $issue, $reason)),+ ]; }; ($((stable_removed, $feature: ident, $ver: expr, $issue: expr, None),)+) => { /// Represents stable features which have since been removed (it was once Accepted) - const STABLE_REMOVED_FEATURES: &'static [(&'static str, &'static str, Option)] = &[ - $((stringify!($feature), $ver, $issue)),+ + const STABLE_REMOVED_FEATURES: &[(&str, &str, Option, Option<&str>)] = &[ + $((stringify!($feature), $ver, $issue, None)),+ ]; }; ($((accepted, $feature: ident, $ver: expr, $issue: expr, None),)+) => { /// Those language feature has since been Accepted (it was once Active) - const ACCEPTED_FEATURES: &'static [(&'static str, &'static str, Option)] = &[ - $((stringify!($feature), $ver, $issue)),+ + const ACCEPTED_FEATURES: &[(&str, &str, Option, Option<&str>)] = &[ + $((stringify!($feature), $ver, $issue, None)),+ ]; } } @@ -460,29 +460,29 @@ declare_features! ( ); declare_features! ( - (removed, import_shadowing, "1.0.0", None, None), - (removed, managed_boxes, "1.0.0", None, None), + (removed, import_shadowing, "1.0.0", None, None, None), + (removed, managed_boxes, "1.0.0", None, None, None), // Allows use of unary negate on unsigned integers, e.g. -e for e: u8 - (removed, negate_unsigned, "1.0.0", Some(29645), None), - (removed, reflect, "1.0.0", Some(27749), None), + (removed, negate_unsigned, "1.0.0", Some(29645), None, None), + (removed, reflect, "1.0.0", Some(27749), None, None), // A way to temporarily opt out of opt in copy. This will *never* be accepted. - (removed, opt_out_copy, "1.0.0", None, None), - (removed, quad_precision_float, "1.0.0", None, None), - (removed, struct_inherit, "1.0.0", None, None), - (removed, test_removed_feature, "1.0.0", None, None), - (removed, visible_private_types, "1.0.0", None, None), - (removed, unsafe_no_drop_flag, "1.0.0", None, None), + (removed, opt_out_copy, "1.0.0", None, None, None), + (removed, quad_precision_float, "1.0.0", None, None, None), + (removed, struct_inherit, "1.0.0", None, None, None), + (removed, test_removed_feature, "1.0.0", None, None, None), + (removed, visible_private_types, "1.0.0", None, None, None), + (removed, unsafe_no_drop_flag, "1.0.0", None, None, None), // Allows using items which are missing stability attributes // rustc internal - (removed, unmarked_api, "1.0.0", None, None), - (removed, pushpop_unsafe, "1.2.0", None, None), - (removed, allocator, "1.0.0", None, None), - // Allows the `#[simd]` attribute -- removed in favor of `#[repr(simd)]` - (removed, simd, "1.0.0", Some(27731), None), - // Merged into `slice_patterns` - (removed, advanced_slice_patterns, "1.0.0", Some(23121), None), - // Subsumed by `use` - (removed, macro_reexport, "1.0.0", Some(29638), None), + (removed, unmarked_api, "1.0.0", None, None, None), + (removed, pushpop_unsafe, "1.2.0", None, None, None), + (removed, allocator, "1.0.0", None, None, None), + (removed, simd, "1.0.0", Some(27731), None, + Some("removed in favor of `#[repr(simd)]`")), + (removed, advanced_slice_patterns, "1.0.0", Some(23121), None, + Some("merged into `#![feature(slice_patterns)]`")), + (removed, macro_reexport, "1.0.0", Some(29638), None, + Some("subsumed by `#![feature(use_extern_macros)]` and `pub use`")), ); declare_features! ( @@ -1200,7 +1200,7 @@ fn find_lang_feature_issue(feature: &str) -> Option { let found = ACCEPTED_FEATURES.iter().chain(REMOVED_FEATURES).chain(STABLE_REMOVED_FEATURES) .find(|t| t.0 == feature); match found { - Some(&(_, _, issue)) => issue, + Some(&(_, _, issue, _)) => issue, None => panic!("Feature `{}` is not declared anywhere", feature), } } @@ -1814,8 +1814,12 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], crate_edition: Edition) -> Features { - fn feature_removed(span_handler: &Handler, span: Span) { - span_err!(span_handler, span, E0557, "feature has been removed"); + fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) { + let mut err = struct_span_err!(span_handler, span, E0557, "feature has been removed"); + if let Some(reason) = reason { + err.span_note(span, reason); + } + err.emit(); } let mut features = Features::new(); @@ -1848,19 +1852,19 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], set(&mut features, mi.span); feature_checker.collect(&features, mi.span); } - else if let Some(&(_, _, _)) = REMOVED_FEATURES.iter() - .find(|& &(n, _, _)| name == n) + else if let Some(&(.., reason)) = REMOVED_FEATURES.iter() + .find(|& &(n, ..)| name == n) .or_else(|| STABLE_REMOVED_FEATURES.iter() - .find(|& &(n, _, _)| name == n)) { - feature_removed(span_handler, mi.span); + .find(|& &(n, ..)| name == n)) { + feature_removed(span_handler, mi.span, reason); } - else if let Some(&(_, _, _)) = ACCEPTED_FEATURES.iter() - .find(|& &(n, _, _)| name == n) { + else if let Some(&(..)) = ACCEPTED_FEATURES.iter() + .find(|& &(n, ..)| name == n) { features.declared_stable_lang_features.push((name, mi.span)); } else if let Some(&edition) = ALL_EDITIONS.iter() .find(|e| name == e.feature_name()) { if edition <= crate_edition { - feature_removed(span_handler, mi.span); + feature_removed(span_handler, mi.span, None); } else { for &(.., f_edition, set) in ACTIVE_FEATURES.iter() { if let Some(f_edition) = f_edition { diff --git a/src/test/ui/macro-reexport-removed.stderr b/src/test/ui/macro-reexport-removed.stderr index 4d262e96081..ba0ab232e86 100644 --- a/src/test/ui/macro-reexport-removed.stderr +++ b/src/test/ui/macro-reexport-removed.stderr @@ -1,6 +1,12 @@ error[E0557]: feature has been removed --> $DIR/macro-reexport-removed.rs:13:12 | +LL | #![feature(macro_reexport)] //~ ERROR feature has been removed + | ^^^^^^^^^^^^^^ + | +note: subsumed by `#![feature(use_extern_macros)]` and `pub use` + --> $DIR/macro-reexport-removed.rs:13:12 + | LL | #![feature(macro_reexport)] //~ ERROR feature has been removed | ^^^^^^^^^^^^^^ -- cgit 1.4.1-3-g733a5 From 730c7222ee85bbea677f08447ca83bf539a1bdf8 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 30 Apr 2018 14:06:24 +0300 Subject: Fix an error from "unused" lint + Fix rebase --- src/libstd/lib.rs | 1 + src/test/rustdoc/cross-crate-links.rs | 2 +- .../issue-43106-gating-of-builtin-attrs.stderr | 154 ++++++++++----------- 3 files changed, 75 insertions(+), 82 deletions(-) (limited to 'src') diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index c6ee5b57be2..fc05833e285 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -353,6 +353,7 @@ pub use core::{assert_eq, assert_ne, debug_assert, debug_assert_eq, debug_assert #[stable(feature = "rust1", since = "1.0.0")] pub use core::{unreachable, unimplemented, write, writeln, try}; +#[allow(unused_imports)] // macros from `alloc` are not used on all platforms #[macro_use] extern crate alloc as alloc_crate; extern crate alloc_system; diff --git a/src/test/rustdoc/cross-crate-links.rs b/src/test/rustdoc/cross-crate-links.rs index 15a774dc935..6078352fc0e 100644 --- a/src/test/rustdoc/cross-crate-links.rs +++ b/src/test/rustdoc/cross-crate-links.rs @@ -66,6 +66,6 @@ pub use all_item_types::FOO_STATIC; #[doc(no_inline)] pub use all_item_types::FOO_CONSTANT; -// @has 'foo/index.html' '//a[@href="../all_item_types/macro.foo_macro.html"]' 'foo_macro' +// @has 'foo/index.html' '//a[@href="../foo/macro.foo_macro.html"]' 'foo_macro' #[doc(no_inline)] pub use all_item_types::foo_macro; diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr index 7a94c1f0351..f8e5f58ca0e 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr +++ b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr @@ -12,14 +12,6 @@ LL | mod inner { #![macro_escape] } | = help: consider an outer attribute, #[macro_use] mod ... -warning: `#[must_use]` on functions is experimental (see issue #43302) - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:643:5 - | -LL | #[must_use = "1400"] fn f() { } - | ^^^^^^^^^^^^^^^^^^^^ - | - = help: add #![feature(fn_must_use)] to the crate attributes to enable - warning: unknown lint: `x5400` --> $DIR/issue-43106-gating-of-builtin-attrs.rs:49:33 | @@ -763,433 +755,433 @@ LL | #[no_std = "2600"] | ^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:672:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:671:17 | LL | mod inner { #![crate_name="0900"] } | ^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:672:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:671:17 | LL | mod inner { #![crate_name="0900"] } | ^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:676:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:675:5 | LL | #[crate_name = "0900"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:676:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:675:5 | LL | #[crate_name = "0900"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:680:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:679:5 | LL | #[crate_name = "0900"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:680:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:679:5 | LL | #[crate_name = "0900"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:684:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:683:5 | LL | #[crate_name = "0900"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:684:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:683:5 | LL | #[crate_name = "0900"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:688:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:687:5 | LL | #[crate_name = "0900"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:688:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:687:5 | LL | #[crate_name = "0900"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:668:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:667:1 | LL | #[crate_name = "0900"] | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:668:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:667:1 | LL | #[crate_name = "0900"] | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:697:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:696:17 | LL | mod inner { #![crate_type="0800"] } | ^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:697:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:696:17 | LL | mod inner { #![crate_type="0800"] } | ^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:701:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:700:5 | LL | #[crate_type = "0800"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:701:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:700:5 | LL | #[crate_type = "0800"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:705:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:704:5 | LL | #[crate_type = "0800"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:705:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:704:5 | LL | #[crate_type = "0800"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:709:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:708:5 | LL | #[crate_type = "0800"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:709:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:708:5 | LL | #[crate_type = "0800"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:713:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:712:5 | LL | #[crate_type = "0800"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:713:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:712:5 | LL | #[crate_type = "0800"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:693:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:692:1 | LL | #[crate_type = "0800"] | ^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:693:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:692:1 | LL | #[crate_type = "0800"] | ^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:722:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:721:17 | LL | mod inner { #![feature(x0600)] } | ^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:722:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:721:17 | LL | mod inner { #![feature(x0600)] } | ^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:726:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:725:5 | LL | #[feature(x0600)] fn f() { } | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:726:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:725:5 | LL | #[feature(x0600)] fn f() { } | ^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:730:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:729:5 | LL | #[feature(x0600)] struct S; | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:730:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:729:5 | LL | #[feature(x0600)] struct S; | ^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:734:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:733:5 | LL | #[feature(x0600)] type T = S; | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:734:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:733:5 | LL | #[feature(x0600)] type T = S; | ^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:738:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:737:5 | LL | #[feature(x0600)] impl S { } | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:738:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:737:5 | LL | #[feature(x0600)] impl S { } | ^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:718:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:717:1 | LL | #[feature(x0600)] | ^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:718:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:717:1 | LL | #[feature(x0600)] | ^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:748:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:747:17 | LL | mod inner { #![no_main="0400"] } | ^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:748:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:747:17 | LL | mod inner { #![no_main="0400"] } | ^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:752:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:751:5 | LL | #[no_main = "0400"] fn f() { } | ^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:752:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:751:5 | LL | #[no_main = "0400"] fn f() { } | ^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:756:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:755:5 | LL | #[no_main = "0400"] struct S; | ^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:756:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:755:5 | LL | #[no_main = "0400"] struct S; | ^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:760:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:759:5 | LL | #[no_main = "0400"] type T = S; | ^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:760:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:759:5 | LL | #[no_main = "0400"] type T = S; | ^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:764:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:763:5 | LL | #[no_main = "0400"] impl S { } | ^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:764:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:763:5 | LL | #[no_main = "0400"] impl S { } | ^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:744:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:743:1 | LL | #[no_main = "0400"] | ^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:744:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:743:1 | LL | #[no_main = "0400"] | ^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:786:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:785:17 | LL | mod inner { #![recursion_limit="0200"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:786:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:785:17 | LL | mod inner { #![recursion_limit="0200"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:790:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:789:5 | LL | #[recursion_limit="0200"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:790:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:789:5 | LL | #[recursion_limit="0200"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:794:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:793:5 | LL | #[recursion_limit="0200"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:794:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:793:5 | LL | #[recursion_limit="0200"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:798:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:797:5 | LL | #[recursion_limit="0200"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:798:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:797:5 | LL | #[recursion_limit="0200"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:802:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:801:5 | LL | #[recursion_limit="0200"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:802:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:801:5 | LL | #[recursion_limit="0200"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:782:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:781:1 | LL | #[recursion_limit="0200"] | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:782:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:781:1 | LL | #[recursion_limit="0200"] | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:811:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:810:17 | LL | mod inner { #![type_length_limit="0100"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:811:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:810:17 | LL | mod inner { #![type_length_limit="0100"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:815:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:814:5 | LL | #[type_length_limit="0100"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:815:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:814:5 | LL | #[type_length_limit="0100"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:819:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:818:5 | LL | #[type_length_limit="0100"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:819:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:818:5 | LL | #[type_length_limit="0100"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:823:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:822:5 | LL | #[type_length_limit="0100"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:823:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:822:5 | LL | #[type_length_limit="0100"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:827:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:826:5 | LL | #[type_length_limit="0100"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:827:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:826:5 | LL | #[type_length_limit="0100"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: unused attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:807:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:806:1 | LL | #[type_length_limit="0100"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo] - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:807:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:806:1 | LL | #[type_length_limit="0100"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1267,7 +1259,7 @@ LL | #![proc_macro_derive = "2500"] //~ WARN unused attribute | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: compilation successful - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:838:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:837:1 | LL | / fn main() { //~ ERROR compilation successful LL | | println!("Hello World"); -- cgit 1.4.1-3-g733a5 From f29e62aadf9efa961b3da9d960fb35f748aed0d5 Mon Sep 17 00:00:00 2001 From: Vadzim Dambrouski Date: Tue, 1 May 2018 17:48:31 +0300 Subject: Fix a warning in libcore on 16bit targets. This code is assuming that usize >= 32bits, but it is not the case on 16bit targets. It is producing a warning that will fail the compilation on MSP430 if deny(warnings) is enabled. It is very unlikely that someone would actually use this code on a microcontroller, but since unicode was merged into libcore we have compile it on 16bit targets. --- src/libcore/unicode/bool_trie.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/libcore/unicode/bool_trie.rs b/src/libcore/unicode/bool_trie.rs index 3e45b08f399..0e6437fded5 100644 --- a/src/libcore/unicode/bool_trie.rs +++ b/src/libcore/unicode/bool_trie.rs @@ -42,15 +42,15 @@ pub struct BoolTrie { } impl BoolTrie { pub fn lookup(&self, c: char) -> bool { - let c = c as usize; + let c = c as u32; if c < 0x800 { - trie_range_leaf(c, self.r1[c >> 6]) + trie_range_leaf(c, self.r1[(c >> 6) as usize]) } else if c < 0x10000 { - let child = self.r2[(c >> 6) - 0x20]; + let child = self.r2[(c >> 6) as usize - 0x20]; trie_range_leaf(c, self.r3[child as usize]) } else { - let child = self.r4[(c >> 12) - 0x10]; - let leaf = self.r5[((child as usize) << 6) + ((c >> 6) & 0x3f)]; + let child = self.r4[(c >> 12) as usize - 0x10]; + let leaf = self.r5[((child as usize) << 6) + ((c >> 6) as usize & 0x3f)]; trie_range_leaf(c, self.r6[leaf as usize]) } } @@ -63,14 +63,14 @@ pub struct SmallBoolTrie { impl SmallBoolTrie { pub fn lookup(&self, c: char) -> bool { - let c = c as usize; - match self.r1.get(c >> 6) { + let c = c as u32; + match self.r1.get((c >> 6) as usize) { Some(&child) => trie_range_leaf(c, self.r2[child as usize]), None => false, } } } -fn trie_range_leaf(c: usize, bitmap_chunk: u64) -> bool { +fn trie_range_leaf(c: u32, bitmap_chunk: u64) -> bool { ((bitmap_chunk >> (c & 63)) & 1) != 0 } -- cgit 1.4.1-3-g733a5 From 7f6d47314bde7b8c49651bcb3802f0994d531a34 Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 1 May 2018 00:13:14 +0100 Subject: Correct initial field alignment for repr(C)/repr(int) --- src/librustc/ty/layout.rs | 8 +++++-- src/test/run-pass/repr_c_int_align.rs | 39 +++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 src/test/run-pass/repr_c_int_align.rs (limited to 'src') diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 53dde3e6903..a319b341ebb 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -940,11 +940,15 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { // We increase the size of the discriminant to avoid LLVM copying // padding when it doesn't need to. This normally causes unaligned // load/stores and excessive memcpy/memset operations. By using a - // bigger integer size, LLVM can be sure about it's contents and + // bigger integer size, LLVM can be sure about its contents and // won't be so conservative. // Use the initial field alignment - let mut ity = Integer::for_abi_align(dl, start_align).unwrap_or(min_ity); + let mut ity = if def.repr.c() || def.repr.int.is_some() { + min_ity + } else { + Integer::for_abi_align(dl, start_align).unwrap_or(min_ity) + }; // If the alignment is not larger than the chosen discriminant size, // don't use the alignment as the final size. diff --git a/src/test/run-pass/repr_c_int_align.rs b/src/test/run-pass/repr_c_int_align.rs new file mode 100644 index 00000000000..32d015c3ca2 --- /dev/null +++ b/src/test/run-pass/repr_c_int_align.rs @@ -0,0 +1,39 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -O + +#![allow(dead_code)] + +#[repr(C, u8)] +enum ReprCu8 { + A(u16), + B, +} + +#[repr(C)] +struct ReprC { + tag: u8, + padding: u8, + payload: u16, +} + +fn main() { + let r1 = ReprC { tag: 0, padding: 0, payload: 0 }; + let r2 = ReprC { tag: 0, padding: 1, payload: 1 }; + + let t1: &ReprCu8 = unsafe { std::mem::transmute(&r1) }; + let t2: &ReprCu8 = unsafe { std::mem::transmute(&r2) }; + + match (t1, t2) { + (ReprCu8::A(_), ReprCu8::A(_)) => (), + _ => assert!(false) + }; +} -- cgit 1.4.1-3-g733a5 From 4da1f71e4be9f9105f504f9a303d05b69ab8971d Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 1 May 2018 18:52:27 +0100 Subject: Add repr(u8) to the test --- src/test/run-pass/repr_c_int_align.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'src') diff --git a/src/test/run-pass/repr_c_int_align.rs b/src/test/run-pass/repr_c_int_align.rs index 32d015c3ca2..af4eb615302 100644 --- a/src/test/run-pass/repr_c_int_align.rs +++ b/src/test/run-pass/repr_c_int_align.rs @@ -18,6 +18,12 @@ enum ReprCu8 { B, } +#[repr(u8)] +enum Repru8 { + A(u16), + B, +} + #[repr(C)] struct ReprC { tag: u8, @@ -26,6 +32,7 @@ struct ReprC { } fn main() { + // Test `repr(C, u8)`. let r1 = ReprC { tag: 0, padding: 0, payload: 0 }; let r2 = ReprC { tag: 0, padding: 1, payload: 1 }; @@ -36,4 +43,13 @@ fn main() { (ReprCu8::A(_), ReprCu8::A(_)) => (), _ => assert!(false) }; + + // Test `repr(u8)`. + let t1: &Repru8 = unsafe { std::mem::transmute(&r1) }; + let t2: &Repru8 = unsafe { std::mem::transmute(&r2) }; + + match (t1, t2) { + (Repru8::A(_), Repru8::A(_)) => (), + _ => assert!(false) + }; } -- cgit 1.4.1-3-g733a5 From 993f7c5715743600e924c5e90c5bff7a64879063 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 1 May 2018 21:25:38 +0300 Subject: rustbuild: Normalize paths coming from Python slightly Fixes #49785 --- src/bootstrap/config.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 1b4b2c5fb2a..7175f6a6764 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -325,6 +325,14 @@ struct TomlTarget { } impl Config { + fn path_from_python(var_key: &str) -> PathBuf { + match env::var_os(var_key) { + // Do not trust paths from Python and normalize them slightly (#49785). + Some(var_val) => Path::new(&var_val).components().collect(), + _ => panic!("expected '{}' to be set", var_key), + } + } + pub fn default_opts() -> Config { let mut config = Config::default(); config.llvm_enabled = true; @@ -348,9 +356,9 @@ impl Config { config.deny_warnings = true; // set by bootstrap.py - config.src = env::var_os("SRC").map(PathBuf::from).expect("'SRC' to be set"); config.build = INTERNER.intern_str(&env::var("BUILD").expect("'BUILD' to be set")); - config.out = env::var_os("BUILD_DIR").map(PathBuf::from).expect("'BUILD_DIR' set"); + config.src = Config::path_from_python("SRC"); + config.out = Config::path_from_python("BUILD_DIR"); let stage0_root = config.out.join(&config.build).join("stage0/bin"); config.initial_rustc = stage0_root.join(exe("rustc", &config.build)); -- cgit 1.4.1-3-g733a5 From 2d0d73ea5a004158e07ec6169b517c7ca6cbe3b0 Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 1 May 2018 20:25:30 +0100 Subject: Add a print_types_sizes regression test --- src/test/ui/print_type_sizes/repr_int_c.rs | 35 ++++++++++++++++++++++++++ src/test/ui/print_type_sizes/repr_int_c.stdout | 12 +++++++++ 2 files changed, 47 insertions(+) create mode 100644 src/test/ui/print_type_sizes/repr_int_c.rs create mode 100644 src/test/ui/print_type_sizes/repr_int_c.stdout (limited to 'src') diff --git a/src/test/ui/print_type_sizes/repr_int_c.rs b/src/test/ui/print_type_sizes/repr_int_c.rs new file mode 100644 index 00000000000..04bb2ab26f3 --- /dev/null +++ b/src/test/ui/print_type_sizes/repr_int_c.rs @@ -0,0 +1,35 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z print-type-sizes +// compile-pass + +// This test makes sure that the tag is not grown for `repr(C)` or `repr(u8)` +// variants (see https://github.com/rust-lang/rust/issues/50098 for the original bug). + +#![feature(start)] +#![allow(dead_code)] + +#[repr(C, u8)] +enum ReprCu8 { + A(u16), + B, +} + +#[repr(u8)] +enum Repru8 { + A(u16), + B, +} + +#[start] +fn start(_: isize, _: *const *const u8) -> isize { + 0 +} diff --git a/src/test/ui/print_type_sizes/repr_int_c.stdout b/src/test/ui/print_type_sizes/repr_int_c.stdout new file mode 100644 index 00000000000..254b3c7a853 --- /dev/null +++ b/src/test/ui/print_type_sizes/repr_int_c.stdout @@ -0,0 +1,12 @@ +print-type-size type: `ReprCu8`: 4 bytes, alignment: 2 bytes +print-type-size discriminant: 1 bytes +print-type-size variant `A`: 3 bytes +print-type-size padding: 1 bytes +print-type-size field `.0`: 2 bytes, alignment: 2 bytes +print-type-size variant `B`: 1 bytes +print-type-size type: `Repru8`: 4 bytes, alignment: 2 bytes +print-type-size discriminant: 1 bytes +print-type-size variant `A`: 3 bytes +print-type-size padding: 1 bytes +print-type-size field `.0`: 2 bytes, alignment: 2 bytes +print-type-size variant `B`: 0 bytes -- cgit 1.4.1-3-g733a5 From edb8d1c0d4b2e32088f3c6a77437b091b10ddf7e Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Fri, 13 Apr 2018 17:11:53 +0200 Subject: Conservatively assume dropping a generator touches its upvars, via locals' dtors. This is meant to address rust-lang/rust#49918. Review feedback: put back comment justifying skipping interior traversal. Review feedback: dropck generators like trait objects: all their upvars must outlive the generator itself, so just create a DtorckConstraint saying so. --- src/librustc_traits/dropck_outlives.rs | 40 +++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs index 5f4daf0d568..ba31ce2692f 100644 --- a/src/librustc_traits/dropck_outlives.rs +++ b/src/librustc_traits/dropck_outlives.rs @@ -193,14 +193,38 @@ fn dtorck_constraint_for_ty<'a, 'gcx, 'tcx>( .map(|ty| dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty)) .collect(), - ty::TyGenerator(def_id, substs, _) => { - // Note that the interior types are ignored here. - // Any type reachable inside the interior must also be reachable - // through the upvars. - substs - .upvar_tys(def_id, tcx) - .map(|ty| dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty)) - .collect() + ty::TyGenerator(def_id, substs, _interior) => { + // rust-lang/rust#49918: types can be constructed, stored + // in the interior, and sit idle when generator yields + // (and is subsequently dropped). + // + // It would be nice to descend into interior of a + // generator to determine what effects dropping it might + // have (by looking at any drop effects associated with + // its interior). + // + // However, the interior's representation uses things like + // TyGeneratorWitness that explicitly assume they are not + // traversed in such a manner. So instead, we will + // simplify things for now by treating all generators as + // if they were like trait objects, where its upvars must + // all be alive for the generator's (potential) + // destructor. + // + // In particular, skipping over `_interior` is safe + // because any side-effects from dropping `_interior` can + // only take place through references with lifetimes + // derived from lifetimes attached to the upvars, and we + // *do* incorporate the upvars here. + + let constraint = DtorckConstraint { + outlives: substs.upvar_tys(def_id, tcx).map(|t| t.into()).collect(), + dtorck_types: vec![], + overflows: vec![], + }; + debug!("dtorck_constraint: generator {:?} => {:?}", def_id, constraint); + + Ok(constraint) } ty::TyAdt(def, substs) => { -- cgit 1.4.1-3-g733a5 From f12d7a55fca7215a08029c90634ab54f883a9f1c Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Mon, 16 Apr 2018 12:41:32 +0200 Subject: Update ui/generator tests to reflect changes from new generator drop rules. --- src/test/ui/generator/borrowing.nll.stderr | 38 +++++++++++++++------- src/test/ui/generator/borrowing.rs | 4 +-- src/test/ui/generator/dropck.nll.stderr | 26 +++++++++------ src/test/ui/generator/dropck.rs | 5 +-- src/test/ui/generator/dropck.stderr | 15 +++++++-- .../ref-escapes-but-not-over-yield.nll.stderr | 18 +++++++--- 6 files changed, 74 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/test/ui/generator/borrowing.nll.stderr b/src/test/ui/generator/borrowing.nll.stderr index 1801da6c8b2..243e9018585 100644 --- a/src/test/ui/generator/borrowing.nll.stderr +++ b/src/test/ui/generator/borrowing.nll.stderr @@ -1,14 +1,30 @@ -error: compilation successful - --> $DIR/borrowing.rs:15:1 +error[E0597]: `a` does not live long enough + --> $DIR/borrowing.rs:18:18 | -LL | / fn main() { #![rustc_error] // rust-lang/rust#49855 -LL | | let _b = { -LL | | let a = 3; -LL | | unsafe { (|| yield &a).resume() } -... | -LL | | }; -LL | | } - | |_^ +LL | unsafe { (|| yield &a).resume() } + | ^^^^^^^^^^^^^ + | | + | borrowed value does not live long enough + | borrow may end up in a temporary, created here +LL | //~^ ERROR: `a` does not live long enough +LL | }; + | -- temporary later dropped here, potentially using the reference + | | + | borrowed value only lives until here -error: aborting due to previous error +error[E0597]: `a` does not live long enough + --> $DIR/borrowing.rs:24:9 + | +LL | / || { +LL | | yield &a +LL | | //~^ ERROR: `a` does not live long enough +LL | | } + | |_________^ borrowed value does not live long enough +LL | }; + | - borrowed value only lives until here +LL | } + | - borrow later used here, when `_b` is dropped + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/generator/borrowing.rs b/src/test/ui/generator/borrowing.rs index f80aca9fb00..e56927d8182 100644 --- a/src/test/ui/generator/borrowing.rs +++ b/src/test/ui/generator/borrowing.rs @@ -8,11 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(generators, generator_trait, rustc_attrs)] +#![feature(generators, generator_trait)] use std::ops::Generator; -fn main() { #![rustc_error] // rust-lang/rust#49855 +fn main() { let _b = { let a = 3; unsafe { (|| yield &a).resume() } diff --git a/src/test/ui/generator/dropck.nll.stderr b/src/test/ui/generator/dropck.nll.stderr index 72ebaab3278..c352fd6a62f 100644 --- a/src/test/ui/generator/dropck.nll.stderr +++ b/src/test/ui/generator/dropck.nll.stderr @@ -1,14 +1,20 @@ -error: compilation successful - --> $DIR/dropck.rs:16:1 +error[E0597]: `ref_` does not live long enough + --> $DIR/dropck.rs:22:11 | -LL | / fn main() { #![rustc_error] // rust-lang/rust#49855 -LL | | let (cell, mut gen); -LL | | cell = Box::new(RefCell::new(0)); -LL | | let ref_ = Box::leak(Box::new(Some(cell.borrow_mut()))); -... | -LL | | // drops the RefCell and then the Ref, leading to use-after-free -LL | | } - | |_^ +LL | gen = || { + | ___________^ +LL | | // but the generator can use it to drop a `Ref<'a, i32>`. +LL | | let _d = ref_.take(); //~ ERROR `ref_` does not live long enough +LL | | yield; +LL | | }; + | |_____^ borrowed value does not live long enough +... +LL | } + | - + | | + | borrowed value only lives until here + | borrow later used here, when `gen` is dropped error: aborting due to previous error +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/generator/dropck.rs b/src/test/ui/generator/dropck.rs index 8f4ba64fd57..857288818c6 100644 --- a/src/test/ui/generator/dropck.rs +++ b/src/test/ui/generator/dropck.rs @@ -8,15 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(generators, generator_trait, box_leak, rustc_attrs)] +#![feature(generators, generator_trait, box_leak)] use std::cell::RefCell; use std::ops::Generator; -fn main() { #![rustc_error] // rust-lang/rust#49855 +fn main() { let (cell, mut gen); cell = Box::new(RefCell::new(0)); let ref_ = Box::leak(Box::new(Some(cell.borrow_mut()))); + //~^ ERROR `*cell` does not live long enough [E0597] // the upvar is the non-dropck `&mut Option>`. gen = || { // but the generator can use it to drop a `Ref<'a, i32>`. diff --git a/src/test/ui/generator/dropck.stderr b/src/test/ui/generator/dropck.stderr index 4a22d299701..1a6fed2dd35 100644 --- a/src/test/ui/generator/dropck.stderr +++ b/src/test/ui/generator/dropck.stderr @@ -1,5 +1,16 @@ +error[E0597]: `*cell` does not live long enough + --> $DIR/dropck.rs:19:40 + | +LL | let ref_ = Box::leak(Box::new(Some(cell.borrow_mut()))); + | ^^^^ borrowed value does not live long enough +... +LL | } + | - `*cell` dropped here while still borrowed + | + = note: values in a scope are dropped in the opposite order they are created + error[E0597]: `ref_` does not live long enough - --> $DIR/dropck.rs:23:18 + --> $DIR/dropck.rs:24:18 | LL | gen = || { | -- capture occurs here @@ -12,6 +23,6 @@ LL | } | = note: values in a scope are dropped in the opposite order they are created -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/generator/ref-escapes-but-not-over-yield.nll.stderr b/src/test/ui/generator/ref-escapes-but-not-over-yield.nll.stderr index 08839c23c37..70870b98365 100644 --- a/src/test/ui/generator/ref-escapes-but-not-over-yield.nll.stderr +++ b/src/test/ui/generator/ref-escapes-but-not-over-yield.nll.stderr @@ -1,11 +1,19 @@ error[E0597]: `b` does not live long enough --> $DIR/ref-escapes-but-not-over-yield.rs:24:13 | -LL | a = &b; - | ^^ borrowed value does not live long enough -LL | //~^ ERROR `b` does not live long enough -LL | }; - | - borrowed value only lives until here +LL | let mut b = move || { + | _________________- +LL | | yield(); +LL | | let b = 5; +LL | | a = &b; + | | ^^ borrowed value does not live long enough +LL | | //~^ ERROR `b` does not live long enough +LL | | }; + | | - + | | | + | | borrowed value only lives until here + | |_____temporary later dropped here, potentially using the reference + | borrow may end up in a temporary, created here error: aborting due to previous error -- cgit 1.4.1-3-g733a5 From c1607f80b3d57b66386c1cab4b2b6ae069d4caba Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 1 May 2018 21:44:37 +0100 Subject: Add E0589 to the error index --- src/libsyntax/diagnostic_list.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/libsyntax/diagnostic_list.rs b/src/libsyntax/diagnostic_list.rs index c9cac1b1142..d1f123f6f6c 100644 --- a/src/libsyntax/diagnostic_list.rs +++ b/src/libsyntax/diagnostic_list.rs @@ -244,6 +244,18 @@ fn main() { ``` "##, +E0589: r##" +The value of `N` that was specified for `repr(align(N))` was not a power +of two, or was greater than 2^29. + +```compile_fail,E0589 +#[repr(align(15))] // error: invalid `repr(align)` attribute: not a power of two +enum Foo { + Bar(u64), +} +``` +"##, + E0658: r##" An unstable feature was used. @@ -321,7 +333,6 @@ register_diagnostics! { E0555, // malformed feature attribute, expected #![feature(...)] E0556, // malformed feature, expected just one word E0584, // file for module `..` found at both .. and .. - E0589, // invalid `repr(align)` attribute E0629, // missing 'feature' (rustc_const_unstable) E0630, // rustc_const_unstable attribute must be paired with stable/unstable attribute E0693, // incorrect `repr(align)` attribute format -- cgit 1.4.1-3-g733a5 From cd2f5f7d977936c409f4bec28075c8918e239f4c Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 1 May 2018 21:26:23 +0100 Subject: Reduce the maximum alignment to repr(align(1 << 29)) This brings it into line with LLVM's maximum permitted alignment. --- src/librustc_target/abi/mod.rs | 8 ++++---- src/libsyntax/attr.rs | 6 +++--- src/test/compile-fail/repr-align.rs | 5 ++++- 3 files changed, 11 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index f73085196f4..fd1f779f9ec 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -326,9 +326,9 @@ impl AddAssign for Size { } /// Alignment of a type in bytes, both ABI-mandated and preferred. -/// Each field is a power of two, giving the alignment a maximum value of -/// 2(28 - 1), which is limited by LLVM to a i32, -/// with a maximum capacity of 231 - 1 or 2147483647. +/// Each field is a power of two, giving the alignment a maximum value +/// of 2(28 - 1), which is limited by LLVM to a +/// maximum capacity of 229 or 536870912. #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] pub struct Align { abi_pow2: u8, @@ -356,7 +356,7 @@ impl Align { } if bytes != 1 { Err(format!("`{}` is not a power of 2", align)) - } else if pow > 30 { + } else if pow > 29 { Err(format!("`{}` is too large", align)) } else { Ok(pow) diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index f0557277267..13f8bb9a318 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -1012,11 +1012,11 @@ pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec let parse_alignment = |node: &ast::LitKind| -> Result { if let ast::LitKind::Int(literal, ast::LitIntType::Unsuffixed) = node { if literal.is_power_of_two() { - // rustc::ty::layout::Align restricts align to <= 2147483647 - if *literal <= 2147483647 { + // rustc::ty::layout::Align restricts align to <= 2^29 + if *literal <= 1 << 29 { Ok(*literal as u32) } else { - Err("larger than 2147483647") + Err("larger than 2^29") } } else { Err("not a power of two") diff --git a/src/test/compile-fail/repr-align.rs b/src/test/compile-fail/repr-align.rs index 7c8eb6a2de9..9b0408de2a4 100644 --- a/src/test/compile-fail/repr-align.rs +++ b/src/test/compile-fail/repr-align.rs @@ -15,7 +15,10 @@ struct A(i32); #[repr(align(15))] //~ ERROR: invalid `repr(align)` attribute: not a power of two struct B(i32); -#[repr(align(4294967296))] //~ ERROR: invalid `repr(align)` attribute: larger than 2147483647 +#[repr(align(4294967296))] //~ ERROR: invalid `repr(align)` attribute: larger than 2^29 struct C(i32); +#[repr(align(536870912))] // ok: this is the largest accepted alignment +struct D(i32); + fn main() {} -- cgit 1.4.1-3-g733a5 From 6457241133b20cf447dec325c0f846e4dea51c71 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 2 May 2018 07:50:58 +1200 Subject: Update RLS and Rustfmt --- src/Cargo.lock | 71 ++++++++++++++++++++++++++++++++++--------------------- src/tools/rls | 2 +- src/tools/rustfmt | 2 +- 3 files changed, 46 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/Cargo.lock b/src/Cargo.lock index 940ca1aace0..f482bed3176 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1623,7 +1623,7 @@ dependencies = [ [[package]] name = "rls" -version = "0.126.0" +version = "0.127.0" dependencies = [ "cargo 0.28.0", "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1644,7 +1644,7 @@ dependencies = [ "rls-rustc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rls-vfs 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustfmt-nightly 0.6.0", + "rustfmt-nightly 0.6.1", "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1739,16 +1739,17 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_cratesio_shim" -version = "110.0.0" +version = "113.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_data_structures" -version = "110.0.0" +version = "113.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1756,53 +1757,66 @@ dependencies = [ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-rustc_errors" -version = "110.0.0" +version = "113.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rustc-ap-rustc_target" +version = "113.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_cratesio_shim 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rustc-ap-serialize" -version = "110.0.0" +version = "113.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-ap-syntax" -version = "110.0.0" +version = "113.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_cratesio_shim 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_data_structures 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-rustc_errors 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax_pos 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_errors 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax_pos 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-ap-syntax_pos" -version = "110.0.0" +version = "113.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc-ap-rustc_data_structures 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-serialize 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_data_structures 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-serialize 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2221,20 +2235,22 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "0.6.0" +version = "0.6.1" dependencies = [ "assert_cli 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "derive-new 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-ap-syntax 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-rustc_target 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-ap-syntax 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3120,12 +3136,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rls-rustc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "885f66b92757420572cbb02e033d4a9558c7413ca9b7ac206f28fd58ffdb44ea" "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a" "checksum rls-vfs 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "be231e1e559c315bc60ced5ad2cc2d7a9c208ed7d4e2c126500149836fda19bb" -"checksum rustc-ap-rustc_cratesio_shim 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0256e318ad99c467d24bd7188f2d4a3028360621bb92d769b4b65fc44717d514" -"checksum rustc-ap-rustc_data_structures 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83430df7f76ea85c1f70fe145041576eee8fd5d77053bf426df24b480918d185" -"checksum rustc-ap-rustc_errors 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2b03f874277103039816f6467b1ff30a81b1d6a29d4de6efccefe4c488f6535a" -"checksum rustc-ap-serialize 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a2e47cf949f06b0c7ab7566c2f69d49f28cb3ecf1bb8bf0bda48b1ba5b7945ae" -"checksum rustc-ap-syntax 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "625e6fb41fde299082cda3bceb08f81c9ba56b14a2ec737b4366f9c3c9be07d8" -"checksum rustc-ap-syntax_pos 110.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "474a23ef1a1245ae02c5fd6a1e9a0725ce6fd25ca2294703c03bddce041f867b" +"checksum rustc-ap-rustc_cratesio_shim 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a01334797c5c4cf56cc40bb9636d7b4c4a076665b9b9b7f100fd666cf0a02ffc" +"checksum rustc-ap-rustc_data_structures 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "03d6f8f7da0de905f6ef80dc14dce3bbc372430622b6aeb421cf13190bc70e8a" +"checksum rustc-ap-rustc_errors 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3dfd6183804a685c48601651d8c8c7b0daa8f83b0b5e24edfbcb6a0337085127" +"checksum rustc-ap-rustc_target 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5f223157f51bf0e0621bef099de862468892ee4c4b83056f48f63e1bc00ccb72" +"checksum rustc-ap-serialize 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2104a55a87d65cba8a845656f1f19a35da52af403863cd2a4bd5876ba522d879" +"checksum rustc-ap-syntax 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b50671adb9b0a7c57a4690ac6a40cb614879f543b64aada42f55b66212492323" +"checksum rustc-ap-syntax_pos 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "55793c2a775230c42661194c48d44b35d4c8439d79ad8528e56651e854c48c63" "checksum rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11fb43a206a04116ffd7cfcf9bcb941f8eb6cc7ff667272246b0a1c74259a3cb" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7" diff --git a/src/tools/rls b/src/tools/rls index 9144e223a5b..99796f6a659 160000 --- a/src/tools/rls +++ b/src/tools/rls @@ -1 +1 @@ -Subproject commit 9144e223a5b90e078366275ff3dcdd406e62eae3 +Subproject commit 99796f6a6592b4d897719a1736ec580c96f5441a diff --git a/src/tools/rustfmt b/src/tools/rustfmt index 0f4ed08d0e3..d8982e5efe8 160000 --- a/src/tools/rustfmt +++ b/src/tools/rustfmt @@ -1 +1 @@ -Subproject commit 0f4ed08d0e3d180d66e46904126c3792f57668a9 +Subproject commit d8982e5efe8fda1d6f64e88a67da2f05b6af225e -- cgit 1.4.1-3-g733a5 From e27d20a7ba01a67d7b46ff0edef2fa53f5421035 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 30 Jan 2018 13:12:37 +0900 Subject: Add tests for a new feature 'tool_attributes' --- .../compile-fail/feature-gate-tool_attributes.rs | 15 ++++++++++++++ src/test/compile-fail/unknown-tool-name.rs | 16 +++++++++++++++ src/test/compile-fail/unknown_tool_attributes-1.rs | 18 +++++++++++++++++ src/test/run-pass/tool_attributes.rs | 23 ++++++++++++++++++++++ src/test/ui/feature-gate-tool_attributes.rs | 15 ++++++++++++++ src/test/ui/feature-gate-tool_attributes.stderr | 10 ++++++++++ 6 files changed, 97 insertions(+) create mode 100644 src/test/compile-fail/feature-gate-tool_attributes.rs create mode 100644 src/test/compile-fail/unknown-tool-name.rs create mode 100644 src/test/compile-fail/unknown_tool_attributes-1.rs create mode 100644 src/test/run-pass/tool_attributes.rs create mode 100644 src/test/ui/feature-gate-tool_attributes.rs create mode 100644 src/test/ui/feature-gate-tool_attributes.stderr (limited to 'src') diff --git a/src/test/compile-fail/feature-gate-tool_attributes.rs b/src/test/compile-fail/feature-gate-tool_attributes.rs new file mode 100644 index 00000000000..5a7536ca330 --- /dev/null +++ b/src/test/compile-fail/feature-gate-tool_attributes.rs @@ -0,0 +1,15 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + #[rustfmt::skip] //~ ERROR scoped attribute `rustfmt::skip` is experimental + let x = + 3; +} diff --git a/src/test/compile-fail/unknown-tool-name.rs b/src/test/compile-fail/unknown-tool-name.rs new file mode 100644 index 00000000000..1ee837b05d8 --- /dev/null +++ b/src/test/compile-fail/unknown-tool-name.rs @@ -0,0 +1,16 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(tool_attributes)] + +#![foo::bar] //~ ERROR An unkown tool name found in scoped attributes: `foo::bar`. [E0693] + +#[foo::bar] //~ ERROR An unkown tool name found in scoped attributes: `foo::bar`. [E0693] +fn main() {} diff --git a/src/test/compile-fail/unknown_tool_attributes-1.rs b/src/test/compile-fail/unknown_tool_attributes-1.rs new file mode 100644 index 00000000000..08a7bfed278 --- /dev/null +++ b/src/test/compile-fail/unknown_tool_attributes-1.rs @@ -0,0 +1,18 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Make sure that 'custom_attributes' feature does not allow scoped attributes. + +#![feature(custom_attributes)] + +#[foo::bar] +//~^ ERROR scoped attribute `foo::bar` is experimental (see issue #44690) [E0658] +//~^^ ERROR An unkown tool name found in scoped attributes: `foo::bar`. [E0693] +fn main() {} diff --git a/src/test/run-pass/tool_attributes.rs b/src/test/run-pass/tool_attributes.rs new file mode 100644 index 00000000000..eb13930de40 --- /dev/null +++ b/src/test/run-pass/tool_attributes.rs @@ -0,0 +1,23 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Scoped attributes should not trigger an unused attributes lint. + +#![feature(tool_attributes)] +#![deny(unused_attributes)] + +fn main() { + #[rustfmt::skip] + foo (); +} + +fn foo() { + assert!(true); +} diff --git a/src/test/ui/feature-gate-tool_attributes.rs b/src/test/ui/feature-gate-tool_attributes.rs new file mode 100644 index 00000000000..2b7cf56d938 --- /dev/null +++ b/src/test/ui/feature-gate-tool_attributes.rs @@ -0,0 +1,15 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + #[rustfmt::skip] //~ ERROR scoped attribute `rustfmt::skip` is experimental + let x = 3 + ; +} diff --git a/src/test/ui/feature-gate-tool_attributes.stderr b/src/test/ui/feature-gate-tool_attributes.stderr new file mode 100644 index 00000000000..13307bd7133 --- /dev/null +++ b/src/test/ui/feature-gate-tool_attributes.stderr @@ -0,0 +1,10 @@ +error[E0658]: scoped attribute `rustfmt::skip` is experimental (see issue #44690) + --> $DIR/feature-gate-tool_attributes.rs:12:5 + | +12 | #[rustfmt::skip] //~ ERROR scoped attribute `rustfmt::skip` is experimental + | ^^^^^^^^^^^^^^^^ + | + = help: add #![feature(tool_attributes)] to the crate attributes to enable + +error: aborting due to previous error + -- cgit 1.4.1-3-g733a5 From 759bd01e039452a1a357d347aea51348f9ffc443 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 30 Jan 2018 14:30:39 +0900 Subject: Allow Path for name of MetaItem --- src/librustc/ich/impls_syntax.rs | 16 +++-- src/librustc_driver/lib.rs | 2 +- src/librustc_resolve/macros.rs | 2 +- src/libsyntax/ast.rs | 4 +- src/libsyntax/attr.rs | 139 ++++++++++++++++++++++++++++----------- src/libsyntax/ext/derive.rs | 3 +- src/libsyntax/ext/expand.rs | 2 +- src/libsyntax/parse/attr.rs | 7 +- src/libsyntax/print/pprust.rs | 36 +++++----- 9 files changed, 141 insertions(+), 70 deletions(-) (limited to 'src') diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index c1e86473996..ed7b79b392d 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -211,6 +211,17 @@ impl<'a> HashStable> for [ast::Attribute] { } } +impl<'a> HashStable> for ast::Path { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher) { + self.segments.len().hash_stable(hcx, hasher); + for segment in &self.segments { + segment.identifier.name.hash_stable(hcx, hasher); + } + } +} + impl<'a> HashStable> for ast::Attribute { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, @@ -229,10 +240,7 @@ impl<'a> HashStable> for ast::Attribute { } = *self; style.hash_stable(hcx, hasher); - path.segments.len().hash_stable(hcx, hasher); - for segment in &path.segments { - segment.ident.name.hash_stable(hcx, hasher); - } + path.hash_stable(hcx, hasher); for tt in tokens.trees() { tt.hash_stable(hcx, hasher); } diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 3f166daac71..67ba55a6aab 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -1060,7 +1060,7 @@ impl RustcDefaultCalls { let mut cfgs = Vec::new(); for &(name, ref value) in sess.parse_sess.config.iter() { let gated_cfg = GatedCfg::gate(&ast::MetaItem { - ident: ast::Ident::with_empty_ctxt(name), + name: ast::Path::from_ident(DUMMY_SP, name.to_ident()), node: ast::MetaItemKind::Word, span: DUMMY_SP, }); diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 3d20f922ac0..35228748f06 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -235,7 +235,7 @@ impl<'a> base::Resolver for Resolver<'a> { if name == "derive" { let result = attrs[i].parse_list(&self.session.parse_sess, |parser| { - parser.parse_path_allowing_meta(PathStyle::Mod) + parser.parse_path(PathStyle::Mod) }); let mut traits = match result { diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index b590a4a6286..bc457f49fcf 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -474,10 +474,10 @@ pub enum NestedMetaItemKind { /// A spanned compile-time attribute item. /// -/// E.g. `#[test]`, `#[derive(..)]` or `#[feature = "foo"]` +/// E.g. `#[test]`, `#[derive(..)]`, `#[rustfmt::skip]` or `#[feature = "foo"]` #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct MetaItem { - pub ident: Ident, + pub name: Path, pub node: MetaItemKind, pub span: Span, } diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index f0557277267..7a0231dc3f4 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -137,7 +137,7 @@ impl NestedMetaItem { /// 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.ident.name)) + self.meta_item().and_then(|meta_item| Some(meta_item.name())) } /// Gets the string value if self is a MetaItem and the MetaItem is a @@ -154,7 +154,7 @@ impl NestedMetaItem { if meta_item_list.len() == 1 { let nested_item = &meta_item_list[0]; if nested_item.is_literal() { - Some((meta_item.ident.name, nested_item.literal().unwrap())) + Some((meta_item.name(), nested_item.literal().unwrap())) } else { None } @@ -204,6 +204,10 @@ impl NestedMetaItem { } } +fn name_from_path(path: &ast::Path) -> Name { + path.segments.iter().next().unwrap().identifier.name +} + impl Attribute { pub fn check_name(&self, name: &str) -> bool { let matches = self.path == name; @@ -215,7 +219,7 @@ impl Attribute { pub fn name(&self) -> Option { match self.path.segments.len() { - 1 => Some(self.path.segments[0].ident.name), + 1 => Some(self.path.segments[0].identifier.name), _ => None, } } @@ -250,6 +254,10 @@ impl Attribute { } impl MetaItem { + pub fn name(&self) -> Name { + name_from_path(&self.name) + } + pub fn value_str(&self) -> Option { match self.node { MetaItemKind::NameValue(ref v) => { @@ -279,7 +287,7 @@ impl MetaItem { pub fn span(&self) -> Span { self.span } pub fn check_name(&self, name: &str) -> bool { - self.ident.name == name + self.name() == name } pub fn is_value_str(&self) -> bool { @@ -296,10 +304,7 @@ impl Attribute { pub fn meta(&self) -> Option { let mut tokens = self.tokens.trees().peekable(); Some(MetaItem { - ident: match self.path.segments.len() { - 1 => self.path.segments[0].ident, - _ => return None, - }, + name: self.path.clone(), node: if let Some(node) = MetaItemKind::from_tokens(&mut tokens) { if tokens.peek().is_some() { return None; @@ -344,12 +349,8 @@ impl Attribute { } pub fn parse_meta<'a>(&self, sess: &'a ParseSess) -> PResult<'a, MetaItem> { - if self.path.segments.len() > 1 { - sess.span_diagnostic.span_err(self.path.span, "expected ident, found path"); - } - Ok(MetaItem { - ident: self.path.segments.last().unwrap().ident, + name: self.path.clone(), node: self.parse(sess, |parser| parser.parse_meta_item_kind())?, span: self.span, }) @@ -397,8 +398,31 @@ pub fn mk_list_item(span: Span, ident: Ident, items: Vec) -> Met pub fn mk_word_item(ident: Ident) -> MetaItem { MetaItem { ident, span: ident.span, node: MetaItemKind::Word } } -pub fn mk_nested_word_item(ident: Ident) -> NestedMetaItem { - respan(ident.span, NestedMetaItemKind::MetaItem(mk_word_item(ident))) + +pub fn mk_word_item(name: Name) -> MetaItem { + mk_spanned_word_item(DUMMY_SP, name) +} + +macro_rules! mk_spanned_meta_item { + ($sp:ident, $name:ident, $node:expr) => { + MetaItem { + span: $sp, + name: ast::Path::from_ident($sp, ast::Ident::with_empty_ctxt($name)), + node: $node, + } + } +} + +pub fn mk_spanned_name_value_item(sp: Span, name: Name, value: ast::Lit) -> MetaItem { + mk_spanned_meta_item!(sp, name, MetaItemKind::NameValue(value)) +} + +pub fn mk_spanned_list_item(sp: Span, name: Name, items: Vec) -> MetaItem { + mk_spanned_meta_item!(sp, name, MetaItemKind::List(items)) +} + +pub fn mk_spanned_word_item(sp: Span, name: Name) -> MetaItem { + mk_spanned_meta_item!(sp, name, MetaItemKind::Word) } pub fn mk_attr_id() -> AttrId { @@ -422,7 +446,7 @@ pub fn mk_spanned_attr_inner(sp: Span, id: AttrId, item: MetaItem) -> Attribute Attribute { id, style: ast::AttrStyle::Inner, - path: ast::Path::from_ident(item.ident), + path: item.name, tokens: item.node.tokens(item.span), is_sugared_doc: false, span: sp, @@ -440,7 +464,7 @@ pub fn mk_spanned_attr_outer(sp: Span, id: AttrId, item: MetaItem) -> Attribute Attribute { id, style: ast::AttrStyle::Outer, - path: ast::Path::from_ident(item.ident), + path: item.name, tokens: item.node.tokens(item.span), is_sugared_doc: false, span: sp, @@ -489,7 +513,7 @@ pub fn contains_feature_attr(attrs: &[Attribute], feature_name: &str) -> bool { item.check_name("feature") && item.meta_item_list().map(|list| { list.iter().any(|mi| { - mi.word().map(|w| w.ident.name == feature_name) + mi.word().map(|w| w.name() == feature_name) .unwrap_or(false) }) }).unwrap_or(false) @@ -562,7 +586,7 @@ pub fn cfg_matches(cfg: &ast::MetaItem, sess: &ParseSess, features: Option<&Feat if let (Some(feats), Some(gated_cfg)) = (features, GatedCfg::gate(cfg)) { gated_cfg.check_and_emit(sess, feats); } - sess.config.contains(&(cfg.ident.name, cfg.value_str())) + sess.config.contains(&(cfg.name(), cfg.value_str())) }) } @@ -583,7 +607,7 @@ 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.ident.name.as_str() { + match &*cfg.name().as_str() { "any" => mis.iter().any(|mi| { eval_condition(mi.meta_item().unwrap(), sess, eval) }), @@ -676,7 +700,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler, let meta = meta.as_ref().unwrap(); let get = |meta: &MetaItem, item: &mut Option| { if item.is_some() { - handle_errors(diagnostic, meta.span, AttrError::MultipleItem(meta.ident.name)); + handle_errors(diagnostic, meta.span, AttrError::MultipleItem(meta.name())); return false } if let Some(v) = meta.value_str() { @@ -695,14 +719,14 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler, )+ for meta in metas { if let Some(mi) = meta.meta_item() { - match &*mi.ident.name.as_str() { + match &*mi.name().as_str() { $( stringify!($name) => if !get(mi, &mut $name) { continue 'outer }, )+ _ => { handle_errors(diagnostic, mi.span, - AttrError::UnknownMetaItem(mi.ident.name)); + AttrError::UnknownMetaItem(mi.name())); continue 'outer } } @@ -714,7 +738,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler, } } - match &*meta.ident.name.as_str() { + match &*meta.name().as_str() { "rustc_deprecated" => { if rustc_depr.is_some() { span_err!(diagnostic, item_sp, E0540, @@ -769,13 +793,13 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler, let mut issue = None; for meta in metas { if let Some(mi) = meta.meta_item() { - match &*mi.ident.name.as_str() { + 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 }, _ => { handle_errors(diagnostic, meta.span, - AttrError::UnknownMetaItem(mi.ident.name)); + AttrError::UnknownMetaItem(mi.name())); continue 'outer } } @@ -825,12 +849,12 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler, let mut since = None; for meta in metas { if let NestedMetaItemKind::MetaItem(ref mi) = meta.node { - match &*mi.ident.name.as_str() { + match &*mi.name().as_str() { "feature" => if !get(mi, &mut feature) { continue 'outer }, "since" => if !get(mi, &mut since) { continue 'outer }, _ => { handle_errors(diagnostic, meta.span, - AttrError::UnknownMetaItem(mi.ident.name)); + AttrError::UnknownMetaItem(mi.name())); continue 'outer } } @@ -917,7 +941,7 @@ fn find_deprecation_generic<'a, I>(diagnostic: &Handler, depr = if let Some(metas) = attr.meta_item_list() { let get = |meta: &MetaItem, item: &mut Option| { if item.is_some() { - handle_errors(diagnostic, meta.span, AttrError::MultipleItem(meta.ident.name)); + handle_errors(diagnostic, meta.span, AttrError::MultipleItem(meta.name())); return false } if let Some(v) = meta.value_str() { @@ -933,12 +957,12 @@ fn find_deprecation_generic<'a, I>(diagnostic: &Handler, let mut note = None; for meta in metas { if let NestedMetaItemKind::MetaItem(ref mi) = meta.node { - match &*mi.ident.name.as_str() { + match &*mi.name().as_str() { "since" => if !get(mi, &mut since) { continue 'outer }, "note" => if !get(mi, &mut note) { continue 'outer }, _ => { handle_errors(diagnostic, meta.span, - AttrError::UnknownMetaItem(mi.ident.name)); + AttrError::UnknownMetaItem(mi.name())); continue 'outer } } @@ -990,7 +1014,7 @@ pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec let mut recognised = false; if let Some(mi) = item.word() { - let word = &*mi.ident.name.as_str(); + let word = &*mi.name().as_str(); let hint = match word { "C" => Some(ReprC), "packed" => Some(ReprPacked(1)), @@ -1127,18 +1151,52 @@ impl IntType { impl MetaItem { fn tokens(&self) -> TokenStream { - let ident = TokenTree::Token(self.span, Token::from_ast_ident(self.ident)); - TokenStream::concat(vec![ident.into(), self.node.tokens(self.span)]) + let mut idents = vec![]; + let mut last_pos = BytePos(0 as u32); + for (i, segment) in self.name.segments.iter().enumerate() { + let is_first = i == 0; + if !is_first { + let mod_sep_span = Span::new(last_pos, segment.span.lo(), segment.span.ctxt()); + idents.push(TokenTree::Token(mod_sep_span, Token::ModSep).into()); + } + idents.push(TokenTree::Token(segment.span, Token::Ident(segment.identifier)).into()); + last_pos = segment.span.hi(); + } + idents.push(self.node.tokens(self.span)); + TokenStream::concat(idents) } fn from_tokens(tokens: &mut iter::Peekable) -> Option where I: Iterator, { - let (span, ident) = match tokens.next() { - Some(TokenTree::Token(span, Token::Ident(ident, _))) => (span, ident), + let name = match tokens.next() { + Some(TokenTree::Token(span, Token::Ident(ident))) => { + if let Some(TokenTree::Token(_, Token::ModSep)) = tokens.peek() { + tokens.next(); + let mut segments = vec![]; + loop { + if let Some(TokenTree::Token(span, Token::Ident(ident))) = tokens.next() { + segments.push(ast::PathSegment::from_ident(ident, span)); + } else { + return None; + } + if let Some(TokenTree::Token(_, Token::ModSep)) = tokens.peek() { + tokens.next(); + } else { + break; + } + } + ast::Path { span, segments } + } else { + ast::Path::from_ident(span, ident) + } + } Some(TokenTree::Token(_, Token::Interpolated(ref nt))) => match nt.0 { - token::Nonterminal::NtIdent(ident, _) => (ident.span, ident), + token::Nonterminal::NtIdent(ident) => { + ast::Path::from_ident(ident.span, ident.node) + } token::Nonterminal::NtMeta(ref meta) => return Some(meta.clone()), + token::Nonterminal::NtPath(ref path) => path.clone(), _ => return None, }, _ => return None, @@ -1147,10 +1205,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(span.hi()), - _ => span.hi(), + MetaItemKind::List(..) => list_closing_paren_pos.unwrap_or(name.span.hi()), + _ => name.span.hi(), }; - Some(MetaItem { ident, node, span: span.with_hi(hi) }) + let span = name.span.with_hi(hi); + Some(MetaItem { name, node, span }) } } diff --git a/src/libsyntax/ext/derive.rs b/src/libsyntax/ext/derive.rs index 6bf166dfe95..afb233533ba 100644 --- a/src/libsyntax/ext/derive.rs +++ b/src/libsyntax/ext/derive.rs @@ -26,8 +26,7 @@ pub fn collect_derives(cx: &mut ExtCtxt, attrs: &mut Vec) -> Vec return true; } - match attr.parse_list(cx.parse_sess, - |parser| parser.parse_path_allowing_meta(PathStyle::Mod)) { + match attr.parse_list(cx.parse_sess, |parser| parser.parse_path(PathStyle::Mod)) { Ok(ref traits) if traits.is_empty() => { cx.span_warn(attr.span, "empty trait list in `derive`"); false diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 2f3b35c33f3..1d16a7eb091 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -810,7 +810,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: keywords::Invalid.ident(), + name: Path::from_ident(DUMMY_SP, keywords::Invalid.ident()), span: DUMMY_SP, node: ast::MetaItemKind::Word, }; diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index 90f08ab1468..0671f29648f 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(); - (ast::Path::from_ident(meta.ident), meta.node.tokens(meta.span)) + (meta.name, meta.node.tokens(meta.span)) } else { (self.parse_path(PathStyle::Mod)?, self.parse_tokens()) }) @@ -225,9 +225,10 @@ impl<'a> Parser<'a> { } let lo = self.span; - let ident = self.parse_ident()?; + let name = self.parse_path(PathStyle::Mod)?; let node = self.parse_meta_item_kind()?; - Ok(ast::MetaItem { ident, node: node, span: lo.to(self.prev_span) }) + let span = lo.to(self.prev_span); + Ok(ast::MetaItem { name, node, span }) } pub fn parse_meta_item_kind(&mut self) -> PResult<'a, ast::MetaItemKind> { diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 88860df10e2..e8beb7e442c 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -714,6 +714,22 @@ pub trait PrintState<'a> { Ok(()) } + fn print_attribute_path(&mut self, path: &ast::Path) -> io::Result<()> { + for (i, segment) in path.segments.iter().enumerate() { + if i > 0 { + self.writer().word("::")? + } + if segment.identifier.name != keywords::CrateRoot.name() && + segment.identifier.name != keywords::DollarCrate.name() + { + self.writer().word(&segment.identifier.name.as_str())?; + } else if segment.identifier.name == keywords::DollarCrate.name() { + self.print_dollar_crate(segment.identifier.ctxt)?; + } + } + Ok(()) + } + fn print_attribute(&mut self, attr: &ast::Attribute) -> io::Result<()> { self.print_attribute_inline(attr, false) } @@ -735,17 +751,7 @@ pub trait PrintState<'a> { if let Some(mi) = attr.meta() { self.print_meta_item(&mi)? } else { - for (i, segment) in attr.path.segments.iter().enumerate() { - if i > 0 { - self.writer().word("::")? - } - if segment.ident.name != keywords::CrateRoot.name() && - segment.ident.name != keywords::DollarCrate.name() { - self.writer().word(&segment.ident.name.as_str())?; - } else if segment.ident.name == keywords::DollarCrate.name() { - self.print_dollar_crate(segment.ident.span.ctxt())?; - } - } + self.print_attribute_path(&attr.path)?; self.writer().space()?; self.print_tts(attr.tokens.clone())?; } @@ -767,16 +773,14 @@ 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.writer().word(&item.ident.name.as_str())?; - } + ast::MetaItemKind::Word => self.print_attribute_path(&item.name)?, ast::MetaItemKind::NameValue(ref value) => { - self.word_space(&item.ident.name.as_str())?; + self.print_attribute_path(&item.name)?; self.word_space("=")?; self.print_literal(value)?; } ast::MetaItemKind::List(ref items) => { - self.writer().word(&item.ident.name.as_str())?; + self.print_attribute_path(&item.name)?; self.popen()?; self.commasep(Consistent, &items[..], -- cgit 1.4.1-3-g733a5 From 9b3aea602c37d53bbecf8bff8c77ccbfbefc23d0 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 30 Jan 2018 14:53:01 +0900 Subject: Remove Option from the return type of Attribute::name() --- src/librustc/hir/check_attr.rs | 5 +---- src/librustc/ich/impls_syntax.rs | 5 ++--- src/librustc/lint/levels.rs | 2 +- src/librustc/middle/stability.rs | 2 +- src/librustc_lint/builtin.rs | 3 +-- src/librustc_lint/lib.rs | 1 - src/librustc_lint/unused.rs | 3 +-- src/librustc_resolve/macros.rs | 6 +++--- src/librustdoc/clean/mod.rs | 2 +- src/librustdoc/html/render.rs | 2 +- src/libsyntax/attr.rs | 9 ++++----- src/libsyntax/ext/derive.rs | 3 ++- src/libsyntax/feature_gate.rs | 2 +- src/libsyntax/parse/parser.rs | 8 ++++---- src/libsyntax/print/pprust.rs | 1 + src/libsyntax_ext/deriving/custom.rs | 8 +++----- src/libsyntax_ext/deriving/generic/mod.rs | 2 +- 17 files changed, 28 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index cad6ff8ae9f..e8bdb9d5d5f 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -153,10 +153,7 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> { // ``` let hints: Vec<_> = item.attrs .iter() - .filter(|attr| match attr.name() { - Some(name) => name == "repr", - None => false, - }) + .filter(|attr| attr.name() == "repr") .filter_map(|attr| attr.meta_item_list()) .flat_map(|hints| hints) .collect(); diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index ed7b79b392d..d90dba2ff04 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -199,8 +199,7 @@ impl<'a> HashStable> for [ast::Attribute] { let filtered: AccumulateVec<[&ast::Attribute; 8]> = self .iter() .filter(|attr| { - !attr.is_sugared_doc && - attr.name().map(|name| !hcx.is_ignored_attr(name)).unwrap_or(true) + !attr.is_sugared_doc && !hcx.is_ignored_attr(attr.name()) }) .collect(); @@ -227,7 +226,7 @@ impl<'a> HashStable> for ast::Attribute { hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { // Make sure that these have been filtered out. - debug_assert!(self.name().map(|name| !hcx.is_ignored_attr(name)).unwrap_or(true)); + debug_assert!(!hcx.is_ignored_attr(self.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 e8b536d5267..0eeb0cf6c37 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -198,7 +198,7 @@ impl<'a> LintLevelsBuilder<'a> { "malformed lint attribute"); }; for attr in attrs { - let level = match attr.name().and_then(|name| Level::from_str(&name.as_str())) { + let level = match Level::from_str(&attr.name().as_str()) { None => continue, Some(lvl) => lvl, }; diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 328b2db2b58..279908d2b67 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -205,7 +205,7 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> { } else { // Emit errors for non-staged-api crates. for attr in attrs { - let tag = unwrap_or!(attr.name(), continue); + 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 \ diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 91ce6f3854a..f06062fa4ac 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -675,9 +675,8 @@ impl LintPass for DeprecatedAttr { impl EarlyLintPass for DeprecatedAttr { fn check_attribute(&mut self, cx: &EarlyContext, attr: &ast::Attribute) { - let name = unwrap_or!(attr.name(), return); for &&(n, _, ref g) in &self.depr_attrs { - if name == n { + if attr.name() == n { if let &AttributeGate::Gated(Stability::Deprecated(link), ref name, ref reason, diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 65b340d6568..4f6d23dce6d 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -30,7 +30,6 @@ #![feature(quote)] #![feature(rustc_diagnostic_macros)] -#[macro_use] extern crate syntax; #[macro_use] extern crate rustc; diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 9e1b75ba336..8df40b62ddd 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -192,8 +192,6 @@ impl LintPass for UnusedAttributes { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAttributes { fn check_attribute(&mut self, cx: &LateContext, attr: &ast::Attribute) { debug!("checking attribute: {:?}", attr); - let name = unwrap_or!(attr.name(), return); - // Note that check_name() marks the attribute as used if it matches. for &(ref name, ty, _) in BUILTIN_ATTRIBUTES { match ty { @@ -213,6 +211,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAttributes { } } + let name = attr.name(); if !attr::is_used(attr) { debug!("Emitting warning for: {:?}", attr); cx.span_lint(UNUSED_ATTRIBUTES, attr.span, "unused attribute"); diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 35228748f06..4afc621ad8b 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -209,7 +209,7 @@ impl<'a> base::Resolver for Resolver<'a> { fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec, allow_derive: bool) -> Option { for i in 0..attrs.len() { - let name = unwrap_or!(attrs[i].name(), continue); + let name = attrs[i].name(); if self.session.plugin_attributes.borrow().iter() .any(|&(ref attr_nm, _)| name == &**attr_nm) { @@ -231,11 +231,11 @@ impl<'a> base::Resolver for Resolver<'a> { // Check for legacy derives for i in 0..attrs.len() { - let name = unwrap_or!(attrs[i].name(), continue); + let name = attrs[i].name(); if name == "derive" { let result = attrs[i].parse_list(&self.session.parse_sess, |parser| { - parser.parse_path(PathStyle::Mod) + parser.parse_path_allowing_meta(PathStyle::Mod) }); let mut traits = match result { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index bd64ac67ac9..d124a17b421 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -3661,7 +3661,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 denied = self.vis != hir::Public || self.attrs.iter().any(|a| { - a.name().unwrap() == "doc" && match a.meta_item_list() { + a.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/html/render.rs b/src/librustdoc/html/render.rs index 4e9781cc560..9248210c269 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -3319,7 +3319,7 @@ fn render_attributes(w: &mut fmt::Formatter, it: &clean::Item) -> fmt::Result { let mut attrs = String::new(); for attr in &it.attrs.other_attrs { - let name = attr.name().unwrap(); + let name = attr.name(); if !ATTRIBUTE_WHITELIST.contains(&&*name.as_str()) { continue; } diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 7a0231dc3f4..f805ba80885 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -217,11 +217,10 @@ impl Attribute { matches } - pub fn name(&self) -> Option { - match self.path.segments.len() { - 1 => Some(self.path.segments[0].identifier.name), - _ => None, - } + /// Returns the first segment of the name of this attribute. + /// E.g. `foo` for `#[foo]`, `rustfmt` for `#[rustfmt::skip]`. + pub fn name(&self) -> Name { + name_from_path(&self.path) } pub fn value_str(&self) -> Option { diff --git a/src/libsyntax/ext/derive.rs b/src/libsyntax/ext/derive.rs index afb233533ba..6bf166dfe95 100644 --- a/src/libsyntax/ext/derive.rs +++ b/src/libsyntax/ext/derive.rs @@ -26,7 +26,8 @@ pub fn collect_derives(cx: &mut ExtCtxt, attrs: &mut Vec) -> Vec return true; } - match attr.parse_list(cx.parse_sess, |parser| parser.parse_path(PathStyle::Mod)) { + match attr.parse_list(cx.parse_sess, + |parser| parser.parse_path_allowing_meta(PathStyle::Mod)) { Ok(ref traits) if traits.is_empty() => { cx.span_warn(attr.span, "empty trait list in `derive`"); false diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index b1f3c74d9f7..9bae8e73c7f 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1132,7 +1132,7 @@ 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 = unwrap_or!(attr.name(), return).as_str(); + let name = attr.name().as_str(); for &(n, ty, ref gateage) in BUILTIN_ATTRIBUTES { if name == n { if let Gated(_, name, desc, ref has_feature) = *gateage { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 324cadc84e8..d8fd3870495 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1955,19 +1955,19 @@ impl<'a> Parser<'a> { /// Like `parse_path`, but also supports parsing `Word` meta items into paths for back-compat. /// This is used when parsing derive macro paths in `#[derive]` attributes. pub fn parse_path_allowing_meta(&mut self, style: PathStyle) -> PResult<'a, ast::Path> { - let meta_ident = match self.token { + let meta_name = match self.token { token::Interpolated(ref nt) => match nt.0 { token::NtMeta(ref meta) => match meta.node { - ast::MetaItemKind::Word => Some(meta.ident), + ast::MetaItemKind::Word => Some(meta.name.clone()), _ => None, }, _ => None, }, _ => None, }; - if let Some(ident) = meta_ident { + if let Some(path) = meta_name { self.bump(); - return Ok(ast::Path::from_ident(ident)); + return Ok(path); } self.parse_path(style) } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index e8beb7e442c..96f7caf165c 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -776,6 +776,7 @@ pub trait PrintState<'a> { ast::MetaItemKind::Word => self.print_attribute_path(&item.name)?, ast::MetaItemKind::NameValue(ref value) => { self.print_attribute_path(&item.name)?; + self.writer().space()?; self.word_space("=")?; self.print_literal(value)?; } diff --git a/src/libsyntax_ext/deriving/custom.rs b/src/libsyntax_ext/deriving/custom.rs index 5fd5e299488..76da1746a03 100644 --- a/src/libsyntax_ext/deriving/custom.rs +++ b/src/libsyntax_ext/deriving/custom.rs @@ -22,11 +22,9 @@ struct MarkAttrs<'a>(&'a [ast::Name]); impl<'a> Visitor<'a> for MarkAttrs<'a> { fn visit_attribute(&mut self, attr: &Attribute) { - if let Some(name) = attr.name() { - if self.0.contains(&name) { - mark_used(attr); - mark_known(attr); - } + if self.0.contains(&attr.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 becd70149fd..80f65957c39 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -472,7 +472,7 @@ impl<'a> TraitDef<'a> { attrs.extend(item.attrs .iter() .filter(|a| { - a.name().is_some() && match &*a.name().unwrap().as_str() { + match &*a.name().as_str() { "allow" | "warn" | "deny" | "forbid" | "stable" | "unstable" => true, _ => false, } -- cgit 1.4.1-3-g733a5 From 6c28f84e37c48faa63488ada95242282cf1a09e9 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 30 Jan 2018 19:28:55 +0900 Subject: Gate tool_attributes feature --- src/libsyntax/attr.rs | 10 ++++++++++ src/libsyntax/diagnostic_list.rs | 1 + src/libsyntax/ext/expand.rs | 6 +++++- src/libsyntax/feature_gate.rs | 5 ++++- 4 files changed, 20 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index f805ba80885..12360e55c71 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -107,6 +107,12 @@ pub fn is_known(attr: &Attribute) -> bool { }) } +const RUST_KNOWN_TOOL: &[&str] = &["clippy", "rustfmt"]; + +pub fn is_known_tool(attr: &Attribute) -> bool { + RUST_KNOWN_TOOL.contains(&attr.name().as_str().as_ref()) +} + impl NestedMetaItem { /// Returns the MetaItem if self is a NestedMetaItemKind::MetaItem. pub fn meta_item(&self) -> Option<&MetaItem> { @@ -250,6 +256,10 @@ impl Attribute { pub fn is_value_str(&self) -> bool { self.value_str().is_some() } + + pub fn is_scoped(&self) -> bool { + self.path.segments.len() > 1 + } } impl MetaItem { diff --git a/src/libsyntax/diagnostic_list.rs b/src/libsyntax/diagnostic_list.rs index c9cac1b1142..dee63b7085e 100644 --- a/src/libsyntax/diagnostic_list.rs +++ b/src/libsyntax/diagnostic_list.rs @@ -325,4 +325,5 @@ register_diagnostics! { E0629, // missing 'feature' (rustc_const_unstable) E0630, // rustc_const_unstable attribute must be paired with stable/unstable attribute E0693, // incorrect `repr(align)` attribute format + E0694, // an unknown tool name found in scoped attributes } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 1d16a7eb091..41cd9c595d2 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -1017,7 +1017,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { fn check_attributes(&mut self, attrs: &[ast::Attribute]) { let features = self.cx.ecfg.features.unwrap(); for attr in attrs.iter() { - feature_gate::check_attribute(attr, self.cx.parse_sess, features); + self.check_attribute_inner(attr, features); // macros are expanded before any lint passes so this warning has to be hardcoded if attr.path == "derive" { @@ -1030,6 +1030,10 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { fn check_attribute(&mut self, at: &ast::Attribute) { let features = self.cx.ecfg.features.unwrap(); + self.check_attribute_inner(at, features); + } + + fn check_attribute_inner(&mut self, at: &ast::Attribute, features: &Features) { feature_gate::check_attribute(at, self.cx.parse_sess, features); } } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 9bae8e73c7f..4405c1a2658 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -460,6 +460,9 @@ declare_features! ( // Access to crate names passed via `--extern` through prelude (active, extern_prelude, "1.27.0", Some(44660), Some(Edition::Edition2018)), + + // Scoped attributes + (active, tool_attributes, "1.25.0", Some(44690)), ); declare_features! ( @@ -1079,7 +1082,7 @@ pub struct GatedCfg { impl GatedCfg { pub fn gate(cfg: &ast::MetaItem) -> Option { - let name = cfg.ident.name.as_str(); + let name = cfg.name().as_str(); GATED_CFGS.iter() .position(|info| info.0 == name) .map(|idx| { -- cgit 1.4.1-3-g733a5 From 8ad2d21a9c83e1d764f208d5fffd18842033f432 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Tue, 30 Jan 2018 19:29:11 +0900 Subject: Add tool_attributes feature to unstable book --- .../src/language-features/tool-attributes.md | 26 ++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 src/doc/unstable-book/src/language-features/tool-attributes.md (limited to 'src') diff --git a/src/doc/unstable-book/src/language-features/tool-attributes.md b/src/doc/unstable-book/src/language-features/tool-attributes.md new file mode 100644 index 00000000000..15fc84a3e2a --- /dev/null +++ b/src/doc/unstable-book/src/language-features/tool-attributes.md @@ -0,0 +1,26 @@ +# `tool_attributes` + +The tracking issue for this feature is: [#44690] + +[#44690]: https://github.com/rust-lang/rust/issues/44690 + +------------------------ + +Tool attributes let you use scoped attributes to control the behavior +of certain tools. + +Currently tool names which can be appear in scoped attributes are restricted to +`clippy` and `rustfmt`. + +## An example + +```rust +#![feature(tool_attributes)] + +#[rustfmt::skip] +fn foo() { println!("hello, world"); } + +fn main() { + foo(); +} +``` -- cgit 1.4.1-3-g733a5 From 0de65441170292f243806e6239967ee85bff6c66 Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 4 Feb 2018 15:36:26 +0900 Subject: Change Attribute::name to return the last segment And fix some typos --- src/libsyntax/attr.rs | 11 +++++++---- src/test/compile-fail/unknown-tool-name.rs | 4 ++-- src/test/compile-fail/unknown_tool_attributes-1.rs | 2 +- 3 files changed, 10 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 12360e55c71..8fa5f55490e 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -110,7 +110,9 @@ pub fn is_known(attr: &Attribute) -> bool { const RUST_KNOWN_TOOL: &[&str] = &["clippy", "rustfmt"]; pub fn is_known_tool(attr: &Attribute) -> bool { - RUST_KNOWN_TOOL.contains(&attr.name().as_str().as_ref()) + let tool_name = + attr.path.segments.iter().next().expect("empty path in attribute").identifier.name; + RUST_KNOWN_TOOL.contains(&tool_name.as_str().as_ref()) } impl NestedMetaItem { @@ -211,7 +213,7 @@ impl NestedMetaItem { } fn name_from_path(path: &ast::Path) -> Name { - path.segments.iter().next().unwrap().identifier.name + path.segments.last().expect("empty path in attribute").identifier.name } impl Attribute { @@ -223,8 +225,8 @@ impl Attribute { matches } - /// Returns the first segment of the name of this attribute. - /// E.g. `foo` for `#[foo]`, `rustfmt` for `#[rustfmt::skip]`. + /// 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) } @@ -1162,6 +1164,7 @@ impl MetaItem { fn tokens(&self) -> TokenStream { let mut idents = vec![]; let mut last_pos = BytePos(0 as u32); + // FIXME: Share code with `parse_path`. for (i, segment) in self.name.segments.iter().enumerate() { let is_first = i == 0; if !is_first { diff --git a/src/test/compile-fail/unknown-tool-name.rs b/src/test/compile-fail/unknown-tool-name.rs index 1ee837b05d8..0cb897917b4 100644 --- a/src/test/compile-fail/unknown-tool-name.rs +++ b/src/test/compile-fail/unknown-tool-name.rs @@ -10,7 +10,7 @@ #![feature(tool_attributes)] -#![foo::bar] //~ ERROR An unkown tool name found in scoped attributes: `foo::bar`. [E0693] +#![foo::bar] //~ ERROR An unknown tool name found in scoped attributes: `foo::bar`. [E0693] -#[foo::bar] //~ ERROR An unkown tool name found in scoped attributes: `foo::bar`. [E0693] +#[foo::bar] //~ ERROR An unknown tool name found in scoped attributes: `foo::bar`. [E0693] fn main() {} diff --git a/src/test/compile-fail/unknown_tool_attributes-1.rs b/src/test/compile-fail/unknown_tool_attributes-1.rs index 08a7bfed278..fbc46219461 100644 --- a/src/test/compile-fail/unknown_tool_attributes-1.rs +++ b/src/test/compile-fail/unknown_tool_attributes-1.rs @@ -14,5 +14,5 @@ #[foo::bar] //~^ ERROR scoped attribute `foo::bar` is experimental (see issue #44690) [E0658] -//~^^ ERROR An unkown tool name found in scoped attributes: `foo::bar`. [E0693] +//~^^ ERROR An unknown tool name found in scoped attributes: `foo::bar`. [E0693] fn main() {} -- cgit 1.4.1-3-g733a5 From 24a6284fcd1d40c0d8f8b58d29a672ec78cfa94b Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Sun, 4 Feb 2018 16:00:24 +0900 Subject: Fix failures in rustdoc --- src/librustdoc/clean/cfg.rs | 242 ++++++++++++-------------------------------- 1 file changed, 63 insertions(+), 179 deletions(-) (limited to 'src') diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index 7f89b3e6b3a..f8cd6ebc464 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -67,7 +67,7 @@ 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.ident.name; + let name = cfg.name(); match cfg.node { MetaItemKind::Word => Ok(Cfg::Cfg(name, None)), MetaItemKind::NameValue(ref lit) => match lit.node { @@ -436,6 +436,42 @@ mod test { Cfg::Cfg(Symbol::intern(name), Some(Symbol::intern(value))) } + fn dummy_meta_item_word(name: &str) -> MetaItem { + MetaItem { + name: Path::from_ident(DUMMY_SP, Ident::from_str(name)), + node: MetaItemKind::Word, + span: DUMMY_SP, + } + } + + macro_rules! dummy_meta_item_list { + ($name:ident, [$($list:ident),* $(,)*]) => { + MetaItem { + name: Path::from_ident(DUMMY_SP, Ident::from_str(stringify!($name))), + node: MetaItemKind::List(vec![ + $( + dummy_spanned(NestedMetaItemKind::MetaItem( + dummy_meta_item_word(stringify!($list)), + )), + )* + ]), + span: DUMMY_SP, + } + }; + + ($name:ident, [$($list:expr),* $(,)*]) => { + MetaItem { + name: Path::from_ident(DUMMY_SP, Ident::from_str(stringify!($name))), + node: MetaItemKind::List(vec![ + $( + dummy_spanned(NestedMetaItemKind::MetaItem($list)), + )* + ]), + span: DUMMY_SP, + } + }; + } + #[test] fn test_cfg_not() { with_globals(|| { @@ -561,15 +597,11 @@ mod test { #[test] fn test_parse_ok() { with_globals(|| { - let mi = MetaItem { - ident: Ident::from_str("all"), - node: MetaItemKind::Word, - span: DUMMY_SP, - }; + let mi = dummy_meta_item_word("all"); assert_eq!(Cfg::parse(&mi), Ok(word_cfg("all"))); let mi = MetaItem { - ident: Ident::from_str("all"), + name: Path::from_ident(DUMMY_SP, Ident::from_str("all")), node: MetaItemKind::NameValue(dummy_spanned(LitKind::Str( Symbol::intern("done"), StrStyle::Cooked, @@ -578,111 +610,24 @@ mod test { }; assert_eq!(Cfg::parse(&mi), Ok(name_value_cfg("all", "done"))); - let mi = MetaItem { - ident: Ident::from_str("all"), - node: MetaItemKind::List(vec![ - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - ident: Ident::from_str("a"), - node: MetaItemKind::Word, - span: DUMMY_SP, - })), - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - ident: Ident::from_str("b"), - node: MetaItemKind::Word, - span: DUMMY_SP, - })), - ]), - span: DUMMY_SP, - }; + let mi = dummy_meta_item_list!(all, [a, b]); assert_eq!(Cfg::parse(&mi), Ok(word_cfg("a") & word_cfg("b"))); - let mi = MetaItem { - ident: Ident::from_str("any"), - node: MetaItemKind::List(vec![ - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - ident: Ident::from_str("a"), - node: MetaItemKind::Word, - span: DUMMY_SP, - })), - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - ident: Ident::from_str("b"), - node: MetaItemKind::Word, - span: DUMMY_SP, - })), - ]), - span: DUMMY_SP, - }; + let mi = dummy_meta_item_list!(any, [a, b]); assert_eq!(Cfg::parse(&mi), Ok(word_cfg("a") | word_cfg("b"))); - let mi = MetaItem { - ident: Ident::from_str("not"), - node: MetaItemKind::List(vec![ - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - ident: Ident::from_str("a"), - node: MetaItemKind::Word, - span: DUMMY_SP, - })), - ]), - span: DUMMY_SP, - }; + let mi = dummy_meta_item_list!(not, [a]); assert_eq!(Cfg::parse(&mi), Ok(!word_cfg("a"))); - let mi = MetaItem { - ident: Ident::from_str("not"), - node: MetaItemKind::List(vec![ - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - ident: Ident::from_str("any"), - node: MetaItemKind::List(vec![ - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - ident: Ident::from_str("a"), - node: MetaItemKind::Word, - span: DUMMY_SP, - })), - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - ident: Ident::from_str("all"), - node: MetaItemKind::List(vec![ - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - ident: Ident::from_str("b"), - node: MetaItemKind::Word, - span: DUMMY_SP, - })), - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - ident: Ident::from_str("c"), - node: MetaItemKind::Word, - span: DUMMY_SP, - })), - ]), - span: DUMMY_SP, - })), - ]), - span: DUMMY_SP, - })), + let mi = dummy_meta_item_list!(not, [ + dummy_meta_item_list!(any, [ + dummy_meta_item_word("a"), + dummy_meta_item_list!(all, [b, c]), ]), - span: DUMMY_SP, - }; + ]); assert_eq!(Cfg::parse(&mi), Ok(!(word_cfg("a") | (word_cfg("b") & word_cfg("c"))))); - let mi = MetaItem { - ident: Ident::from_str("all"), - node: MetaItemKind::List(vec![ - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - ident: Ident::from_str("a"), - node: MetaItemKind::Word, - span: DUMMY_SP, - })), - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - ident: Ident::from_str("b"), - node: MetaItemKind::Word, - span: DUMMY_SP, - })), - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - ident: Ident::from_str("c"), - node: MetaItemKind::Word, - span: DUMMY_SP, - })), - ]), - span: DUMMY_SP, - }; + let mi = dummy_meta_item_list!(all, [a, b, c]); assert_eq!(Cfg::parse(&mi), Ok(word_cfg("a") & word_cfg("b") & word_cfg("c"))); }) } @@ -691,97 +636,36 @@ mod test { fn test_parse_err() { with_globals(|| { let mi = MetaItem { - ident: Ident::from_str("foo"), + name: Path::from_ident(DUMMY_SP, Ident::from_str("foo")), node: MetaItemKind::NameValue(dummy_spanned(LitKind::Bool(false))), span: DUMMY_SP, }; assert!(Cfg::parse(&mi).is_err()); - let mi = MetaItem { - ident: Ident::from_str("not"), - node: MetaItemKind::List(vec![ - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - ident: Ident::from_str("a"), - node: MetaItemKind::Word, - span: DUMMY_SP, - })), - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - ident: Ident::from_str("b"), - node: MetaItemKind::Word, - span: DUMMY_SP, - })), - ]), - span: DUMMY_SP, - }; + let mi = dummy_meta_item_list!(not, [a, b]); assert!(Cfg::parse(&mi).is_err()); - let mi = MetaItem { - ident: Ident::from_str("not"), - node: MetaItemKind::List(vec![]), - span: DUMMY_SP, - }; + let mi = dummy_meta_item_list!(not, []); assert!(Cfg::parse(&mi).is_err()); - let mi = MetaItem { - ident: Ident::from_str("foo"), - node: MetaItemKind::List(vec![ - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - ident: Ident::from_str("a"), - node: MetaItemKind::Word, - span: DUMMY_SP, - })), - ]), - span: DUMMY_SP, - }; + let mi = dummy_meta_item_list!(foo, []); assert!(Cfg::parse(&mi).is_err()); - let mi = MetaItem { - ident: Ident::from_str("all"), - node: MetaItemKind::List(vec![ - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - ident: Ident::from_str("foo"), - node: MetaItemKind::List(vec![]), - span: DUMMY_SP, - })), - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - ident: Ident::from_str("b"), - node: MetaItemKind::Word, - span: DUMMY_SP, - })), - ]), - span: DUMMY_SP, - }; + let mi = dummy_meta_item_list!(all, [ + dummy_meta_item_list!(foo, []), + dummy_meta_item_word("b"), + ]); assert!(Cfg::parse(&mi).is_err()); - let mi = MetaItem { - ident: Ident::from_str("any"), - node: MetaItemKind::List(vec![ - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - ident: Ident::from_str("a"), - node: MetaItemKind::Word, - span: DUMMY_SP, - })), - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - ident: Ident::from_str("foo"), - node: MetaItemKind::List(vec![]), - span: DUMMY_SP, - })), - ]), - span: DUMMY_SP, - }; + let mi = dummy_meta_item_list!(any, [ + dummy_meta_item_word("a"), + dummy_meta_item_list!(foo, []), + ]); assert!(Cfg::parse(&mi).is_err()); - let mi = MetaItem { - ident: Ident::from_str("not"), - node: MetaItemKind::List(vec![ - dummy_spanned(NestedMetaItemKind::MetaItem(MetaItem { - ident: Ident::from_str("foo"), - node: MetaItemKind::List(vec![]), - span: DUMMY_SP, - })), - ]), - span: DUMMY_SP, - }; + let mi = dummy_meta_item_list!(not, [ + dummy_meta_item_list!(foo, []), + ]); assert!(Cfg::parse(&mi).is_err()); }) } -- cgit 1.4.1-3-g733a5 From 121abd0599f6fd056dca84fe1df724fb7822b355 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 17 Apr 2018 15:33:39 +0200 Subject: make it compile again --- src/librustc/hir/check_attr.rs | 2 +- src/librustc/ich/impls_syntax.rs | 2 +- src/librustc/lint/levels.rs | 4 +- src/librustc/session/config.rs | 2 +- src/librustc/traits/on_unimplemented.rs | 2 +- src/librustc_driver/lib.rs | 2 +- src/librustc_incremental/assert_dep_graph.rs | 2 +- src/librustc_resolve/build_reduced_graph.rs | 2 +- src/librustdoc/clean/cfg.rs | 10 +-- src/librustdoc/html/render.rs | 2 +- src/libsyntax/ast.rs | 2 +- src/libsyntax/attr.rs | 83 +++++++++------------- src/libsyntax/ext/expand.rs | 2 +- src/libsyntax/feature_gate.rs | 32 ++++++--- src/libsyntax/parse/attr.rs | 6 +- src/libsyntax/parse/parser.rs | 6 +- src/libsyntax/print/pprust.rs | 16 ++--- src/test/compile-fail/unknown-tool-name.rs | 4 +- src/test/compile-fail/unknown_tool_attributes-1.rs | 2 +- src/test/ui/feature-gate-tool_attributes.stderr | 3 +- 20 files changed, 92 insertions(+), 94 deletions(-) (limited to 'src') diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index e8bdb9d5d5f..24a1256c9d3 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -308,7 +308,7 @@ impl<'a, 'tcx> CheckAttrVisitor<'a, 'tcx> { fn check_used(&self, item: &hir::Item, target: Target) { for attr in &item.attrs { - if attr.name().map(|name| name == "used").unwrap_or(false) && target != Target::Static { + if attr.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 d90dba2ff04..1cf9b7bf478 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -216,7 +216,7 @@ impl<'a> HashStable> for ast::Path { hasher: &mut StableHasher) { self.segments.len().hash_stable(hcx, hasher); for segment in &self.segments { - segment.identifier.name.hash_stable(hcx, hasher); + segment.ident.name.hash_stable(hcx, hasher); } } } diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index 0eeb0cf6c37..d158f52c643 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -221,7 +221,7 @@ impl<'a> LintLevelsBuilder<'a> { continue } }; - let name = word.ident.name; + let name = word.name(); match store.check_lint_name(&name.as_str()) { CheckLintNameResult::Ok(ids) => { let src = LintSource::Node(name, li.span); @@ -260,7 +260,7 @@ impl<'a> LintLevelsBuilder<'a> { Some(li.span.into()), &msg); if name.as_str().chars().any(|c| c.is_uppercase()) { - let name_lower = name.as_str().to_lowercase(); + let name_lower = name.as_str().to_lowercase().to_string(); if let CheckLintNameResult::NoLint = store.check_lint_name(&name_lower) { db.emit(); diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 59b40e9e2dc..dc97c941567 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1683,7 +1683,7 @@ pub fn parse_cfgspecs(cfgspecs: Vec) -> ast::CrateConfig { early_error(ErrorOutputType::default(), &msg) } - (meta_item.ident.name, meta_item.value_str()) + (meta_item.name(), meta_item.value_str()) }) .collect::() } diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs index d1fd70ae02d..3cf7af30b3d 100644 --- a/src/librustc/traits/on_unimplemented.rs +++ b/src/librustc/traits/on_unimplemented.rs @@ -190,7 +190,7 @@ 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.ident.name.as_str().to_string(), + options.contains(&(c.name().as_str().to_string(), match c.value_str().map(|s| s.as_str().to_string()) { Some(s) => Some(s), None => None diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 67ba55a6aab..a1052ca6c3c 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -1060,7 +1060,7 @@ impl RustcDefaultCalls { let mut cfgs = Vec::new(); for &(name, ref value) in sess.parse_sess.config.iter() { let gated_cfg = GatedCfg::gate(&ast::MetaItem { - name: ast::Path::from_ident(DUMMY_SP, name.to_ident()), + ident: ast::Path::from_ident(name.to_ident()), node: ast::MetaItemKind::Word, span: DUMMY_SP, }); diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs index 57311a7b588..38e891008f7 100644 --- a/src/librustc_incremental/assert_dep_graph.rs +++ b/src/librustc_incremental/assert_dep_graph.rs @@ -110,7 +110,7 @@ impl<'a, 'tcx> IfThisChanged<'a, 'tcx> { for list_item in attr.meta_item_list().unwrap_or_default() { match list_item.word() { Some(word) if value.is_none() => - value = Some(word.ident.name), + value = Some(word.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_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index e5e6c22c7a2..4522a0b8624 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -702,7 +702,7 @@ impl<'a> Resolver<'a> { match attr.meta_item_list() { Some(names) => for attr in names { if let Some(word) = attr.word() { - imports.imports.push((word.ident.name, attr.span())); + imports.imports.push((word.name(), attr.span())); } else { span_err!(self.session, attr.span(), E0466, "bad macro import"); } diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index f8cd6ebc464..d5e0f95ddf4 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -438,7 +438,7 @@ mod test { fn dummy_meta_item_word(name: &str) -> MetaItem { MetaItem { - name: Path::from_ident(DUMMY_SP, Ident::from_str(name)), + ident: Path::from_ident(Ident::from_str(name)), node: MetaItemKind::Word, span: DUMMY_SP, } @@ -447,7 +447,7 @@ mod test { macro_rules! dummy_meta_item_list { ($name:ident, [$($list:ident),* $(,)*]) => { MetaItem { - name: Path::from_ident(DUMMY_SP, Ident::from_str(stringify!($name))), + ident: Path::from_ident(Ident::from_str(stringify!($name))), node: MetaItemKind::List(vec![ $( dummy_spanned(NestedMetaItemKind::MetaItem( @@ -461,7 +461,7 @@ mod test { ($name:ident, [$($list:expr),* $(,)*]) => { MetaItem { - name: Path::from_ident(DUMMY_SP, Ident::from_str(stringify!($name))), + ident: Path::from_ident(Ident::from_str(stringify!($name))), node: MetaItemKind::List(vec![ $( dummy_spanned(NestedMetaItemKind::MetaItem($list)), @@ -601,7 +601,7 @@ mod test { assert_eq!(Cfg::parse(&mi), Ok(word_cfg("all"))); let mi = MetaItem { - name: Path::from_ident(DUMMY_SP, Ident::from_str("all")), + ident: Path::from_ident(Ident::from_str("all")), node: MetaItemKind::NameValue(dummy_spanned(LitKind::Str( Symbol::intern("done"), StrStyle::Cooked, @@ -636,7 +636,7 @@ mod test { fn test_parse_err() { with_globals(|| { let mi = MetaItem { - name: Path::from_ident(DUMMY_SP, Ident::from_str("foo")), + ident: 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 9248210c269..e9520573f8b 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -3284,7 +3284,7 @@ fn item_enum(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, } fn render_attribute(attr: &ast::MetaItem) -> Option { - let name = attr.ident.name; + let name = attr.name(); if attr.is_word() { Some(format!("{}", name)) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index bc457f49fcf..f8cd6103bdf 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -477,7 +477,7 @@ pub enum NestedMetaItemKind { /// E.g. `#[test]`, `#[derive(..)]`, `#[rustfmt::skip]` or `#[feature = "foo"]` #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)] pub struct MetaItem { - pub name: Path, + pub ident: Path, pub node: MetaItemKind, pub span: Span, } diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 8fa5f55490e..82e04ff32ca 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -18,7 +18,7 @@ use ast; use ast::{AttrId, Attribute, Name, Ident}; use ast::{MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind}; use ast::{Lit, LitKind, Expr, ExprKind, Item, Local, Stmt, StmtKind}; -use codemap::{Spanned, respan, dummy_spanned}; +use codemap::{BytePos, Spanned, respan, dummy_spanned}; use syntax_pos::Span; use errors::Handler; use feature_gate::{Features, GatedCfg}; @@ -111,7 +111,7 @@ const RUST_KNOWN_TOOL: &[&str] = &["clippy", "rustfmt"]; pub fn is_known_tool(attr: &Attribute) -> bool { let tool_name = - attr.path.segments.iter().next().expect("empty path in attribute").identifier.name; + attr.path.segments.iter().next().expect("empty path in attribute").ident.name; RUST_KNOWN_TOOL.contains(&tool_name.as_str().as_ref()) } @@ -213,7 +213,7 @@ impl NestedMetaItem { } fn name_from_path(path: &ast::Path) -> Name { - path.segments.last().expect("empty path in attribute").identifier.name + path.segments.last().expect("empty path in attribute").ident.name } impl Attribute { @@ -266,7 +266,7 @@ impl Attribute { impl MetaItem { pub fn name(&self) -> Name { - name_from_path(&self.name) + name_from_path(&self.ident) } pub fn value_str(&self) -> Option { @@ -315,7 +315,7 @@ impl Attribute { pub fn meta(&self) -> Option { let mut tokens = self.tokens.trees().peekable(); Some(MetaItem { - name: self.path.clone(), + ident: self.path.clone(), node: if let Some(node) = MetaItemKind::from_tokens(&mut tokens) { if tokens.peek().is_some() { return None; @@ -361,7 +361,7 @@ impl Attribute { pub fn parse_meta<'a>(&self, sess: &'a ParseSess) -> PResult<'a, MetaItem> { Ok(MetaItem { - name: self.path.clone(), + ident: self.path.clone(), node: self.parse(sess, |parser| parser.parse_meta_item_kind())?, span: self.span, }) @@ -399,41 +399,19 @@ 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, span, node: MetaItemKind::NameValue(value) } + MetaItem { ident: ast::Path::from_ident(ident), span, node: MetaItemKind::NameValue(value) } } pub fn mk_list_item(span: Span, ident: Ident, items: Vec) -> MetaItem { - MetaItem { ident, span, node: MetaItemKind::List(items) } + MetaItem { ident: ast::Path::from_ident(ident), span, node: MetaItemKind::List(items) } } pub fn mk_word_item(ident: Ident) -> MetaItem { - MetaItem { ident, span: ident.span, node: MetaItemKind::Word } + MetaItem { ident: ast::Path::from_ident(ident), span: ident.span, node: MetaItemKind::Word } } -pub fn mk_word_item(name: Name) -> MetaItem { - mk_spanned_word_item(DUMMY_SP, name) -} - -macro_rules! mk_spanned_meta_item { - ($sp:ident, $name:ident, $node:expr) => { - MetaItem { - span: $sp, - name: ast::Path::from_ident($sp, ast::Ident::with_empty_ctxt($name)), - node: $node, - } - } -} - -pub fn mk_spanned_name_value_item(sp: Span, name: Name, value: ast::Lit) -> MetaItem { - mk_spanned_meta_item!(sp, name, MetaItemKind::NameValue(value)) -} - -pub fn mk_spanned_list_item(sp: Span, name: Name, items: Vec) -> MetaItem { - mk_spanned_meta_item!(sp, name, MetaItemKind::List(items)) -} - -pub fn mk_spanned_word_item(sp: Span, name: Name) -> MetaItem { - mk_spanned_meta_item!(sp, name, MetaItemKind::Word) +pub fn mk_nested_word_item(ident: Ident) -> NestedMetaItem { + respan(ident.span, NestedMetaItemKind::MetaItem(mk_word_item(ident))) } pub fn mk_attr_id() -> AttrId { @@ -457,7 +435,7 @@ pub fn mk_spanned_attr_inner(sp: Span, id: AttrId, item: MetaItem) -> Attribute Attribute { id, style: ast::AttrStyle::Inner, - path: item.name, + path: item.ident, tokens: item.node.tokens(item.span), is_sugared_doc: false, span: sp, @@ -475,7 +453,7 @@ pub fn mk_spanned_attr_outer(sp: Span, id: AttrId, item: MetaItem) -> Attribute Attribute { id, style: ast::AttrStyle::Outer, - path: item.name, + path: item.ident, tokens: item.node.tokens(item.span), is_sugared_doc: false, span: sp, @@ -1082,7 +1060,7 @@ pub fn find_repr_attrs(diagnostic: &Handler, attr: &Attribute) -> Vec } } else { if let Some(meta_item) = item.meta_item() { - if meta_item.ident.name == "align" { + if meta_item.name() == "align" { if let MetaItemKind::NameValue(ref value) = meta_item.node { recognised = true; let mut err = struct_span_err!(diagnostic, item.span, E0693, @@ -1165,14 +1143,17 @@ impl MetaItem { let mut idents = vec![]; let mut last_pos = BytePos(0 as u32); // FIXME: Share code with `parse_path`. - for (i, segment) in self.name.segments.iter().enumerate() { + for (i, segment) in self.ident.segments.iter().enumerate() { let is_first = i == 0; if !is_first { - let mod_sep_span = Span::new(last_pos, segment.span.lo(), segment.span.ctxt()); + let mod_sep_span = Span::new(last_pos, + segment.ident.span.lo(), + segment.ident.span.ctxt()); idents.push(TokenTree::Token(mod_sep_span, Token::ModSep).into()); } - idents.push(TokenTree::Token(segment.span, Token::Ident(segment.identifier)).into()); - last_pos = segment.span.hi(); + idents.push(TokenTree::Token(segment.ident.span, + Token::from_ast_ident(segment.ident)).into()); + last_pos = segment.ident.span.hi(); } idents.push(self.node.tokens(self.span)); TokenStream::concat(idents) @@ -1181,14 +1162,14 @@ impl MetaItem { fn from_tokens(tokens: &mut iter::Peekable) -> Option where I: Iterator, { - let name = match tokens.next() { - Some(TokenTree::Token(span, Token::Ident(ident))) => { + let ident = match tokens.next() { + Some(TokenTree::Token(span, Token::Ident(ident, _))) => { if let Some(TokenTree::Token(_, Token::ModSep)) = tokens.peek() { tokens.next(); let mut segments = vec![]; loop { - if let Some(TokenTree::Token(span, Token::Ident(ident))) = tokens.next() { - segments.push(ast::PathSegment::from_ident(ident, span)); + if let Some(TokenTree::Token(_, Token::Ident(ident, _))) = tokens.next() { + segments.push(ast::PathSegment::from_ident(ident)); } else { return None; } @@ -1200,12 +1181,12 @@ impl MetaItem { } ast::Path { span, segments } } else { - ast::Path::from_ident(span, ident) + ast::Path::from_ident(ident) } } Some(TokenTree::Token(_, Token::Interpolated(ref nt))) => match nt.0 { - token::Nonterminal::NtIdent(ident) => { - ast::Path::from_ident(ident.span, ident.node) + token::Nonterminal::NtIdent(ident, _) => { + ast::Path::from_ident(ident) } token::Nonterminal::NtMeta(ref meta) => return Some(meta.clone()), token::Nonterminal::NtPath(ref path) => path.clone(), @@ -1217,11 +1198,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(name.span.hi()), - _ => name.span.hi(), + MetaItemKind::List(..) => list_closing_paren_pos.unwrap_or(ident.span.hi()), + _ => ident.span.hi(), }; - let span = name.span.with_hi(hi); - Some(MetaItem { name, node, span }) + let span = ident.span.with_hi(hi); + Some(MetaItem { ident, node, span }) } } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 41cd9c595d2..584b9455a93 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -810,7 +810,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 - name: Path::from_ident(DUMMY_SP, keywords::Invalid.ident()), + ident: Path::from_ident(keywords::Invalid.ident()), span: DUMMY_SP, node: ast::MetaItemKind::Word, }; diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 4405c1a2658..18bf5445123 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -462,7 +462,7 @@ declare_features! ( (active, extern_prelude, "1.27.0", Some(44660), Some(Edition::Edition2018)), // Scoped attributes - (active, tool_attributes, "1.25.0", Some(44690)), + (active, tool_attributes, "1.25.0", Some(44690), None), ); declare_features! ( @@ -1175,12 +1175,28 @@ impl<'a> Context<'a> { // before the plugin attributes are registered // so we skip this then if !is_macro { - gate_feature!(self, custom_attribute, attr.span, - &format!("The attribute `{}` is currently \ - unknown to the compiler and \ - may have meaning \ - added to it in the future", - attr.path)); + if attr.is_scoped() { + gate_feature!(self, tool_attributes, attr.span, + &format!("scoped attribute `{}` is experimental", attr.path)); + if attr::is_known_tool(attr) { + attr::mark_used(attr); + } else { + span_err!( + self.parse_sess.span_diagnostic, + attr.span, + E0694, + "an unknown tool name found in scoped attribute: `{}`.", + attr.path + ); + } + } else { + gate_feature!(self, custom_attribute, attr.span, + &format!("the attribute `{}` is currently \ + unknown to the compiler and \ + may have meaning \ + added to it in the future", + attr.path)); + } } } } @@ -1846,7 +1862,7 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], for mi in list { let name = if let Some(word) = mi.word() { - word.ident.name + word.name() } else { span_err!(span_handler, mi.span, E0556, "malformed feature, expected just one word"); diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index 0671f29648f..cceed589212 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.name, meta.node.tokens(meta.span)) + (meta.ident, meta.node.tokens(meta.span)) } else { (self.parse_path(PathStyle::Mod)?, self.parse_tokens()) }) @@ -225,10 +225,10 @@ impl<'a> Parser<'a> { } let lo = self.span; - let name = self.parse_path(PathStyle::Mod)?; + let ident = self.parse_path(PathStyle::Mod)?; let node = self.parse_meta_item_kind()?; let span = lo.to(self.prev_span); - Ok(ast::MetaItem { name, node, span }) + Ok(ast::MetaItem { ident, node, span }) } pub 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 d8fd3870495..0e3bced3222 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1955,17 +1955,17 @@ impl<'a> Parser<'a> { /// Like `parse_path`, but also supports parsing `Word` meta items into paths for back-compat. /// This is used when parsing derive macro paths in `#[derive]` attributes. pub fn parse_path_allowing_meta(&mut self, style: PathStyle) -> PResult<'a, ast::Path> { - let meta_name = match self.token { + let meta_ident = match self.token { token::Interpolated(ref nt) => match nt.0 { token::NtMeta(ref meta) => match meta.node { - ast::MetaItemKind::Word => Some(meta.name.clone()), + ast::MetaItemKind::Word => Some(meta.ident.clone()), _ => None, }, _ => None, }, _ => None, }; - if let Some(path) = meta_name { + if let Some(path) = meta_ident { self.bump(); return Ok(path); } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 96f7caf165c..f78e3f3084b 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -719,12 +719,12 @@ pub trait PrintState<'a> { if i > 0 { self.writer().word("::")? } - if segment.identifier.name != keywords::CrateRoot.name() && - segment.identifier.name != keywords::DollarCrate.name() + if segment.ident.name != keywords::CrateRoot.name() && + segment.ident.name != keywords::DollarCrate.name() { - self.writer().word(&segment.identifier.name.as_str())?; - } else if segment.identifier.name == keywords::DollarCrate.name() { - self.print_dollar_crate(segment.identifier.ctxt)?; + self.writer().word(&segment.ident.name.as_str())?; + } else if segment.ident.name == keywords::DollarCrate.name() { + self.print_dollar_crate(segment.ident.span.ctxt())?; } } Ok(()) @@ -773,15 +773,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.name)?, + ast::MetaItemKind::Word => self.print_attribute_path(&item.ident)?, ast::MetaItemKind::NameValue(ref value) => { - self.print_attribute_path(&item.name)?; + self.print_attribute_path(&item.ident)?; self.writer().space()?; self.word_space("=")?; self.print_literal(value)?; } ast::MetaItemKind::List(ref items) => { - self.print_attribute_path(&item.name)?; + self.print_attribute_path(&item.ident)?; self.popen()?; self.commasep(Consistent, &items[..], diff --git a/src/test/compile-fail/unknown-tool-name.rs b/src/test/compile-fail/unknown-tool-name.rs index 0cb897917b4..c2192a21d90 100644 --- a/src/test/compile-fail/unknown-tool-name.rs +++ b/src/test/compile-fail/unknown-tool-name.rs @@ -10,7 +10,7 @@ #![feature(tool_attributes)] -#![foo::bar] //~ ERROR An unknown tool name found in scoped attributes: `foo::bar`. [E0693] +#![foo::bar] //~ ERROR an unknown tool name found in scoped attribute: `foo::bar`. [E0694] -#[foo::bar] //~ ERROR An unknown tool name found in scoped attributes: `foo::bar`. [E0693] +#[foo::bar] //~ ERROR an unknown tool name found in scoped attribute: `foo::bar`. [E0694] fn main() {} diff --git a/src/test/compile-fail/unknown_tool_attributes-1.rs b/src/test/compile-fail/unknown_tool_attributes-1.rs index fbc46219461..ba38c297a11 100644 --- a/src/test/compile-fail/unknown_tool_attributes-1.rs +++ b/src/test/compile-fail/unknown_tool_attributes-1.rs @@ -14,5 +14,5 @@ #[foo::bar] //~^ ERROR scoped attribute `foo::bar` is experimental (see issue #44690) [E0658] -//~^^ ERROR An unknown tool name found in scoped attributes: `foo::bar`. [E0693] +//~^^ ERROR an unknown tool name found in scoped attribute: `foo::bar`. [E0694] fn main() {} diff --git a/src/test/ui/feature-gate-tool_attributes.stderr b/src/test/ui/feature-gate-tool_attributes.stderr index 13307bd7133..da89c4a5ef6 100644 --- a/src/test/ui/feature-gate-tool_attributes.stderr +++ b/src/test/ui/feature-gate-tool_attributes.stderr @@ -1,10 +1,11 @@ error[E0658]: scoped attribute `rustfmt::skip` is experimental (see issue #44690) --> $DIR/feature-gate-tool_attributes.rs:12:5 | -12 | #[rustfmt::skip] //~ ERROR scoped attribute `rustfmt::skip` is experimental +LL | #[rustfmt::skip] //~ ERROR scoped attribute `rustfmt::skip` is experimental | ^^^^^^^^^^^^^^^^ | = help: add #![feature(tool_attributes)] to the crate attributes to enable error: aborting due to previous error +For more information about this error, try `rustc --explain E0658`. -- cgit 1.4.1-3-g733a5 From 84f450866041e0269875acb1350920308cdc109f Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 24 Apr 2018 16:57:41 +0200 Subject: fix tests --- src/libsyntax/attr.rs | 30 +++++++++++----------- src/libsyntax/feature_gate.rs | 4 +-- .../auxiliary/macro_crate_test.rs | 2 +- .../auxiliary/macro_crate_test.rs | 2 +- 4 files changed, 19 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 82e04ff32ca..b8660c49233 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -15,7 +15,7 @@ pub use self::ReprAttr::*; pub use self::IntType::*; use ast; -use ast::{AttrId, Attribute, Name, Ident}; +use ast::{AttrId, Attribute, Name, Ident, Path, PathSegment}; use ast::{MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind}; use ast::{Lit, LitKind, Expr, ExprKind, Item, Local, Stmt, StmtKind}; use codemap::{BytePos, Spanned, respan, dummy_spanned}; @@ -212,7 +212,7 @@ impl NestedMetaItem { } } -fn name_from_path(path: &ast::Path) -> Name { +fn name_from_path(path: &Path) -> Name { path.segments.last().expect("empty path in attribute").ident.name } @@ -399,15 +399,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: ast::Path::from_ident(ident), span, node: MetaItemKind::NameValue(value) } + MetaItem { ident: Path::from_ident(ident), span, node: MetaItemKind::NameValue(value) } } pub fn mk_list_item(span: Span, ident: Ident, items: Vec) -> MetaItem { - MetaItem { ident: ast::Path::from_ident(ident), span, node: MetaItemKind::List(items) } + MetaItem { ident: Path::from_ident(ident), span, node: MetaItemKind::List(items) } } pub fn mk_word_item(ident: Ident) -> MetaItem { - MetaItem { ident: ast::Path::from_ident(ident), span: ident.span, node: MetaItemKind::Word } + MetaItem { ident: Path::from_ident(ident), span: ident.span, node: MetaItemKind::Word } } pub fn mk_nested_word_item(ident: Ident) -> NestedMetaItem { @@ -466,7 +466,7 @@ pub fn mk_sugared_doc_attr(id: AttrId, text: Symbol, span: Span) -> Attribute { Attribute { id, style, - path: ast::Path::from_ident(Ident::from_str("doc").with_span_pos(span)), + path: Path::from_ident(Ident::from_str("doc").with_span_pos(span)), tokens: MetaItemKind::NameValue(lit).tokens(span), is_sugared_doc: true, span, @@ -1142,7 +1142,6 @@ impl MetaItem { fn tokens(&self) -> TokenStream { let mut idents = vec![]; let mut last_pos = BytePos(0 as u32); - // FIXME: Share code with `parse_path`. for (i, segment) in self.ident.segments.iter().enumerate() { let is_first = i == 0; if !is_first { @@ -1162,14 +1161,16 @@ impl MetaItem { fn from_tokens(tokens: &mut iter::Peekable) -> Option where I: Iterator, { + // FIXME: Share code with `parse_path`. let ident = match tokens.next() { Some(TokenTree::Token(span, Token::Ident(ident, _))) => { if let Some(TokenTree::Token(_, Token::ModSep)) = tokens.peek() { + let mut segments = vec![PathSegment::from_ident(ident.with_span_pos(span))]; tokens.next(); - let mut segments = vec![]; loop { - if let Some(TokenTree::Token(_, Token::Ident(ident, _))) = tokens.next() { - segments.push(ast::PathSegment::from_ident(ident)); + if let Some(TokenTree::Token(span, + Token::Ident(ident, _))) = tokens.next() { + segments.push(PathSegment::from_ident(ident.with_span_pos(span))); } else { return None; } @@ -1179,15 +1180,14 @@ impl MetaItem { break; } } - ast::Path { span, segments } + let span = span.with_hi(segments.last().unwrap().ident.span.hi()); + Path { span, segments } } else { - ast::Path::from_ident(ident) + Path::from_ident(ident.with_span_pos(span)) } } Some(TokenTree::Token(_, Token::Interpolated(ref nt))) => match nt.0 { - token::Nonterminal::NtIdent(ident, _) => { - ast::Path::from_ident(ident) - } + token::Nonterminal::NtIdent(ident, _) => Path::from_ident(ident), token::Nonterminal::NtMeta(ref meta) => return Some(meta.clone()), token::Nonterminal::NtPath(ref path) => path.clone(), _ => return None, diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 18bf5445123..d8db76a95ff 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -460,7 +460,7 @@ declare_features! ( // Access to crate names passed via `--extern` through prelude (active, extern_prelude, "1.27.0", Some(44660), Some(Edition::Edition2018)), - + // Scoped attributes (active, tool_attributes, "1.25.0", Some(44690), None), ); @@ -1191,7 +1191,7 @@ impl<'a> Context<'a> { } } else { gate_feature!(self, custom_attribute, attr.span, - &format!("the attribute `{}` is currently \ + &format!("The attribute `{}` is currently \ unknown to the compiler and \ may have meaning \ added to it in the future", diff --git a/src/test/compile-fail-fulldeps/auxiliary/macro_crate_test.rs b/src/test/compile-fail-fulldeps/auxiliary/macro_crate_test.rs index 040f0b661be..fb0f9105b0d 100644 --- a/src/test/compile-fail-fulldeps/auxiliary/macro_crate_test.rs +++ b/src/test/compile-fail-fulldeps/auxiliary/macro_crate_test.rs @@ -117,7 +117,7 @@ fn expand_duplicate(cx: &mut ExtCtxt, let copy_name = match mi.node { ast::MetaItemKind::List(ref xs) => { if let Some(word) = xs[0].word() { - word.ident + word.ident.segments.last().unwrap().ident } else { cx.span_err(mi.span, "Expected word"); return; diff --git a/src/test/run-pass-fulldeps/auxiliary/macro_crate_test.rs b/src/test/run-pass-fulldeps/auxiliary/macro_crate_test.rs index 2f80408ac1c..d698af50579 100644 --- a/src/test/run-pass-fulldeps/auxiliary/macro_crate_test.rs +++ b/src/test/run-pass-fulldeps/auxiliary/macro_crate_test.rs @@ -112,7 +112,7 @@ fn expand_duplicate(cx: &mut ExtCtxt, let copy_name = match mi.node { ast::MetaItemKind::List(ref xs) => { if let Some(word) = xs[0].word() { - word.ident + word.ident.segments.last().unwrap().ident } else { cx.span_err(mi.span, "Expected word"); return; -- cgit 1.4.1-3-g733a5 From df8f5375a6b246a4ffee3b074ec749ad95a1f430 Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Wed, 7 Feb 2018 10:16:44 -0700 Subject: introduce `UniverseIndex` into `InferCtxt` Always using root environment for now. --- src/librustc/infer/mod.rs | 12 ++++++++++++ src/librustc/ty/mod.rs | 4 +--- 2 files changed, 13 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 553926dba8f..08ae535b8e8 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -183,6 +183,17 @@ pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { // obligations within. This is expected to be done 'late enough' // that all type inference variables have been bound and so forth. pub region_obligations: RefCell)>>, + + /// What is the innermost universe we have created? Starts out as + /// `UniverseIndex::root()` but grows from there as we enter + /// universal quantifiers. + /// + /// NB: At present, we exclude the universal quantifiers on the + /// item we are type-checking, and just consider those names as + /// part of the root universe. So this would only get incremented + /// when we enter into a higher-ranked (`for<..>`) type or trait + /// bound. + pub universe: ty::UniverseIndex, } /// A map returned by `skolemize_late_bound_regions()` indicating the skolemized @@ -455,6 +466,7 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> { err_count_on_creation: tcx.sess.err_count(), in_snapshot: Cell::new(false), region_obligations: RefCell::new(vec![]), + universe: ty::UniverseIndex::ROOT, })) } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 4fdc247686f..744b92dbe0d 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1376,9 +1376,7 @@ pub struct UniverseIndex(u32); impl UniverseIndex { /// The root universe, where things that the user defined are /// visible. - pub fn root() -> UniverseIndex { - UniverseIndex(0) - } + pub const ROOT: Self = UniverseIndex(0); /// A "subuniverse" corresponds to being inside a `forall` quantifier. /// So, for example, suppose we have this type in universe `U`: -- cgit 1.4.1-3-g733a5 From e904d56928b20b854c26447553525b6585172d89 Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Wed, 7 Feb 2018 10:27:42 -0700 Subject: add universes to type inference variables This gives each type inference variable a notion of universe but doesn't do anything with it. We can always get the "current universe" from infer_ctxt. This relies on the property of type variables that they can never interact with siblings. --- src/librustc/infer/combine.rs | 4 ++-- src/librustc/infer/mod.rs | 5 +++-- src/librustc/infer/type_variable.rs | 13 ++++++++++--- 3 files changed, 15 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs index 096aed85f55..ccba5a09cf6 100644 --- a/src/librustc/infer/combine.rs +++ b/src/librustc/infer/combine.rs @@ -407,7 +407,7 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, ' drop(variables); self.relate(&u, &u) } - TypeVariableValue::Unknown { .. } => { + TypeVariableValue::Unknown { universe } => { match self.ambient_variance { // Invariant: no need to make a fresh type variable. ty::Invariant => return Ok(t), @@ -424,7 +424,7 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, ' } let origin = *variables.var_origin(vid); - let new_var_id = variables.new_var(false, origin); + let new_var_id = variables.new_var(universe, false, origin); let u = self.tcx().mk_var(new_var_id); debug!("generalize: replacing original vid={:?} with new={:?}", vid, u); diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 08ae535b8e8..3ec5ae6bc8f 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -853,7 +853,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { pub fn next_ty_var_id(&self, diverging: bool, origin: TypeVariableOrigin) -> TyVid { self.type_variables .borrow_mut() - .new_var(diverging, origin) + .new_var(self.universe, diverging, origin) } pub fn next_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> { @@ -921,7 +921,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { -> Ty<'tcx> { let ty_var_id = self.type_variables .borrow_mut() - .new_var(false, + .new_var(self.universe, + false, TypeVariableOrigin::TypeParameterDefinition(span, def.name)); self.tcx.mk_var(ty_var_id) diff --git a/src/librustc/infer/type_variable.rs b/src/librustc/infer/type_variable.rs index 5e96f4eb576..a5c2191232e 100644 --- a/src/librustc/infer/type_variable.rs +++ b/src/librustc/infer/type_variable.rs @@ -78,10 +78,12 @@ struct TypeVariableData { #[derive(Copy, Clone, Debug)] pub enum TypeVariableValue<'tcx> { Known { value: Ty<'tcx> }, - Unknown, + Unknown { universe: ty::UniverseIndex }, } impl<'tcx> TypeVariableValue<'tcx> { + /// If this value is known, returns the type it is known to be. + /// Otherwise, `None`. pub fn known(&self) -> Option> { match *self { TypeVariableValue::Unknown { .. } => None, @@ -181,10 +183,11 @@ impl<'tcx> TypeVariableTable<'tcx> { /// The code in this module doesn't care, but it can be useful /// for improving error messages. pub fn new_var(&mut self, + universe: ty::UniverseIndex, diverging: bool, origin: TypeVariableOrigin) -> ty::TyVid { - let eq_key = self.eq_relations.new_key(TypeVariableValue::Unknown); + let eq_key = self.eq_relations.new_key(TypeVariableValue::Unknown { universe }); let sub_key = self.sub_relations.new_key(()); assert_eq!(eq_key.vid, sub_key); @@ -437,7 +440,11 @@ impl<'tcx> ut::UnifyValue for TypeVariableValue<'tcx> { (&TypeVariableValue::Unknown { .. }, &TypeVariableValue::Known { .. }) => Ok(*value2), // If both sides are *unknown*, it hardly matters, does it? - (&TypeVariableValue::Unknown, &TypeVariableValue::Unknown) => Ok(*value1), + (&TypeVariableValue::Unknown { universe: universe1 }, + &TypeVariableValue::Unknown { universe: universe2 }) => { + let universe = cmp::min(universe1, universe2); + Ok(TypeVariableValue::Unknown { universe }) + } } } } -- cgit 1.4.1-3-g733a5 From 360cbf2f486dea1c89253187e431f414ecbaa20d Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Wed, 7 Feb 2018 11:17:31 -0700 Subject: change skolemizations to use universe index This is sort of confusing "side step". All it does is to change the representation of a skolemized region. but the source of that universe index is not the inference context, which is what we eventually want, but rather an internal counter in the region inference context. We'll patch that up later. But doing this now ought to help with confusing diffs later. --- src/librustc/infer/region_constraints/mod.rs | 36 ++++++++++++++-------------- src/librustc/ty/mod.rs | 20 +++++++++++++--- src/librustc/ty/sty.rs | 7 +----- src/librustc/util/ppaux.rs | 4 ++-- 4 files changed, 38 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs index 4113a2dd417..bfae2b8b1c2 100644 --- a/src/librustc/infer/region_constraints/mod.rs +++ b/src/librustc/infer/region_constraints/mod.rs @@ -48,7 +48,7 @@ pub struct RegionConstraintCollector<'tcx> { glbs: CombineMap<'tcx>, /// Number of skolemized variables currently active. - skolemization_count: u32, + skolemization_count: ty::UniverseIndex, /// Global counter used during the GLB algorithm to create unique /// names for fresh bound regions @@ -233,7 +233,7 @@ type CombineMap<'tcx> = FxHashMap, RegionVid>; pub struct RegionSnapshot { length: usize, region_snapshot: ut::Snapshot>, - skolemization_count: u32, + skolemization_count: ty::UniverseIndex, } /// When working with skolemized regions, we often wish to find all of @@ -277,7 +277,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> { data: RegionConstraintData::default(), lubs: FxHashMap(), glbs: FxHashMap(), - skolemization_count: 0, + skolemization_count: ty::UniverseIndex::ROOT, bound_count: 0, undo_log: Vec::new(), unification_table: ut::UnificationTable::new(), @@ -329,7 +329,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> { unification_table, } = self; - assert_eq!(*skolemization_count, 0); + assert_eq!(*skolemization_count, ty::UniverseIndex::ROOT); // Clear the tables of (lubs, glbs), so that we will create // fresh regions if we do a LUB operation. As it happens, @@ -375,7 +375,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> { assert!(self.undo_log[snapshot.length] == OpenSnapshot); assert!( self.skolemization_count == snapshot.skolemization_count, - "failed to pop skolemized regions: {} now vs {} at start", + "failed to pop skolemized regions: {:?} now vs {:?} at start", self.skolemization_count, snapshot.skolemization_count ); @@ -485,9 +485,9 @@ impl<'tcx> RegionConstraintCollector<'tcx> { assert!(self.in_snapshot()); assert!(self.undo_log[snapshot.length] == OpenSnapshot); - let sc = self.skolemization_count; - self.skolemization_count = sc + 1; - tcx.mk_region(ReSkolemized(ty::SkolemizedRegionVid { index: sc }, br)) + let universe = self.skolemization_count.subuniverse(); + self.skolemization_count = universe; + tcx.mk_region(ReSkolemized(universe, br)) } /// Removes all the edges to/from the skolemized regions that are @@ -505,20 +505,20 @@ impl<'tcx> RegionConstraintCollector<'tcx> { assert!(self.in_snapshot()); assert!(self.undo_log[snapshot.length] == OpenSnapshot); assert!( - self.skolemization_count as usize >= skols.len(), + self.skolemization_count.as_usize() >= skols.len(), "popping more skolemized variables than actually exist, \ - sc now = {}, skols.len = {}", + sc now = {:?}, skols.len = {:?}", self.skolemization_count, skols.len() ); - let last_to_pop = self.skolemization_count; - let first_to_pop = last_to_pop - (skols.len() as u32); + let last_to_pop = self.skolemization_count.subuniverse(); + let first_to_pop = ty::UniverseIndex::from(last_to_pop.as_u32() - skols.len() as u32); assert!( first_to_pop >= snapshot.skolemization_count, "popping more regions than snapshot contains, \ - sc now = {}, sc then = {}, skols.len = {}", + sc now = {:?}, sc then = {:?}, skols.len = {:?}", self.skolemization_count, snapshot.skolemization_count, skols.len() @@ -526,13 +526,13 @@ impl<'tcx> RegionConstraintCollector<'tcx> { debug_assert! { skols.iter() .all(|&k| match *k { - ty::ReSkolemized(index, _) => - index.index >= first_to_pop && - index.index < last_to_pop, + ty::ReSkolemized(universe, _) => + universe >= first_to_pop && + universe < last_to_pop, _ => false }), - "invalid skolemization keys or keys out of range ({}..{}): {:?}", + "invalid skolemization keys or keys out of range ({:?}..{:?}): {:?}", snapshot.skolemization_count, self.skolemization_count, skols @@ -867,7 +867,7 @@ impl fmt::Debug for RegionSnapshot { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, - "RegionSnapshot(length={},skolemization={})", + "RegionSnapshot(length={},skolemization={:?})", self.length, self.skolemization_count ) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 744b92dbe0d..c4fe112a9e9 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -69,7 +69,7 @@ pub use self::sty::{ExistentialTraitRef, PolyExistentialTraitRef}; pub use self::sty::{ExistentialProjection, PolyExistentialProjection, Const}; pub use self::sty::{BoundRegion, EarlyBoundRegion, FreeRegion, Region}; pub use self::sty::RegionKind; -pub use self::sty::{TyVid, IntVid, FloatVid, RegionVid, SkolemizedRegionVid}; +pub use self::sty::{TyVid, IntVid, FloatVid, RegionVid}; pub use self::sty::BoundRegion::*; pub use self::sty::InferTy::*; pub use self::sty::RegionKind::*; @@ -1370,7 +1370,7 @@ impl<'tcx> InstantiatedPredicates<'tcx> { /// type name in a non-zero universe is a skolemized type -- an /// idealized representative of "types in general" that we use for /// checking generic functions. -#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] pub struct UniverseIndex(u32); impl UniverseIndex { @@ -1390,7 +1390,21 @@ impl UniverseIndex { /// region `'a`, but that region was not nameable from `U` because /// it was not in scope there. pub fn subuniverse(self) -> UniverseIndex { - UniverseIndex(self.0 + 1) + UniverseIndex(self.0.checked_add(1).unwrap()) + } + + pub fn as_u32(&self) -> u32 { + self.0 + } + + pub fn as_usize(&self) -> usize { + self.0 as usize + } +} + +impl From for UniverseIndex { + fn from(index: u32) -> Self { + UniverseIndex(index) } } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 0d655562214..382db571b52 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1021,7 +1021,7 @@ pub enum RegionKind { /// A skolemized region - basically the higher-ranked version of ReFree. /// Should not exist after typeck. - ReSkolemized(SkolemizedRegionVid, BoundRegion), + ReSkolemized(ty::UniverseIndex, BoundRegion), /// Empty lifetime is for data that is never accessed. /// Bottom in the region lattice. We treat ReEmpty somewhat @@ -1075,11 +1075,6 @@ newtype_index!(RegionVid DEBUG_FORMAT = custom, }); -#[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, PartialOrd, Ord)] -pub struct SkolemizedRegionVid { - pub index: u32, -} - #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub enum InferTy { TyVar(TyVid), diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index b777f513e6d..894a18b79cc 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -808,8 +808,8 @@ define_print! { write!(f, "'?{}", c.index()) } - ty::ReSkolemized(id, ref bound_region) => { - write!(f, "ReSkolemized({}, {:?})", id.index, bound_region) + ty::ReSkolemized(universe, ref bound_region) => { + write!(f, "ReSkolemized({:?}, {:?})", universe, bound_region) } ty::ReEmpty => write!(f, "ReEmpty"), -- cgit 1.4.1-3-g733a5 From 6234a898287fc2241f81373d9ad289788b49ebf1 Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Wed, 7 Feb 2018 11:47:57 -0700 Subject: store RegionVariableInfo and not just RegionVariableOrigin --- src/librustc/infer/lexical_region_resolve/mod.rs | 16 +++++------ src/librustc/infer/mod.rs | 18 ++++++------ src/librustc/infer/region_constraints/mod.rs | 33 +++++++++++++--------- .../borrow_check/nll/region_infer/mod.rs | 10 +++---- 4 files changed, 42 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/librustc/infer/lexical_region_resolve/mod.rs b/src/librustc/infer/lexical_region_resolve/mod.rs index 00b2ac7449f..5984a831e6f 100644 --- a/src/librustc/infer/lexical_region_resolve/mod.rs +++ b/src/librustc/infer/lexical_region_resolve/mod.rs @@ -15,7 +15,7 @@ use infer::RegionVariableOrigin; use infer::region_constraints::Constraint; use infer::region_constraints::GenericKind; use infer::region_constraints::RegionConstraintData; -use infer::region_constraints::VarOrigins; +use infer::region_constraints::VarInfos; use infer::region_constraints::VerifyBound; use middle::free_region::RegionRelations; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; @@ -37,7 +37,7 @@ mod graphviz; /// all the variables as well as a set of errors that must be reported. pub fn resolve<'tcx>( region_rels: &RegionRelations<'_, '_, 'tcx>, - var_origins: VarOrigins, + var_infos: VarInfos, data: RegionConstraintData<'tcx>, ) -> ( LexicalRegionResolutions<'tcx>, @@ -47,7 +47,7 @@ pub fn resolve<'tcx>( let mut errors = vec![]; let mut resolver = LexicalResolver { region_rels, - var_origins, + var_infos, data, }; let values = resolver.infer_variable_values(&mut errors); @@ -103,7 +103,7 @@ type RegionGraph<'tcx> = graph::Graph<(), Constraint<'tcx>>; struct LexicalResolver<'cx, 'gcx: 'tcx, 'tcx: 'cx> { region_rels: &'cx RegionRelations<'cx, 'gcx, 'tcx>, - var_origins: VarOrigins, + var_infos: VarInfos, data: RegionConstraintData<'tcx>, } @@ -132,7 +132,7 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> { } fn num_vars(&self) -> usize { - self.var_origins.len() + self.var_infos.len() } /// Initially, the value for all variables is set to `'empty`, the @@ -279,7 +279,7 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> { (&ReVar(v_id), _) | (_, &ReVar(v_id)) => { span_bug!( - self.var_origins[v_id].span(), + self.var_infos[v_id].origin.span(), "lub_concrete_regions invoked with non-concrete \ regions: {:?}, {:?}", a, @@ -576,7 +576,7 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> { if !self.region_rels .is_subregion_of(lower_bound.region, upper_bound.region) { - let origin = self.var_origins[node_idx].clone(); + let origin = self.var_infos[node_idx].origin.clone(); debug!( "region inference error at {:?} for {:?}: SubSupConflict sub: {:?} \ sup: {:?}", @@ -598,7 +598,7 @@ impl<'cx, 'gcx, 'tcx> LexicalResolver<'cx, 'gcx, 'tcx> { } span_bug!( - self.var_origins[node_idx].span(), + self.var_infos[node_idx].origin.span(), "collect_error_for_expanding_node() could not find \ error for var {:?}, lower_bounds={:?}, \ upper_bounds={:?}", diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 3ec5ae6bc8f..6e455f1e973 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -42,7 +42,7 @@ use arena::SyncDroplessArena; use self::combine::CombineFields; use self::higher_ranked::HrMatchResult; use self::region_constraints::{RegionConstraintCollector, RegionSnapshot}; -use self::region_constraints::{GenericKind, VerifyBound, RegionConstraintData, VarOrigins}; +use self::region_constraints::{GenericKind, VerifyBound, RegionConstraintData, VarInfos}; use self::lexical_region_resolve::LexicalRegionResolutions; use self::outlives::env::OutlivesEnvironment; use self::type_variable::TypeVariableOrigin; @@ -889,7 +889,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// Number of region variables created so far. pub fn num_region_vars(&self) -> usize { - self.borrow_region_constraints().var_origins().len() + self.borrow_region_constraints().num_region_vars() } /// Just a convenient wrapper of `next_region_var` for using during NLL. @@ -1017,12 +1017,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { region_context, region_map, outlives_env.free_region_map()); - let (var_origins, data) = self.region_constraints.borrow_mut() + let (var_infos, data) = self.region_constraints.borrow_mut() .take() .expect("regions already resolved") - .into_origins_and_data(); + .into_infos_and_data(); let (lexical_region_resolutions, errors) = - lexical_region_resolve::resolve(region_rels, var_origins, data); + lexical_region_resolve::resolve(region_rels, var_infos, data); let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions)); assert!(old_value.is_none()); @@ -1070,13 +1070,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// hence that `resolve_regions_and_report_errors` can never be /// called. This is used only during NLL processing to "hand off" ownership /// of the set of region vairables into the NLL region context. - pub fn take_region_var_origins(&self) -> VarOrigins { - let (var_origins, data) = self.region_constraints.borrow_mut() + pub fn take_region_var_origins(&self) -> VarInfos { + let (var_infos, data) = self.region_constraints.borrow_mut() .take() .expect("regions already resolved") - .into_origins_and_data(); + .into_infos_and_data(); assert!(data.is_empty()); - var_origins + var_infos } pub fn ty_to_string(&self, t: Ty<'tcx>) -> String { diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs index bfae2b8b1c2..4d5f8b2b11e 100644 --- a/src/librustc/infer/region_constraints/mod.rs +++ b/src/librustc/infer/region_constraints/mod.rs @@ -33,7 +33,7 @@ mod taint; pub struct RegionConstraintCollector<'tcx> { /// For each `RegionVid`, the corresponding `RegionVariableOrigin`. - var_origins: IndexVec, + var_infos: IndexVec, data: RegionConstraintData<'tcx>, @@ -76,7 +76,7 @@ pub struct RegionConstraintCollector<'tcx> { unification_table: ut::UnificationTable>, } -pub type VarOrigins = IndexVec; +pub type VarInfos = IndexVec; /// The full set of region constraints gathered up by the collector. /// Describes constraints between the region variables and other @@ -230,6 +230,11 @@ enum CombineMapType { type CombineMap<'tcx> = FxHashMap, RegionVid>; +#[derive(Debug, Clone, Copy)] +pub struct RegionVariableInfo { + pub origin: RegionVariableOrigin, +} + pub struct RegionSnapshot { length: usize, region_snapshot: ut::Snapshot>, @@ -273,7 +278,7 @@ impl TaintDirections { impl<'tcx> RegionConstraintCollector<'tcx> { pub fn new() -> RegionConstraintCollector<'tcx> { RegionConstraintCollector { - var_origins: VarOrigins::default(), + var_infos: VarInfos::default(), data: RegionConstraintData::default(), lubs: FxHashMap(), glbs: FxHashMap(), @@ -284,8 +289,8 @@ impl<'tcx> RegionConstraintCollector<'tcx> { } } - pub fn var_origins(&self) -> &VarOrigins { - &self.var_origins + pub fn num_region_vars(&self) -> usize { + self.var_infos.len() } pub fn region_constraint_data(&self) -> &RegionConstraintData<'tcx> { @@ -295,9 +300,9 @@ impl<'tcx> RegionConstraintCollector<'tcx> { /// Once all the constraints have been gathered, extract out the final data. /// /// Not legal during a snapshot. - pub fn into_origins_and_data(self) -> (VarOrigins, RegionConstraintData<'tcx>) { + pub fn into_infos_and_data(self) -> (VarInfos, RegionConstraintData<'tcx>) { assert!(!self.in_snapshot()); - (self.var_origins, self.data) + (self.var_infos, self.data) } /// Takes (and clears) the current set of constraints. Note that @@ -319,7 +324,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> { // should think carefully about whether it needs to be cleared // or updated in some way. let RegionConstraintCollector { - var_origins, + var_infos, data, lubs, glbs, @@ -343,7 +348,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> { // also insert `a <= b` and a `b <= a` edges, so the // `RegionConstraintData` contains the relationship here. *unification_table = ut::UnificationTable::new(); - for vid in var_origins.indices() { + for vid in var_infos.indices() { unification_table.new_key(unify_key::RegionVidKey { min_vid: vid }); } @@ -411,8 +416,8 @@ impl<'tcx> RegionConstraintCollector<'tcx> { // nothing to do here } AddVar(vid) => { - self.var_origins.pop().unwrap(); - assert_eq!(self.var_origins.len(), vid.index() as usize); + self.var_infos.pop().unwrap(); + assert_eq!(self.var_infos.len(), vid.index() as usize); } AddConstraint(ref constraint) => { self.data.constraints.remove(constraint); @@ -434,7 +439,9 @@ impl<'tcx> RegionConstraintCollector<'tcx> { } pub fn new_region_var(&mut self, origin: RegionVariableOrigin) -> RegionVid { - let vid = self.var_origins.push(origin.clone()); + let vid = self.var_infos.push(RegionVariableInfo { + origin, + }); let u_vid = self.unification_table .new_key(unify_key::RegionVidKey { min_vid: vid }); @@ -452,7 +459,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> { /// Returns the origin for the given variable. pub fn var_origin(&self, vid: RegionVid) -> RegionVariableOrigin { - self.var_origins[vid].clone() + self.var_infos[vid].origin } /// Creates a new skolemized region. Skolemized regions are fresh diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs index 08391401cc6..4d1f3e2b430 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs @@ -16,7 +16,7 @@ use rustc::infer::RegionObligation; use rustc::infer::RegionVariableOrigin; use rustc::infer::SubregionOrigin; use rustc::infer::error_reporting::nice_region_error::NiceRegionError; -use rustc::infer::region_constraints::{GenericKind, VarOrigins}; +use rustc::infer::region_constraints::{GenericKind, VarInfos}; use rustc::mir::{ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegionRequirements, Local, Location, Mir}; use rustc::traits::ObligationCause; @@ -256,19 +256,19 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// of those will be constant regions representing the free /// regions defined in `universal_regions`. pub(crate) fn new( - var_origins: VarOrigins, + var_infos: VarInfos, universal_regions: UniversalRegions<'tcx>, mir: &Mir<'tcx>, ) -> Self { - let num_region_variables = var_origins.len(); + let num_region_variables = var_infos.len(); let num_universal_regions = universal_regions.len(); let elements = &Rc::new(RegionValueElements::new(mir, num_universal_regions)); // Create a RegionDefinition for each inference variable. - let definitions = var_origins + let definitions = var_infos .into_iter() - .map(|origin| RegionDefinition::new(origin)) + .map(|info| RegionDefinition::new(info.origin)) .collect(); let mut result = Self { -- cgit 1.4.1-3-g733a5 From 2f69b798af9cdf88637395a49ed10ea6163399b6 Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Wed, 7 Feb 2018 12:22:47 -0700 Subject: give a universe to region variables --- src/librustc/infer/mod.rs | 4 +++- src/librustc/infer/region_constraints/mod.rs | 36 ++++++++++++++++++++++++---- 2 files changed, 34 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 6e455f1e973..e40282aea08 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -884,7 +884,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// during diagnostics / error-reporting. pub fn next_region_var(&self, origin: RegionVariableOrigin) -> ty::Region<'tcx> { - self.tcx.mk_region(ty::ReVar(self.borrow_region_constraints().new_region_var(origin))) + let region_var = self.borrow_region_constraints() + .new_region_var(self.universe, origin); + self.tcx.mk_region(ty::ReVar(region_var)) } /// Number of region variables created so far. diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs index 4d5f8b2b11e..b2a580420c6 100644 --- a/src/librustc/infer/region_constraints/mod.rs +++ b/src/librustc/infer/region_constraints/mod.rs @@ -25,9 +25,7 @@ use ty::ReStatic; use ty::{BrFresh, ReLateBound, ReSkolemized, ReVar}; use std::collections::BTreeMap; -use std::fmt; -use std::mem; -use std::u32; +use std::{cmp, fmt, mem, u32}; mod taint; @@ -233,6 +231,7 @@ type CombineMap<'tcx> = FxHashMap, RegionVid>; #[derive(Debug, Clone, Copy)] pub struct RegionVariableInfo { pub origin: RegionVariableOrigin, + pub universe: ty::UniverseIndex, } pub struct RegionSnapshot { @@ -438,9 +437,12 @@ impl<'tcx> RegionConstraintCollector<'tcx> { } } - pub fn new_region_var(&mut self, origin: RegionVariableOrigin) -> RegionVid { + pub fn new_region_var(&mut self, + universe: ty::UniverseIndex, + origin: RegionVariableOrigin) -> RegionVid { let vid = self.var_infos.push(RegionVariableInfo { origin, + universe, }); let u_vid = self.unification_table @@ -457,6 +459,11 @@ impl<'tcx> RegionConstraintCollector<'tcx> { return vid; } + /// Returns the universe for the given variable. + pub fn var_universe(&self, vid: RegionVid) -> ty::UniverseIndex { + self.var_infos[vid].universe + } + /// Returns the origin for the given variable. pub fn var_origin(&self, vid: RegionVid) -> RegionVariableOrigin { self.var_infos[vid].origin @@ -812,7 +819,10 @@ impl<'tcx> RegionConstraintCollector<'tcx> { if let Some(&c) = self.combine_map(t).get(&vars) { return tcx.mk_region(ReVar(c)); } - let c = self.new_region_var(MiscVariable(origin.span())); + let a_universe = self.universe(a); + let b_universe = self.universe(b); + let c_universe = cmp::max(a_universe, b_universe); + let c = self.new_region_var(c_universe, MiscVariable(origin.span())); self.combine_map(t).insert(vars, c); if self.in_snapshot() { self.undo_log.push(AddCombination(t, vars)); @@ -828,6 +838,22 @@ impl<'tcx> RegionConstraintCollector<'tcx> { new_r } + fn universe(&self, region: Region<'tcx>) -> ty::UniverseIndex { + match *region { + ty::ReScope(..) | + ty::ReStatic | + ty::ReEmpty | + ty::ReErased | + ty::ReFree(..) | + ty::ReEarlyBound(..) => ty::UniverseIndex::ROOT, + ty::ReSkolemized(universe, _) => universe, + ty::ReClosureBound(vid) | + ty::ReVar(vid) => self.var_universe(vid), + ty::ReLateBound(..) => + bug!("universe(): encountered bound region {:?}", region), + } + } + pub fn vars_created_since_snapshot(&self, mark: &RegionSnapshot) -> Vec { self.undo_log[mark.length..] .iter() -- cgit 1.4.1-3-g733a5 From bf2a6c3ff9e4c37526813f255f70f73db7119564 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 2 May 2018 12:30:45 +0200 Subject: Allow unaligned reads in constants --- src/librustc_mir/hair/pattern/mod.rs | 2 +- src/librustc_mir/interpret/eval_context.rs | 4 +--- src/test/ui/const-eval/ice-packed.rs | 28 ++++++++++++++++++++++++++++ 3 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/const-eval/ice-packed.rs (limited to 'src') diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 619b4596b42..623e0de478b 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -792,7 +792,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { ConstVal::Value(miri) => const_val_field( self.tcx, self.param_env, instance, variant_opt, field, miri, cv.ty, - ).unwrap(), + ).expect("field access failed"), _ => bug!("{:#?} is not a valid adt", cv), }; self.const_to_pat(instance, val, id, span) diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index e1b358a5eb7..bea29b6926a 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -1340,9 +1340,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M use syntax::ast::FloatTy; let layout = self.layout_of(ty)?; - // do the strongest layout check of the two - let align = layout.align.max(ptr_align); - self.memory.check_align(ptr, align)?; + self.memory.check_align(ptr, ptr_align)?; if layout.size.bytes() == 0 { return Ok(Some(Value::ByVal(PrimVal::Undef))); diff --git a/src/test/ui/const-eval/ice-packed.rs b/src/test/ui/const-eval/ice-packed.rs new file mode 100644 index 00000000000..1db12a06b03 --- /dev/null +++ b/src/test/ui/const-eval/ice-packed.rs @@ -0,0 +1,28 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-pass +#[derive(Copy, Clone, PartialEq, Eq)] +#[repr(packed)] +pub struct Num(u64); + +impl Num { + pub const ZERO: Self = Num(0); +} + +pub fn decrement(a: Num) -> Num { + match a { + Num::ZERO => Num::ZERO, + a => Num(a.0 - 1) + } +} + +fn main() { +} -- cgit 1.4.1-3-g733a5 From ce64f9d823bf5bbaff899227b4c776abd84c395b Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Wed, 2 May 2018 08:28:42 -0600 Subject: Fix rebase issues --- src/librustc/infer/region_constraints/mod.rs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs index b2a580420c6..fc128b1a6d8 100644 --- a/src/librustc/infer/region_constraints/mod.rs +++ b/src/librustc/infer/region_constraints/mod.rs @@ -851,6 +851,8 @@ impl<'tcx> RegionConstraintCollector<'tcx> { ty::ReVar(vid) => self.var_universe(vid), ty::ReLateBound(..) => bug!("universe(): encountered bound region {:?}", region), + ty::ReCanonical(..) => + bug!("region_universe(): encountered canonical region {:?}", region), } } -- cgit 1.4.1-3-g733a5 From f5d240b432b0f1a157a66249b296e0a246525688 Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Thu, 8 Feb 2018 13:14:24 -0700 Subject: Wrap `InferCtxt::universe` in a cell We'll need this in order to start tracking skolemizatoins here, and it's easier to update all the field accesses now rather than later. --- src/librustc/infer/mod.rs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index e40282aea08..e5311ccfb7d 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -193,7 +193,7 @@ pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { /// part of the root universe. So this would only get incremented /// when we enter into a higher-ranked (`for<..>`) type or trait /// bound. - pub universe: ty::UniverseIndex, + universe: Cell, } /// A map returned by `skolemize_late_bound_regions()` indicating the skolemized @@ -466,7 +466,7 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> { err_count_on_creation: tcx.sess.err_count(), in_snapshot: Cell::new(false), region_obligations: RefCell::new(vec![]), - universe: ty::UniverseIndex::ROOT, + universe: Cell::new(ty::UniverseIndex::ROOT), })) } } @@ -853,7 +853,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { pub fn next_ty_var_id(&self, diverging: bool, origin: TypeVariableOrigin) -> TyVid { self.type_variables .borrow_mut() - .new_var(self.universe, diverging, origin) + .new_var(self.universe(), diverging, origin) } pub fn next_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> { @@ -885,7 +885,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { pub fn next_region_var(&self, origin: RegionVariableOrigin) -> ty::Region<'tcx> { let region_var = self.borrow_region_constraints() - .new_region_var(self.universe, origin); + .new_region_var(self.universe(), origin); self.tcx.mk_region(ty::ReVar(region_var)) } @@ -923,7 +923,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { -> Ty<'tcx> { let ty_var_id = self.type_variables .borrow_mut() - .new_var(self.universe, + .new_var(self.universe(), false, TypeVariableOrigin::TypeParameterDefinition(span, def.name)); @@ -1371,6 +1371,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.evaluation_cache.clear(); self.projection_cache.borrow_mut().clear(); } + + fn universe(&self) -> ty::UniverseIndex { + self.universe.get() + } } impl<'a, 'gcx, 'tcx> TypeTrace<'tcx> { -- cgit 1.4.1-3-g733a5 From 04708ba60e79608956758513daa844ef14760c8b Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Thu, 8 Feb 2018 14:12:32 -0700 Subject: track skol levels in the InferCtxt rather than via counter --- src/librustc/infer/higher_ranked/mod.rs | 12 ++--- src/librustc/infer/mod.rs | 9 +++- src/librustc/infer/region_constraints/mod.rs | 81 +++------------------------- src/librustc/traits/project.rs | 2 +- src/librustc/traits/select.rs | 9 ++-- 5 files changed, 26 insertions(+), 87 deletions(-) (limited to 'src') diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs index c35cdf91fe7..d60d449f6c2 100644 --- a/src/librustc/infer/higher_ranked/mod.rs +++ b/src/librustc/infer/higher_ranked/mod.rs @@ -62,7 +62,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> { // Second, we instantiate each bound region in the supertype with a // fresh concrete region. let (b_prime, skol_map) = - self.infcx.skolemize_late_bound_regions(b, snapshot); + self.infcx.skolemize_late_bound_regions(b); debug!("a_prime={:?}", a_prime); debug!("b_prime={:?}", b_prime); @@ -587,14 +587,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// /// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trait-hrtb.html pub fn skolemize_late_bound_regions(&self, - binder: &ty::Binder, - snapshot: &CombinedSnapshot<'a, 'tcx>) + binder: &ty::Binder) -> (T, SkolemizationMap<'tcx>) where T : TypeFoldable<'tcx> { let (result, map) = self.tcx.replace_late_bound_regions(binder, |br| { - self.borrow_region_constraints() - .push_skolemized(self.tcx, br, &snapshot.region_constraints_snapshot) + self.universe.set(self.universe().subuniverse()); + self.tcx.mk_region(ty::ReSkolemized(self.universe(), br)) }); debug!("skolemize_bound_regions(binder={:?}, result={:?}, map={:?})", @@ -779,7 +778,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { debug!("pop_skolemized({:?})", skol_map); let skol_regions: FxHashSet<_> = skol_map.values().cloned().collect(); self.borrow_region_constraints() - .pop_skolemized(self.tcx, &skol_regions, &snapshot.region_constraints_snapshot); + .pop_skolemized(self.universe(), &skol_regions, &snapshot.region_constraints_snapshot); + self.universe.set(snapshot.universe); if !skol_map.is_empty() { self.projection_cache.borrow_mut().rollback_skolemized( &snapshot.projection_cache_snapshot); diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index e5311ccfb7d..c62e7f8d9b6 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -501,6 +501,7 @@ pub struct CombinedSnapshot<'a, 'tcx:'a> { float_snapshot: ut::Snapshot>, region_constraints_snapshot: RegionSnapshot, region_obligations_snapshot: usize, + universe: ty::UniverseIndex, was_in_snapshot: bool, _in_progress_tables: Option>>, } @@ -630,6 +631,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { float_snapshot: self.float_unification_table.borrow_mut().snapshot(), region_constraints_snapshot: self.borrow_region_constraints().start_snapshot(), region_obligations_snapshot: self.region_obligations.borrow().len(), + universe: self.universe(), was_in_snapshot: in_snapshot, // Borrow tables "in progress" (i.e. during typeck) // to ban writes from within a snapshot to them. @@ -647,10 +649,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { float_snapshot, region_constraints_snapshot, region_obligations_snapshot, + universe, was_in_snapshot, _in_progress_tables } = snapshot; self.in_snapshot.set(was_in_snapshot); + self.universe.set(universe); self.projection_cache .borrow_mut() @@ -679,6 +683,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { float_snapshot, region_constraints_snapshot, region_obligations_snapshot: _, + universe: _, was_in_snapshot, _in_progress_tables } = snapshot; @@ -823,7 +828,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { Some(self.commit_if_ok(|snapshot| { let (ty::SubtypePredicate { a_is_expected, a, b}, skol_map) = - self.skolemize_late_bound_regions(predicate, snapshot); + self.skolemize_late_bound_regions(predicate); let cause_span = cause.span; let ok = self.at(cause, param_env).sub_exp(a_is_expected, a, b)?; @@ -840,7 +845,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { { self.commit_if_ok(|snapshot| { let (ty::OutlivesPredicate(r_a, r_b), skol_map) = - self.skolemize_late_bound_regions(predicate, snapshot); + self.skolemize_late_bound_regions(predicate); let origin = SubregionOrigin::from_obligation_cause(cause, || RelateRegionParamBound(cause.span)); diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs index fc128b1a6d8..c388fa21371 100644 --- a/src/librustc/infer/region_constraints/mod.rs +++ b/src/librustc/infer/region_constraints/mod.rs @@ -22,7 +22,7 @@ use rustc_data_structures::unify as ut; use ty::{self, Ty, TyCtxt}; use ty::{Region, RegionVid}; use ty::ReStatic; -use ty::{BrFresh, ReLateBound, ReSkolemized, ReVar}; +use ty::{BrFresh, ReLateBound, ReVar}; use std::collections::BTreeMap; use std::{cmp, fmt, mem, u32}; @@ -45,9 +45,6 @@ pub struct RegionConstraintCollector<'tcx> { /// exist). This prevents us from making many such regions. glbs: CombineMap<'tcx>, - /// Number of skolemized variables currently active. - skolemization_count: ty::UniverseIndex, - /// Global counter used during the GLB algorithm to create unique /// names for fresh bound regions bound_count: u32, @@ -237,7 +234,6 @@ pub struct RegionVariableInfo { pub struct RegionSnapshot { length: usize, region_snapshot: ut::Snapshot>, - skolemization_count: ty::UniverseIndex, } /// When working with skolemized regions, we often wish to find all of @@ -281,7 +277,6 @@ impl<'tcx> RegionConstraintCollector<'tcx> { data: RegionConstraintData::default(), lubs: FxHashMap(), glbs: FxHashMap(), - skolemization_count: ty::UniverseIndex::ROOT, bound_count: 0, undo_log: Vec::new(), unification_table: ut::UnificationTable::new(), @@ -327,14 +322,11 @@ impl<'tcx> RegionConstraintCollector<'tcx> { data, lubs, glbs, - skolemization_count, bound_count: _, undo_log: _, unification_table, } = self; - assert_eq!(*skolemization_count, ty::UniverseIndex::ROOT); - // Clear the tables of (lubs, glbs), so that we will create // fresh regions if we do a LUB operation. As it happens, // LUB/GLB are not performed by the MIR type-checker, which is @@ -369,7 +361,6 @@ impl<'tcx> RegionConstraintCollector<'tcx> { RegionSnapshot { length, region_snapshot: self.unification_table.snapshot(), - skolemization_count: self.skolemization_count, } } @@ -377,12 +368,6 @@ impl<'tcx> RegionConstraintCollector<'tcx> { debug!("RegionConstraintCollector: commit({})", snapshot.length); assert!(self.undo_log.len() > snapshot.length); assert!(self.undo_log[snapshot.length] == OpenSnapshot); - assert!( - self.skolemization_count == snapshot.skolemization_count, - "failed to pop skolemized regions: {:?} now vs {:?} at start", - self.skolemization_count, - snapshot.skolemization_count - ); if snapshot.length == 0 { self.undo_log.truncate(0); @@ -402,7 +387,6 @@ impl<'tcx> RegionConstraintCollector<'tcx> { } let c = self.undo_log.pop().unwrap(); assert!(c == OpenSnapshot); - self.skolemization_count = snapshot.skolemization_count; self.unification_table.rollback_to(snapshot.region_snapshot); } @@ -469,48 +453,13 @@ impl<'tcx> RegionConstraintCollector<'tcx> { self.var_infos[vid].origin } - /// Creates a new skolemized region. Skolemized regions are fresh - /// regions used when performing higher-ranked computations. They - /// must be used in a very particular way and are never supposed - /// to "escape" out into error messages or the code at large. - /// - /// The idea is to always create a snapshot. Skolemized regions - /// can be created in the context of this snapshot, but before the - /// snapshot is committed or rolled back, they must be popped - /// (using `pop_skolemized_regions`), so that their numbers can be - /// recycled. Normally you don't have to think about this: you use - /// the APIs in `higher_ranked/mod.rs`, such as - /// `skolemize_late_bound_regions` and `plug_leaks`, which will - /// guide you on this path (ensure that the `SkolemizationMap` is - /// consumed and you are good). For more info on how skolemization - /// for HRTBs works, see the [rustc guide]. - /// - /// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/trait-hrtb.html - /// - /// The `snapshot` argument to this function is not really used; - /// it's just there to make it explicit which snapshot bounds the - /// skolemized region that results. It should always be the top-most snapshot. - pub fn push_skolemized( - &mut self, - tcx: TyCtxt<'_, '_, 'tcx>, - br: ty::BoundRegion, - snapshot: &RegionSnapshot, - ) -> Region<'tcx> { - assert!(self.in_snapshot()); - assert!(self.undo_log[snapshot.length] == OpenSnapshot); - - let universe = self.skolemization_count.subuniverse(); - self.skolemization_count = universe; - tcx.mk_region(ReSkolemized(universe, br)) - } - /// Removes all the edges to/from the skolemized regions that are /// in `skols`. This is used after a higher-ranked operation /// completes to remove all trace of the skolemized regions /// created in that time. pub fn pop_skolemized( &mut self, - _tcx: TyCtxt<'_, '_, 'tcx>, + skolemization_count: ty::UniverseIndex, skols: &FxHashSet>, snapshot: &RegionSnapshot, ) { @@ -519,24 +468,16 @@ impl<'tcx> RegionConstraintCollector<'tcx> { assert!(self.in_snapshot()); assert!(self.undo_log[snapshot.length] == OpenSnapshot); assert!( - self.skolemization_count.as_usize() >= skols.len(), + skolemization_count.as_usize() >= skols.len(), "popping more skolemized variables than actually exist, \ sc now = {:?}, skols.len = {:?}", - self.skolemization_count, + skolemization_count, skols.len() ); - let last_to_pop = self.skolemization_count.subuniverse(); + let last_to_pop = skolemization_count.subuniverse(); let first_to_pop = ty::UniverseIndex::from(last_to_pop.as_u32() - skols.len() as u32); - assert!( - first_to_pop >= snapshot.skolemization_count, - "popping more regions than snapshot contains, \ - sc now = {:?}, sc then = {:?}, skols.len = {:?}", - self.skolemization_count, - snapshot.skolemization_count, - skols.len() - ); debug_assert! { skols.iter() .all(|&k| match *k { @@ -547,8 +488,8 @@ impl<'tcx> RegionConstraintCollector<'tcx> { false }), "invalid skolemization keys or keys out of range ({:?}..{:?}): {:?}", - snapshot.skolemization_count, - self.skolemization_count, + first_to_pop, + last_to_pop, skols } @@ -565,7 +506,6 @@ impl<'tcx> RegionConstraintCollector<'tcx> { self.rollback_undo_entry(undo_entry); } - self.skolemization_count = snapshot.skolemization_count; return; fn kill_constraint<'tcx>( @@ -900,12 +840,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> { impl fmt::Debug for RegionSnapshot { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "RegionSnapshot(length={},skolemization={:?})", - self.length, - self.skolemization_count - ) + write!(f, "RegionSnapshot(length={})", self.length) } } diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 1f1fdfafe33..45fa588bbf5 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -188,7 +188,7 @@ pub fn poly_project_and_unify_type<'cx, 'gcx, 'tcx>( let infcx = selcx.infcx(); infcx.commit_if_ok(|snapshot| { let (skol_predicate, skol_map) = - infcx.skolemize_late_bound_regions(&obligation.predicate, snapshot); + infcx.skolemize_late_bound_regions(&obligation.predicate); let skol_obligation = obligation.with(skol_predicate); let r = match project_and_unify_type(selcx, &skol_obligation) { diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 4ba3655bb64..54b2cf28082 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1509,7 +1509,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let poly_trait_predicate = self.infcx().resolve_type_vars_if_possible(&obligation.predicate); let (skol_trait_predicate, skol_map) = - self.infcx().skolemize_late_bound_regions(&poly_trait_predicate, snapshot); + self.infcx().skolemize_late_bound_regions(&poly_trait_predicate); debug!("match_projection_obligation_against_definition_bounds: \ skol_trait_predicate={:?} skol_map={:?}", skol_trait_predicate, @@ -2338,7 +2338,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { self.in_snapshot(|this, snapshot| { let (skol_ty, skol_map) = - this.infcx().skolemize_late_bound_regions(&ty, snapshot); + this.infcx().skolemize_late_bound_regions(&ty); let Normalized { value: normalized_ty, mut obligations } = project::normalize_with_depth(this, param_env, @@ -2559,7 +2559,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let trait_obligations = self.in_snapshot(|this, snapshot| { let poly_trait_ref = obligation.predicate.to_poly_trait_ref(); let (trait_ref, skol_map) = - this.infcx().skolemize_late_bound_regions(&poly_trait_ref, snapshot); + this.infcx().skolemize_late_bound_regions(&poly_trait_ref); let cause = obligation.derived_cause(ImplDerivedObligation); this.impl_or_trait_obligations(cause, obligation.recursion_depth + 1, @@ -3142,8 +3142,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } let (skol_obligation, skol_map) = self.infcx().skolemize_late_bound_regions( - &obligation.predicate, - snapshot); + &obligation.predicate); let skol_obligation_trait_ref = skol_obligation.trait_ref; let impl_substs = self.infcx.fresh_substs_for_item(obligation.cause.span, -- cgit 1.4.1-3-g733a5 From 4ac9717a1f7b8b07d1ed15411550f4de68665d44 Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Wed, 2 May 2018 11:52:18 -0600 Subject: Fix rebase issues --- src/librustc/infer/higher_ranked/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs index d60d449f6c2..b8437e39ddc 100644 --- a/src/librustc/infer/higher_ranked/mod.rs +++ b/src/librustc/infer/higher_ranked/mod.rs @@ -114,7 +114,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> { // First, we instantiate each bound region in the matcher // with a skolemized region. let ((a_match, a_value), skol_map) = - self.infcx.skolemize_late_bound_regions(a_pair, snapshot); + self.infcx.skolemize_late_bound_regions(a_pair); debug!("higher_ranked_match: a_match={:?}", a_match); debug!("higher_ranked_match: skol_map={:?}", skol_map); -- cgit 1.4.1-3-g733a5 From 68a1fdfee49eeca4d3379423879c5299b5d8e0b0 Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Wed, 2 May 2018 15:02:11 -0600 Subject: Add a comment explaining unification w/ universes --- src/librustc/infer/type_variable.rs | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/librustc/infer/type_variable.rs b/src/librustc/infer/type_variable.rs index a5c2191232e..d40e1b3760f 100644 --- a/src/librustc/infer/type_variable.rs +++ b/src/librustc/infer/type_variable.rs @@ -442,6 +442,11 @@ impl<'tcx> ut::UnifyValue for TypeVariableValue<'tcx> { // If both sides are *unknown*, it hardly matters, does it? (&TypeVariableValue::Unknown { universe: universe1 }, &TypeVariableValue::Unknown { universe: universe2 }) => { + // If we unify two unbound variables, ?T and ?U, then whatever + // value they wind up taking (which must be the same value) must + // be nameable by both universes. Therefore, the resulting + // universe is the minimum of the two universes, because that is + // the one which contains the fewest names in scope. let universe = cmp::min(universe1, universe2); Ok(TypeVariableValue::Unknown { universe }) } -- cgit 1.4.1-3-g733a5 From 1cefb5ce310fe7f799d0926d2644a25a567d2ddb Mon Sep 17 00:00:00 2001 From: Andre Bogus Date: Wed, 2 May 2018 23:53:40 +0200 Subject: nano-optimization for memchr::repeat_byte --- src/libcore/slice/memchr.rs | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/libcore/slice/memchr.rs b/src/libcore/slice/memchr.rs index 69c9cb37dcf..469404f7f6b 100644 --- a/src/libcore/slice/memchr.rs +++ b/src/libcore/slice/memchr.rs @@ -39,21 +39,10 @@ fn repeat_byte(b: u8) -> usize { (b as usize) << 8 | b as usize } -#[cfg(target_pointer_width = "32")] +#[cfg(not(target_pointer_width = "16"))] #[inline] fn repeat_byte(b: u8) -> usize { - let mut rep = (b as usize) << 8 | b as usize; - rep = rep << 16 | rep; - rep -} - -#[cfg(target_pointer_width = "64")] -#[inline] -fn repeat_byte(b: u8) -> usize { - let mut rep = (b as usize) << 8 | b as usize; - rep = rep << 16 | rep; - rep = rep << 32 | rep; - rep + (b as usize) * (::usize::MAX / 255) } /// Return the first index matching the byte `x` in `text`. -- cgit 1.4.1-3-g733a5 From f6841470f1beb007052b12a090c1eb109c7259e8 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 2 May 2018 16:39:54 -0700 Subject: Revert "Implement FromStr for PathBuf" This reverts commit 05a9acc3b844ff284a3e3d85dde2d9798abfb215. --- src/libstd/path.rs | 27 --------------------------- 1 file changed, 27 deletions(-) (limited to 'src') diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 955a6af1ae6..696711a70d4 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -87,7 +87,6 @@ use io; use iter::{self, FusedIterator}; use ops::{self, Deref}; use rc::Rc; -use str::FromStr; use sync::Arc; use ffi::{OsStr, OsString}; @@ -1441,32 +1440,6 @@ impl From for PathBuf { } } -/// Error returned from [`PathBuf::from_str`][`from_str`]. -/// -/// Note that parsing a path will never fail. This error is just a placeholder -/// for implementing `FromStr` for `PathBuf`. -/// -/// [`from_str`]: struct.PathBuf.html#method.from_str -#[derive(Debug, Clone, PartialEq, Eq)] -#[stable(feature = "path_from_str", since = "1.26.0")] -pub enum ParsePathError {} - -#[stable(feature = "path_from_str", since = "1.26.0")] -impl fmt::Display for ParsePathError { - fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result { - match *self {} - } -} - -#[stable(feature = "path_from_str", since = "1.26.0")] -impl FromStr for PathBuf { - type Err = ParsePathError; - - fn from_str(s: &str) -> Result { - Ok(PathBuf::from(s)) - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl> iter::FromIterator

for PathBuf { fn from_iter>(iter: I) -> PathBuf { -- cgit 1.4.1-3-g733a5 From d5d389e4f11b1fad2d42453942f81271bbddee78 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 2 May 2018 11:50:21 +1000 Subject: Use escape_default() for strings in LitKind::token(). This avoids converting every char to \u{...} form, which bloats the resulting strings unnecessarily. It also provides consistency with the existing escape_default() calls in LitKind::token() used for raw string literals, char literals, and raw byte char literals. There are two benefits from this change. - Compilation is faster. Most of the rustc-perf benchmarks see a non-trivial speedup, particularly for incremental rebuilds, with the best speedup over 13%, and multiple others over 10%. - Generated rlibs are smaller. An extreme example is libfutures.rlib, which shrinks from 2073306 bytes to 1765927 bytes, a 15% reduction. --- src/libsyntax/attr.rs | 5 +---- src/libsyntax/lib.rs | 1 + 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index c68a743303a..05fabbee389 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -1228,10 +1228,7 @@ impl LitKind { match *self { LitKind::Str(string, ast::StrStyle::Cooked) => { - let mut escaped = String::new(); - for ch in string.as_str().chars() { - escaped.extend(ch.escape_unicode()); - } + let escaped = string.as_str().escape_default(); Token::Literal(token::Lit::Str_(Symbol::intern(&escaped)), None) } LitKind::Str(string, ast::StrStyle::Raw(n)) => { diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 870ce1926ad..f148aaf7267 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -25,6 +25,7 @@ #![feature(non_exhaustive)] #![feature(const_atomic_usize_new)] #![feature(rustc_attrs)] +#![feature(str_escape)] #![recursion_limit="256"] -- cgit 1.4.1-3-g733a5 From 7a56360ecef1dca261110281e78385fc8f14b154 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 3 May 2018 08:55:58 +1000 Subject: Remove parse::escape_default(). str::escape_default() can be used instead. --- src/libsyntax/parse/mod.rs | 8 ++------ src/libsyntax/print/pprust.rs | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index ff09c6aa2f0..f252020bc31 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -298,14 +298,10 @@ pub fn char_lit(lit: &str, diag: Option<(Span, &Handler)>) -> (char, isize) { } } -pub fn escape_default(s: &str) -> String { - s.chars().map(char::escape_default).flat_map(|x| x).collect() -} - /// Parse a string representing a string literal into its final form. Does /// unescaping. pub fn str_lit(lit: &str, diag: Option<(Span, &Handler)>) -> String { - debug!("parse_str_lit: given {}", escape_default(lit)); + debug!("str_lit: given {}", lit.escape_default()); let mut res = String::with_capacity(lit.len()); let error = |i| format!("lexer should have rejected {} at {}", lit, i); @@ -374,7 +370,7 @@ pub fn str_lit(lit: &str, diag: Option<(Span, &Handler)>) -> String { /// Parse a string representing a raw string literal into its final form. The /// only operation this does is convert embedded CRLF into a single LF. pub fn raw_str_lit(lit: &str) -> String { - debug!("raw_str_lit: given {}", escape_default(lit)); + debug!("raw_str_lit: given {}", lit.escape_default()); let mut res = String::with_capacity(lit.len()); let mut chars = lit.chars().peekable(); diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 88860df10e2..27c5a14ff0e 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -656,7 +656,7 @@ pub trait PrintState<'a> { style: ast::StrStyle) -> io::Result<()> { let st = match style { ast::StrStyle::Cooked => { - (format!("\"{}\"", parse::escape_default(st))) + (format!("\"{}\"", st.escape_default())) } ast::StrStyle::Raw(n) => { (format!("r{delim}\"{string}\"{delim}", -- cgit 1.4.1-3-g733a5 From cd54b3e4483a331326a7508de6c24c90664ae392 Mon Sep 17 00:00:00 2001 From: Michael Lamparski Date: Wed, 2 May 2018 20:51:39 -0400 Subject: forbid empty identifiers from concat_idents --- src/libsyntax_ext/concat_idents.rs | 5 +++++ src/test/ui/issue-50403.rs | 15 +++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 src/test/ui/issue-50403.rs (limited to 'src') diff --git a/src/libsyntax_ext/concat_idents.rs b/src/libsyntax_ext/concat_idents.rs index 544b1410d3d..b8345e7cf40 100644 --- a/src/libsyntax_ext/concat_idents.rs +++ b/src/libsyntax_ext/concat_idents.rs @@ -31,6 +31,11 @@ pub fn expand_syntax_ext<'cx>(cx: &'cx mut ExtCtxt, return base::DummyResult::expr(sp); } + if tts.is_empty() { + cx.span_err(sp, "concat_idents! takes 1 or more arguments."); + return DummyResult::expr(sp); + } + let mut res_str = String::new(); for (i, e) in tts.iter().enumerate() { if i & 1 == 1 { diff --git a/src/test/ui/issue-50403.rs b/src/test/ui/issue-50403.rs new file mode 100644 index 00000000000..8d4c6c5140f --- /dev/null +++ b/src/test/ui/issue-50403.rs @@ -0,0 +1,15 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(concat_idents)] + +fn main() { + let x = concat_idents!(); //~ ERROR concat_idents! takes 1 or more arguments +} -- cgit 1.4.1-3-g733a5 From e740b97be699c9445b8a1a7af6348ca2d4c460ce Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 3 May 2018 09:12:26 +1000 Subject: Always inline simple BytePos and CharPos methods. Because they are (a) trivial, and (b) super hot. This change speeds up most rustc-benchmarks, the best by 5%. --- src/libsyntax_pos/lib.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src') diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 8d37b4aa396..8b4a3ea26a1 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -1150,13 +1150,17 @@ pub struct CharPos(pub usize); // have been unsuccessful impl Pos for BytePos { + #[inline(always)] fn from_usize(n: usize) -> BytePos { BytePos(n as u32) } + + #[inline(always)] fn to_usize(&self) -> usize { let BytePos(n) = *self; n as usize } } impl Add for BytePos { type Output = BytePos; + #[inline(always)] fn add(self, rhs: BytePos) -> BytePos { BytePos((self.to_usize() + rhs.to_usize()) as u32) } @@ -1165,6 +1169,7 @@ impl Add for BytePos { impl Sub for BytePos { type Output = BytePos; + #[inline(always)] fn sub(self, rhs: BytePos) -> BytePos { BytePos((self.to_usize() - rhs.to_usize()) as u32) } @@ -1183,13 +1188,17 @@ impl Decodable for BytePos { } impl Pos for CharPos { + #[inline(always)] fn from_usize(n: usize) -> CharPos { CharPos(n) } + + #[inline(always)] fn to_usize(&self) -> usize { let CharPos(n) = *self; n } } impl Add for CharPos { type Output = CharPos; + #[inline(always)] fn add(self, rhs: CharPos) -> CharPos { CharPos(self.to_usize() + rhs.to_usize()) } @@ -1198,6 +1207,7 @@ impl Add for CharPos { impl Sub for CharPos { type Output = CharPos; + #[inline(always)] fn sub(self, rhs: CharPos) -> CharPos { CharPos(self.to_usize() - rhs.to_usize()) } -- cgit 1.4.1-3-g733a5 From fbc57a7c7a9c01db5881aa77148bbe5fd7a066fd Mon Sep 17 00:00:00 2001 From: Michael Lamparski Date: Thu, 3 May 2018 00:25:14 -0400 Subject: add missing output for ui test --- src/test/ui/issue-50403.stderr | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/test/ui/issue-50403.stderr (limited to 'src') diff --git a/src/test/ui/issue-50403.stderr b/src/test/ui/issue-50403.stderr new file mode 100644 index 00000000000..f2871c72e25 --- /dev/null +++ b/src/test/ui/issue-50403.stderr @@ -0,0 +1,8 @@ +error: concat_idents! takes 1 or more arguments. + --> $DIR/issue-50403.rs:14:13 + | +LL | let x = concat_idents!(); //~ ERROR concat_idents! takes 1 or more arguments + | ^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + -- cgit 1.4.1-3-g733a5 From 4bc48480c08b9749e6b7f1701a1e03529496382d Mon Sep 17 00:00:00 2001 From: Keith Yeung Date: Mon, 30 Apr 2018 15:31:37 -0700 Subject: Skip checking for unused mutable locals that have no name --- src/librustc_mir/borrow_check/mod.rs | 6 +++--- src/test/compile-fail/nll/unused-mut-issue-50343.rs | 17 +++++++++++++++++ src/test/run-pass/nll/issue-50343.rs | 17 +++++++++++++++++ 3 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 src/test/compile-fail/nll/unused-mut-issue-50343.rs create mode 100644 src/test/run-pass/nll/issue-50343.rs (limited to 'src') diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 3145be7df85..4b714100816 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -295,10 +295,10 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( continue; } - // Skip over locals that begin with an underscore + // Skip over locals that begin with an underscore or have no name match local_decl.name { - Some(name) if name.as_str().starts_with("_") => continue, - _ => {}, + Some(name) => if name.as_str().starts_with("_") { continue; }, + None => continue, } let source_info = local_decl.source_info; diff --git a/src/test/compile-fail/nll/unused-mut-issue-50343.rs b/src/test/compile-fail/nll/unused-mut-issue-50343.rs new file mode 100644 index 00000000000..e9110b8114b --- /dev/null +++ b/src/test/compile-fail/nll/unused-mut-issue-50343.rs @@ -0,0 +1,17 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(nll)] +#![deny(unused_mut)] + +fn main() { + vec![(42, 22)].iter().map(|(mut x, _y)| ()).count(); + //~^ ERROR: variable does not need to be mutable +} diff --git a/src/test/run-pass/nll/issue-50343.rs b/src/test/run-pass/nll/issue-50343.rs new file mode 100644 index 00000000000..f01d99c68cc --- /dev/null +++ b/src/test/run-pass/nll/issue-50343.rs @@ -0,0 +1,17 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(nll)] +#![deny(unused_mut)] + +fn main() { + vec![42].iter().map(|_| ()).count(); + vec![(42, 22)].iter().map(|(_x, _y)| ()).count(); +} -- cgit 1.4.1-3-g733a5 From 8e38d02d986a5fa5ef51b6995058d7327aa0da4b Mon Sep 17 00:00:00 2001 From: Michael Lamparski Date: Thu, 3 May 2018 06:49:30 -0400 Subject: update concat_idents doc stubs --- src/libcore/macros.rs | 4 ++-- src/libstd/macros.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index f9371ed0575..c830c22ee5f 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -606,8 +606,8 @@ mod builtin { #[macro_export] #[cfg(dox)] macro_rules! concat_idents { - ($($e:ident),*) => ({ /* compiler built-in */ }); - ($($e:ident,)*) => ({ /* compiler built-in */ }); + ($($e:ident),+) => ({ /* compiler built-in */ }); + ($($e:ident,)+) => ({ /* compiler built-in */ }); } /// Concatenates literals into a static string slice. diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 6902ec82047..d1274a40900 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -450,8 +450,8 @@ pub mod builtin { #[unstable(feature = "concat_idents_macro", issue = "29599")] #[macro_export] macro_rules! concat_idents { - ($($e:ident),*) => ({ /* compiler built-in */ }); - ($($e:ident,)*) => ({ /* compiler built-in */ }); + ($($e:ident),+) => ({ /* compiler built-in */ }); + ($($e:ident,)+) => ({ /* compiler built-in */ }); } /// Concatenates literals into a static string slice. -- cgit 1.4.1-3-g733a5 From 390c3cee6a8e0c0550eb6213c0e7e5f74c4fbc31 Mon Sep 17 00:00:00 2001 From: rleungx Date: Thu, 3 May 2018 19:09:34 +0800 Subject: check if the token is a lifetime before parsing --- src/libsyntax/ext/tt/macro_parser.rs | 8 +++++++- src/libsyntax/parse/parser.rs | 2 +- src/test/compile-fail/macro-non-lifetime.rs | 20 ++++++++++++++++++++ 3 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 src/test/compile-fail/macro-non-lifetime.rs (limited to 'src') diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index d9c3deb30da..71634ada894 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -835,7 +835,13 @@ fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal { "path" => token::NtPath(panictry!(p.parse_path_common(PathStyle::Type, false))), "meta" => token::NtMeta(panictry!(p.parse_meta_item())), "vis" => token::NtVis(panictry!(p.parse_visibility(true))), - "lifetime" => token::NtLifetime(p.expect_lifetime().ident), + "lifetime" => if p.check_lifetime() { + token::NtLifetime(p.expect_lifetime().ident) + } else { + let token_str = pprust::token_to_string(&p.token); + p.fatal(&format!("expected a lifetime, found `{}`", &token_str)).emit(); + FatalError.raise(); + } // this is not supposed to happen, since it has been checked // when compiling the macro. _ => p.span_bug(sp, "invalid fragment specifier"), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 324cadc84e8..bbee03bb0d5 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2042,7 +2042,7 @@ impl<'a> Parser<'a> { }) } - fn check_lifetime(&mut self) -> bool { + pub fn check_lifetime(&mut self) -> bool { self.expected_tokens.push(TokenType::Lifetime); self.token.is_lifetime() } diff --git a/src/test/compile-fail/macro-non-lifetime.rs b/src/test/compile-fail/macro-non-lifetime.rs new file mode 100644 index 00000000000..a2706e83229 --- /dev/null +++ b/src/test/compile-fail/macro-non-lifetime.rs @@ -0,0 +1,20 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test for issue #50381: non-lifetime passed to :lifetime. + +#![feature(macro_lifetime_matcher)] + +macro_rules! m { ($x:lifetime) => { } } + +fn main() { + m!(a); + //~^ ERROR expected a lifetime, found `a` +} -- cgit 1.4.1-3-g733a5 From f67c683950001615805638e2d2b4d1a82347d3c0 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Mon, 26 Feb 2018 14:46:43 +0100 Subject: Include the test name when reporting that an expected line was not found in a mir-opt test. --- src/tools/compiletest/src/runtest.rs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index d1dac370c9e..01d9f52424d 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2735,10 +2735,12 @@ impl<'test> TestCx<'test> { panic!( "Did not find expected line, error: {}\n\ Expected Line: {:?}\n\ + Test Name: {}\n\ Expected:\n{}\n\ Actual:\n{}", extra_msg, expected_line, + test_name, expected_content, normalize_all ); -- cgit 1.4.1-3-g733a5 From 1c3fd02a4cf1769988ea3f91da54e3c1cacdd9ef Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Mon, 5 Mar 2018 16:55:27 +0100 Subject: Improve instrumentation for the bug reported during `fn report_borrowed_value_does_not_live_long_enough`. --- src/librustc_mir/borrow_check/error_reporting.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 3dc5a7a8490..db2e078586e 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -471,7 +471,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { | (RegionKind::ReClosureBound(_), _) | (RegionKind::ReCanonical(_), _) | (RegionKind::ReErased, _) => { - span_bug!(drop_span, "region does not make sense in this context"); + span_bug!(drop_span, "region {:?} does not make sense in this context", + borrow.region); } } } -- cgit 1.4.1-3-g733a5 From b00db7c75b85d521a17372750512111657baaea2 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Mon, 5 Mar 2018 16:54:20 +0100 Subject: Instrument `statement_effect_on_borrows` for the `lhs = &place` case. --- src/librustc_mir/dataflow/impls/borrows.rs | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index a21691813a4..098ad8e558f 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -179,8 +179,14 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { if let RegionKind::ReEmpty = region { // If the borrowed value dies before the borrow is used, the region for // the borrow can be empty. Don't track the borrow in that case. + debug!("Borrows::statement_effect_on_borrows \ + location: {:?} stmt: {:?} has empty region, killing {:?}", + location, stmt.kind, index); sets.kill(&index); return + } else { + debug!("Borrows::statement_effect_on_borrows location: {:?} stmt: {:?}", + location, stmt.kind); } assert!(self.borrow_set.region_map.get(region).unwrap_or_else(|| { -- cgit 1.4.1-3-g733a5 From a72790d879a6266b4dc75ab3014c00735cf67610 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Mon, 26 Feb 2018 15:45:13 +0100 Subject: When using NLL, implicitly borrow match bindings for any guard, deref'ing such borrows within that guard. Review feedback: Add comment noting a point where we may or may not need to add a cast when we finish the work on rust-lang/rust#27282. Review feedback: Pass a newtype'd `ArmHasGuard` rather than a raw boolean. Review feedback: toggle "ref binding in guards" semantics via specific method. (This should ease a follow-up PR that just unconditionally adopts the new semantics.) --- src/librustc/ty/context.rs | 8 + src/librustc_mir/build/block.rs | 9 +- src/librustc_mir/build/expr/as_place.rs | 15 +- src/librustc_mir/build/matches/mod.rs | 297 ++++++++++++++++++++++++++++---- src/librustc_mir/build/mod.rs | 82 ++++++++- 5 files changed, 373 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index ce4439e7c54..3d154e43a9a 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1467,6 +1467,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.borrowck_mode().use_mir() } + /// If true, pattern variables for use in guards on match arms + /// will be bound as references to the data, and occurrences of + /// those variables in the guard expression will implicitly + /// dereference those bindings. (See rust-lang/rust#27282.) + pub fn all_pat_vars_are_implicit_refs_within_guards(self) -> bool { + self.borrowck_mode().use_mir() + } + /// If true, we should enable two-phase borrows checks. This is /// done with either `-Ztwo-phase-borrows` or with /// `#![feature(nll)]`. diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir/build/block.rs index 94702927d26..fae06db3162 100644 --- a/src/librustc_mir/build/block.rs +++ b/src/librustc_mir/build/block.rs @@ -9,6 +9,8 @@ // except according to those terms. use build::{BlockAnd, BlockAndExtension, Builder}; +use build::ForGuard::OutsideGuard; +use build::matches::ArmHasGuard; use hair::*; use rustc::mir::*; use rustc::hir; @@ -113,7 +115,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // Declare the bindings, which may create a visibility scope. let remainder_span = remainder_scope.span(this.hir.tcx(), &this.hir.region_scope_tree); - let scope = this.declare_bindings(None, remainder_span, lint_level, &pattern); + let scope = this.declare_bindings(None, remainder_span, lint_level, &pattern, + ArmHasGuard(false)); // Evaluate the initializer, if present. if let Some(init) = initializer { @@ -135,8 +138,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } this.visit_bindings(&pattern, &mut |this, _, _, node, span, _| { - this.storage_live_binding(block, node, span); - this.schedule_drop_for_binding(node, span); + this.storage_live_binding(block, node, span, OutsideGuard); + this.schedule_drop_for_binding(node, span, OutsideGuard); }) } diff --git a/src/librustc_mir/build/expr/as_place.rs b/src/librustc_mir/build/expr/as_place.rs index 19ec13324d6..365b9babd08 100644 --- a/src/librustc_mir/build/expr/as_place.rs +++ b/src/librustc_mir/build/expr/as_place.rs @@ -11,6 +11,7 @@ //! See docs in build/expr/mod.rs use build::{BlockAnd, BlockAndExtension, Builder}; +use build::ForGuard::{OutsideGuard, WithinGuard}; use build::expr::category::Category; use hair::*; use rustc::mir::*; @@ -86,8 +87,18 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { block.and(Place::Local(Local::new(1))) } ExprKind::VarRef { id } => { - let index = this.var_indices[&id]; - block.and(Place::Local(index)) + let place = if this.is_bound_var_in_guard(id) { + let index = this.var_local_id(id, WithinGuard); + if this.hir.tcx().all_pat_vars_are_implicit_refs_within_guards() { + Place::Local(index).deref() + } else { + Place::Local(index) + } + } else { + let index = this.var_local_id(id, OutsideGuard); + Place::Local(index) + }; + block.and(place) } ExprKind::StaticRef { id } => { block.and(Place::Static(Box::new(Static { def_id: id, ty: expr.ty }))) diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 7eb52a3cdee..6946ac4c7b2 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -14,6 +14,8 @@ //! details. use build::{BlockAnd, BlockAndExtension, Builder}; +use build::{GuardFrame, GuardFrameLocal, LocalsForNode}; +use build::ForGuard::{self, OutsideGuard, WithinGuard}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::bitvec::BitVector; use rustc::ty::{self, Ty}; @@ -28,6 +30,11 @@ mod simplify; mod test; mod util; +/// ArmHasGuard is isomorphic to a boolean flag. It indicates whether +/// a match arm has a guard expression attached to it. +#[derive(Copy, Clone, Debug)] +pub(crate) struct ArmHasGuard(pub bool); + impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { pub fn match_expr(&mut self, destination: &Place<'tcx>, @@ -66,7 +73,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let body = self.hir.mirror(arm.body.clone()); let scope = self.declare_bindings(None, body.span, LintLevel::Inherited, - &arm.patterns[0]); + &arm.patterns[0], + ArmHasGuard(arm.guard.is_some())); (body, scope.unwrap_or(self.visibility_scope)) }).collect(); @@ -149,7 +157,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { var: NodeId, span: Span) { if self.hir.tcx().sess.opts.debugging_opts.disable_nll_user_type_assert { return; } - let local_id = self.var_indices[&var]; + let local_id = self.var_local_id(var, OutsideGuard); let source_info = self.source_info(span); debug!("user_assert_ty: local_id={:?}", hir_id.local_id); @@ -173,14 +181,15 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { PatternKind::Binding { mode: BindingMode::ByValue, var, subpattern: None, .. } => { - let place = self.storage_live_binding(block, var, irrefutable_pat.span); + let place = self.storage_live_binding(block, var, irrefutable_pat.span, + OutsideGuard); if let Some(ty) = ty { self.user_assert_ty(block, ty, var, irrefutable_pat.span); } unpack!(block = self.into(&place, block, initializer)); - self.schedule_drop_for_binding(var, irrefutable_pat.span); + self.schedule_drop_for_binding(var, irrefutable_pat.span, OutsideGuard); block.unit() } _ => { @@ -220,7 +229,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } // now apply the bindings, which will also declare the variables - self.bind_matched_candidate(block, candidate.bindings); + self.bind_matched_candidate_for_arm_body(block, &candidate.bindings, false); block.unit() } @@ -232,7 +241,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { mut var_scope: Option, scope_span: Span, lint_level: LintLevel, - pattern: &Pattern<'tcx>) + pattern: &Pattern<'tcx>, + has_guard: ArmHasGuard) -> Option { assert!(!(var_scope.is_some() && lint_level.is_explicit()), "can't have both a var and a lint scope at the same time"); @@ -254,15 +264,20 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { span, scope: var_scope.unwrap() }; - this.declare_binding(source_info, syntactic_scope, mutability, name, var, ty); + this.declare_binding(source_info, syntactic_scope, mutability, name, var, + ty, has_guard); }); var_scope } - pub fn storage_live_binding(&mut self, block: BasicBlock, var: NodeId, span: Span) + pub fn storage_live_binding(&mut self, + block: BasicBlock, + var: NodeId, + span: Span, + for_guard: ForGuard) -> Place<'tcx> { - let local_id = self.var_indices[&var]; + let local_id = self.var_local_id(var, for_guard); let source_info = self.source_info(span); self.cfg.push(block, Statement { source_info, @@ -271,8 +286,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { Place::Local(local_id) } - pub fn schedule_drop_for_binding(&mut self, var: NodeId, span: Span) { - let local_id = self.var_indices[&var]; + pub fn schedule_drop_for_binding(&mut self, + var: NodeId, + span: Span, + for_guard: ForGuard) { + let local_id = self.var_local_id(var, for_guard); let var_ty = self.local_decls[local_id].ty; let hir_id = self.hir.tcx().hir.node_to_hir_id(var); let region_scope = self.hir.region_scope_tree.var_scope(hir_id.local_id); @@ -770,14 +788,129 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { vec![candidate.next_candidate_pre_binding_block], }); - self.bind_matched_candidate(block, candidate.bindings); + // rust-lang/rust#27282: The `autoref` business deserves some + // explanation here. + // + // The intent of the `autoref` flag is that when it is true, + // then any pattern bindings of type T will map to a `&T` + // within the context of the guard expression, but will + // continue to map to a `T` in the context of the arm body. To + // avoid surfacing this distinction in the user source code + // (which would be a severe change to the language and require + // far more revision to the compiler), when `autoref` is true, + // then any occurrence of the identifier in the guard + // expression will automatically get a deref op applied to it. + // + // So an input like: + // + // ``` + // let place = Foo::new(); + // match place { foo if inspect(foo) + // => feed(foo), ... } + // ``` + // + // will be treated as if it were really something like: + // + // ``` + // let place = Foo::new(); + // match place { Foo { .. } if { let tmp1 = &place; inspect(*tmp1) } + // => { let tmp2 = place; feed(tmp2) }, ... } + // + // And an input like: + // + // ``` + // let place = Foo::new(); + // match place { ref mut foo if inspect(foo) + // => feed(foo), ... } + // ``` + // + // will be treated as if it were really something like: + // + // ``` + // let place = Foo::new(); + // match place { Foo { .. } if { let tmp1 = & &mut place; inspect(*tmp1) } + // => { let tmp2 = &mut place; feed(tmp2) }, ... } + // ``` + // + // In short, any pattern binding will always look like *some* + // kind of `&T` within the guard at least in terms of how the + // MIR-borrowck views it, and this will ensure that guard + // expressions cannot mutate their the match inputs via such + // bindings. (It also ensures that guard expressions can at + // most *copy* values from such bindings; non-Copy things + // cannot be moved via pattern bindings in guard expressions.) + // + // ---- + // + // Implementation notes (under assumption `autoref` is true). + // + // To encode the distinction above, we must inject the + // temporaries `tmp1` and `tmp2`. + // + // There are two cases of interest: binding by-value, and binding by-ref. + // + // 1. Binding by-value: Things are simple. + // + // * Establishing `tmp1` creates a reference into the + // matched place. This code is emitted by + // bind_matched_candidate_for_guard. + // + // * `tmp2` is only initialized "lazily", after we have + // checked the guard. Thus, the code that can trigger + // moves out of the candidate can only fire after the + // guard evaluated to true. This initialization code is + // emitted by bind_matched_candidate_for_arm. + // + // 2. Binding by-reference: Things are tricky. + // + // * Here, the guard expression wants a `&&` or `&&mut` + // into the original input. This means we need to borrow + // a reference that we do not immediately have at hand + // (because all we have is the places associated with the + // match input itself; it is up to us to create a place + // holding a `&` or `&mut` that we can then borrow). + // + // * Therefore, when the binding is by-reference, we + // *eagerly* introduce the binding for the arm body + // (`tmp2`) and then borrow it (`tmp1`). + // + // * This is documented with "NOTE tricky business" below. + // + // FIXME The distinction in how `tmp2` is initialized is + // currently encoded in a pretty awkward fashion; namely, by + // passing a boolean to bind_matched_candidate_for_arm_body + // indicating whether all of the by-ref bindings were already + // initialized. + // + // * Also: pnkfelix thinks "laziness" is natural; but since + // MIR-borrowck did not complain with earlier (universally + // eager) MIR codegen, laziness might not be *necessary*. + + let autoref = self.hir.tcx().all_pat_vars_are_implicit_refs_within_guards(); if let Some(guard) = candidate.guard { + if autoref { + self.bind_matched_candidate_for_guard(block, &candidate.bindings); + let guard_frame = GuardFrame { + locals: candidate.bindings.iter() + .map(|b| GuardFrameLocal::new(b.var_id, b.binding_mode)) + .collect(), + }; + debug!("Entering guard translation context: {:?}", guard_frame); + self.guard_context.push(guard_frame); + } else { + self.bind_matched_candidate_for_arm_body(block, &candidate.bindings, false); + } + // the block to branch to if the guard fails; if there is no // guard, this block is simply unreachable let guard = self.hir.mirror(guard); let source_info = self.source_info(guard.span); let cond = unpack!(block = self.as_local_operand(block, guard)); + if autoref { + let guard_frame = self.guard_context.pop().unwrap(); + debug!("Exiting guard translation context with locals: {:?}", guard_frame); + } let false_edge_block = self.cfg.start_new_block(); self.cfg.terminate(block, source_info, @@ -785,6 +918,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { false_edge_block)); let otherwise = self.cfg.start_new_block(); + if autoref { + self.bind_matched_candidate_for_arm_body(block, &candidate.bindings, true); + } self.cfg.terminate(false_edge_block, source_info, TerminatorKind::FalseEdges { real_target: otherwise, @@ -793,47 +929,137 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { }); Some(otherwise) } else { + self.bind_matched_candidate_for_arm_body(block, &candidate.bindings, false); self.cfg.terminate(block, candidate_source_info, TerminatorKind::Goto { target: arm_block }); None } } - fn bind_matched_candidate(&mut self, - block: BasicBlock, - bindings: Vec>) { - debug!("bind_matched_candidate(block={:?}, bindings={:?})", + fn bind_matched_candidate_for_guard(&mut self, + block: BasicBlock, + bindings: &[Binding<'tcx>]) { + debug!("bind_matched_candidate_for_guard(block={:?}, bindings={:?})", block, bindings); + // Assign each of the bindings. Since we are binding for a + // guard expression, this will never trigger moves out of the + // candidate. + let re_empty = self.hir.tcx().types.re_empty; + for binding in bindings { + let source_info = self.source_info(binding.span); + let local_for_guard = self.storage_live_binding( + block, binding.var_id, binding.span, WithinGuard); + // Question: Why schedule drops if bindings are all + // shared-&'s? Answer: Because schedule_drop_for_binding + // also emits StorageDead's for those locals. + self.schedule_drop_for_binding(binding.var_id, binding.span, WithinGuard); + match binding.binding_mode { + BindingMode::ByValue => { + let rvalue = Rvalue::Ref(re_empty, BorrowKind::Shared, binding.source.clone()); + self.cfg.push_assign(block, source_info, &local_for_guard, rvalue); + } + BindingMode::ByRef(region, borrow_kind) => { + // NOTE tricky business: For `ref id` and `ref mut + // id` patterns, we want `id` within the guard to + // correspond to a temp of type `& &T` or `& &mut + // T`, while within the arm body it will + // correspond to a temp of type `&T` or `&mut T`, + // as usual. + // + // But to inject the level of indirection, we need + // something to point to. + // + // So: + // + // 1. First set up the local for the arm body + // (even though we have not yet evaluated the + // guard itself), + // + // 2. Then setup the local for the guard, which is + // just a reference to the local from step 1. + // + // Note that since we are setting up the local for + // the arm body a bit eagerly here (and likewise + // scheduling its drop code), we should *not* do + // it redundantly later on. + // + // While we could have kept track of this with a + // flag or collection of such bindings, the + // treatment of all of these cases is uniform, so + // we should be safe just avoiding the code + // without maintaining such state.) + let local_for_arm_body = self.storage_live_binding( + block, binding.var_id, binding.span, OutsideGuard); + self.schedule_drop_for_binding(binding.var_id, binding.span, OutsideGuard); + + // rust-lang/rust#27282: this potentially mutable + // borrow may require a cast in the future to + // avoid conflicting with an implicit borrow of + // the whole match input; or maybe it just + // requires an extension of our two-phase borrows + // system. See discussion on rust-lang/rust#49870. + let rvalue = Rvalue::Ref(region, borrow_kind, binding.source.clone()); + self.cfg.push_assign(block, source_info, &local_for_arm_body, rvalue); + let rvalue = Rvalue::Ref(region, BorrowKind::Shared, local_for_arm_body); + self.cfg.push_assign(block, source_info, &local_for_guard, rvalue); + } + } + } + } + + fn bind_matched_candidate_for_arm_body(&mut self, + block: BasicBlock, + bindings: &[Binding<'tcx>], + already_initialized_state_for_refs: bool) { + debug!("bind_matched_candidate_for_arm_body(block={:?}, bindings={:?}, \ + already_initialized_state_for_refs={:?})", + block, bindings, already_initialized_state_for_refs); + // Assign each of the bindings. This may trigger moves out of the candidate. for binding in bindings { + if let BindingMode::ByRef(..) = binding.binding_mode { + // See "NOTE tricky business" above + if already_initialized_state_for_refs { continue; } + } + let source_info = self.source_info(binding.span); - let local = self.storage_live_binding(block, binding.var_id, binding.span); - self.schedule_drop_for_binding(binding.var_id, binding.span); + let local = self.storage_live_binding(block, binding.var_id, binding.span, + OutsideGuard); + self.schedule_drop_for_binding(binding.var_id, binding.span, OutsideGuard); let rvalue = match binding.binding_mode { - BindingMode::ByValue => - Rvalue::Use(self.consume_by_copy_or_move(binding.source)), - BindingMode::ByRef(region, borrow_kind) => - Rvalue::Ref(region, borrow_kind, binding.source), + BindingMode::ByValue => { + Rvalue::Use(self.consume_by_copy_or_move(binding.source.clone())) + } + BindingMode::ByRef(region, borrow_kind) => { + Rvalue::Ref(region, borrow_kind, binding.source.clone()) + } }; self.cfg.push_assign(block, source_info, &local, rvalue); } } + /// Each binding (`ref mut var`/`ref var`/`mut var`/`var`, where + /// the bound `var` has type `T` in the arm body) in a pattern + /// maps to *two* locals. The first local is a binding for + /// occurrences of `var` in the guard, which will all have type + /// `&T`. The second local is a binding for occurrences of `var` + /// in the arm body, which will have type `T`. fn declare_binding(&mut self, source_info: SourceInfo, syntactic_scope: VisibilityScope, mutability: Mutability, name: Name, var_id: NodeId, - var_ty: Ty<'tcx>) - -> Local + var_ty: Ty<'tcx>, + has_guard: ArmHasGuard) { debug!("declare_binding(var_id={:?}, name={:?}, var_ty={:?}, source_info={:?}, \ syntactic_scope={:?})", var_id, name, var_ty, source_info, syntactic_scope); - let var = self.local_decls.push(LocalDecl::<'tcx> { + let tcx = self.hir.tcx(); + let for_arm_body = self.local_decls.push(LocalDecl::<'tcx> { mutability, ty: var_ty.clone(), name: Some(name), @@ -842,10 +1068,21 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { internal: false, is_user_variable: true, }); - self.var_indices.insert(var_id, var); - - debug!("declare_binding: var={:?}", var); - - var + let locals = if has_guard.0 && tcx.all_pat_vars_are_implicit_refs_within_guards() { + let for_guard = self.local_decls.push(LocalDecl::<'tcx> { + mutability, + ty: tcx.mk_imm_ref(tcx.types.re_empty, var_ty), + name: Some(name), + source_info, + syntactic_scope, + internal: false, + is_user_variable: true, + }); + LocalsForNode::Two { for_guard, for_arm_body } + } else { + LocalsForNode::One(for_arm_body) + }; + debug!("declare_binding: vars={:?}", locals); + self.var_indices.insert(var_id, locals); } } diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 0d836f5cb97..dd2a336af41 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -291,8 +291,14 @@ struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { visibility_scope_info: IndexVec, visibility_scope: VisibilityScope, + /// the guard-context: each time we build the guard expression for + /// a match arm, we push onto this stack, and then pop when we + /// finish building it. + guard_context: Vec, + /// Maps node ids of variable bindings to the `Local`s created for them. - var_indices: NodeMap, + /// (A match binding can have two locals; the 2nd is for the arm's guard.) + var_indices: NodeMap, local_decls: IndexVec>, unit_temp: Option>, @@ -305,6 +311,74 @@ struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { cached_unreachable_block: Option, } +impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { + fn is_bound_var_in_guard(&self, id: ast::NodeId) -> bool { + self.guard_context.iter().any(|frame| frame.locals.iter().any(|local| local.id == id)) + } + + fn var_local_id(&self, id: ast::NodeId, for_guard: ForGuard) -> Local { + self.var_indices[&id].local_id(for_guard) + } +} + +#[derive(Debug)] +enum LocalsForNode { + One(Local), + Two { for_guard: Local, for_arm_body: Local }, +} + +#[derive(Debug)] +struct GuardFrameLocal { + id: ast::NodeId, +} + +impl GuardFrameLocal { + fn new(id: ast::NodeId, _binding_mode: BindingMode) -> Self { + GuardFrameLocal { + id: id, + } + } +} + +#[derive(Debug)] +struct GuardFrame { + /// These are the id's of names that are bound by patterns of the + /// arm of *this* guard. + /// + /// (Frames higher up the stack will have the id's bound in arms + /// further out, such as in a case like: + /// + /// match E1 { + /// P1(id1) if (... (match E2 { P2(id2) if ... => B2 })) => B1, + /// } + /// + /// here, when building for FIXME + locals: Vec, +} + +/// ForGuard is isomorphic to a boolean flag. It indicates whether we are +/// talking about the temp for a local binding for a use within a guard expression, +/// or a temp for use outside of a guard expressions. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +enum ForGuard { + WithinGuard, + OutsideGuard, +} + +impl LocalsForNode { + fn local_id(&self, for_guard: ForGuard) -> Local { + match (self, for_guard) { + (&LocalsForNode::One(local_id), ForGuard::OutsideGuard) | + (&LocalsForNode::Two { for_guard: local_id, .. }, ForGuard::WithinGuard) | + (&LocalsForNode::Two { for_arm_body: local_id, .. }, ForGuard::OutsideGuard) => + local_id, + + (&LocalsForNode::One(_), ForGuard::WithinGuard) => + bug!("anything with one local should never be within a guard."), + } + } +} + struct CFG<'tcx> { basic_blocks: IndexVec>, } @@ -548,6 +622,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { visibility_scopes: IndexVec::new(), visibility_scope: ARGUMENT_VISIBILITY_SCOPE, visibility_scope_info: IndexVec::new(), + guard_context: vec![], push_unsafe_count: 0, unpushed_unsafe: safety, breakable_scopes: vec![], @@ -636,11 +711,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // Don't introduce extra copies for simple bindings PatternKind::Binding { mutability, var, mode: BindingMode::ByValue, .. } => { self.local_decls[local].mutability = mutability; - self.var_indices.insert(var, local); + self.var_indices.insert(var, LocalsForNode::One(local)); } _ => { scope = self.declare_bindings(scope, ast_body.span, - LintLevel::Inherited, &pattern); + LintLevel::Inherited, &pattern, + matches::ArmHasGuard(false)); unpack!(block = self.place_into_pattern(block, pattern, &place)); } } -- cgit 1.4.1-3-g733a5 From 28d18fabe37252127ffeef3ad54590f47fd9c081 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 10 Apr 2018 14:33:24 +0200 Subject: Unit test for the new implicit borrow and deref within the guard expressions of matches (activated only when using new NLL mode). Review feedback: removed 27282 from filename. (The test still references it in a relevant comment in the file itself so that seemed like a reasonable compromise.) --- .../compile-fail/nll/match-guards-always-borrow.rs | 61 ++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 src/test/compile-fail/nll/match-guards-always-borrow.rs (limited to 'src') diff --git a/src/test/compile-fail/nll/match-guards-always-borrow.rs b/src/test/compile-fail/nll/match-guards-always-borrow.rs new file mode 100644 index 00000000000..98553144627 --- /dev/null +++ b/src/test/compile-fail/nll/match-guards-always-borrow.rs @@ -0,0 +1,61 @@ +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//revisions: ast mir +//[mir] compile-flags: -Z borrowck=mir + +#![feature(rustc_attrs)] + +// Here is arielb1's basic example from rust-lang/rust#27282 +// that AST borrowck is flummoxed by: + +fn should_reject_destructive_mutate_in_guard() { + match Some(&4) { + None => {}, + ref mut foo if { + (|| { let bar = foo; bar.take() })(); + //[mir]~^ ERROR cannot move out of borrowed content [E0507] + false } => { }, + Some(s) => std::process::exit(*s), + } +} + +// Here below is a case that needs to keep working: we only use the +// binding via immutable-borrow in the guard, and we mutate in the arm +// body. +fn allow_mutate_in_arm_body() { + match Some(&4) { + None => {}, + ref mut foo if foo.is_some() && false => { foo.take(); () } + Some(s) => std::process::exit(*s), + } +} + +// Here below is a case that needs to keep working: we only use the +// binding via immutable-borrow in the guard, and we move into the arm +// body. +fn allow_move_into_arm_body() { + match Some(&4) { + None => {}, + mut foo if foo.is_some() && false => { foo.take(); () } + Some(s) => std::process::exit(*s), + } +} + +// Since this is a compile-fail test that is explicitly encoding the +// different behavior of AST- vs MIR-borrowck where AST-borrowck does +// not error, we need to use rustc_error to placate the test harness +// that wants *some* error to occur. +#[rustc_error] +fn main() { //[ast]~ ERROR compilation successful + should_reject_destructive_mutate_in_guard(); + allow_mutate_in_arm_body(); + allow_move_into_arm_body(); +} -- cgit 1.4.1-3-g733a5 From 7cf142f78b82b0b2ae08b52ccb6a6e15c0270c38 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 2 May 2018 10:28:37 +1000 Subject: Avoid many `cmt` allocations. `cmt` is a ref-counted wrapper around `cmt_` The use of refcounting keeps `cmt` handling simple, but a lot of `cmt` instances are very short-lived, and heap-allocating the short-lived ones takes up time. This patch changes things in the following ways. - Most of the functions that produced `cmt` instances now produce `cmt_` instances. The `Rc::new` calls that occurred within those functions now occur at their call sites (but only when necessary, which isn't that often). - Many of the functions that took `cmt` arguments now take `&cmt_` arguments. This includes all the methods in the `Delegate` trait. As a result, the vast majority of the heap allocations are avoided. In an extreme case, the number of calls to malloc in tuple-stress drops from 9.9M to 7.9M, a drop of 20%. And the compile times for many runs of coercions, deep-vector, and tuple-stress drop by 1--2%. --- src/librustc/middle/expr_use_visitor.rs | 60 ++++++------ src/librustc/middle/mem_categorization.rs | 105 ++++++++++----------- src/librustc_borrowck/borrowck/check_loans.rs | 30 +++--- .../borrowck/gather_loans/gather_moves.rs | 29 +++--- .../borrowck/gather_loans/lifetime.rs | 15 ++- src/librustc_borrowck/borrowck/gather_loans/mod.rs | 34 ++++--- .../borrowck/gather_loans/restrictions.rs | 16 ++-- src/librustc_borrowck/borrowck/mod.rs | 26 ++--- src/librustc_mir/hair/pattern/check_match.rs | 12 +-- src/librustc_passes/rvalue_promotion.rs | 12 +-- src/librustc_typeck/check/regionck.rs | 47 +++++---- src/librustc_typeck/check/upvar.rs | 31 +++--- 12 files changed, 208 insertions(+), 209 deletions(-) (limited to 'src') diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 2cc5a4a8fe6..725fcf1e646 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -28,6 +28,7 @@ use ty::{self, TyCtxt, adjustment}; use hir::{self, PatKind}; use rustc_data_structures::sync::Lrc; +use std::rc::Rc; use syntax::ast; use syntax::ptr::P; use syntax_pos::Span; @@ -44,7 +45,7 @@ pub trait Delegate<'tcx> { fn consume(&mut self, consume_id: ast::NodeId, consume_span: Span, - cmt: mc::cmt<'tcx>, + cmt: &mc::cmt_<'tcx>, mode: ConsumeMode); // The value found at `cmt` has been determined to match the @@ -61,14 +62,14 @@ pub trait Delegate<'tcx> { // called on a subpart of an input passed to `matched_pat). fn matched_pat(&mut self, matched_pat: &hir::Pat, - cmt: mc::cmt<'tcx>, + cmt: &mc::cmt_<'tcx>, mode: MatchMode); // The value found at `cmt` is either copied or moved via the // pattern binding `consume_pat`, depending on mode. fn consume_pat(&mut self, consume_pat: &hir::Pat, - cmt: mc::cmt<'tcx>, + cmt: &mc::cmt_<'tcx>, mode: ConsumeMode); // The value found at `borrow` is being borrowed at the point @@ -76,7 +77,7 @@ pub trait Delegate<'tcx> { fn borrow(&mut self, borrow_id: ast::NodeId, borrow_span: Span, - cmt: mc::cmt<'tcx>, + cmt: &mc::cmt_<'tcx>, loan_region: ty::Region<'tcx>, bk: ty::BorrowKind, loan_cause: LoanCause); @@ -90,7 +91,7 @@ pub trait Delegate<'tcx> { fn mutate(&mut self, assignment_id: ast::NodeId, assignment_span: Span, - assignee_cmt: mc::cmt<'tcx>, + assignee_cmt: &mc::cmt_<'tcx>, mode: MutateMode); } @@ -316,11 +317,11 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { let fn_body_scope_r = self.tcx().mk_region(ty::ReScope(region::Scope::Node(body.value.hir_id.local_id))); - let arg_cmt = self.mc.cat_rvalue( + let arg_cmt = Rc::new(self.mc.cat_rvalue( arg.id, arg.pat.span, fn_body_scope_r, // Args live only as long as the fn body. - arg_ty); + arg_ty)); self.walk_irrefutable_pat(arg_cmt, &arg.pat); } @@ -335,11 +336,11 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { fn delegate_consume(&mut self, consume_id: ast::NodeId, consume_span: Span, - cmt: mc::cmt<'tcx>) { + cmt: &mc::cmt_<'tcx>) { debug!("delegate_consume(consume_id={}, cmt={:?})", consume_id, cmt); - let mode = copy_or_move(&self.mc, self.param_env, &cmt, DirectRefMove); + let mode = copy_or_move(&self.mc, self.param_env, cmt, DirectRefMove); self.delegate.consume(consume_id, consume_span, cmt, mode); } @@ -353,7 +354,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { debug!("consume_expr(expr={:?})", expr); let cmt = return_if_err!(self.mc.cat_expr(expr)); - self.delegate_consume(expr.id, expr.span, cmt); + self.delegate_consume(expr.id, expr.span, &cmt); self.walk_expr(expr); } @@ -362,7 +363,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { expr: &hir::Expr, mode: MutateMode) { let cmt = return_if_err!(self.mc.cat_expr(expr)); - self.delegate.mutate(assignment_expr.id, assignment_expr.span, cmt, mode); + self.delegate.mutate(assignment_expr.id, assignment_expr.span, &cmt, mode); self.walk_expr(expr); } @@ -375,7 +376,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { expr, r, bk); let cmt = return_if_err!(self.mc.cat_expr(expr)); - self.delegate.borrow(expr.id, expr.span, cmt, r, bk, cause); + self.delegate.borrow(expr.id, expr.span, &cmt, r, bk, cause); self.walk_expr(expr) } @@ -435,7 +436,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { } hir::ExprMatch(ref discr, ref arms, _) => { - let discr_cmt = return_if_err!(self.mc.cat_expr(&discr)); + let discr_cmt = Rc::new(return_if_err!(self.mc.cat_expr(&discr))); let r = self.tcx().types.re_empty; self.borrow_expr(&discr, r, ty::ImmBorrow, MatchDiscriminant); @@ -619,7 +620,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { // "assigns", which is handled by // `walk_pat`: self.walk_expr(&expr); - let init_cmt = return_if_err!(self.mc.cat_expr(&expr)); + let init_cmt = Rc::new(return_if_err!(self.mc.cat_expr(&expr))); self.walk_irrefutable_pat(init_cmt, &local.pat); } } @@ -652,7 +653,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { None => { return; } }; - let with_cmt = return_if_err!(self.mc.cat_expr(&with_expr)); + let with_cmt = Rc::new(return_if_err!(self.mc.cat_expr(&with_expr))); // Select just those fields of the `with` // expression that will actually be used @@ -671,7 +672,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { with_field.name, with_field.ty(self.tcx(), substs) ); - self.delegate_consume(with_expr.id, with_expr.span, cmt_field); + self.delegate_consume(with_expr.id, with_expr.span, &cmt_field); } } } @@ -710,7 +711,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { adjustment::Adjust::Unsize => { // Creating a closure/fn-pointer or unsizing consumes // the input and stores it into the resulting rvalue. - self.delegate_consume(expr.id, expr.span, cmt.clone()); + self.delegate_consume(expr.id, expr.span, &cmt); } adjustment::Adjust::Deref(None) => {} @@ -722,12 +723,11 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { // this is an autoref of `x`. adjustment::Adjust::Deref(Some(ref deref)) => { let bk = ty::BorrowKind::from_mutbl(deref.mutbl); - self.delegate.borrow(expr.id, expr.span, cmt.clone(), - deref.region, bk, AutoRef); + self.delegate.borrow(expr.id, expr.span, &cmt, deref.region, bk, AutoRef); } adjustment::Adjust::Borrow(ref autoref) => { - self.walk_autoref(expr, cmt.clone(), autoref); + self.walk_autoref(expr, &cmt, autoref); } } cmt = return_if_err!(self.mc.cat_expr_adjusted(expr, cmt, &adjustment)); @@ -739,7 +739,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { /// after all relevant autoderefs have occurred. fn walk_autoref(&mut self, expr: &hir::Expr, - cmt_base: mc::cmt<'tcx>, + cmt_base: &mc::cmt_<'tcx>, autoref: &adjustment::AutoBorrow<'tcx>) { debug!("walk_autoref(expr.id={} cmt_base={:?} autoref={:?})", expr.id, @@ -852,7 +852,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { // Each match binding is effectively an assignment to the // binding being produced. let def = Def::Local(canonical_id); - if let Ok(binding_cmt) = mc.cat_def(pat.id, pat.span, pat_ty, def) { + if let Ok(ref binding_cmt) = mc.cat_def(pat.id, pat.span, pat_ty, def) { delegate.mutate(pat.id, pat.span, binding_cmt, MutateMode::Init); } @@ -861,13 +861,13 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { ty::BindByReference(m) => { if let ty::TyRef(r, _) = pat_ty.sty { let bk = ty::BorrowKind::from_mutbl(m); - delegate.borrow(pat.id, pat.span, cmt_pat, r, bk, RefBinding); + delegate.borrow(pat.id, pat.span, &cmt_pat, r, bk, RefBinding); } } ty::BindByValue(..) => { let mode = copy_or_move(mc, param_env, &cmt_pat, PatBindingMove); debug!("walk_pat binding consuming pat"); - delegate.consume_pat(pat, cmt_pat, mode); + delegate.consume_pat(pat, &cmt_pat, mode); } } } @@ -891,12 +891,12 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { let downcast_cmt = mc.cat_downcast_if_needed(pat, cmt_pat, variant_did); debug!("variant downcast_cmt={:?} pat={:?}", downcast_cmt, pat); - delegate.matched_pat(pat, downcast_cmt, match_mode); + delegate.matched_pat(pat, &downcast_cmt, match_mode); } Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) | Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => { debug!("struct cmt_pat={:?} pat={:?}", cmt_pat, pat); - delegate.matched_pat(pat, cmt_pat, match_mode); + delegate.matched_pat(pat, &cmt_pat, match_mode); } _ => {} } @@ -924,12 +924,12 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { self.param_env, &cmt_var, CaptureMove); - self.delegate.consume(closure_expr.id, freevar.span, cmt_var, mode); + self.delegate.consume(closure_expr.id, freevar.span, &cmt_var, mode); } ty::UpvarCapture::ByRef(upvar_borrow) => { self.delegate.borrow(closure_expr.id, fn_decl_span, - cmt_var, + &cmt_var, upvar_borrow.region, upvar_borrow.kind, ClosureCapture(freevar.span)); @@ -943,7 +943,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { closure_id: ast::NodeId, closure_span: Span, upvar: &hir::Freevar) - -> mc::McResult> { + -> mc::McResult> { // Create the cmt for the variable being borrowed, from the // caller's perspective let var_hir_id = self.tcx().hir.node_to_hir_id(upvar.var_id()); @@ -954,7 +954,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { fn copy_or_move<'a, 'gcx, 'tcx>(mc: &mc::MemCategorizationContext<'a, 'gcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, - cmt: &mc::cmt<'tcx>, + cmt: &mc::cmt_<'tcx>, move_reason: MoveReason) -> ConsumeMode { diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 6f41f07dce8..f40a41cd299 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -572,13 +572,13 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { Ok(ret_ty) } - pub fn cat_expr(&self, expr: &hir::Expr) -> McResult> { + pub fn cat_expr(&self, expr: &hir::Expr) -> McResult> { // This recursion helper avoids going through *too many* // adjustments, since *only* non-overloaded deref recurses. fn helper<'a, 'gcx, 'tcx>(mc: &MemCategorizationContext<'a, 'gcx, 'tcx>, expr: &hir::Expr, adjustments: &[adjustment::Adjustment<'tcx>]) - -> McResult> { + -> McResult> { match adjustments.split_last() { None => mc.cat_expr_unadjusted(expr), Some((adjustment, previous)) => { @@ -591,24 +591,24 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } pub fn cat_expr_adjusted(&self, expr: &hir::Expr, - previous: cmt<'tcx>, + previous: cmt_<'tcx>, adjustment: &adjustment::Adjustment<'tcx>) - -> McResult> { + -> McResult> { self.cat_expr_adjusted_with(expr, || Ok(previous), adjustment) } fn cat_expr_adjusted_with(&self, expr: &hir::Expr, previous: F, adjustment: &adjustment::Adjustment<'tcx>) - -> McResult> - where F: FnOnce() -> McResult> + -> McResult> + where F: FnOnce() -> McResult> { debug!("cat_expr_adjusted_with({:?}): {:?}", adjustment, expr); let target = self.resolve_type_vars_if_possible(&adjustment.target); match adjustment.kind { adjustment::Adjust::Deref(overloaded) => { // Equivalent to *expr or something similar. - let base = if let Some(deref) = overloaded { + let base = Rc::new(if let Some(deref) = overloaded { let ref_ty = self.tcx.mk_ref(deref.region, ty::TypeAndMut { ty: target, mutbl: deref.mutbl, @@ -616,7 +616,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { self.cat_rvalue_node(expr.id, expr.span, ref_ty) } else { previous()? - }; + }); self.cat_deref(expr, base, false) } @@ -633,7 +633,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } } - pub fn cat_expr_unadjusted(&self, expr: &hir::Expr) -> McResult> { + pub fn cat_expr_unadjusted(&self, expr: &hir::Expr) -> McResult> { debug!("cat_expr: id={} expr={:?}", expr.id, expr); let expr_ty = self.expr_ty(expr)?; @@ -642,13 +642,13 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { if self.tables.is_method_call(expr) { self.cat_overloaded_place(expr, e_base, false) } else { - let base_cmt = self.cat_expr(&e_base)?; + let base_cmt = Rc::new(self.cat_expr(&e_base)?); self.cat_deref(expr, base_cmt, false) } } hir::ExprField(ref base, f_name) => { - let base_cmt = self.cat_expr(&base)?; + let base_cmt = Rc::new(self.cat_expr(&base)?); debug!("cat_expr(cat_field): id={} expr={:?} base={:?}", expr.id, expr, @@ -666,7 +666,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { // dereferencing. self.cat_overloaded_place(expr, base, true) } else { - let base_cmt = self.cat_expr(&base)?; + let base_cmt = Rc::new(self.cat_expr(&base)?); self.cat_index(expr, base_cmt, expr_ty, InteriorOffsetKind::Index) } } @@ -701,7 +701,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { span: Span, expr_ty: Ty<'tcx>, def: Def) - -> McResult> { + -> McResult> { debug!("cat_def: id={} expr={:?} def={:?}", id, expr_ty, def); @@ -718,14 +718,14 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { return Ok(self.cat_rvalue_node(id, span, expr_ty)); } } - Ok(Rc::new(cmt_ { + Ok(cmt_ { id:id, span:span, cat:Categorization::StaticItem, mutbl: if mutbl { McDeclared } else { McImmutable}, ty:expr_ty, note: NoteNone - })) + }) } Def::Upvar(var_id, _, fn_node_id) => { @@ -733,14 +733,14 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } Def::Local(vid) => { - Ok(Rc::new(cmt_ { + Ok(cmt_ { id, span, cat: Categorization::Local(vid), mutbl: MutabilityCategory::from_local(self.tcx, self.tables, vid), ty: expr_ty, note: NoteNone - })) + }) } def => span_bug!(span, "unexpected definition in memory categorization: {:?}", def) @@ -754,7 +754,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { span: Span, var_id: ast::NodeId, fn_node_id: ast::NodeId) - -> McResult> + -> McResult> { let fn_hir_id = self.tcx.hir.node_to_hir_id(fn_node_id); @@ -861,7 +861,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } }; - let ret = Rc::new(cmt_result); + let ret = cmt_result; debug!("cat_upvar ret={:?}", ret); Ok(ret) } @@ -938,7 +938,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { id: ast::NodeId, span: Span, expr_ty: Ty<'tcx>) - -> cmt<'tcx> { + -> cmt_<'tcx> { let hir_id = self.tcx.hir.node_to_hir_id(id); let promotable = self.rvalue_promotable_map.as_ref().map(|m| m.contains(&hir_id.local_id)) .unwrap_or(false); @@ -966,15 +966,15 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { cmt_id: ast::NodeId, span: Span, temp_scope: ty::Region<'tcx>, - expr_ty: Ty<'tcx>) -> cmt<'tcx> { - let ret = Rc::new(cmt_ { + expr_ty: Ty<'tcx>) -> cmt_<'tcx> { + let ret = cmt_ { id:cmt_id, span:span, cat:Categorization::Rvalue(temp_scope), mutbl:McDeclared, ty:expr_ty, note: NoteNone - }); + }; debug!("cat_rvalue ret {:?}", ret); ret } @@ -985,15 +985,15 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { f_index: usize, f_name: Name, f_ty: Ty<'tcx>) - -> cmt<'tcx> { - let ret = Rc::new(cmt_ { + -> cmt_<'tcx> { + let ret = cmt_ { id: node.id(), span: node.span(), mutbl: base_cmt.mutbl.inherit(), cat: Categorization::Interior(base_cmt, InteriorField(FieldIndex(f_index, f_name))), ty: f_ty, note: NoteNone - }); + }; debug!("cat_field ret {:?}", ret); ret } @@ -1002,7 +1002,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { expr: &hir::Expr, base: &hir::Expr, implicit: bool) - -> McResult> { + -> McResult> { debug!("cat_overloaded_place: implicit={}", implicit); // Reconstruct the output assuming it's a reference with the @@ -1022,7 +1022,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { mutbl, }); - let base_cmt = self.cat_rvalue_node(expr.id, expr.span, ref_ty); + let base_cmt = Rc::new(self.cat_rvalue_node(expr.id, expr.span, ref_ty)); self.cat_deref(expr, base_cmt, implicit) } @@ -1030,7 +1030,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { node: &N, base_cmt: cmt<'tcx>, implicit: bool) - -> McResult> { + -> McResult> { debug!("cat_deref: base_cmt={:?}", base_cmt); let base_cmt_ty = base_cmt.ty; @@ -1052,7 +1052,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } ref ty => bug!("unexpected type in cat_deref: {:?}", ty) }; - let ret = Rc::new(cmt_ { + let ret = cmt_ { id: node.id(), span: node.span(), // For unique ptrs, we inherit mutability from the owning reference. @@ -1060,7 +1060,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { cat: Categorization::Deref(base_cmt, ptr), ty: deref_ty, note: NoteNone - }); + }; debug!("cat_deref ret {:?}", ret); Ok(ret) } @@ -1070,7 +1070,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { base_cmt: cmt<'tcx>, element_ty: Ty<'tcx>, context: InteriorOffsetKind) - -> McResult> { + -> McResult> { //! Creates a cmt for an indexing operation (`[]`). //! //! One subtle aspect of indexing that may not be @@ -1089,8 +1089,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { //! - `base_cmt`: the cmt of `elt` let interior_elem = InteriorElement(context); - let ret = - self.cat_imm_interior(elt, base_cmt, element_ty, interior_elem); + let ret = self.cat_imm_interior(elt, base_cmt, element_ty, interior_elem); debug!("cat_index ret {:?}", ret); return Ok(ret); } @@ -1100,15 +1099,15 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { base_cmt: cmt<'tcx>, interior_ty: Ty<'tcx>, interior: InteriorKind) - -> cmt<'tcx> { - let ret = Rc::new(cmt_ { + -> cmt_<'tcx> { + let ret = cmt_ { id: node.id(), span: node.span(), mutbl: base_cmt.mutbl.inherit(), cat: Categorization::Interior(base_cmt, interior), ty: interior_ty, note: NoteNone - }); + }; debug!("cat_imm_interior ret={:?}", ret); ret } @@ -1232,7 +1231,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { .get(pat.hir_id) .map(|v| v.len()) .unwrap_or(0) { - cmt = self.cat_deref(pat, cmt, true /* implicit */)?; + cmt = Rc::new(self.cat_deref(pat, cmt, true /* implicit */)?); } let cmt = cmt; // lose mutability @@ -1279,7 +1278,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) { let subpat_ty = self.pat_ty(&subpat)?; // see (*2) let interior = InteriorField(FieldIndex(i, Name::intern(&i.to_string()))); - let subcmt = self.cat_imm_interior(pat, cmt.clone(), subpat_ty, interior); + let subcmt = Rc::new(self.cat_imm_interior(pat, cmt.clone(), subpat_ty, interior)); self.cat_pattern_(subcmt, &subpat, op)?; } } @@ -1302,7 +1301,8 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { for fp in field_pats { let field_ty = self.pat_ty(&fp.node.pat)?; // see (*2) let f_index = self.tcx.field_index(fp.node.id, self.tables); - let cmt_field = self.cat_field(pat, cmt.clone(), f_index, fp.node.name, field_ty); + let cmt_field = + Rc::new(self.cat_field(pat, cmt.clone(), f_index, fp.node.name, field_ty)); self.cat_pattern_(cmt_field, &fp.node.pat, op)?; } } @@ -1320,7 +1320,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) { let subpat_ty = self.pat_ty(&subpat)?; // see (*2) let interior = InteriorField(FieldIndex(i, Name::intern(&i.to_string()))); - let subcmt = self.cat_imm_interior(pat, cmt.clone(), subpat_ty, interior); + let subcmt = Rc::new(self.cat_imm_interior(pat, cmt.clone(), subpat_ty, interior)); self.cat_pattern_(subcmt, &subpat, op)?; } } @@ -1329,7 +1329,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { // box p1, &p1, &mut p1. we can ignore the mutability of // PatKind::Ref since that information is already contained // in the type. - let subcmt = self.cat_deref(pat, cmt, false)?; + let subcmt = Rc::new(self.cat_deref(pat, cmt, false)?); self.cat_pattern_(subcmt, &subpat, op)?; } @@ -1342,7 +1342,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } }; let context = InteriorOffsetKind::Pattern; - let elt_cmt = self.cat_index(pat, cmt, element_ty, context)?; + let elt_cmt = Rc::new(self.cat_index(pat, cmt, element_ty, context)?); for before_pat in before { self.cat_pattern_(elt_cmt.clone(), &before_pat, op)?; } @@ -1379,7 +1379,7 @@ pub enum AliasableReason { } impl<'tcx> cmt_<'tcx> { - pub fn guarantor(&self) -> cmt<'tcx> { + pub fn guarantor(&self) -> cmt_<'tcx> { //! Returns `self` after stripping away any derefs or //! interior content. The return value is basically the `cmt` which //! determines how long the value in `self` remains live. @@ -1392,7 +1392,7 @@ impl<'tcx> cmt_<'tcx> { Categorization::Deref(_, BorrowedPtr(..)) | Categorization::Deref(_, Implicit(..)) | Categorization::Upvar(..) => { - Rc::new((*self).clone()) + (*self).clone() } Categorization::Downcast(ref b, _) | Categorization::Interior(ref b, _) | @@ -1442,16 +1442,17 @@ impl<'tcx> cmt_<'tcx> { } } - // Digs down through one or two layers of deref and grabs the cmt - // for the upvar if a note indicates there is one. - pub fn upvar(&self) -> Option> { + // Digs down through one or two layers of deref and grabs the + // Categorization of the cmt for the upvar if a note indicates there is + // one. + pub fn upvar_cat(&self) -> Option<&Categorization<'tcx>> { match self.note { NoteClosureEnv(..) | NoteUpvarRef(..) => { Some(match self.cat { Categorization::Deref(ref inner, _) => { match inner.cat { - Categorization::Deref(ref inner, _) => inner.clone(), - Categorization::Upvar(..) => inner.clone(), + Categorization::Deref(ref inner, _) => &inner.cat, + Categorization::Upvar(..) => &inner.cat, _ => bug!() } } @@ -1462,7 +1463,6 @@ impl<'tcx> cmt_<'tcx> { } } - pub fn descriptive_string(&self, tcx: TyCtxt) -> String { match self.cat { Categorization::StaticItem => { @@ -1479,8 +1479,7 @@ impl<'tcx> cmt_<'tcx> { } } Categorization::Deref(_, pk) => { - let upvar = self.upvar(); - match upvar.as_ref().map(|i| &i.cat) { + match self.upvar_cat() { Some(&Categorization::Upvar(ref var)) => { var.to_string() } diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index a01b3cbf47b..79baf0ec151 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -99,7 +99,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> { fn consume(&mut self, consume_id: ast::NodeId, consume_span: Span, - cmt: mc::cmt<'tcx>, + cmt: &mc::cmt_<'tcx>, mode: euv::ConsumeMode) { debug!("consume(consume_id={}, cmt={:?}, mode={:?})", consume_id, cmt, mode); @@ -110,12 +110,12 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> { fn matched_pat(&mut self, _matched_pat: &hir::Pat, - _cmt: mc::cmt, + _cmt: &mc::cmt_, _mode: euv::MatchMode) { } fn consume_pat(&mut self, consume_pat: &hir::Pat, - cmt: mc::cmt<'tcx>, + cmt: &mc::cmt_<'tcx>, mode: euv::ConsumeMode) { debug!("consume_pat(consume_pat={:?}, cmt={:?}, mode={:?})", consume_pat, @@ -128,7 +128,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> { fn borrow(&mut self, borrow_id: ast::NodeId, borrow_span: Span, - cmt: mc::cmt<'tcx>, + cmt: &mc::cmt_<'tcx>, loan_region: ty::Region<'tcx>, bk: ty::BorrowKind, loan_cause: euv::LoanCause) @@ -139,7 +139,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> { bk, loan_cause); let hir_id = self.tcx().hir.node_to_hir_id(borrow_id); - if let Some(lp) = opt_loan_path(&cmt) { + if let Some(lp) = opt_loan_path(cmt) { let moved_value_use_kind = match loan_cause { euv::ClosureCapture(_) => MovedInCapture, _ => MovedInUse, @@ -155,13 +155,13 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> { fn mutate(&mut self, assignment_id: ast::NodeId, assignment_span: Span, - assignee_cmt: mc::cmt<'tcx>, + assignee_cmt: &mc::cmt_<'tcx>, mode: euv::MutateMode) { debug!("mutate(assignment_id={}, assignee_cmt={:?})", assignment_id, assignee_cmt); - if let Some(lp) = opt_loan_path(&assignee_cmt) { + if let Some(lp) = opt_loan_path(assignee_cmt) { match mode { MutateMode::Init | MutateMode::JustWrite => { // In a case like `path = 1`, then path does not @@ -363,10 +363,10 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { } pub fn check_for_loans_across_yields(&self, - cmt: mc::cmt<'tcx>, + cmt: &mc::cmt_<'tcx>, loan_region: ty::Region<'tcx>, borrow_span: Span) { - pub fn borrow_of_local_data<'tcx>(cmt: &mc::cmt<'tcx>) -> bool { + pub fn borrow_of_local_data<'tcx>(cmt: &mc::cmt_<'tcx>) -> bool { match cmt.cat { // Borrows of static items is allowed Categorization::StaticItem => false, @@ -401,7 +401,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { return; } - if !borrow_of_local_data(&cmt) { + if !borrow_of_local_data(cmt) { return; } @@ -649,9 +649,9 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { fn consume_common(&self, id: hir::ItemLocalId, span: Span, - cmt: mc::cmt<'tcx>, + cmt: &mc::cmt_<'tcx>, mode: euv::ConsumeMode) { - if let Some(lp) = opt_loan_path(&cmt) { + if let Some(lp) = opt_loan_path(cmt) { let moved_value_use_kind = match mode { euv::Copy => { self.check_for_copy_of_frozen_path(id, span, &lp); @@ -876,11 +876,11 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { fn check_assignment(&self, assignment_id: hir::ItemLocalId, assignment_span: Span, - assignee_cmt: mc::cmt<'tcx>) { + assignee_cmt: &mc::cmt_<'tcx>) { debug!("check_assignment(assignee_cmt={:?})", assignee_cmt); // Check that we don't invalidate any outstanding loans - if let Some(loan_path) = opt_loan_path(&assignee_cmt) { + if let Some(loan_path) = opt_loan_path(assignee_cmt) { let scope = region::Scope::Node(assignment_id); self.each_in_scope_loan_affecting_path(scope, &loan_path, |loan| { self.report_illegal_mutation(assignment_span, &loan_path, loan); @@ -892,7 +892,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { // needs to be done here instead of in check_loans because we // depend on move data. if let Categorization::Local(local_id) = assignee_cmt.cat { - let lp = opt_loan_path(&assignee_cmt).unwrap(); + let lp = opt_loan_path(assignee_cmt).unwrap(); self.move_data.each_assignment_of(assignment_id, &lp, |assign| { if assignee_cmt.mutbl.is_mutable() { let hir_id = self.bccx.tcx.hir.node_to_hir_id(local_id); diff --git a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs index 465457f5ab3..ac905d6de5d 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs @@ -26,10 +26,10 @@ use syntax_pos::Span; use rustc::hir::*; use rustc::hir::map::Node::*; -struct GatherMoveInfo<'tcx> { +struct GatherMoveInfo<'c, 'tcx: 'c> { id: hir::ItemLocalId, kind: MoveKind, - cmt: mc::cmt<'tcx>, + cmt: &'c mc::cmt_<'tcx>, span_path_opt: Option> } @@ -87,7 +87,7 @@ pub fn gather_move_from_expr<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, move_data: &MoveData<'tcx>, move_error_collector: &mut MoveErrorCollector<'tcx>, move_expr_id: hir::ItemLocalId, - cmt: mc::cmt<'tcx>, + cmt: &mc::cmt_<'tcx>, move_reason: euv::MoveReason) { let kind = match move_reason { euv::DirectRefMove | euv::PatBindingMove => MoveExpr, @@ -102,11 +102,11 @@ pub fn gather_move_from_expr<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, gather_move(bccx, move_data, move_error_collector, move_info); } -pub fn gather_move_from_pat<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, - move_data: &MoveData<'tcx>, - move_error_collector: &mut MoveErrorCollector<'tcx>, - move_pat: &hir::Pat, - cmt: mc::cmt<'tcx>) { +pub fn gather_move_from_pat<'a, 'c, 'tcx: 'c>(bccx: &BorrowckCtxt<'a, 'tcx>, + move_data: &MoveData<'tcx>, + move_error_collector: &mut MoveErrorCollector<'tcx>, + move_pat: &hir::Pat, + cmt: &'c mc::cmt_<'tcx>) { let source = get_pattern_source(bccx.tcx,move_pat); let pat_span_path_opt = match move_pat.node { PatKind::Binding(_, _, ref path1, _) => { @@ -132,18 +132,17 @@ pub fn gather_move_from_pat<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, gather_move(bccx, move_data, move_error_collector, move_info); } -fn gather_move<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, +fn gather_move<'a, 'c, 'tcx: 'c>(bccx: &BorrowckCtxt<'a, 'tcx>, move_data: &MoveData<'tcx>, move_error_collector: &mut MoveErrorCollector<'tcx>, - move_info: GatherMoveInfo<'tcx>) { + move_info: GatherMoveInfo<'c, 'tcx>) { debug!("gather_move(move_id={:?}, cmt={:?})", move_info.id, move_info.cmt); - let potentially_illegal_move = - check_and_get_illegal_move_origin(bccx, &move_info.cmt); + let potentially_illegal_move = check_and_get_illegal_move_origin(bccx, move_info.cmt); if let Some(illegal_move_origin) = potentially_illegal_move { debug!("illegal_move_origin={:?}", illegal_move_origin); - let error = MoveError::with_move_info(illegal_move_origin, + let error = MoveError::with_move_info(Rc::new(illegal_move_origin), move_info.span_path_opt); move_error_collector.add_error(error); return; @@ -177,8 +176,8 @@ pub fn gather_assignment<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, // (keep in sync with move_error::report_cannot_move_out_of ) fn check_and_get_illegal_move_origin<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, - cmt: &mc::cmt<'tcx>) - -> Option> { + cmt: &mc::cmt_<'tcx>) + -> Option> { match cmt.cat { Categorization::Deref(_, mc::BorrowedPtr(..)) | Categorization::Deref(_, mc::Implicit(..)) | diff --git a/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs b/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs index 97fa94b5e5c..6d73500d318 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs @@ -27,7 +27,7 @@ pub fn guarantee_lifetime<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, item_scope: region::Scope, span: Span, cause: euv::LoanCause, - cmt: mc::cmt<'tcx>, + cmt: &'a mc::cmt_<'tcx>, loan_region: ty::Region<'tcx>, _: ty::BorrowKind) -> Result<(),()> { @@ -41,8 +41,8 @@ pub fn guarantee_lifetime<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, span, cause, loan_region, - cmt_original: cmt.clone()}; - ctxt.check(&cmt, None) + cmt_original: cmt}; + ctxt.check(cmt, None) } /////////////////////////////////////////////////////////////////////////// @@ -57,12 +57,11 @@ struct GuaranteeLifetimeContext<'a, 'tcx: 'a> { span: Span, cause: euv::LoanCause, loan_region: ty::Region<'tcx>, - cmt_original: mc::cmt<'tcx> + cmt_original: &'a mc::cmt_<'tcx> } impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> { - - fn check(&self, cmt: &mc::cmt<'tcx>, discr_scope: Option) -> R { + fn check(&self, cmt: &mc::cmt_<'tcx>, discr_scope: Option) -> R { //! Main routine. Walks down `cmt` until we find the //! "guarantor". Reports an error if `self.loan_region` is //! larger than scope of `cmt`. @@ -102,7 +101,7 @@ impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> { } } - fn scope(&self, cmt: &mc::cmt<'tcx>) -> ty::Region<'tcx> { + fn scope(&self, cmt: &mc::cmt_<'tcx>) -> ty::Region<'tcx> { //! Returns the maximal region scope for the which the //! place `cmt` is guaranteed to be valid without any //! rooting etc, and presuming `cmt` is not mutated. @@ -136,7 +135,7 @@ impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> { } fn report_error(&self, code: bckerr_code<'tcx>) { - self.bccx.report(BckError { cmt: self.cmt_original.clone(), + self.bccx.report(BckError { cmt: self.cmt_original, span: self.span, cause: BorrowViolation(self.cause), code: code }); diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index 49234f4ed7f..a74eba39955 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -76,7 +76,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> { fn consume(&mut self, consume_id: ast::NodeId, _consume_span: Span, - cmt: mc::cmt<'tcx>, + cmt: &mc::cmt_<'tcx>, mode: euv::ConsumeMode) { debug!("consume(consume_id={}, cmt={:?}, mode={:?})", consume_id, cmt, mode); @@ -93,7 +93,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> { fn matched_pat(&mut self, matched_pat: &hir::Pat, - cmt: mc::cmt<'tcx>, + cmt: &mc::cmt_<'tcx>, mode: euv::MatchMode) { debug!("matched_pat(matched_pat={:?}, cmt={:?}, mode={:?})", matched_pat, @@ -103,7 +103,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> { fn consume_pat(&mut self, consume_pat: &hir::Pat, - cmt: mc::cmt<'tcx>, + cmt: &mc::cmt_<'tcx>, mode: euv::ConsumeMode) { debug!("consume_pat(consume_pat={:?}, cmt={:?}, mode={:?})", consume_pat, @@ -123,7 +123,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> { fn borrow(&mut self, borrow_id: ast::NodeId, borrow_span: Span, - cmt: mc::cmt<'tcx>, + cmt: &mc::cmt_<'tcx>, loan_region: ty::Region<'tcx>, bk: ty::BorrowKind, loan_cause: euv::LoanCause) @@ -144,7 +144,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> { fn mutate(&mut self, assignment_id: ast::NodeId, assignment_span: Span, - assignee_cmt: mc::cmt<'tcx>, + assignee_cmt: &mc::cmt_<'tcx>, mode: euv::MutateMode) { self.guarantee_assignment_valid(assignment_id, @@ -165,7 +165,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> { fn check_aliasability<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, borrow_span: Span, loan_cause: AliasableViolationKind, - cmt: mc::cmt<'tcx>, + cmt: &mc::cmt_<'tcx>, req_kind: ty::BorrowKind) -> Result<(),()> { @@ -206,7 +206,7 @@ fn check_aliasability<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, fn check_mutability<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, borrow_span: Span, cause: AliasableViolationKind, - cmt: mc::cmt<'tcx>, + cmt: &mc::cmt_<'tcx>, req_kind: ty::BorrowKind) -> Result<(),()> { debug!("check_mutability(cause={:?} cmt={:?} req_kind={:?}", @@ -246,10 +246,10 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { fn guarantee_assignment_valid(&mut self, assignment_id: ast::NodeId, assignment_span: Span, - cmt: mc::cmt<'tcx>, + cmt: &mc::cmt_<'tcx>, mode: euv::MutateMode) { - let opt_lp = opt_loan_path(&cmt); + let opt_lp = opt_loan_path(cmt); debug!("guarantee_assignment_valid(assignment_id={}, cmt={:?}) opt_lp={:?}", assignment_id, cmt, opt_lp); @@ -259,14 +259,14 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { } else { // Check that we don't allow assignments to non-mutable data. if check_mutability(self.bccx, assignment_span, MutabilityViolation, - cmt.clone(), ty::MutBorrow).is_err() { + cmt, ty::MutBorrow).is_err() { return; // reported an error, no sense in reporting more. } } // Check that we don't allow assignments to aliasable data if check_aliasability(self.bccx, assignment_span, MutabilityViolation, - cmt.clone(), ty::MutBorrow).is_err() { + cmt, ty::MutBorrow).is_err() { return; // reported an error, no sense in reporting more. } @@ -300,7 +300,7 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { fn guarantee_valid(&mut self, borrow_id: hir::ItemLocalId, borrow_span: Span, - cmt: mc::cmt<'tcx>, + cmt: &mc::cmt_<'tcx>, req_kind: ty::BorrowKind, loan_region: ty::Region<'tcx>, cause: euv::LoanCause) { @@ -320,28 +320,26 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { // Check that the lifetime of the borrow does not exceed // the lifetime of the data being borrowed. if lifetime::guarantee_lifetime(self.bccx, self.item_ub, - borrow_span, cause, cmt.clone(), loan_region, - req_kind).is_err() { + borrow_span, cause, cmt, loan_region, req_kind).is_err() { return; // reported an error, no sense in reporting more. } // Check that we don't allow mutable borrows of non-mutable data. if check_mutability(self.bccx, borrow_span, BorrowViolation(cause), - cmt.clone(), req_kind).is_err() { + cmt, req_kind).is_err() { return; // reported an error, no sense in reporting more. } // Check that we don't allow mutable borrows of aliasable data. if check_aliasability(self.bccx, borrow_span, BorrowViolation(cause), - cmt.clone(), req_kind).is_err() { + cmt, req_kind).is_err() { return; // reported an error, no sense in reporting more. } // Compute the restrictions that are required to enforce the // loan is safe. let restr = restrictions::compute_restrictions( - self.bccx, borrow_span, cause, - cmt.clone(), loan_region); + self.bccx, borrow_span, cause, &cmt, loan_region); debug!("guarantee_valid(): restrictions={:?}", restr); diff --git a/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs b/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs index e3adb51433b..0b90127cc7e 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/restrictions.rs @@ -30,7 +30,7 @@ pub enum RestrictionResult<'tcx> { pub fn compute_restrictions<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, span: Span, cause: euv::LoanCause, - cmt: mc::cmt<'tcx>, + cmt: &mc::cmt_<'tcx>, loan_region: ty::Region<'tcx>) -> RestrictionResult<'tcx> { let ctxt = RestrictionsContext { @@ -55,7 +55,7 @@ struct RestrictionsContext<'a, 'tcx: 'a> { impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> { fn restrict(&self, - cmt: mc::cmt<'tcx>) -> RestrictionResult<'tcx> { + cmt: &mc::cmt_<'tcx>) -> RestrictionResult<'tcx> { debug!("restrict(cmt={:?})", cmt); let new_lp = |v: LoanPathKind<'tcx>| Rc::new(LoanPath::new(v, cmt.ty)); @@ -86,7 +86,7 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> { // When we borrow the interior of an enum, we have to // ensure the enum itself is not mutated, because that // could cause the type of the memory to change. - self.restrict(cmt_base) + self.restrict(&cmt_base) } Categorization::Interior(cmt_base, interior) => { @@ -101,7 +101,7 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> { }; let interior = interior.cleaned(); let base_ty = cmt_base.ty; - let result = self.restrict(cmt_base); + let result = self.restrict(&cmt_base); // Borrowing one union field automatically borrows all its fields. match base_ty.sty { ty::TyAdt(adt_def, _) if adt_def.is_union() => match result { @@ -145,7 +145,7 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> { // // Eventually we should make these non-special and // just rely on Deref implementation. - let result = self.restrict(cmt_base); + let result = self.restrict(&cmt_base); self.extend(result, &cmt, LpDeref(pk)) } mc::Implicit(bk, lt) | mc::BorrowedPtr(bk, lt) => { @@ -155,7 +155,7 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> { BckError { span: self.span, cause: BorrowViolation(self.cause), - cmt: cmt_base, + cmt: &cmt_base, code: err_borrowed_pointer_too_short( self.loan_region, lt)}); return RestrictionResult::Safe; @@ -169,7 +169,7 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> { // The referent can be aliased after the // references lifetime ends (by a newly-unfrozen // borrow). - let result = self.restrict(cmt_base); + let result = self.restrict(&cmt_base); self.extend(result, &cmt, LpDeref(pk)) } } @@ -183,7 +183,7 @@ impl<'a, 'tcx> RestrictionsContext<'a, 'tcx> { fn extend(&self, result: RestrictionResult<'tcx>, - cmt: &mc::cmt<'tcx>, + cmt: &mc::cmt_<'tcx>, elem: LoanPathElem<'tcx>) -> RestrictionResult<'tcx> { match result { RestrictionResult::Safe => RestrictionResult::Safe, diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 6d832d4060a..98235b2920f 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -497,7 +497,7 @@ impl<'a, 'tcx> LoanPath<'tcx> { // Avoid "cannot borrow immutable field `self.x` as mutable" as that implies that a field *can* be // mutable independently of the struct it belongs to. (#35937) -pub fn opt_loan_path_is_field<'tcx>(cmt: &mc::cmt<'tcx>) -> (Option>>, bool) { +pub fn opt_loan_path_is_field<'tcx>(cmt: &mc::cmt_<'tcx>) -> (Option>>, bool) { let new_lp = |v: LoanPathKind<'tcx>| Rc::new(LoanPath::new(v, cmt.ty)); match cmt.cat { @@ -545,7 +545,7 @@ pub fn opt_loan_path_is_field<'tcx>(cmt: &mc::cmt<'tcx>) -> (Option(cmt: &mc::cmt<'tcx>) -> Option>> { +pub fn opt_loan_path<'tcx>(cmt: &mc::cmt_<'tcx>) -> Option>> { opt_loan_path_is_field(cmt).0 } @@ -564,10 +564,10 @@ pub enum bckerr_code<'tcx> { // Combination of an error code and the categorization of the expression // that caused it #[derive(Debug, PartialEq)] -pub struct BckError<'tcx> { +pub struct BckError<'c, 'tcx: 'c> { span: Span, cause: AliasableViolationKind, - cmt: mc::cmt<'tcx>, + cmt: &'c mc::cmt_<'tcx>, code: bckerr_code<'tcx> } @@ -599,7 +599,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { region_rels.is_subregion_of(r_sub, r_sup) } - pub fn report(&self, err: BckError<'tcx>) { + pub fn report(&self, err: BckError<'a, 'tcx>) { // Catch and handle some particular cases. match (&err.code, &err.cause) { (&err_out_of_scope(&ty::ReScope(_), &ty::ReStatic, _), @@ -800,7 +800,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { self.tcx.sess.span_err_with_code(s, msg, code); } - fn report_bckerr(&self, err: &BckError<'tcx>) { + fn report_bckerr(&self, err: &BckError<'a, 'tcx>) { let error_span = err.span.clone(); match err.code { @@ -1011,7 +1011,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { db.emit(); } err_borrowed_pointer_too_short(loan_scope, ptr_scope) => { - let descr = self.cmt_to_path_or_string(&err.cmt); + let descr = self.cmt_to_path_or_string(err.cmt); let mut db = self.lifetime_too_short_for_reborrow(error_span, &descr, Origin::Ast); let descr = match opt_loan_path(&err.cmt) { Some(lp) => { @@ -1042,7 +1042,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { span: Span, kind: AliasableViolationKind, cause: mc::AliasableReason, - cmt: mc::cmt<'tcx>) { + cmt: &mc::cmt_<'tcx>) { let mut is_closure = false; let prefix = match kind { MutabilityViolation => { @@ -1240,7 +1240,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { } fn report_out_of_scope_escaping_closure_capture(&self, - err: &BckError<'tcx>, + err: &BckError<'a, 'tcx>, capture_span: Span) { let cmt_path_or_string = self.cmt_to_path_or_string(&err.cmt); @@ -1274,18 +1274,18 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { } } - fn note_and_explain_mutbl_error(&self, db: &mut DiagnosticBuilder, err: &BckError<'tcx>, + fn note_and_explain_mutbl_error(&self, db: &mut DiagnosticBuilder, err: &BckError<'a, 'tcx>, error_span: &Span) { match err.cmt.note { mc::NoteClosureEnv(upvar_id) | mc::NoteUpvarRef(upvar_id) => { // If this is an `Fn` closure, it simply can't mutate upvars. // If it's an `FnMut` closure, the original variable was declared immutable. // We need to determine which is the case here. - let kind = match err.cmt.upvar().unwrap().cat { + let kind = match err.cmt.upvar_cat().unwrap() { Categorization::Upvar(mc::Upvar { kind, .. }) => kind, _ => bug!() }; - if kind == ty::ClosureKind::Fn { + if *kind == ty::ClosureKind::Fn { let closure_node_id = self.tcx.hir.local_def_id_to_node_id(upvar_id.closure_expr_id); db.span_help(self.tcx.hir.span(closure_node_id), @@ -1389,7 +1389,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { cmt.descriptive_string(self.tcx) } - pub fn cmt_to_path_or_string(&self, cmt: &mc::cmt<'tcx>) -> String { + pub fn cmt_to_path_or_string(&self, cmt: &mc::cmt_<'tcx>) -> String { match opt_loan_path(cmt) { Some(lp) => format!("`{}`", self.loan_path_to_string(&lp)), None => self.cmt_to_string(cmt), diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index d924baaf005..77bcd88cecb 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -17,7 +17,7 @@ use super::{Pattern, PatternContext, PatternError, PatternKind}; use rustc::middle::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor}; use rustc::middle::expr_use_visitor::{LoanCause, MutateMode}; use rustc::middle::expr_use_visitor as euv; -use rustc::middle::mem_categorization::{cmt}; +use rustc::middle::mem_categorization::cmt_; use rustc::middle::region; use rustc::session::Session; use rustc::ty::{self, Ty, TyCtxt}; @@ -573,13 +573,13 @@ struct MutationChecker<'a, 'tcx: 'a> { } impl<'a, 'tcx> Delegate<'tcx> for MutationChecker<'a, 'tcx> { - fn matched_pat(&mut self, _: &Pat, _: cmt, _: euv::MatchMode) {} - fn consume(&mut self, _: ast::NodeId, _: Span, _: cmt, _: ConsumeMode) {} - fn consume_pat(&mut self, _: &Pat, _: cmt, _: ConsumeMode) {} + fn matched_pat(&mut self, _: &Pat, _: &cmt_, _: euv::MatchMode) {} + fn consume(&mut self, _: ast::NodeId, _: Span, _: &cmt_, _: ConsumeMode) {} + fn consume_pat(&mut self, _: &Pat, _: &cmt_, _: ConsumeMode) {} fn borrow(&mut self, _: ast::NodeId, span: Span, - _: cmt, + _: &cmt_, _: ty::Region<'tcx>, kind:ty:: BorrowKind, _: LoanCause) { @@ -594,7 +594,7 @@ impl<'a, 'tcx> Delegate<'tcx> for MutationChecker<'a, 'tcx> { } } fn decl_without_init(&mut self, _: ast::NodeId, _: Span) {} - fn mutate(&mut self, _: ast::NodeId, span: Span, _: cmt, mode: MutateMode) { + fn mutate(&mut self, _: ast::NodeId, span: Span, _: &cmt_, mode: MutateMode) { match mode { MutateMode::JustWrite | MutateMode::WriteAndRead => { struct_span_err!(self.cx.tcx.sess, span, E0302, "cannot assign in a pattern guard") diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs index c5d2f0041a0..3a577341f7e 100644 --- a/src/librustc_passes/rvalue_promotion.rs +++ b/src/librustc_passes/rvalue_promotion.rs @@ -468,13 +468,13 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'gcx> { fn consume(&mut self, _consume_id: ast::NodeId, _consume_span: Span, - _cmt: mc::cmt, + _cmt: &mc::cmt_, _mode: euv::ConsumeMode) {} fn borrow(&mut self, borrow_id: ast::NodeId, _borrow_span: Span, - cmt: mc::cmt<'tcx>, + cmt: &mc::cmt_<'tcx>, _loan_region: ty::Region<'tcx>, bk: ty::BorrowKind, loan_cause: euv::LoanCause) { @@ -489,7 +489,7 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'gcx> { _ => {} } - let mut cur = &cmt; + let mut cur = cmt; loop { match cur.cat { Categorization::Rvalue(..) => { @@ -521,11 +521,11 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for CheckCrateVisitor<'a, 'gcx> { fn mutate(&mut self, _assignment_id: ast::NodeId, _assignment_span: Span, - _assignee_cmt: mc::cmt, + _assignee_cmt: &mc::cmt_, _mode: euv::MutateMode) { } - fn matched_pat(&mut self, _: &hir::Pat, _: mc::cmt, _: euv::MatchMode) {} + fn matched_pat(&mut self, _: &hir::Pat, _: &mc::cmt_, _: euv::MatchMode) {} - fn consume_pat(&mut self, _consume_pat: &hir::Pat, _cmt: mc::cmt, _mode: euv::ConsumeMode) {} + fn consume_pat(&mut self, _consume_pat: &hir::Pat, _cmt: &mc::cmt_, _mode: euv::ConsumeMode) {} } diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index b5e862fac95..e7e70a19e49 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -96,6 +96,7 @@ use rustc::ty::adjustment; use std::mem; use std::ops::Deref; +use std::rc::Rc; use rustc_data_structures::sync::Lrc; use syntax::ast; use syntax_pos::Span; @@ -513,7 +514,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> { // the adjusted form if there is an adjustment. match cmt_result { Ok(head_cmt) => { - self.check_safety_of_rvalue_destructor_if_necessary(head_cmt, expr.span); + self.check_safety_of_rvalue_destructor_if_necessary(&head_cmt, expr.span); } Err(..) => { self.tcx.sess.delay_span_bug(expr.span, "cat_expr Errd"); @@ -799,7 +800,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { /// Invoked on any adjustments that occur. Checks that if this is a region pointer being /// dereferenced, the lifetime of the pointer includes the deref expr. - fn constrain_adjustments(&mut self, expr: &hir::Expr) -> mc::McResult> { + fn constrain_adjustments(&mut self, expr: &hir::Expr) -> mc::McResult> { debug!("constrain_adjustments(expr={:?})", expr); let mut cmt = self.with_mc(|mc| mc.cat_expr_unadjusted(expr))?; @@ -814,7 +815,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { // If necessary, constrain destructors in the unadjusted form of this // expression. - self.check_safety_of_rvalue_destructor_if_necessary(cmt.clone(), expr.span); + self.check_safety_of_rvalue_destructor_if_necessary(&cmt, expr.span); let expr_region = self.tcx.mk_region(ty::ReScope( region::Scope::Node(expr.hir_id.local_id))); @@ -837,7 +838,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { }); self.link_region(expr.span, deref.region, - ty::BorrowKind::from_mutbl(deref.mutbl), cmt.clone()); + ty::BorrowKind::from_mutbl(deref.mutbl), &cmt); // Specialized version of constrain_call. self.type_must_outlive(infer::CallRcvr(expr.span), @@ -847,7 +848,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { } if let adjustment::Adjust::Borrow(ref autoref) = adjustment.kind { - self.link_autoref(expr, cmt.clone(), autoref); + self.link_autoref(expr, &cmt, autoref); // Require that the resulting region encompasses // the current node. @@ -878,7 +879,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { } fn check_safety_of_rvalue_destructor_if_necessary(&mut self, - cmt: mc::cmt<'tcx>, + cmt: &mc::cmt_<'tcx>, span: Span) { match cmt.cat { Categorization::Rvalue(region) => { @@ -980,7 +981,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { debug!("link_addr_of: cmt={:?}", cmt); - self.link_region_from_node_type(expr.span, expr.hir_id, mutability, cmt); + self.link_region_from_node_type(expr.span, expr.hir_id, mutability, &cmt); } /// Computes the guarantors for any ref bindings in a `let` and @@ -992,7 +993,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { None => { return; } Some(ref expr) => &**expr, }; - let discr_cmt = ignore_err!(self.with_mc(|mc| mc.cat_expr(init_expr))); + let discr_cmt = Rc::new(ignore_err!(self.with_mc(|mc| mc.cat_expr(init_expr)))); self.link_pattern(discr_cmt, &local.pat); } @@ -1001,7 +1002,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { /// linked to the lifetime of its guarantor (if any). fn link_match(&self, discr: &hir::Expr, arms: &[hir::Arm]) { debug!("regionck::for_match()"); - let discr_cmt = ignore_err!(self.with_mc(|mc| mc.cat_expr(discr))); + let discr_cmt = Rc::new(ignore_err!(self.with_mc(|mc| mc.cat_expr(discr)))); debug!("discr_cmt={:?}", discr_cmt); for arm in arms { for root_pat in &arm.pats { @@ -1019,7 +1020,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { let arg_ty = self.node_ty(arg.hir_id); let re_scope = self.tcx.mk_region(ty::ReScope(body_scope)); let arg_cmt = self.with_mc(|mc| { - mc.cat_rvalue(arg.id, arg.pat.span, re_scope, arg_ty) + Rc::new(mc.cat_rvalue(arg.id, arg.pat.span, re_scope, arg_ty)) }); debug!("arg_ty={:?} arg_cmt={:?} arg={:?}", arg_ty, @@ -1044,7 +1045,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { .expect("missing binding mode"); if let ty::BindByReference(mutbl) = bm { self.link_region_from_node_type(sub_pat.span, sub_pat.hir_id, - mutbl, sub_cmt); + mutbl, &sub_cmt); } } _ => {} @@ -1057,15 +1058,14 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { /// autoref'd. fn link_autoref(&self, expr: &hir::Expr, - expr_cmt: mc::cmt<'tcx>, + expr_cmt: &mc::cmt_<'tcx>, autoref: &adjustment::AutoBorrow<'tcx>) { debug!("link_autoref(autoref={:?}, expr_cmt={:?})", autoref, expr_cmt); match *autoref { adjustment::AutoBorrow::Ref(r, m) => { - self.link_region(expr.span, r, - ty::BorrowKind::from_mutbl(m.into()), expr_cmt); + self.link_region(expr.span, r, ty::BorrowKind::from_mutbl(m.into()), expr_cmt); } adjustment::AutoBorrow::RawPtr(m) => { @@ -1081,15 +1081,14 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { span: Span, id: hir::HirId, mutbl: hir::Mutability, - cmt_borrowed: mc::cmt<'tcx>) { + cmt_borrowed: &mc::cmt_<'tcx>) { debug!("link_region_from_node_type(id={:?}, mutbl={:?}, cmt_borrowed={:?})", id, mutbl, cmt_borrowed); let rptr_ty = self.resolve_node_type(id); if let ty::TyRef(r, _) = rptr_ty.sty { debug!("rptr_ty={}", rptr_ty); - self.link_region(span, r, ty::BorrowKind::from_mutbl(mutbl), - cmt_borrowed); + self.link_region(span, r, ty::BorrowKind::from_mutbl(mutbl), cmt_borrowed); } } @@ -1101,19 +1100,19 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { span: Span, borrow_region: ty::Region<'tcx>, borrow_kind: ty::BorrowKind, - borrow_cmt: mc::cmt<'tcx>) { - let mut borrow_cmt = borrow_cmt; - let mut borrow_kind = borrow_kind; - + borrow_cmt: &mc::cmt_<'tcx>) { let origin = infer::DataBorrowed(borrow_cmt.ty, span); self.type_must_outlive(origin, borrow_cmt.ty, borrow_region); + let mut borrow_kind = borrow_kind; + let mut borrow_cmt_cat = borrow_cmt.cat.clone(); + loop { debug!("link_region(borrow_region={:?}, borrow_kind={:?}, borrow_cmt={:?})", borrow_region, borrow_kind, borrow_cmt); - match borrow_cmt.cat.clone() { + match borrow_cmt_cat { Categorization::Deref(ref_cmt, mc::Implicit(ref_kind, ref_region)) | Categorization::Deref(ref_cmt, mc::BorrowedPtr(ref_kind, ref_region)) => { match self.link_reborrowed_region(span, @@ -1121,7 +1120,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { ref_cmt, ref_region, ref_kind, borrow_cmt.note) { Some((c, k)) => { - borrow_cmt = c; + borrow_cmt_cat = c.cat.clone(); borrow_kind = k; } None => { @@ -1135,7 +1134,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { Categorization::Interior(cmt_base, _) => { // Borrowing interior or owned data requires the base // to be valid and borrowable in the same fashion. - borrow_cmt = cmt_base; + borrow_cmt_cat = cmt_base.cat.clone(); borrow_kind = borrow_kind; } diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index 4fc3344dab2..58dc5839578 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -298,7 +298,8 @@ struct InferBorrowKind<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { } impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> { - fn adjust_upvar_borrow_kind_for_consume(&mut self, cmt: mc::cmt<'tcx>, mode: euv::ConsumeMode) { + fn adjust_upvar_borrow_kind_for_consume(&mut self, cmt: &mc::cmt_<'tcx>, + mode: euv::ConsumeMode) { debug!( "adjust_upvar_borrow_kind_for_consume(cmt={:?}, mode={:?})", cmt, @@ -377,7 +378,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> { /// Indicates that `cmt` is being directly mutated (e.g., assigned /// to). If cmt contains any by-ref upvars, this implies that /// those upvars must be borrowed using an `&mut` borrow. - fn adjust_upvar_borrow_kind_for_mut(&mut self, cmt: mc::cmt<'tcx>) { + fn adjust_upvar_borrow_kind_for_mut(&mut self, cmt: &mc::cmt_<'tcx>) { debug!("adjust_upvar_borrow_kind_for_mut(cmt={:?})", cmt); match cmt.cat.clone() { @@ -386,7 +387,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> { Categorization::Downcast(base, _) => { // Interior or owned data is mutable if base is // mutable, so iterate to the base. - self.adjust_upvar_borrow_kind_for_mut(base); + self.adjust_upvar_borrow_kind_for_mut(&base); } Categorization::Deref(base, mc::BorrowedPtr(..)) | @@ -396,7 +397,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> { // borrowed pointer implies that the // pointer itself must be unique, but not // necessarily *mutable* - self.adjust_upvar_borrow_kind_for_unique(base); + self.adjust_upvar_borrow_kind_for_unique(&base); } } @@ -410,7 +411,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> { } } - fn adjust_upvar_borrow_kind_for_unique(&mut self, cmt: mc::cmt<'tcx>) { + fn adjust_upvar_borrow_kind_for_unique(&mut self, cmt: &mc::cmt_<'tcx>) { debug!("adjust_upvar_borrow_kind_for_unique(cmt={:?})", cmt); match cmt.cat.clone() { @@ -419,7 +420,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> { Categorization::Downcast(base, _) => { // Interior or owned data is unique if base is // unique. - self.adjust_upvar_borrow_kind_for_unique(base); + self.adjust_upvar_borrow_kind_for_unique(&base); } Categorization::Deref(base, mc::BorrowedPtr(..)) | @@ -427,7 +428,7 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> { if !self.try_adjust_upvar_deref(cmt, ty::UniqueImmBorrow) { // for a borrowed pointer to be unique, its // base must be unique - self.adjust_upvar_borrow_kind_for_unique(base); + self.adjust_upvar_borrow_kind_for_unique(&base); } } @@ -439,7 +440,9 @@ impl<'a, 'gcx, 'tcx> InferBorrowKind<'a, 'gcx, 'tcx> { } } - fn try_adjust_upvar_deref(&mut self, cmt: mc::cmt<'tcx>, borrow_kind: ty::BorrowKind) -> bool { + fn try_adjust_upvar_deref(&mut self, cmt: &mc::cmt_<'tcx>, borrow_kind: ty::BorrowKind) + -> bool + { assert!(match borrow_kind { ty::MutBorrow => true, ty::UniqueImmBorrow => true, @@ -581,17 +584,19 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'gcx, 'tcx> { &mut self, _consume_id: ast::NodeId, _consume_span: Span, - cmt: mc::cmt<'tcx>, + cmt: &mc::cmt_<'tcx>, mode: euv::ConsumeMode, ) { debug!("consume(cmt={:?},mode={:?})", cmt, mode); self.adjust_upvar_borrow_kind_for_consume(cmt, mode); } - fn matched_pat(&mut self, _matched_pat: &hir::Pat, _cmt: mc::cmt<'tcx>, _mode: euv::MatchMode) { + fn matched_pat(&mut self, _matched_pat: &hir::Pat, _cmt: &mc::cmt_<'tcx>, + _mode: euv::MatchMode) { } - fn consume_pat(&mut self, _consume_pat: &hir::Pat, cmt: mc::cmt<'tcx>, mode: euv::ConsumeMode) { + fn consume_pat(&mut self, _consume_pat: &hir::Pat, cmt: &mc::cmt_<'tcx>, + mode: euv::ConsumeMode) { debug!("consume_pat(cmt={:?},mode={:?})", cmt, mode); self.adjust_upvar_borrow_kind_for_consume(cmt, mode); } @@ -600,7 +605,7 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'gcx, 'tcx> { &mut self, borrow_id: ast::NodeId, _borrow_span: Span, - cmt: mc::cmt<'tcx>, + cmt: &mc::cmt_<'tcx>, _loan_region: ty::Region<'tcx>, bk: ty::BorrowKind, _loan_cause: euv::LoanCause, @@ -629,7 +634,7 @@ impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for InferBorrowKind<'a, 'gcx, 'tcx> { &mut self, _assignment_id: ast::NodeId, _assignment_span: Span, - assignee_cmt: mc::cmt<'tcx>, + assignee_cmt: &mc::cmt_<'tcx>, _mode: euv::MutateMode, ) { debug!("mutate(assignee_cmt={:?})", assignee_cmt); -- cgit 1.4.1-3-g733a5 From 14f32f64c8d4700b40ce4e49596b460869b15fe7 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Thu, 3 May 2018 22:24:50 +0900 Subject: rustdoc: Resolve nested `impl Trait`s --- src/librustdoc/clean/mod.rs | 63 ++++++++++++++++---------------- src/test/rustdoc/universal-impl-trait.rs | 7 ++++ 2 files changed, 39 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index bd64ac67ac9..ffba91c9248 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1755,8 +1755,18 @@ pub struct Generics { impl Clean for hir::Generics { fn clean(&self, cx: &DocContext) -> Generics { + let mut params = Vec::with_capacity(self.params.len()); + for p in &self.params { + let p = p.clean(cx); + if let GenericParam::Type(ref tp) = p { + if tp.synthetic == Some(hir::SyntheticTyParamKind::ImplTrait) { + cx.impl_trait_bounds.borrow_mut().insert(tp.did, tp.bounds.clone()); + } + } + params.push(p); + } let mut g = Generics { - params: self.params.clean(cx), + params, where_predicates: self.where_clause.predicates.clean(cx) }; @@ -1869,9 +1879,11 @@ pub struct Method { impl<'a> Clean for (&'a hir::MethodSig, &'a hir::Generics, hir::BodyId) { fn clean(&self, cx: &DocContext) -> Method { - let generics = self.1.clean(cx); + let (generics, decl) = enter_impl_trait(cx, || { + (self.1.clean(cx), (&*self.0.decl, self.2).clean(cx)) + }); Method { - decl: enter_impl_trait(cx, &generics.params, || (&*self.0.decl, self.2).clean(cx)), + decl, generics, unsafety: self.0.unsafety, constness: self.0.constness, @@ -1899,8 +1911,9 @@ pub struct Function { impl Clean for doctree::Function { fn clean(&self, cx: &DocContext) -> Item { - let generics = self.generics.clean(cx); - let decl = enter_impl_trait(cx, &generics.params, || (&self.decl, self.body).clean(cx)); + let (generics, decl) = enter_impl_trait(cx, || { + (self.generics.clean(cx), (&self.decl, self.body).clean(cx)) + }); Item { name: Some(self.name.clean(cx)), attrs: self.attrs.clean(cx), @@ -2139,12 +2152,12 @@ impl Clean for hir::TraitItem { MethodItem((sig, &self.generics, body).clean(cx)) } hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(ref names)) => { - let generics = self.generics.clean(cx); + let (generics, decl) = enter_impl_trait(cx, || { + (self.generics.clean(cx), (&*sig.decl, &names[..]).clean(cx)) + }); TyMethodItem(TyMethod { unsafety: sig.unsafety.clone(), - decl: enter_impl_trait(cx, &generics.params, || { - (&*sig.decl, &names[..]).clean(cx) - }), + decl, generics, abi: sig.abi }) @@ -3415,12 +3428,12 @@ pub struct BareFunctionDecl { impl Clean for hir::BareFnTy { fn clean(&self, cx: &DocContext) -> BareFunctionDecl { - let generic_params = self.generic_params.clean(cx); + let (generic_params, decl) = enter_impl_trait(cx, || { + (self.generic_params.clean(cx), (&*self.decl, &self.arg_names[..]).clean(cx)) + }); BareFunctionDecl { unsafety: self.unsafety, - decl: enter_impl_trait(cx, &generic_params, || { - (&*self.decl, &self.arg_names[..]).clean(cx) - }), + decl, generic_params, abi: self.abi, } @@ -3722,11 +3735,11 @@ impl Clean for hir::ForeignItem { fn clean(&self, cx: &DocContext) -> Item { let inner = match self.node { hir::ForeignItemFn(ref decl, ref names, ref generics) => { - let generics = generics.clean(cx); + let (generics, decl) = enter_impl_trait(cx, || { + (generics.clean(cx), (&**decl, &names[..]).clean(cx)) + }); ForeignFunctionItem(Function { - decl: enter_impl_trait(cx, &generics.params, || { - (&**decl, &names[..]).clean(cx) - }), + decl, generics, unsafety: hir::Unsafety::Unsafe, abi: Abi::Rust, @@ -4030,23 +4043,11 @@ pub fn def_id_to_path(cx: &DocContext, did: DefId, name: Option) -> Vec< once(crate_name).chain(relative).collect() } -pub fn enter_impl_trait(cx: &DocContext, gps: &[GenericParam], f: F) -> R +pub fn enter_impl_trait(cx: &DocContext, f: F) -> R where F: FnOnce() -> R, { - let bounds = gps.iter() - .filter_map(|p| { - if let GenericParam::Type(ref tp) = *p { - if tp.synthetic == Some(hir::SyntheticTyParamKind::ImplTrait) { - return Some((tp.did, tp.bounds.clone())); - } - } - - None - }) - .collect::>>(); - - let old_bounds = mem::replace(&mut *cx.impl_trait_bounds.borrow_mut(), bounds); + let old_bounds = mem::replace(&mut *cx.impl_trait_bounds.borrow_mut(), Default::default()); let r = f(); assert!(cx.impl_trait_bounds.borrow().is_empty()); *cx.impl_trait_bounds.borrow_mut() = old_bounds; diff --git a/src/test/rustdoc/universal-impl-trait.rs b/src/test/rustdoc/universal-impl-trait.rs index 4cf99562c52..af51ff3d941 100644 --- a/src/test/rustdoc/universal-impl-trait.rs +++ b/src/test/rustdoc/universal-impl-trait.rs @@ -11,6 +11,8 @@ #![feature(universal_impl_trait)] #![crate_name = "foo"] +use std::io::Read; + // @has foo/fn.foo.html // @has - //pre 'foo(' // @matches - '_x: impl S { // @matches - '_baz:.+struct\.S\.html.+impl .+trait\.Clone\.html' pub fn baz(_baz: S) { } + + // @has - 'qux(' + // @matches - 'trait\.Read\.html' + pub fn qux(_qux: impl IntoIterator>) { + } } // @has - 'method(' -- cgit 1.4.1-3-g733a5 From 70c52e5e19b277adf8eb3212f620e93699c24ed4 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 3 May 2018 14:17:58 +0300 Subject: Update Cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/tools/cargo b/src/tools/cargo index 122fd5be520..66b0ffa81c5 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 122fd5be5201913d42e219e132d6569493583bca +Subproject commit 66b0ffa81c560be1b79511b51f49cbb23bc78651 -- cgit 1.4.1-3-g733a5 From 83c45051f83e7dac6f5cb2d53f00f42b574d8165 Mon Sep 17 00:00:00 2001 From: kennytm Date: Thu, 3 May 2018 22:36:44 +0800 Subject: Fix issue #50415. --- src/librustc/hir/lowering.rs | 4 ++-- src/test/run-pass/issue-50415.rs | 27 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 src/test/run-pass/issue-50415.rs (limited to 'src') diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 196f7879980..51f0c1d7047 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -3121,9 +3121,9 @@ impl<'a> LoweringContext<'a> { } // Desugar `..=` to `std::ops::RangeInclusive::new(, )` ExprKind::Range(Some(ref e1), Some(ref e2), RangeLimits::Closed) => { - // FIXME: Use head_sp directly after RangeInclusive::new() is stabilized in stage0. + // FIXME: Use e.span directly after RangeInclusive::new() is stabilized in stage0. let span = self.allow_internal_unstable(CompilerDesugaringKind::DotFill, e.span); - let id = self.lower_node_id(e.id); + let id = self.next_id(); let e1 = self.lower_expr(e1); let e2 = self.lower_expr(e2); let ty_path = P(self.std_path(span, &["ops", "RangeInclusive"], false)); diff --git a/src/test/run-pass/issue-50415.rs b/src/test/run-pass/issue-50415.rs new file mode 100644 index 00000000000..aa493ce0321 --- /dev/null +++ b/src/test/run-pass/issue-50415.rs @@ -0,0 +1,27 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + // -------- Simplified test case -------- + + let _ = || 0..=1; + + // -------- Original test case -------- + + let full_length = 1024; + let range = { + // do some stuff, omit here + None + }; + + let range = range.map(|(s, t)| s..=t).unwrap_or(0..=(full_length-1)); + + assert_eq!(range, 0..=1023); +} -- cgit 1.4.1-3-g733a5 From b71f6364d22e1e9cea597003e4c563c32e5f651c Mon Sep 17 00:00:00 2001 From: Harm Berntsen Date: Thu, 3 May 2018 14:35:59 +0200 Subject: Add armv5te-unknown-linux-musl target --- src/bootstrap/configure.py | 2 + src/ci/docker/dist-armv5te-linux-musl/Dockerfile | 47 ++++++++++++++++++++++ .../spec/armv5te_unknown_linux_musl.rs | 38 +++++++++++++++++ src/librustc_target/spec/mod.rs | 1 + src/tools/build-manifest/src/main.rs | 1 + 5 files changed, 89 insertions(+) create mode 100644 src/ci/docker/dist-armv5te-linux-musl/Dockerfile create mode 100644 src/librustc_target/spec/armv5te_unknown_linux_musl.rs (limited to 'src') diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index a0123da6d8f..54b6526c5c8 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -120,6 +120,8 @@ v("musl-root-arm", "target.arm-unknown-linux-musleabi.musl-root", "arm-unknown-linux-musleabi install directory") v("musl-root-armhf", "target.arm-unknown-linux-musleabihf.musl-root", "arm-unknown-linux-musleabihf install directory") +v("musl-root-armv5te", "target.armv5te-unknown-linux-musl.musl-root", + "armv5te-unknown-linux-musleabi install directory") v("musl-root-armv7", "target.armv7-unknown-linux-musleabihf.musl-root", "armv7-unknown-linux-musleabihf install directory") v("musl-root-aarch64", "target.aarch64-unknown-linux-musl.musl-root", diff --git a/src/ci/docker/dist-armv5te-linux-musl/Dockerfile b/src/ci/docker/dist-armv5te-linux-musl/Dockerfile new file mode 100644 index 00000000000..42eaebcc3db --- /dev/null +++ b/src/ci/docker/dist-armv5te-linux-musl/Dockerfile @@ -0,0 +1,47 @@ +FROM ubuntu:16.04 + +RUN apt-get update && apt-get install -y --no-install-recommends \ + g++ \ + make \ + file \ + curl \ + ca-certificates \ + python2.7 \ + git \ + cmake \ + sudo \ + xz-utils \ + zlib1g-dev \ + g++-arm-linux-gnueabi \ + bzip2 \ + patch \ + pkg-config + +WORKDIR /build + +# Suppress some warnings in the openwrt toolchains we downloaded +ENV STAGING_DIR=/tmp + +COPY scripts/musl.sh /build +RUN env \ + CC=arm-linux-gnueabi-gcc CFLAGS="-march=armv5te -marm -mfloat-abi=soft" \ + CXX=arm-linux-gnueabi-g++ CXXFLAGS="-march=armv5te -marm -mfloat-abi=soft" \ + bash musl.sh armv5te && \ + rm -rf /build/* + +ENV TARGETS=armv5te-unknown-linux-musl + +# FIXME: remove armv5te vars after https://github.com/alexcrichton/cc-rs/issues/271 +# get fixed and cc update +ENV CC_armv5te_unknown_linux_musl=arm-linux-gnueabi-gcc \ + CFLAGS_armv5te_unknown_linux_musl="-march=armv5te -marm -mfloat-abi=soft" + +ENV RUST_CONFIGURE_ARGS \ + --musl-root-armv5te=/musl-armv5te \ + --disable-docs + +ENV SCRIPT python2.7 ../x.py dist --target $TARGETS + +# sccache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh diff --git a/src/librustc_target/spec/armv5te_unknown_linux_musl.rs b/src/librustc_target/spec/armv5te_unknown_linux_musl.rs new file mode 100644 index 00000000000..2d4e95ab01d --- /dev/null +++ b/src/librustc_target/spec/armv5te_unknown_linux_musl.rs @@ -0,0 +1,38 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; + +pub fn target() -> TargetResult { + let base = super::linux_musl_base::opts(); + Ok(Target { + // It's important we use "gnueabihf" and not "musleabihf" here. LLVM + // uses it to determine the calling convention and float ABI, and LLVM + // doesn't support the "musleabihf" value. + llvm_target: "armv5te-unknown-linux-gnueabi".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "32".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), + arch: "arm".to_string(), + target_os: "linux".to_string(), + target_env: "musl".to_string(), + target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, + + options: TargetOptions { + features: "+soft-float,+strict-align".to_string(), + // Atomic operations provided by compiler-builtins + max_atomic_width: Some(32), + abi_blacklist: super::arm_base::abi_blacklist(), + .. base + } + }) +} diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 1e94f037885..e4071b316c1 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -283,6 +283,7 @@ supported_targets! { ("arm-unknown-linux-musleabihf", arm_unknown_linux_musleabihf), ("armv4t-unknown-linux-gnueabi", armv4t_unknown_linux_gnueabi), ("armv5te-unknown-linux-gnueabi", armv5te_unknown_linux_gnueabi), + ("armv5te-unknown-linux-musl", armv5te_unknown_linux_musl), ("armv7-unknown-linux-gnueabihf", armv7_unknown_linux_gnueabihf), ("armv7-unknown-linux-musleabihf", armv7_unknown_linux_musleabihf), ("aarch64-unknown-linux-gnu", aarch64_unknown_linux_gnu), diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 9f238929215..ba5bb45d767 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -57,6 +57,7 @@ static TARGETS: &'static [&'static str] = &[ "arm-unknown-linux-musleabi", "arm-unknown-linux-musleabihf", "armv5te-unknown-linux-gnueabi", + "armv5te-unknown-linux-musl", "armv7-apple-ios", "armv7-linux-androideabi", "armv7-unknown-cloudabi-eabihf", -- cgit 1.4.1-3-g733a5 From a876d28b4ae546b6acc0da85862aef8afb6ea389 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 29 Apr 2018 21:32:53 +0200 Subject: Fix invalid path generation in rustdoc search --- src/librustdoc/html/render.rs | 2 +- src/test/rustdoc-js/alias-2.js | 6 ++++-- src/test/rustdoc-js/alias.js | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 4e9781cc560..29e7bd37fc2 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1427,7 +1427,7 @@ impl<'a> Cache { } if let Some(ref item_name) = item.name { let path = self.paths.get(&item.def_id) - .map(|p| p.0.join("::").to_string()) + .map(|p| p.0[..p.0.len() - 1].join("::")) .unwrap_or("std".to_owned()); for alias in item.attrs.lists("doc") .filter(|a| a.check_name("alias")) diff --git a/src/test/rustdoc-js/alias-2.js b/src/test/rustdoc-js/alias-2.js index f31786df67c..0c5ec4fccbc 100644 --- a/src/test/rustdoc-js/alias-2.js +++ b/src/test/rustdoc-js/alias-2.js @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-order + const QUERY = '+'; const EXPECTED = { 'others': [ - { 'path': 'std::ops::AddAssign', 'name': 'AddAssign' }, - { 'path': 'std::ops::Add', 'name': 'Add' }, + { 'path': 'std::ops', 'name': 'AddAssign' }, + { 'path': 'std::ops', 'name': 'Add' }, ], }; diff --git a/src/test/rustdoc-js/alias.js b/src/test/rustdoc-js/alias.js index a0500f24c17..0ca5991c06c 100644 --- a/src/test/rustdoc-js/alias.js +++ b/src/test/rustdoc-js/alias.js @@ -13,7 +13,7 @@ const QUERY = '['; const EXPECTED = { 'others': [ { 'path': 'std', 'name': 'slice' }, - { 'path': 'std::ops::IndexMut', 'name': 'IndexMut' }, - { 'path': 'std::ops::Index', 'name': 'Index' }, + { 'path': 'std::ops', 'name': 'IndexMut' }, + { 'path': 'std::ops', 'name': 'Index' }, ], }; -- cgit 1.4.1-3-g733a5 From b53993684549a76a4223bed15e4f04754e20c242 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 3 May 2018 16:24:21 -0700 Subject: Remove the deprecated std::net::{lookup_host,LookupHost} These are unstable, and were deprecated by #47510, since Rust 1.25. The internal `sys` implementations are still kept to support the call in the common `resolve_socket_addr`. --- src/libstd/net/addr.rs | 4 +-- src/libstd/net/mod.rs | 65 ----------------------------------- src/test/run-pass/sync-send-in-std.rs | 6 ++-- 3 files changed, 3 insertions(+), 72 deletions(-) (limited to 'src') diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs index bc2c9f522d3..e80c3eeb876 100644 --- a/src/libstd/net/addr.rs +++ b/src/libstd/net/addr.rs @@ -13,11 +13,10 @@ use hash; use io; use mem; use net::{ntoh, hton, IpAddr, Ipv4Addr, Ipv6Addr}; -#[allow(deprecated)] -use net::lookup_host; use option; use sys::net::netc as c; use sys_common::{FromInner, AsInner, IntoInner}; +use sys_common::net::lookup_host; use vec; use iter; use slice; @@ -856,7 +855,6 @@ impl ToSocketAddrs for (Ipv6Addr, u16) { } } -#[allow(deprecated)] fn resolve_socket_addr(s: &str, p: u16) -> io::Result> { let ips = lookup_host(s)?; let v: Vec<_> = ips.map(|mut a| { a.set_port(p); a }).collect(); diff --git a/src/libstd/net/mod.rs b/src/libstd/net/mod.rs index b0d5e563cb9..be4bcee8a68 100644 --- a/src/libstd/net/mod.rs +++ b/src/libstd/net/mod.rs @@ -38,9 +38,7 @@ #![stable(feature = "rust1", since = "1.0.0")] -use fmt; use io::{self, Error, ErrorKind}; -use sys_common::net as net_imp; #[stable(feature = "rust1", since = "1.0.0")] pub use self::ip::{IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope}; @@ -128,66 +126,3 @@ fn each_addr(addr: A, mut f: F) -> io::Result "could not resolve to any addresses") })) } - -/// An iterator over `SocketAddr` values returned from a host lookup operation. -#[unstable(feature = "lookup_host", reason = "unsure about the returned \ - iterator and returning socket \ - addresses", - issue = "27705")] -#[rustc_deprecated(since = "1.25.0", reason = "Use the ToSocketAddrs trait instead")] -pub struct LookupHost(net_imp::LookupHost); - -#[unstable(feature = "lookup_host", reason = "unsure about the returned \ - iterator and returning socket \ - addresses", - issue = "27705")] -#[rustc_deprecated(since = "1.25.0", reason = "Use the ToSocketAddrs trait instead")] -#[allow(deprecated)] -impl Iterator for LookupHost { - type Item = SocketAddr; - fn next(&mut self) -> Option { self.0.next() } -} - -#[unstable(feature = "lookup_host", reason = "unsure about the returned \ - iterator and returning socket \ - addresses", - issue = "27705")] -#[rustc_deprecated(since = "1.25.0", reason = "Use the ToSocketAddrs trait instead")] -#[allow(deprecated)] -impl fmt::Debug for LookupHost { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad("LookupHost { .. }") - } -} - -/// Resolve the host specified by `host` as a number of `SocketAddr` instances. -/// -/// This method may perform a DNS query to resolve `host` and may also inspect -/// system configuration to resolve the specified hostname. -/// -/// The returned iterator will skip over any unknown addresses returned by the -/// operating system. -/// -/// # Examples -/// -/// ```no_run -/// #![feature(lookup_host)] -/// -/// use std::net; -/// -/// fn main() -> std::io::Result<()> { -/// for host in net::lookup_host("rust-lang.org")? { -/// println!("found address: {}", host); -/// } -/// Ok(()) -/// } -/// ``` -#[unstable(feature = "lookup_host", reason = "unsure about the returned \ - iterator and returning socket \ - addresses", - issue = "27705")] -#[rustc_deprecated(since = "1.25.0", reason = "Use the ToSocketAddrs trait instead")] -#[allow(deprecated)] -pub fn lookup_host(host: &str) -> io::Result { - net_imp::lookup_host(host).map(LookupHost) -} diff --git a/src/test/run-pass/sync-send-in-std.rs b/src/test/run-pass/sync-send-in-std.rs index f03387957bc..335a9c0d8be 100644 --- a/src/test/run-pass/sync-send-in-std.rs +++ b/src/test/run-pass/sync-send-in-std.rs @@ -11,9 +11,7 @@ // ignore-cloudabi networking not available // ignore-wasm32-bare networking not available -#![feature(lookup_host)] - -use std::net::lookup_host; +use std::net::ToSocketAddrs; fn is_sync(_: T) where T: Sync {} fn is_send(_: T) where T: Send {} @@ -30,5 +28,5 @@ macro_rules! all_sync_send { } fn main() { - all_sync_send!(lookup_host("localhost").unwrap(), next); + all_sync_send!("localhost:80".to_socket_addrs().unwrap(), next); } -- cgit 1.4.1-3-g733a5 From 4952426c50cf4379afa3d1eb3647f30afeb5d690 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Fri, 4 May 2018 07:53:33 +1200 Subject: Update RLS and Rustfmt (and Cargo) --- src/Cargo.lock | 7 ++++--- src/tools/cargo | 2 +- src/tools/rls | 2 +- src/tools/rustfmt | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/Cargo.lock b/src/Cargo.lock index f482bed3176..ccdb24d7375 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -996,9 +996,10 @@ dependencies = [ [[package]] name = "languageserver-types" -version = "0.36.0" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1632,7 +1633,7 @@ dependencies = [ "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "json 0.11.13 (registry+https://github.com/rust-lang/crates.io-index)", "jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "languageserver-types 0.36.0 (registry+https://github.com/rust-lang/crates.io-index)", + "languageserver-types 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3065,7 +3066,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum json 0.11.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9ad0485404155f45cce53a40d4b2d6ac356418300daed05273d9e26f91c390be" "checksum jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ddf83704f4e79979a424d1082dd2c1e52683058056c9280efa19ac5f6bc9033c" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum languageserver-types 0.36.0 (registry+https://github.com/rust-lang/crates.io-index)" = "174cdfb8bed13225bb419bec66ee1c970099c875688645f9c4a82e3af43ba69d" +"checksum languageserver-types 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad4cdd5e52d71aca47050e5b25f03082609c63a1e76b7362ebdd010895b3f854" "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" "checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" "checksum lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a6f08839bc70ef4a3fe1d566d5350f519c5912ea86be0df1740a7d247c7fc0ef" diff --git a/src/tools/cargo b/src/tools/cargo index 66b0ffa81c5..af3f1cd29bc 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 66b0ffa81c560be1b79511b51f49cbb23bc78651 +Subproject commit af3f1cd29bc872b932a13083e531255aab233a7e diff --git a/src/tools/rls b/src/tools/rls index 99796f6a659..d2f44357fef 160000 --- a/src/tools/rls +++ b/src/tools/rls @@ -1 +1 @@ -Subproject commit 99796f6a6592b4d897719a1736ec580c96f5441a +Subproject commit d2f44357fef6d61f316abc403e0a5d917f2771c6 diff --git a/src/tools/rustfmt b/src/tools/rustfmt index d8982e5efe8..b6cd17f28ae 160000 --- a/src/tools/rustfmt +++ b/src/tools/rustfmt @@ -1 +1 @@ -Subproject commit d8982e5efe8fda1d6f64e88a67da2f05b6af225e +Subproject commit b6cd17f28ae314f2484ff05d3ce57652d51c5e85 -- cgit 1.4.1-3-g733a5 From 58eeeb42089a98925b04d9ceb7dbf2c93cc29d45 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Fri, 4 May 2018 06:30:17 +0200 Subject: Check that rustc can be built successfully with parallel queries for PRs. --- src/ci/docker/mingw-check/Dockerfile | 1 + src/ci/docker/x86_64-gnu-debug/Dockerfile | 2 +- src/ci/run.sh | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/ci/docker/mingw-check/Dockerfile b/src/ci/docker/mingw-check/Dockerfile index ae4641009cf..aab339f399c 100644 --- a/src/ci/docker/mingw-check/Dockerfile +++ b/src/ci/docker/mingw-check/Dockerfile @@ -19,4 +19,5 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh +ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1 ENV SCRIPT python2.7 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu diff --git a/src/ci/docker/x86_64-gnu-debug/Dockerfile b/src/ci/docker/x86_64-gnu-debug/Dockerfile index ff6ab1013b4..bdde7ad7fe8 100644 --- a/src/ci/docker/x86_64-gnu-debug/Dockerfile +++ b/src/ci/docker/x86_64-gnu-debug/Dockerfile @@ -16,7 +16,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -ENV PARALLEL_CHECK 1 +ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1 ENV RUST_CONFIGURE_ARGS \ --build=x86_64-unknown-linux-gnu \ --enable-debug \ diff --git a/src/ci/run.sh b/src/ci/run.sh index 119b239d6b2..456f8cc7317 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -78,9 +78,9 @@ fi # sccache server at the start of the build, but no need to worry if this fails. SCCACHE_IDLE_TIMEOUT=10800 sccache --start-server || true -if [ "$PARALLEL_CHECK" != "" ]; then +if [ "$RUN_CHECK_WITH_PARALLEL_QUERIES" != "" ]; then $SRC/configure --enable-experimental-parallel-queries - python2.7 ../x.py check + CARGO_INCREMENTAL=0 python2.7 ../x.py check rm -f config.toml rm -rf build fi -- cgit 1.4.1-3-g733a5 From 80f1912d83c977ac12946f1a12d2523383a0d3b7 Mon Sep 17 00:00:00 2001 From: Harm Berntsen Date: Fri, 4 May 2018 08:47:24 +0200 Subject: Add eabi suffix to armv5te musl target --- src/bootstrap/configure.py | 2 +- src/ci/docker/dist-armv5te-linux-musl/Dockerfile | 47 ---------------------- .../docker/dist-armv5te-linux-musleabi/Dockerfile | 47 ++++++++++++++++++++++ .../spec/armv5te_unknown_linux_musl.rs | 38 ----------------- .../spec/armv5te_unknown_linux_musleabi.rs | 38 +++++++++++++++++ src/librustc_target/spec/mod.rs | 2 +- src/tools/build-manifest/src/main.rs | 2 +- 7 files changed, 88 insertions(+), 88 deletions(-) delete mode 100644 src/ci/docker/dist-armv5te-linux-musl/Dockerfile create mode 100644 src/ci/docker/dist-armv5te-linux-musleabi/Dockerfile delete mode 100644 src/librustc_target/spec/armv5te_unknown_linux_musl.rs create mode 100644 src/librustc_target/spec/armv5te_unknown_linux_musleabi.rs (limited to 'src') diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 54b6526c5c8..3574b7d210a 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -120,7 +120,7 @@ v("musl-root-arm", "target.arm-unknown-linux-musleabi.musl-root", "arm-unknown-linux-musleabi install directory") v("musl-root-armhf", "target.arm-unknown-linux-musleabihf.musl-root", "arm-unknown-linux-musleabihf install directory") -v("musl-root-armv5te", "target.armv5te-unknown-linux-musl.musl-root", +v("musl-root-armv5te", "target.armv5te-unknown-linux-musleabi.musl-root", "armv5te-unknown-linux-musleabi install directory") v("musl-root-armv7", "target.armv7-unknown-linux-musleabihf.musl-root", "armv7-unknown-linux-musleabihf install directory") diff --git a/src/ci/docker/dist-armv5te-linux-musl/Dockerfile b/src/ci/docker/dist-armv5te-linux-musl/Dockerfile deleted file mode 100644 index 42eaebcc3db..00000000000 --- a/src/ci/docker/dist-armv5te-linux-musl/Dockerfile +++ /dev/null @@ -1,47 +0,0 @@ -FROM ubuntu:16.04 - -RUN apt-get update && apt-get install -y --no-install-recommends \ - g++ \ - make \ - file \ - curl \ - ca-certificates \ - python2.7 \ - git \ - cmake \ - sudo \ - xz-utils \ - zlib1g-dev \ - g++-arm-linux-gnueabi \ - bzip2 \ - patch \ - pkg-config - -WORKDIR /build - -# Suppress some warnings in the openwrt toolchains we downloaded -ENV STAGING_DIR=/tmp - -COPY scripts/musl.sh /build -RUN env \ - CC=arm-linux-gnueabi-gcc CFLAGS="-march=armv5te -marm -mfloat-abi=soft" \ - CXX=arm-linux-gnueabi-g++ CXXFLAGS="-march=armv5te -marm -mfloat-abi=soft" \ - bash musl.sh armv5te && \ - rm -rf /build/* - -ENV TARGETS=armv5te-unknown-linux-musl - -# FIXME: remove armv5te vars after https://github.com/alexcrichton/cc-rs/issues/271 -# get fixed and cc update -ENV CC_armv5te_unknown_linux_musl=arm-linux-gnueabi-gcc \ - CFLAGS_armv5te_unknown_linux_musl="-march=armv5te -marm -mfloat-abi=soft" - -ENV RUST_CONFIGURE_ARGS \ - --musl-root-armv5te=/musl-armv5te \ - --disable-docs - -ENV SCRIPT python2.7 ../x.py dist --target $TARGETS - -# sccache -COPY scripts/sccache.sh /scripts/ -RUN sh /scripts/sccache.sh diff --git a/src/ci/docker/dist-armv5te-linux-musleabi/Dockerfile b/src/ci/docker/dist-armv5te-linux-musleabi/Dockerfile new file mode 100644 index 00000000000..af2e410a379 --- /dev/null +++ b/src/ci/docker/dist-armv5te-linux-musleabi/Dockerfile @@ -0,0 +1,47 @@ +FROM ubuntu:16.04 + +RUN apt-get update && apt-get install -y --no-install-recommends \ + g++ \ + make \ + file \ + curl \ + ca-certificates \ + python2.7 \ + git \ + cmake \ + sudo \ + xz-utils \ + zlib1g-dev \ + g++-arm-linux-gnueabi \ + bzip2 \ + patch \ + pkg-config + +WORKDIR /build + +# Suppress some warnings in the openwrt toolchains we downloaded +ENV STAGING_DIR=/tmp + +COPY scripts/musl.sh /build +RUN env \ + CC=arm-linux-gnueabi-gcc CFLAGS="-march=armv5te -marm -mfloat-abi=soft" \ + CXX=arm-linux-gnueabi-g++ CXXFLAGS="-march=armv5te -marm -mfloat-abi=soft" \ + bash musl.sh armv5te && \ + rm -rf /build/* + +ENV TARGETS=armv5te-unknown-linux-musleabi + +# FIXME: remove armv5te vars after https://github.com/alexcrichton/cc-rs/issues/271 +# get fixed and cc update +ENV CC_armv5te_unknown_linux_musleabi=arm-linux-gnueabi-gcc \ + CFLAGS_armv5te_unknown_linux_musleabi="-march=armv5te -marm -mfloat-abi=soft" + +ENV RUST_CONFIGURE_ARGS \ + --musl-root-armv5te=/musl-armv5te \ + --disable-docs + +ENV SCRIPT python2.7 ../x.py dist --target $TARGETS + +# sccache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh diff --git a/src/librustc_target/spec/armv5te_unknown_linux_musl.rs b/src/librustc_target/spec/armv5te_unknown_linux_musl.rs deleted file mode 100644 index 2d4e95ab01d..00000000000 --- a/src/librustc_target/spec/armv5te_unknown_linux_musl.rs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2018 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -use spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; - -pub fn target() -> TargetResult { - let base = super::linux_musl_base::opts(); - Ok(Target { - // It's important we use "gnueabihf" and not "musleabihf" here. LLVM - // uses it to determine the calling convention and float ABI, and LLVM - // doesn't support the "musleabihf" value. - llvm_target: "armv5te-unknown-linux-gnueabi".to_string(), - target_endian: "little".to_string(), - target_pointer_width: "32".to_string(), - target_c_int_width: "32".to_string(), - data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), - arch: "arm".to_string(), - target_os: "linux".to_string(), - target_env: "musl".to_string(), - target_vendor: "unknown".to_string(), - linker_flavor: LinkerFlavor::Gcc, - - options: TargetOptions { - features: "+soft-float,+strict-align".to_string(), - // Atomic operations provided by compiler-builtins - max_atomic_width: Some(32), - abi_blacklist: super::arm_base::abi_blacklist(), - .. base - } - }) -} diff --git a/src/librustc_target/spec/armv5te_unknown_linux_musleabi.rs b/src/librustc_target/spec/armv5te_unknown_linux_musleabi.rs new file mode 100644 index 00000000000..2d4e95ab01d --- /dev/null +++ b/src/librustc_target/spec/armv5te_unknown_linux_musleabi.rs @@ -0,0 +1,38 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; + +pub fn target() -> TargetResult { + let base = super::linux_musl_base::opts(); + Ok(Target { + // It's important we use "gnueabihf" and not "musleabihf" here. LLVM + // uses it to determine the calling convention and float ABI, and LLVM + // doesn't support the "musleabihf" value. + llvm_target: "armv5te-unknown-linux-gnueabi".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "32".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64".to_string(), + arch: "arm".to_string(), + target_os: "linux".to_string(), + target_env: "musl".to_string(), + target_vendor: "unknown".to_string(), + linker_flavor: LinkerFlavor::Gcc, + + options: TargetOptions { + features: "+soft-float,+strict-align".to_string(), + // Atomic operations provided by compiler-builtins + max_atomic_width: Some(32), + abi_blacklist: super::arm_base::abi_blacklist(), + .. base + } + }) +} diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index e4071b316c1..48e771e0aaf 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -283,7 +283,7 @@ supported_targets! { ("arm-unknown-linux-musleabihf", arm_unknown_linux_musleabihf), ("armv4t-unknown-linux-gnueabi", armv4t_unknown_linux_gnueabi), ("armv5te-unknown-linux-gnueabi", armv5te_unknown_linux_gnueabi), - ("armv5te-unknown-linux-musl", armv5te_unknown_linux_musl), + ("armv5te-unknown-linux-musleabi", armv5te_unknown_linux_musleabi), ("armv7-unknown-linux-gnueabihf", armv7_unknown_linux_gnueabihf), ("armv7-unknown-linux-musleabihf", armv7_unknown_linux_musleabihf), ("aarch64-unknown-linux-gnu", aarch64_unknown_linux_gnu), diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index ba5bb45d767..6b548742fb3 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -57,7 +57,7 @@ static TARGETS: &'static [&'static str] = &[ "arm-unknown-linux-musleabi", "arm-unknown-linux-musleabihf", "armv5te-unknown-linux-gnueabi", - "armv5te-unknown-linux-musl", + "armv5te-unknown-linux-musleabi", "armv7-apple-ios", "armv7-linux-androideabi", "armv7-unknown-cloudabi-eabihf", -- cgit 1.4.1-3-g733a5 From 235af75d15860503f4f358ce2ad7b806d1b7f514 Mon Sep 17 00:00:00 2001 From: Harm Berntsen Date: Fri, 4 May 2018 08:53:27 +0200 Subject: Merge armv5te musl container with dist-various-1 --- .../docker/dist-armv5te-linux-musleabi/Dockerfile | 47 ---------------------- src/ci/docker/dist-various-1/Dockerfile | 10 ++++- 2 files changed, 9 insertions(+), 48 deletions(-) delete mode 100644 src/ci/docker/dist-armv5te-linux-musleabi/Dockerfile (limited to 'src') diff --git a/src/ci/docker/dist-armv5te-linux-musleabi/Dockerfile b/src/ci/docker/dist-armv5te-linux-musleabi/Dockerfile deleted file mode 100644 index af2e410a379..00000000000 --- a/src/ci/docker/dist-armv5te-linux-musleabi/Dockerfile +++ /dev/null @@ -1,47 +0,0 @@ -FROM ubuntu:16.04 - -RUN apt-get update && apt-get install -y --no-install-recommends \ - g++ \ - make \ - file \ - curl \ - ca-certificates \ - python2.7 \ - git \ - cmake \ - sudo \ - xz-utils \ - zlib1g-dev \ - g++-arm-linux-gnueabi \ - bzip2 \ - patch \ - pkg-config - -WORKDIR /build - -# Suppress some warnings in the openwrt toolchains we downloaded -ENV STAGING_DIR=/tmp - -COPY scripts/musl.sh /build -RUN env \ - CC=arm-linux-gnueabi-gcc CFLAGS="-march=armv5te -marm -mfloat-abi=soft" \ - CXX=arm-linux-gnueabi-g++ CXXFLAGS="-march=armv5te -marm -mfloat-abi=soft" \ - bash musl.sh armv5te && \ - rm -rf /build/* - -ENV TARGETS=armv5te-unknown-linux-musleabi - -# FIXME: remove armv5te vars after https://github.com/alexcrichton/cc-rs/issues/271 -# get fixed and cc update -ENV CC_armv5te_unknown_linux_musleabi=arm-linux-gnueabi-gcc \ - CFLAGS_armv5te_unknown_linux_musleabi="-march=armv5te -marm -mfloat-abi=soft" - -ENV RUST_CONFIGURE_ARGS \ - --musl-root-armv5te=/musl-armv5te \ - --disable-docs - -ENV SCRIPT python2.7 ../x.py dist --target $TARGETS - -# sccache -COPY scripts/sccache.sh /scripts/ -RUN sh /scripts/sccache.sh diff --git a/src/ci/docker/dist-various-1/Dockerfile b/src/ci/docker/dist-various-1/Dockerfile index 00366301aa1..b195decfcf5 100644 --- a/src/ci/docker/dist-various-1/Dockerfile +++ b/src/ci/docker/dist-various-1/Dockerfile @@ -43,6 +43,10 @@ ENV STAGING_DIR=/tmp COPY scripts/musl.sh /build RUN env \ + CC=arm-linux-gnueabi-gcc CFLAGS="-march=armv5te -marm -mfloat-abi=soft" \ + CXX=arm-linux-gnueabi-g++ CXXFLAGS="-march=armv5te -marm -mfloat-abi=soft" \ + bash musl.sh armv5te && \ + env \ CC=arm-linux-gnueabi-gcc CFLAGS="-march=armv6 -marm" \ CXX=arm-linux-gnueabi-g++ CXXFLAGS="-march=armv6 -marm" \ bash musl.sh arm && \ @@ -84,6 +88,7 @@ ENV TARGETS=$TARGETS,mipsel-unknown-linux-musl ENV TARGETS=$TARGETS,arm-unknown-linux-musleabi ENV TARGETS=$TARGETS,arm-unknown-linux-musleabihf ENV TARGETS=$TARGETS,armv5te-unknown-linux-gnueabi +ENV TARGETS=$TARGETS,armv5te-unknown-linux-musleabi ENV TARGETS=$TARGETS,armv7-unknown-linux-musleabihf ENV TARGETS=$TARGETS,aarch64-unknown-linux-musl ENV TARGETS=$TARGETS,sparc64-unknown-linux-gnu @@ -100,9 +105,12 @@ ENV CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \ CC_sparc64_unknown_linux_gnu=sparc64-linux-gnu-gcc \ CC_x86_64_unknown_redox=x86_64-unknown-redox-gcc \ CC_armv5te_unknown_linux_gnueabi=arm-linux-gnueabi-gcc \ - CFLAGS_armv5te_unknown_linux_gnueabi="-march=armv5te -marm -mfloat-abi=soft" + CFLAGS_armv5te_unknown_linux_gnueabi="-march=armv5te -marm -mfloat-abi=soft" \ + CC_armv5te_unknown_linux_musleabi=arm-linux-gnueabi-gcc \ + CFLAGS_armv5te_unknown_linux_musleabi="-march=armv5te -marm -mfloat-abi=soft" ENV RUST_CONFIGURE_ARGS \ + --musl-root-armv5te=/musl-armv5te \ --musl-root-arm=/musl-arm \ --musl-root-armhf=/musl-armhf \ --musl-root-armv7=/musl-armv7 \ -- cgit 1.4.1-3-g733a5 From 930e76e2af5c1ba9f91240da5de20049b52e739c Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Fri, 4 May 2018 13:17:13 +0200 Subject: Update mir-opt test to reflect change to MIR code-generation. --- src/test/mir-opt/match_false_edges.rs | 114 ++++++++++++++++++---------------- 1 file changed, 61 insertions(+), 53 deletions(-) (limited to 'src') diff --git a/src/test/mir-opt/match_false_edges.rs b/src/test/mir-opt/match_false_edges.rs index 53f17861997..a31298a0f51 100644 --- a/src/test/mir-opt/match_false_edges.rs +++ b/src/test/mir-opt/match_false_edges.rs @@ -54,17 +54,17 @@ fn main() { // ... // _2 = std::option::Option::Some(const 42i32,); // _3 = discriminant(_2); -// _6 = discriminant(_2); -// switchInt(move _6) -> [0isize: bb6, 1isize: bb4, otherwise: bb8]; +// _7 = discriminant(_2); +// switchInt(move _7) -> [0isize: bb6, 1isize: bb4, otherwise: bb8]; // } // bb1: { // resume; // } // bb2: { // arm1 -// StorageLive(_8); -// _8 = _4; -// _1 = (const 1i32, move _8); -// StorageDead(_8); +// StorageLive(_9); +// _9 = _4; +// _1 = (const 1i32, move _9); +// StorageDead(_9); // goto -> bb13; // } // bb3: { // binding3(empty) and arm3 @@ -87,24 +87,26 @@ fn main() { // unreachable; // } // bb9: { // binding1 and guard -// StorageLive(_4); -// _4 = ((_2 as Some).0: i32); -// StorageLive(_7); -// _7 = const guard() -> [return: bb10, unwind: bb1]; +// StorageLive(_5); +// _5 = &((_2 as Some).0: i32); +// StorageLive(_8); +// _8 = const guard() -> [return: bb10, unwind: bb1]; // } // bb10: { // end of guard -// switchInt(move _7) -> [false: bb11, otherwise: bb2]; +// StorageLive(_4); +// _4 = ((_2 as Some).0: i32); +// switchInt(move _8) -> [false: bb11, otherwise: bb2]; // } // bb11: { // to pre_binding2 // falseEdges -> [real: bb5, imaginary: bb5]; // } // bb12: { // bindingNoLandingPads.before.mir2 and arm2 -// StorageLive(_5); -// _5 = ((_2 as Some).0: i32); -// StorageLive(_9); -// _9 = _5; -// _1 = (const 2i32, move _9); -// StorageDead(_9); +// StorageLive(_6); +// _6 = ((_2 as Some).0: i32); +// StorageLive(_10); +// _10 = _6; +// _1 = (const 2i32, move _10); +// StorageDead(_10); // goto -> bb13; // } // bb13: { @@ -118,17 +120,17 @@ fn main() { // ... // _2 = std::option::Option::Some(const 42i32,); // _3 = discriminant(_2); -// _6 = discriminant(_2); -// switchInt(move _6) -> [0isize: bb5, 1isize: bb4, otherwise: bb8]; +// _7 = discriminant(_2); +// switchInt(move _7) -> [0isize: bb5, 1isize: bb4, otherwise: bb8]; // } // bb1: { // resume; // } // bb2: { // arm1 -// StorageLive(_8); -// _8 = _4; -// _1 = (const 1i32, move _8); -// StorageDead(_8); +// StorageLive(_9); +// _9 = _4; +// _1 = (const 1i32, move _9); +// StorageDead(_9); // goto -> bb13; // } // bb3: { // binding3(empty) and arm3 @@ -151,24 +153,26 @@ fn main() { // unreachable; // } // bb9: { // binding1 and guard -// StorageLive(_4); -// _4 = ((_2 as Some).0: i32); -// StorageLive(_7); -// _7 = const guard() -> [return: bb10, unwind: bb1]; +// StorageLive(_5); +// _5 = &((_2 as Some).0: i32); +// StorageLive(_8); +// _8 = const guard() -> [return: bb10, unwind: bb1]; // } // bb10: { // end of guard -// switchInt(move _7) -> [false: bb11, otherwise: bb2]; +// StorageLive(_4); +// _4 = ((_2 as Some).0: i32); +// switchInt(move _8) -> [false: bb11, otherwise: bb2]; // } // bb11: { // to pre_binding2 // falseEdges -> [real: bb6, imaginary: bb5]; // } // bb12: { // binding2 and arm2 -// StorageLive(_5); -// _5 = ((_2 as Some).0: i32); -// StorageLive(_9); -// _9 = _5; -// _1 = (const 2i32, move _9); -// StorageDead(_9); +// StorageLive(_6); +// _6 = ((_2 as Some).0: i32); +// StorageLive(_10); +// _10 = _6; +// _1 = (const 2i32, move _10); +// StorageDead(_10); // goto -> bb13; // } // bb13: { @@ -182,8 +186,8 @@ fn main() { // ... // _2 = std::option::Option::Some(const 1i32,); // _3 = discriminant(_2); -// _8 = discriminant(_2); -// switchInt(move _8) -> [1isize: bb4, otherwise: bb5]; +// _10 = discriminant(_2); +// switchInt(move _10) -> [1isize: bb4, otherwise: bb5]; // } // bb1: { // resume; @@ -213,41 +217,45 @@ fn main() { // unreachable; // } // bb9: { // binding1: Some(w) if guard() -// StorageLive(_4); -// _4 = ((_2 as Some).0: i32); -// StorageLive(_9); -// _9 = const guard() -> [return: bb10, unwind: bb1]; +// StorageLive(_5); +// _5 = &((_2 as Some).0: i32); +// StorageLive(_11); +// _11 = const guard() -> [return: bb10, unwind: bb1]; // } // bb10: { //end of guard -// switchInt(move _9) -> [false: bb11, otherwise: bb2]; +// StorageLive(_4); +// _4 = ((_2 as Some).0: i32); +// switchInt(move _11) -> [false: bb11, otherwise: bb2]; // } // bb11: { // to pre_binding2 // falseEdges -> [real: bb5, imaginary: bb5]; // } // bb12: { // binding2 & arm2 -// StorageLive(_5); -// _5 = _2; +// StorageLive(_6); +// _6 = _2; // _1 = const 2i32; // goto -> bb17; // } // bb13: { // binding3: Some(y) if guard2(y) -// StorageLive(_6); -// _6 = ((_2 as Some).0: i32); -// StorageLive(_11); -// StorageLive(_12); -// _12 = _6; -// _11 = const guard2(move _12) -> [return: bb14, unwind: bb1]; +// StorageLive(_8); +// _8 = &((_2 as Some).0: i32); +// StorageLive(_13); +// StorageLive(_14); +// _14 = (*_8); +// _13 = const guard2(move _14) -> [return: bb14, unwind: bb1]; // } // bb14: { // end of guard2 -// StorageDead(_12); -// switchInt(move _11) -> [false: bb15, otherwise: bb3]; +// StorageDead(_14); +// StorageLive(_7); +// _7 = ((_2 as Some).0: i32); +// switchInt(move _13) -> [false: bb15, otherwise: bb3]; // } // bb15: { // to pre_binding4 // falseEdges -> [real: bb7, imaginary: bb7]; // } // bb16: { // binding4 & arm4 -// StorageLive(_7); -// _7 = _2; +// StorageLive(_9); +// _9 = _2; // _1 = const 4i32; // goto -> bb17; // } -- cgit 1.4.1-3-g733a5 From 3e0ed2fc05780f2d2a0709fb2716631c9eaa47df Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 4 May 2018 14:11:22 -0700 Subject: proc_macro: Explicitly make everything !Send/Sync This commit adds explicit imp blocks to ensure that all publicly exported types (except simple enums) are not `Send` nor `Sync` in the `proc_macro` crate. cc #38356 --- src/libproc_macro/lib.rs | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index f51dbc3772f..8451e5987e9 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -74,6 +74,11 @@ use syntax_pos::hygiene::Mark; #[derive(Clone)] pub struct TokenStream(tokenstream::TokenStream); +#[unstable(feature = "proc_macro", issue = "38356")] +impl !Send for TokenStream {} +#[unstable(feature = "proc_macro", issue = "38356")] +impl !Sync for TokenStream {} + /// Error returned from `TokenStream::from_str`. #[stable(feature = "proc_macro_lib", since = "1.15.0")] #[derive(Debug)] @@ -81,6 +86,11 @@ pub struct LexError { _inner: (), } +#[unstable(feature = "proc_macro", issue = "38356")] +impl !Send for LexError {} +#[unstable(feature = "proc_macro", issue = "38356")] +impl !Sync for LexError {} + impl TokenStream { /// Returns an empty `TokenStream`. #[unstable(feature = "proc_macro", issue = "38356")] @@ -231,6 +241,11 @@ pub fn quote_span(span: Span) -> TokenStream { #[derive(Copy, Clone)] pub struct Span(syntax_pos::Span); +#[unstable(feature = "proc_macro", issue = "38356")] +impl !Send for Span {} +#[unstable(feature = "proc_macro", issue = "38356")] +impl !Sync for Span {} + macro_rules! diagnostic_method { ($name:ident, $level:expr) => ( /// Create a new `Diagnostic` with the given `message` at the span @@ -363,6 +378,11 @@ pub struct LineColumn { pub column: usize } +#[unstable(feature = "proc_macro", issue = "38356")] +impl !Send for LineColumn {} +#[unstable(feature = "proc_macro", issue = "38356")] +impl !Sync for LineColumn {} + /// The source file of a given `Span`. #[unstable(feature = "proc_macro", issue = "38356")] #[derive(Clone)] @@ -393,7 +413,7 @@ impl SourceFile { /// Returns `true` if this source file is a real source file, and not generated by an external /// macro's expansion. - # [unstable(feature = "proc_macro", issue = "38356")] + #[unstable(feature = "proc_macro", issue = "38356")] pub fn is_real(&self) -> bool { // This is a hack until intercrate spans are implemented and we can have real source files // for spans generated in external macros. @@ -450,6 +470,11 @@ pub enum TokenTree { Literal(Literal), } +#[unstable(feature = "proc_macro", issue = "38356")] +impl !Send for TokenTree {} +#[unstable(feature = "proc_macro", issue = "38356")] +impl !Sync for TokenTree {} + impl TokenTree { /// Returns the span of this token, accessing the `span` method of each of /// the internal tokens. @@ -546,6 +571,11 @@ pub struct Group { span: Span, } +#[unstable(feature = "proc_macro", issue = "38356")] +impl !Send for Group {} +#[unstable(feature = "proc_macro", issue = "38356")] +impl !Sync for Group {} + /// Describes how a sequence of token trees is delimited. #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[unstable(feature = "proc_macro", issue = "38356")] @@ -628,6 +658,11 @@ pub struct Op { span: Span, } +#[unstable(feature = "proc_macro", issue = "38356")] +impl !Send for Op {} +#[unstable(feature = "proc_macro", issue = "38356")] +impl !Sync for Op {} + /// Whether an `Op` is either followed immediately by another `Op` or followed by whitespace. #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[unstable(feature = "proc_macro", issue = "38356")] @@ -694,6 +729,11 @@ pub struct Term { span: Span, } +#[unstable(feature = "proc_macro", issue = "38356")] +impl !Send for Term {} +#[unstable(feature = "proc_macro", issue = "38356")] +impl !Sync for Term {} + impl Term { /// Creates a new `Term` with the given `string` as well as the specified /// `span`. @@ -752,6 +792,11 @@ pub struct Literal { span: Span, } +#[unstable(feature = "proc_macro", issue = "38356")] +impl !Send for Literal {} +#[unstable(feature = "proc_macro", issue = "38356")] +impl !Sync for Literal {} + macro_rules! suffixed_int_literals { ($($name:ident => $kind:ident,)*) => ($( /// Creates a new suffixed integer literal with the specified value. -- cgit 1.4.1-3-g733a5 From fd6aa149bca7b896650c5f15a9c0000fc4f0056d Mon Sep 17 00:00:00 2001 From: Pascal Hertleif Date: Fri, 20 Apr 2018 00:04:08 +0200 Subject: First step towards rustfix compiletest mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is the first small step towards testing auto-fixable compiler suggestions using compiletest. Currently, it only checks if next to a UI test there also happens to a `*.rs.fixed` file, and then uses rustfix (added as external crate) on the original file, and asserts that it produces the fixed version. To show that this works, I've included one such test. I picked this test case at random (and because it was simple) -- It is not relevant to the 2018 edition. Indeed, in the near future, we want to be able to restrict rustfix to edition-lints, so this test cast might go away soon. In case you still think this is somewhat feature-complete, here's a quick list of things currently missing that I want to add before telling people they can use this: - [ ] Make this an actual compiletest mode, with `test [fix] …` output and everything - [ ] Assert that fixed files still compile - [ ] Assert that fixed files produce no (or a known set of) diagnostics output - [ ] Update `update-references.sh` to support rustfix - [ ] Use a published version of rustfix (i.e.: publish a new version rustfix that exposes a useful API for this) --- .../closure-immutable-outer-variable.rs.fixed | 20 +++++++ src/tools/compiletest/Cargo.toml | 1 + src/tools/compiletest/src/autofix.rs | 70 ++++++++++++++++++++++ src/tools/compiletest/src/common.rs | 3 +- src/tools/compiletest/src/main.rs | 2 + src/tools/compiletest/src/runtest.rs | 16 ++++- 6 files changed, 110 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/suggestions/closure-immutable-outer-variable.rs.fixed create mode 100644 src/tools/compiletest/src/autofix.rs (limited to 'src') diff --git a/src/test/ui/suggestions/closure-immutable-outer-variable.rs.fixed b/src/test/ui/suggestions/closure-immutable-outer-variable.rs.fixed new file mode 100644 index 00000000000..80a5a45a305 --- /dev/null +++ b/src/test/ui/suggestions/closure-immutable-outer-variable.rs.fixed @@ -0,0 +1,20 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Point at the captured immutable outer variable + +fn foo(mut f: Box) { + f(); +} + +fn main() { + let mut y = true; + foo(Box::new(move || y = false) as Box<_>); //~ ERROR cannot assign to captured outer variable +} diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml index 7d02f0b746d..1710a44380f 100644 --- a/src/tools/compiletest/Cargo.toml +++ b/src/tools/compiletest/Cargo.toml @@ -13,6 +13,7 @@ regex = "0.2" serde = "1.0" serde_json = "1.0" serde_derive = "1.0" +rustfix = { git = "https://github.com/rust-lang-nursery/rustfix" } [target.'cfg(unix)'.dependencies] libc = "0.2" diff --git a/src/tools/compiletest/src/autofix.rs b/src/tools/compiletest/src/autofix.rs new file mode 100644 index 00000000000..29ea5cdff8f --- /dev/null +++ b/src/tools/compiletest/src/autofix.rs @@ -0,0 +1,70 @@ +use rustfix::{get_suggestions_from_json, Replacement}; +use std::collections::HashSet; +use std::error::Error; + +pub fn run_rustfix(code: &str, json: &str) -> String { + let suggestions = get_suggestions_from_json(&json, &HashSet::new()) + .expect("could not load suggestions"); + + let mut fixed = code.to_string(); + + for sug in suggestions.into_iter().rev() { + for sol in sug.solutions { + for r in sol.replacements { + fixed = apply_suggestion(&mut fixed, &r) + .expect("could not apply suggestion"); + } + } + } + + fixed +} + +fn apply_suggestion( + file_content: &mut String, + suggestion: &Replacement, +) -> Result> { + use std::cmp::max; + + let mut new_content = String::new(); + + // Add the lines before the section we want to replace + new_content.push_str(&file_content + .lines() + .take(max(suggestion.snippet.line_range.start.line - 1, 0) as usize) + .collect::>() + .join("\n")); + new_content.push_str("\n"); + + // Parts of line before replacement + new_content.push_str(&file_content + .lines() + .nth(suggestion.snippet.line_range.start.line - 1) + .unwrap_or("") + .chars() + .take(suggestion.snippet.line_range.start.column - 1) + .collect::()); + + // Insert new content! Finally! + new_content.push_str(&suggestion.replacement); + + // Parts of line after replacement + new_content.push_str(&file_content + .lines() + .nth(suggestion.snippet.line_range.end.line - 1) + .unwrap_or("") + .chars() + .skip(suggestion.snippet.line_range.end.column - 1) + .collect::()); + + // Add the lines after the section we want to replace + new_content.push_str("\n"); + new_content.push_str(&file_content + .lines() + .skip(suggestion.snippet.line_range.end.line as usize) + .collect::>() + .join("\n")); + new_content.push_str("\n"); + + Ok(new_content) +} diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 365b47447f2..5159b1a692e 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -269,6 +269,7 @@ pub fn expected_output_path(testpaths: &TestPaths, testpaths.file.with_extension(extension) } -pub const UI_EXTENSIONS: &[&str] = &[UI_STDERR, UI_STDOUT]; +pub const UI_EXTENSIONS: &[&str] = &[UI_STDERR, UI_STDOUT, UI_FIXED]; pub const UI_STDERR: &str = "stderr"; pub const UI_STDOUT: &str = "stdout"; +pub const UI_FIXED: &str = "rs.fixed"; diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 37f7af0abe8..3e7c6500433 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -26,6 +26,7 @@ extern crate regex; extern crate serde_derive; extern crate serde_json; extern crate test; +extern crate rustfix; use std::env; use std::ffi::OsString; @@ -52,6 +53,7 @@ pub mod common; pub mod errors; mod raise_fd_limit; mod read2; +mod autofix; fn main() { env_logger::init(); diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 01d9f52424d..20456a21cb5 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -12,7 +12,7 @@ use common::{Config, TestPaths}; use common::{CompileFail, ParseFail, Pretty, RunFail, RunPass, RunPassValgrind}; use common::{Codegen, CodegenUnits, DebugInfoGdb, DebugInfoLldb, Rustdoc}; use common::{Incremental, MirOpt, RunMake, Ui}; -use common::{expected_output_path, UI_STDERR, UI_STDOUT}; +use common::{expected_output_path, UI_STDERR, UI_STDOUT, UI_FIXED}; use common::CompareMode; use diff; use errors::{self, Error, ErrorKind}; @@ -35,6 +35,7 @@ use std::path::{Path, PathBuf}; use std::process::{Child, Command, ExitStatus, Output, Stdio}; use std::str; +use autofix::run_rustfix; use extract_gdb_version; /// The name of the environment variable that holds dynamic library locations. @@ -2603,6 +2604,19 @@ impl<'test> TestCx<'test> { self.check_error_patterns(&proc_res.stderr, &proc_res); } } + + let fixture_path = expected_output_path(&self.testpaths, None, &None, UI_FIXED); + if fixture_path.exists() { + let unfixed_code = self.load_expected_output_from_path(&self.testpaths.file) + .unwrap(); + let expected_fixed = self.load_expected_output_from_path(&fixture_path).unwrap(); + let fixed_code = run_rustfix(&unfixed_code, &proc_res.stderr); + let errors = self.compare_output("rs.fixed", &fixed_code, &expected_fixed); + if errors > 0 { + panic!("rustfix produced different fixed file!"); + // TODO: Add info for update-references.sh call + } + } } fn run_mir_opt_test(&self) { -- cgit 1.4.1-3-g733a5 From c02aedfcafafe3d2d0fbb4e9d85b2bbbbfa9abb2 Mon Sep 17 00:00:00 2001 From: Pascal Hertleif Date: Wed, 2 May 2018 00:32:31 +0200 Subject: Use rustfix' suggestion fixing API Uses branch from until we publish a new release. --- src/tools/compiletest/Cargo.toml | 2 +- src/tools/compiletest/src/autofix.rs | 70 ------------------------------------ src/tools/compiletest/src/main.rs | 1 - src/tools/compiletest/src/runtest.rs | 7 ++-- 4 files changed, 6 insertions(+), 74 deletions(-) delete mode 100644 src/tools/compiletest/src/autofix.rs (limited to 'src') diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml index 1710a44380f..476e5927a2f 100644 --- a/src/tools/compiletest/Cargo.toml +++ b/src/tools/compiletest/Cargo.toml @@ -13,7 +13,7 @@ regex = "0.2" serde = "1.0" serde_json = "1.0" serde_derive = "1.0" -rustfix = { git = "https://github.com/rust-lang-nursery/rustfix" } +rustfix = { git = "https://github.com/rust-lang-nursery/rustfix", branch = "apply_suggestion" } [target.'cfg(unix)'.dependencies] libc = "0.2" diff --git a/src/tools/compiletest/src/autofix.rs b/src/tools/compiletest/src/autofix.rs deleted file mode 100644 index 29ea5cdff8f..00000000000 --- a/src/tools/compiletest/src/autofix.rs +++ /dev/null @@ -1,70 +0,0 @@ -use rustfix::{get_suggestions_from_json, Replacement}; -use std::collections::HashSet; -use std::error::Error; - -pub fn run_rustfix(code: &str, json: &str) -> String { - let suggestions = get_suggestions_from_json(&json, &HashSet::new()) - .expect("could not load suggestions"); - - let mut fixed = code.to_string(); - - for sug in suggestions.into_iter().rev() { - for sol in sug.solutions { - for r in sol.replacements { - fixed = apply_suggestion(&mut fixed, &r) - .expect("could not apply suggestion"); - } - } - } - - fixed -} - -fn apply_suggestion( - file_content: &mut String, - suggestion: &Replacement, -) -> Result> { - use std::cmp::max; - - let mut new_content = String::new(); - - // Add the lines before the section we want to replace - new_content.push_str(&file_content - .lines() - .take(max(suggestion.snippet.line_range.start.line - 1, 0) as usize) - .collect::>() - .join("\n")); - new_content.push_str("\n"); - - // Parts of line before replacement - new_content.push_str(&file_content - .lines() - .nth(suggestion.snippet.line_range.start.line - 1) - .unwrap_or("") - .chars() - .take(suggestion.snippet.line_range.start.column - 1) - .collect::()); - - // Insert new content! Finally! - new_content.push_str(&suggestion.replacement); - - // Parts of line after replacement - new_content.push_str(&file_content - .lines() - .nth(suggestion.snippet.line_range.end.line - 1) - .unwrap_or("") - .chars() - .skip(suggestion.snippet.line_range.end.column - 1) - .collect::()); - - // Add the lines after the section we want to replace - new_content.push_str("\n"); - new_content.push_str(&file_content - .lines() - .skip(suggestion.snippet.line_range.end.line as usize) - .collect::>() - .join("\n")); - new_content.push_str("\n"); - - Ok(new_content) -} diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 3e7c6500433..a7849d53c3d 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -53,7 +53,6 @@ pub mod common; pub mod errors; mod raise_fd_limit; mod read2; -mod autofix; fn main() { env_logger::init(); diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 20456a21cb5..f0feb9b50f1 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -35,7 +35,6 @@ use std::path::{Path, PathBuf}; use std::process::{Child, Command, ExitStatus, Output, Stdio}; use std::str; -use autofix::run_rustfix; use extract_gdb_version; /// The name of the environment variable that holds dynamic library locations. @@ -2607,10 +2606,14 @@ impl<'test> TestCx<'test> { let fixture_path = expected_output_path(&self.testpaths, None, &None, UI_FIXED); if fixture_path.exists() { + use std::collections::HashSet; + use rustfix::{apply_suggestions, get_suggestions_from_json}; + let unfixed_code = self.load_expected_output_from_path(&self.testpaths.file) .unwrap(); let expected_fixed = self.load_expected_output_from_path(&fixture_path).unwrap(); - let fixed_code = run_rustfix(&unfixed_code, &proc_res.stderr); + let suggestions = get_suggestions_from_json(&proc_res.stderr, &HashSet::new()).unwrap(); + let fixed_code = apply_suggestions(&unfixed_code, &suggestions); let errors = self.compare_output("rs.fixed", &fixed_code, &expected_fixed); if errors > 0 { panic!("rustfix produced different fixed file!"); -- cgit 1.4.1-3-g733a5 From 9680f3b381767010c97b5d3ea0a14fdc19efde0c Mon Sep 17 00:00:00 2001 From: Pascal Hertleif Date: Wed, 2 May 2018 00:33:59 +0200 Subject: Skip NLL compiletest in rustfix mode for now --- src/tools/compiletest/src/common.rs | 4 ++-- src/tools/compiletest/src/runtest.rs | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 5159b1a692e..df0cf61e7c4 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -95,9 +95,9 @@ impl fmt::Display for Mode { } } -#[derive(Clone)] +#[derive(Clone, PartialEq)] pub enum CompareMode { - Nll + Nll, } impl CompareMode { diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index f0feb9b50f1..a7c34921842 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2605,7 +2605,10 @@ impl<'test> TestCx<'test> { } let fixture_path = expected_output_path(&self.testpaths, None, &None, UI_FIXED); - if fixture_path.exists() { + + // TODO(killercup): Add `nll.rs.fixed` files matching + let nll = self.config.compare_mode.as_ref().map(|x| *x == CompareMode::Nll).unwrap_or(false); + if fixture_path.exists() && !nll { use std::collections::HashSet; use rustfix::{apply_suggestions, get_suggestions_from_json}; -- cgit 1.4.1-3-g733a5 From b2645044039cb59858ec494e0ddacbe597757cdb Mon Sep 17 00:00:00 2001 From: Pascal Hertleif Date: Wed, 2 May 2018 00:44:39 +0200 Subject: tidy --- src/tools/compiletest/src/runtest.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index a7c34921842..745952ddf9e 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2606,8 +2606,11 @@ impl<'test> TestCx<'test> { let fixture_path = expected_output_path(&self.testpaths, None, &None, UI_FIXED); - // TODO(killercup): Add `nll.rs.fixed` files matching - let nll = self.config.compare_mode.as_ref().map(|x| *x == CompareMode::Nll).unwrap_or(false); + // FIXME(killercup): Add `nll.rs.fixed` files matching + let nll = self.config.compare_mode + .as_ref() + .map(|x| *x == CompareMode::Nll) + .unwrap_or(false); if fixture_path.exists() && !nll { use std::collections::HashSet; use rustfix::{apply_suggestions, get_suggestions_from_json}; @@ -2620,7 +2623,7 @@ impl<'test> TestCx<'test> { let errors = self.compare_output("rs.fixed", &fixed_code, &expected_fixed); if errors > 0 { panic!("rustfix produced different fixed file!"); - // TODO: Add info for update-references.sh call + // FIXME(killercup): Add info for update-references.sh call } } } -- cgit 1.4.1-3-g733a5 From fa9e55faeb0b4fac282ed47f20780c05f4efc86d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 2 May 2018 08:43:15 -0700 Subject: test: Make a dedicated testsuite for rustfix This commit adds a dedicated mode to compiletest for running rustfix tests, adding a new `src/test/rustfix` directory which will execute all tests as a "rustfix" test, namely requiring that a `*.fixed` is next to the main file which is the result of the rustfix project's application of fixes. The `rustfix` crate is pulled in to actually perform the fixing, and the rustfix compiletest mode will assert a few properties about the fixing: * The expected fixed output must be the same as rustc's output suggestions applied to the original code. * The fixed code must compile successfully * The fixed code must have no further diagnostics emitted about it --- src/Cargo.lock | 15 ++++ src/bootstrap/builder.rs | 2 +- src/bootstrap/test.rs | 6 ++ .../rustfix/closure-immutable-outer-variable.fixed | 20 ++++++ .../rustfix/closure-immutable-outer-variable.rs | 20 ++++++ src/test/rustfix/empty-no-fixes.fixed | 11 +++ src/test/rustfix/empty-no-fixes.rs | 11 +++ src/test/rustfix/empty-no-fixes.rs.fixed | 12 ++++ src/test/rustfix/issue-45562.fixed | 13 ++++ src/test/rustfix/issue-45562.rs | 13 ++++ ...extern-crate-rename-suggestion-formatting.fixed | 12 ++++ ...ad-extern-crate-rename-suggestion-formatting.rs | 12 ++++ ...-46756-consider-borrowing-cast-or-binexpr.fixed | 22 ++++++ ...sue-46756-consider-borrowing-cast-or-binexpr.rs | 22 ++++++ src/test/rustfix/main-no-fixes.fixed | 11 +++ src/test/rustfix/main-no-fixes.rs | 11 +++ src/test/rustfix/main-no-fixes.rs.fixed | 11 +++ src/test/rustfix/missing-comma-in-match.fixed | 17 +++++ src/test/rustfix/missing-comma-in-match.rs | 17 +++++ src/test/rustfix/str-as-char.fixed | 13 ++++ src/test/rustfix/str-as-char.rs | 13 ++++ src/test/rustfix/tuple-float-index.fixed | 15 ++++ src/test/rustfix/tuple-float-index.rs | 15 ++++ src/test/rustfix/update-all-references.sh | 31 ++++++++ src/test/rustfix/update-references.sh | 45 ++++++++++++ src/tools/compiletest/src/common.rs | 41 ++++++----- src/tools/compiletest/src/runtest.rs | 84 +++++++++++++++------- 27 files changed, 471 insertions(+), 44 deletions(-) create mode 100644 src/test/rustfix/closure-immutable-outer-variable.fixed create mode 100644 src/test/rustfix/closure-immutable-outer-variable.rs create mode 100644 src/test/rustfix/empty-no-fixes.fixed create mode 100644 src/test/rustfix/empty-no-fixes.rs create mode 100644 src/test/rustfix/empty-no-fixes.rs.fixed create mode 100644 src/test/rustfix/issue-45562.fixed create mode 100644 src/test/rustfix/issue-45562.rs create mode 100644 src/test/rustfix/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed create mode 100644 src/test/rustfix/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs create mode 100644 src/test/rustfix/issue-46756-consider-borrowing-cast-or-binexpr.fixed create mode 100644 src/test/rustfix/issue-46756-consider-borrowing-cast-or-binexpr.rs create mode 100644 src/test/rustfix/main-no-fixes.fixed create mode 100644 src/test/rustfix/main-no-fixes.rs create mode 100644 src/test/rustfix/main-no-fixes.rs.fixed create mode 100644 src/test/rustfix/missing-comma-in-match.fixed create mode 100644 src/test/rustfix/missing-comma-in-match.rs create mode 100644 src/test/rustfix/str-as-char.fixed create mode 100644 src/test/rustfix/str-as-char.rs create mode 100644 src/test/rustfix/tuple-float-index.fixed create mode 100644 src/test/rustfix/tuple-float-index.rs create mode 100755 src/test/rustfix/update-all-references.sh create mode 100755 src/test/rustfix/update-references.sh (limited to 'src') diff --git a/src/Cargo.lock b/src/Cargo.lock index ccdb24d7375..113369c9971 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -394,6 +394,7 @@ dependencies = [ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "rustfix 0.1.0 (git+https://github.com/rust-lang-nursery/rustfix?branch=apply_suggestion)", "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2234,6 +2235,19 @@ dependencies = [ "rustdoc 0.0.0", ] +[[package]] +name = "rustfix" +version = "0.1.0" +source = "git+https://github.com/rust-lang-nursery/rustfix?branch=apply_suggestion#571b43a1a1777561ddd7a41b37512bf0e3452c1a" +dependencies = [ + "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)", + "colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rustfmt-nightly" version = "0.6.1" @@ -3146,6 +3160,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rustc-ap-syntax_pos 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "55793c2a775230c42661194c48d44b35d4c8439d79ad8528e56651e854c48c63" "checksum rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11fb43a206a04116ffd7cfcf9bcb941f8eb6cc7ff667272246b0a1c74259a3cb" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" +"checksum rustfix 0.1.0 (git+https://github.com/rust-lang-nursery/rustfix?branch=apply_suggestion)" = "" "checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7" "checksum same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cfb6eded0b06a0b512c8ddbcf04089138c9b4362c2f696f3c3d76039d68f3637" "checksum schannel 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "85fd9df495640643ad2d00443b3d78aae69802ad488debab4f1dd52fc1806ade" diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 08bb8ab4815..5920e356bca 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -326,7 +326,7 @@ impl<'a> Builder<'a> { test::TheBook, test::UnstableBook, test::RustcBook, test::Rustfmt, test::Miri, test::Clippy, test::RustdocJS, test::RustdocTheme, // Run run-make last, since these won't pass without make on Windows - test::RunMake, test::RustdocUi), + test::RunMake, test::RustdocUi, test::Rustfix), Kind::Bench => describe!(test::Crate, test::CrateLibrustc), Kind::Doc => describe!(doc::UnstableBook, doc::UnstableBookGen, doc::TheBook, doc::Standalone, doc::Std, doc::Test, doc::WhitelistedRustc, doc::Rustc, diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index e8c40dfdb0a..fa32dd31635 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -716,6 +716,12 @@ default_test!(RunFail { suite: "run-fail" }); +default_test!(Rustfix { + path: "src/test/rustfix", + mode: "rustfix", + suite: "rustfix" +}); + default_test!(RunPassValgrind { path: "src/test/run-pass-valgrind", mode: "run-pass-valgrind", diff --git a/src/test/rustfix/closure-immutable-outer-variable.fixed b/src/test/rustfix/closure-immutable-outer-variable.fixed new file mode 100644 index 00000000000..bddc2eab16d --- /dev/null +++ b/src/test/rustfix/closure-immutable-outer-variable.fixed @@ -0,0 +1,20 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Point at the captured immutable outer variable + +fn foo(mut f: Box) { + f(); +} + +fn main() { + let mut y = true; + foo(Box::new(move || y = false) as Box<_>); +} diff --git a/src/test/rustfix/closure-immutable-outer-variable.rs b/src/test/rustfix/closure-immutable-outer-variable.rs new file mode 100644 index 00000000000..fe8e2bc6c8e --- /dev/null +++ b/src/test/rustfix/closure-immutable-outer-variable.rs @@ -0,0 +1,20 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Point at the captured immutable outer variable + +fn foo(mut f: Box) { + f(); +} + +fn main() { + let y = true; + foo(Box::new(move || y = false) as Box<_>); +} diff --git a/src/test/rustfix/empty-no-fixes.fixed b/src/test/rustfix/empty-no-fixes.fixed new file mode 100644 index 00000000000..39e19566d76 --- /dev/null +++ b/src/test/rustfix/empty-no-fixes.fixed @@ -0,0 +1,11 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags:--crate-type lib diff --git a/src/test/rustfix/empty-no-fixes.rs b/src/test/rustfix/empty-no-fixes.rs new file mode 100644 index 00000000000..39e19566d76 --- /dev/null +++ b/src/test/rustfix/empty-no-fixes.rs @@ -0,0 +1,11 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags:--crate-type lib diff --git a/src/test/rustfix/empty-no-fixes.rs.fixed b/src/test/rustfix/empty-no-fixes.rs.fixed new file mode 100644 index 00000000000..ee58e778253 --- /dev/null +++ b/src/test/rustfix/empty-no-fixes.rs.fixed @@ -0,0 +1,12 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags:--crate-type lib +fn foo() {} diff --git a/src/test/rustfix/issue-45562.fixed b/src/test/rustfix/issue-45562.fixed new file mode 100644 index 00000000000..d7a27a11fc0 --- /dev/null +++ b/src/test/rustfix/issue-45562.fixed @@ -0,0 +1,13 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[no_mangle] pub static RAH: usize = 5; + +fn main() {} diff --git a/src/test/rustfix/issue-45562.rs b/src/test/rustfix/issue-45562.rs new file mode 100644 index 00000000000..39576e9c845 --- /dev/null +++ b/src/test/rustfix/issue-45562.rs @@ -0,0 +1,13 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[no_mangle] pub const RAH: usize = 5; + +fn main() {} diff --git a/src/test/rustfix/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed b/src/test/rustfix/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed new file mode 100644 index 00000000000..d931f90cd04 --- /dev/null +++ b/src/test/rustfix/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed @@ -0,0 +1,12 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate std as other_std; +fn main() {} diff --git a/src/test/rustfix/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs b/src/test/rustfix/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs new file mode 100644 index 00000000000..7c55f9c4eb9 --- /dev/null +++ b/src/test/rustfix/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs @@ -0,0 +1,12 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate std; +fn main() {} diff --git a/src/test/rustfix/issue-46756-consider-borrowing-cast-or-binexpr.fixed b/src/test/rustfix/issue-46756-consider-borrowing-cast-or-binexpr.fixed new file mode 100644 index 00000000000..aaa04ef4004 --- /dev/null +++ b/src/test/rustfix/issue-46756-consider-borrowing-cast-or-binexpr.fixed @@ -0,0 +1,22 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(unused)] + +fn light_flows_our_war_of_mocking_words(and_yet: &usize) -> usize { + and_yet + 1 +} + +fn main() { + let behold: isize = 2; + let with_tears: usize = 3; + light_flows_our_war_of_mocking_words(&(behold as usize)); + light_flows_our_war_of_mocking_words(&(with_tears + 4)); +} diff --git a/src/test/rustfix/issue-46756-consider-borrowing-cast-or-binexpr.rs b/src/test/rustfix/issue-46756-consider-borrowing-cast-or-binexpr.rs new file mode 100644 index 00000000000..d21681747e9 --- /dev/null +++ b/src/test/rustfix/issue-46756-consider-borrowing-cast-or-binexpr.rs @@ -0,0 +1,22 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(unused)] + +fn light_flows_our_war_of_mocking_words(and_yet: &usize) -> usize { + and_yet + 1 +} + +fn main() { + let behold: isize = 2; + let with_tears: usize = 3; + light_flows_our_war_of_mocking_words(behold as usize); + light_flows_our_war_of_mocking_words(with_tears + 4); +} diff --git a/src/test/rustfix/main-no-fixes.fixed b/src/test/rustfix/main-no-fixes.fixed new file mode 100644 index 00000000000..3f07b46791d --- /dev/null +++ b/src/test/rustfix/main-no-fixes.fixed @@ -0,0 +1,11 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() {} diff --git a/src/test/rustfix/main-no-fixes.rs b/src/test/rustfix/main-no-fixes.rs new file mode 100644 index 00000000000..3f07b46791d --- /dev/null +++ b/src/test/rustfix/main-no-fixes.rs @@ -0,0 +1,11 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() {} diff --git a/src/test/rustfix/main-no-fixes.rs.fixed b/src/test/rustfix/main-no-fixes.rs.fixed new file mode 100644 index 00000000000..3f07b46791d --- /dev/null +++ b/src/test/rustfix/main-no-fixes.rs.fixed @@ -0,0 +1,11 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() {} diff --git a/src/test/rustfix/missing-comma-in-match.fixed b/src/test/rustfix/missing-comma-in-match.fixed new file mode 100644 index 00000000000..621a4127bc2 --- /dev/null +++ b/src/test/rustfix/missing-comma-in-match.fixed @@ -0,0 +1,17 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + match &Some(3) { + &None => 1, + &Some(2) => { 3 } + _ => 2 + }; +} diff --git a/src/test/rustfix/missing-comma-in-match.rs b/src/test/rustfix/missing-comma-in-match.rs new file mode 100644 index 00000000000..8ccad7b9c94 --- /dev/null +++ b/src/test/rustfix/missing-comma-in-match.rs @@ -0,0 +1,17 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + match &Some(3) { + &None => 1 + &Some(2) => { 3 } + _ => 2 + }; +} diff --git a/src/test/rustfix/str-as-char.fixed b/src/test/rustfix/str-as-char.fixed new file mode 100644 index 00000000000..0ace6d96613 --- /dev/null +++ b/src/test/rustfix/str-as-char.fixed @@ -0,0 +1,13 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + println!("●●"); +} diff --git a/src/test/rustfix/str-as-char.rs b/src/test/rustfix/str-as-char.rs new file mode 100644 index 00000000000..fa0e474fc7f --- /dev/null +++ b/src/test/rustfix/str-as-char.rs @@ -0,0 +1,13 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + println!('●●'); +} diff --git a/src/test/rustfix/tuple-float-index.fixed b/src/test/rustfix/tuple-float-index.fixed new file mode 100644 index 00000000000..9cb7537b428 --- /dev/null +++ b/src/test/rustfix/tuple-float-index.fixed @@ -0,0 +1,15 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z parse-only + +fn main () { + ((1, (2, 3)).1).1; +} diff --git a/src/test/rustfix/tuple-float-index.rs b/src/test/rustfix/tuple-float-index.rs new file mode 100644 index 00000000000..8bfbd0e74db --- /dev/null +++ b/src/test/rustfix/tuple-float-index.rs @@ -0,0 +1,15 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z parse-only + +fn main () { + (1, (2, 3)).1.1; +} diff --git a/src/test/rustfix/update-all-references.sh b/src/test/rustfix/update-all-references.sh new file mode 100755 index 00000000000..c3f615066bb --- /dev/null +++ b/src/test/rustfix/update-all-references.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash +# +# Copyright 2015 The Rust Project Developers. See the COPYRIGHT +# file at the top-level directory of this distribution and at +# http://rust-lang.org/COPYRIGHT. +# +# Licensed under the Apache License, Version 2.0 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +# A script to update the references for all tests. The idea is that +# you do a run, which will generate files in the build directory +# containing the (normalized) actual output of the compiler. You then +# run this script, which will copy those files over. If you find +# yourself manually editing a foo.stderr file, you're doing it wrong. +# +# See all `update-references.sh`, if you just want to update a single test. + +if [[ "$1" == "--help" || "$1" == "-h" || "$1" == "" || "$2" != "" ]]; then + echo "usage: $0 " + echo "" + echo "For example:" + echo " $0 ../../../build/x86_64-apple-darwin/test/rustfix" +fi + +BUILD_DIR=$PWD/$1 +MY_DIR=$(dirname $0) +cd $MY_DIR +find . -name '*.rs' | xargs ./update-references.sh $BUILD_DIR diff --git a/src/test/rustfix/update-references.sh b/src/test/rustfix/update-references.sh new file mode 100755 index 00000000000..bcca2fec10d --- /dev/null +++ b/src/test/rustfix/update-references.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +# +# Copyright 2015 The Rust Project Developers. See the COPYRIGHT +# file at the top-level directory of this distribution and at +# http://rust-lang.org/COPYRIGHT. +# +# Licensed under the Apache License, Version 2.0 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +# A script to update the references for particular tests. The idea is +# that you do a run, which will generate files in the build directory +# containing the (normalized) actual output of the compiler. This +# script will then copy that output and replace the "expected output" +# files. You can then commit the changes. +# +# If you find yourself manually editing a foo.stderr file, you're +# doing it wrong. + +if [[ "$1" == "--help" || "$1" == "-h" || "$1" == "" || "$2" == "" ]]; then + echo "usage: $0 " + echo "" + echo "For example:" + echo " $0 ../../../build/x86_64-apple-darwin/test/rustfix *.rs */*.rs" +fi + +MYDIR=$(dirname $0) + +BUILD_DIR="$1" +shift + +shopt -s nullglob + +while [[ "$1" != "" ]]; do + for OUT_NAME in $BUILD_DIR/${1%.rs}.*fixed; do + OUT_BASE=`basename "$OUT_NAME"` + if ! (diff $OUT_NAME $MYDIR/$OUT_BASE >& /dev/null); then + echo updating $MYDIR/$OUT_BASE + cp $OUT_NAME $MYDIR + fi + done + shift +done diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index df0cf61e7c4..733fc1f16d2 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -32,6 +32,7 @@ pub enum Mode { RunMake, Ui, MirOpt, + Rustfix, } impl Mode { @@ -67,6 +68,7 @@ impl FromStr for Mode { "run-make" => Ok(RunMake), "ui" => Ok(Ui), "mir-opt" => Ok(MirOpt), + "rustfix" => Ok(Rustfix), _ => Err(()), } } @@ -74,24 +76,25 @@ impl FromStr for Mode { impl fmt::Display for Mode { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(match *self { - CompileFail => "compile-fail", - ParseFail => "parse-fail", - RunFail => "run-fail", - RunPass => "run-pass", - RunPassValgrind => "run-pass-valgrind", - Pretty => "pretty", - DebugInfoGdb => "debuginfo-gdb", - DebugInfoLldb => "debuginfo-lldb", - Codegen => "codegen", - Rustdoc => "rustdoc", - CodegenUnits => "codegen-units", - Incremental => "incremental", - RunMake => "run-make", - Ui => "ui", - MirOpt => "mir-opt", - }, - f) + let s = match *self { + CompileFail => "compile-fail", + ParseFail => "parse-fail", + RunFail => "run-fail", + RunPass => "run-pass", + RunPassValgrind => "run-pass-valgrind", + Pretty => "pretty", + DebugInfoGdb => "debuginfo-gdb", + DebugInfoLldb => "debuginfo-lldb", + Codegen => "codegen", + Rustdoc => "rustdoc", + CodegenUnits => "codegen-units", + Incremental => "incremental", + RunMake => "run-make", + Ui => "ui", + MirOpt => "mir-opt", + Rustfix => "rustfix", + }; + fmt::Display::fmt(s, f) } } @@ -272,4 +275,4 @@ pub fn expected_output_path(testpaths: &TestPaths, pub const UI_EXTENSIONS: &[&str] = &[UI_STDERR, UI_STDOUT, UI_FIXED]; pub const UI_STDERR: &str = "stderr"; pub const UI_STDOUT: &str = "stdout"; -pub const UI_FIXED: &str = "rs.fixed"; +pub const UI_FIXED: &str = "fixed"; diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 745952ddf9e..ea1863b2fd1 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -11,7 +11,7 @@ use common::{Config, TestPaths}; use common::{CompileFail, ParseFail, Pretty, RunFail, RunPass, RunPassValgrind}; use common::{Codegen, CodegenUnits, DebugInfoGdb, DebugInfoLldb, Rustdoc}; -use common::{Incremental, MirOpt, RunMake, Ui}; +use common::{Incremental, MirOpt, RunMake, Ui, Rustfix}; use common::{expected_output_path, UI_STDERR, UI_STDOUT, UI_FIXED}; use common::CompareMode; use diff; @@ -21,6 +21,7 @@ use json; use header::TestProps; use util::logv; use regex::Regex; +use rustfix::{apply_suggestions, get_suggestions_from_json}; use std::collections::VecDeque; use std::collections::HashMap; @@ -241,6 +242,7 @@ impl<'test> TestCx<'test> { CodegenUnits => self.run_codegen_units_test(), Incremental => self.run_incremental_test(), RunMake => self.run_rmake_test(), + Rustfix => self.run_rustfix_test(), Ui => self.run_ui_test(), MirOpt => self.run_mir_opt_test(), } @@ -1687,6 +1689,7 @@ impl<'test> TestCx<'test> { rustc.arg(dir_opt); } + Rustfix | RunPass | RunFail | RunPassValgrind | @@ -2603,29 +2606,6 @@ impl<'test> TestCx<'test> { self.check_error_patterns(&proc_res.stderr, &proc_res); } } - - let fixture_path = expected_output_path(&self.testpaths, None, &None, UI_FIXED); - - // FIXME(killercup): Add `nll.rs.fixed` files matching - let nll = self.config.compare_mode - .as_ref() - .map(|x| *x == CompareMode::Nll) - .unwrap_or(false); - if fixture_path.exists() && !nll { - use std::collections::HashSet; - use rustfix::{apply_suggestions, get_suggestions_from_json}; - - let unfixed_code = self.load_expected_output_from_path(&self.testpaths.file) - .unwrap(); - let expected_fixed = self.load_expected_output_from_path(&fixture_path).unwrap(); - let suggestions = get_suggestions_from_json(&proc_res.stderr, &HashSet::new()).unwrap(); - let fixed_code = apply_suggestions(&unfixed_code, &suggestions); - let errors = self.compare_output("rs.fixed", &fixed_code, &expected_fixed); - if errors > 0 { - panic!("rustfix produced different fixed file!"); - // FIXME(killercup): Add info for update-references.sh call - } - } } fn run_mir_opt_test(&self) { @@ -2950,6 +2930,62 @@ impl<'test> TestCx<'test> { println!("Actual {} saved to {}", kind, output_file.display()); 1 } + + fn run_rustfix_test(&self) { + // First up, compile the test with --error-format=json + let mut rustc = self.make_compile_args( + &self.testpaths.file, + TargetLocation::ThisFile(self.make_exe_name()), + ); + rustc.arg("--error-format").arg("json") + .arg("-L").arg(&self.aux_output_dir_name()); + let proc_res = self.compose_and_run_compiler(rustc, None); + + // Now apply suggestions from rustc to the code itself + let unfixed_code = self.load_expected_output_from_path(&self.testpaths.file) + .unwrap(); + let suggestions = get_suggestions_from_json(&proc_res.stderr, &HashSet::new()).unwrap(); + let fixed_code = apply_suggestions(&unfixed_code, &suggestions); + + // Load up what the expected result of fixing should be + let fixture_path = expected_output_path(&self.testpaths, None, &None, UI_FIXED); + let expected_fixed = self.load_expected_output_from_path(&fixture_path) + .unwrap_or(String::new()); + + // Make sure our fixed code is the same as what we're expecting + let errors = self.compare_output(UI_FIXED, &fixed_code, &expected_fixed); + if errors > 0 { + println!("To update references, run this command from build directory:"); + let relative_path_to_file = self.testpaths + .relative_dir + .join(self.testpaths.file.file_name().unwrap()); + println!( + "{}/update-references.sh '{}' '{}'", + self.config.src_base.display(), + self.config.build_base.display(), + relative_path_to_file.display() + ); + self.fatal_proc_rec( + &format!("{} errors occurred comparing output.", errors), + &proc_res, + ); + } + + // And finally, compile the fixed code and make sure it both succeeds + // and has no diagnostics. + let mut rustc = self.make_compile_args( + &self.testpaths.file.with_extension(UI_FIXED), + TargetLocation::ThisFile(self.make_exe_name()), + ); + rustc.arg("-L").arg(&self.aux_output_dir_name()); + let res = self.compose_and_run_compiler(rustc, None); + if !res.status.success() { + self.fatal_proc_rec("failed to compile fixed code", &res); + } + if !res.stderr.is_empty() { + self.fatal_proc_rec("fixed code is still producing diagnostics", &res); + } + } } struct ProcArgs { -- cgit 1.4.1-3-g733a5 From a563027cb8f2cb1c46d2a1e59f3686d3f3a3213a Mon Sep 17 00:00:00 2001 From: Pascal Hertleif Date: Thu, 3 May 2018 15:35:42 +0200 Subject: Use published rustfix 0.2 version --- src/Cargo.lock | 10 ++++------ src/tools/compiletest/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/Cargo.lock b/src/Cargo.lock index 113369c9971..0f08eaf596a 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -394,7 +394,7 @@ dependencies = [ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "rustfix 0.1.0 (git+https://github.com/rust-lang-nursery/rustfix?branch=apply_suggestion)", + "rustfix 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2237,11 +2237,9 @@ dependencies = [ [[package]] name = "rustfix" -version = "0.1.0" -source = "git+https://github.com/rust-lang-nursery/rustfix?branch=apply_suggestion#571b43a1a1777561ddd7a41b37512bf0e3452c1a" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)", - "colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3160,7 +3158,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rustc-ap-syntax_pos 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "55793c2a775230c42661194c48d44b35d4c8439d79ad8528e56651e854c48c63" "checksum rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11fb43a206a04116ffd7cfcf9bcb941f8eb6cc7ff667272246b0a1c74259a3cb" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" -"checksum rustfix 0.1.0 (git+https://github.com/rust-lang-nursery/rustfix?branch=apply_suggestion)" = "" +"checksum rustfix 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "165a212dd11124d7070892da20f71d82970ef1d1dd41cd804b70f39740a21c85" "checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7" "checksum same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cfb6eded0b06a0b512c8ddbcf04089138c9b4362c2f696f3c3d76039d68f3637" "checksum schannel 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "85fd9df495640643ad2d00443b3d78aae69802ad488debab4f1dd52fc1806ade" diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml index 476e5927a2f..77554f244c8 100644 --- a/src/tools/compiletest/Cargo.toml +++ b/src/tools/compiletest/Cargo.toml @@ -13,7 +13,7 @@ regex = "0.2" serde = "1.0" serde_json = "1.0" serde_derive = "1.0" -rustfix = { git = "https://github.com/rust-lang-nursery/rustfix", branch = "apply_suggestion" } +rustfix = "0.2" [target.'cfg(unix)'.dependencies] libc = "0.2" -- cgit 1.4.1-3-g733a5 From 6f2d023028bbd666be2c211b923b32faf10a41da Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 3 May 2018 11:26:58 -0700 Subject: Fold rustfix tests back into the UI test suite --- src/bootstrap/builder.rs | 2 +- src/bootstrap/test.rs | 6 -- .../closure-immutable-outer-variable.fixed | 22 +++++ .../closure-immutable-outer-variable.nll.fixed | 22 +++++ .../closure-immutable-outer-variable.nll.stderr | 2 +- .../closure-immutable-outer-variable.rs | 2 + .../closure-immutable-outer-variable.stderr | 2 +- src/test/ui/suggestions/issue-45562.fixed | 16 ++++ src/test/ui/suggestions/issue-45562.rs | 2 + src/test/ui/suggestions/issue-45562.stderr | 2 +- ...extern-crate-rename-suggestion-formatting.fixed | 15 ++++ ...ad-extern-crate-rename-suggestion-formatting.rs | 2 + ...xtern-crate-rename-suggestion-formatting.stderr | 2 +- ...-46756-consider-borrowing-cast-or-binexpr.fixed | 26 ++++++ ...sue-46756-consider-borrowing-cast-or-binexpr.rs | 2 + ...46756-consider-borrowing-cast-or-binexpr.stderr | 4 +- .../ui/suggestions/missing-comma-in-match.fixed | 21 +++++ src/test/ui/suggestions/missing-comma-in-match.rs | 2 + .../ui/suggestions/missing-comma-in-match.stderr | 2 +- src/test/ui/suggestions/str-as-char.fixed | 16 ++++ src/test/ui/suggestions/str-as-char.rs | 2 + src/test/ui/suggestions/str-as-char.stderr | 2 +- src/test/ui/suggestions/tuple-float-index.fixed | 16 ++++ src/test/ui/suggestions/tuple-float-index.rs | 1 + src/test/ui/suggestions/tuple-float-index.stderr | 2 +- src/test/ui/update-references.sh | 4 +- src/tools/compiletest/src/common.rs | 3 - src/tools/compiletest/src/header.rs | 10 +++ src/tools/compiletest/src/runtest.rs | 93 ++++++++-------------- 29 files changed, 223 insertions(+), 80 deletions(-) create mode 100644 src/test/ui/suggestions/closure-immutable-outer-variable.fixed create mode 100644 src/test/ui/suggestions/closure-immutable-outer-variable.nll.fixed create mode 100644 src/test/ui/suggestions/issue-45562.fixed create mode 100644 src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed create mode 100644 src/test/ui/suggestions/issue-46756-consider-borrowing-cast-or-binexpr.fixed create mode 100644 src/test/ui/suggestions/missing-comma-in-match.fixed create mode 100644 src/test/ui/suggestions/str-as-char.fixed create mode 100644 src/test/ui/suggestions/tuple-float-index.fixed (limited to 'src') diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 5920e356bca..08bb8ab4815 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -326,7 +326,7 @@ impl<'a> Builder<'a> { test::TheBook, test::UnstableBook, test::RustcBook, test::Rustfmt, test::Miri, test::Clippy, test::RustdocJS, test::RustdocTheme, // Run run-make last, since these won't pass without make on Windows - test::RunMake, test::RustdocUi, test::Rustfix), + test::RunMake, test::RustdocUi), Kind::Bench => describe!(test::Crate, test::CrateLibrustc), Kind::Doc => describe!(doc::UnstableBook, doc::UnstableBookGen, doc::TheBook, doc::Standalone, doc::Std, doc::Test, doc::WhitelistedRustc, doc::Rustc, diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index fa32dd31635..e8c40dfdb0a 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -716,12 +716,6 @@ default_test!(RunFail { suite: "run-fail" }); -default_test!(Rustfix { - path: "src/test/rustfix", - mode: "rustfix", - suite: "rustfix" -}); - default_test!(RunPassValgrind { path: "src/test/run-pass-valgrind", mode: "run-pass-valgrind", diff --git a/src/test/ui/suggestions/closure-immutable-outer-variable.fixed b/src/test/ui/suggestions/closure-immutable-outer-variable.fixed new file mode 100644 index 00000000000..b3a0d592f76 --- /dev/null +++ b/src/test/ui/suggestions/closure-immutable-outer-variable.fixed @@ -0,0 +1,22 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix + +// Point at the captured immutable outer variable + +fn foo(mut f: Box) { + f(); +} + +fn main() { + let mut y = true; + foo(Box::new(move || y = false) as Box<_>); //~ ERROR cannot assign to captured outer variable +} diff --git a/src/test/ui/suggestions/closure-immutable-outer-variable.nll.fixed b/src/test/ui/suggestions/closure-immutable-outer-variable.nll.fixed new file mode 100644 index 00000000000..e162678460c --- /dev/null +++ b/src/test/ui/suggestions/closure-immutable-outer-variable.nll.fixed @@ -0,0 +1,22 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix + +// Point at the captured immutable outer variable + +fn foo(mut f: Box) { + f(); +} + +fn main() { + let y = true; + foo(Box::new(move || y = false) as Box<_>); //~ ERROR cannot assign to captured outer variable +} diff --git a/src/test/ui/suggestions/closure-immutable-outer-variable.nll.stderr b/src/test/ui/suggestions/closure-immutable-outer-variable.nll.stderr index e4e93ecac8e..bc655114c2b 100644 --- a/src/test/ui/suggestions/closure-immutable-outer-variable.nll.stderr +++ b/src/test/ui/suggestions/closure-immutable-outer-variable.nll.stderr @@ -1,5 +1,5 @@ error[E0594]: cannot assign to immutable item `y` - --> $DIR/closure-immutable-outer-variable.rs:19:26 + --> $DIR/closure-immutable-outer-variable.rs:21:26 | LL | foo(Box::new(move || y = false) as Box<_>); //~ ERROR cannot assign to captured outer variable | ^^^^^^^^^ cannot mutate diff --git a/src/test/ui/suggestions/closure-immutable-outer-variable.rs b/src/test/ui/suggestions/closure-immutable-outer-variable.rs index 1d14afd6a01..e162678460c 100644 --- a/src/test/ui/suggestions/closure-immutable-outer-variable.rs +++ b/src/test/ui/suggestions/closure-immutable-outer-variable.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// run-rustfix + // Point at the captured immutable outer variable fn foo(mut f: Box) { diff --git a/src/test/ui/suggestions/closure-immutable-outer-variable.stderr b/src/test/ui/suggestions/closure-immutable-outer-variable.stderr index 3353e2c7291..0ee11d8cf15 100644 --- a/src/test/ui/suggestions/closure-immutable-outer-variable.stderr +++ b/src/test/ui/suggestions/closure-immutable-outer-variable.stderr @@ -1,5 +1,5 @@ error[E0594]: cannot assign to captured outer variable in an `FnMut` closure - --> $DIR/closure-immutable-outer-variable.rs:19:26 + --> $DIR/closure-immutable-outer-variable.rs:21:26 | LL | let y = true; | - help: consider making `y` mutable: `mut y` diff --git a/src/test/ui/suggestions/issue-45562.fixed b/src/test/ui/suggestions/issue-45562.fixed new file mode 100644 index 00000000000..7c01f0d1ee5 --- /dev/null +++ b/src/test/ui/suggestions/issue-45562.fixed @@ -0,0 +1,16 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix + +#[no_mangle] pub static RAH: usize = 5; +//~^ ERROR const items should never be #[no_mangle] + +fn main() {} diff --git a/src/test/ui/suggestions/issue-45562.rs b/src/test/ui/suggestions/issue-45562.rs index f493df56f94..c27d52fcdd3 100644 --- a/src/test/ui/suggestions/issue-45562.rs +++ b/src/test/ui/suggestions/issue-45562.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// run-rustfix + #[no_mangle] pub const RAH: usize = 5; //~^ ERROR const items should never be #[no_mangle] diff --git a/src/test/ui/suggestions/issue-45562.stderr b/src/test/ui/suggestions/issue-45562.stderr index d6960dca054..d9e624cadc7 100644 --- a/src/test/ui/suggestions/issue-45562.stderr +++ b/src/test/ui/suggestions/issue-45562.stderr @@ -1,5 +1,5 @@ error: const items should never be #[no_mangle] - --> $DIR/issue-45562.rs:11:14 + --> $DIR/issue-45562.rs:13:14 | LL | #[no_mangle] pub const RAH: usize = 5; | ---------^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed b/src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed new file mode 100644 index 00000000000..e3287030408 --- /dev/null +++ b/src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed @@ -0,0 +1,15 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix + +extern crate std as other_std; +fn main() {} +//~^^ ERROR the name `std` is defined multiple times [E0259] diff --git a/src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs b/src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs index 4d75127b645..f47ea474d51 100644 --- a/src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs +++ b/src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// run-rustfix + extern crate std; fn main() {} //~^^ ERROR the name `std` is defined multiple times [E0259] diff --git a/src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr b/src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr index 8e2b2d845e9..ecdfec2b3bf 100644 --- a/src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr +++ b/src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr @@ -1,5 +1,5 @@ error[E0259]: the name `std` is defined multiple times - --> $DIR/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs:11:1 + --> $DIR/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs:13:1 | LL | extern crate std; | ^^^^^^^^^^^^^^^^^ `std` reimported here diff --git a/src/test/ui/suggestions/issue-46756-consider-borrowing-cast-or-binexpr.fixed b/src/test/ui/suggestions/issue-46756-consider-borrowing-cast-or-binexpr.fixed new file mode 100644 index 00000000000..77171cad6e7 --- /dev/null +++ b/src/test/ui/suggestions/issue-46756-consider-borrowing-cast-or-binexpr.fixed @@ -0,0 +1,26 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix + +#![allow(unused)] + +fn light_flows_our_war_of_mocking_words(and_yet: &usize) -> usize { + and_yet + 1 +} + +fn main() { + let behold: isize = 2; + let with_tears: usize = 3; + light_flows_our_war_of_mocking_words(&(behold as usize)); + //~^ ERROR mismatched types [E0308] + light_flows_our_war_of_mocking_words(&(with_tears + 4)); + //~^ ERROR mismatched types [E0308] +} diff --git a/src/test/ui/suggestions/issue-46756-consider-borrowing-cast-or-binexpr.rs b/src/test/ui/suggestions/issue-46756-consider-borrowing-cast-or-binexpr.rs index 5617c46afa9..e5ea9b5ed09 100644 --- a/src/test/ui/suggestions/issue-46756-consider-borrowing-cast-or-binexpr.rs +++ b/src/test/ui/suggestions/issue-46756-consider-borrowing-cast-or-binexpr.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// run-rustfix + #![allow(unused)] fn light_flows_our_war_of_mocking_words(and_yet: &usize) -> usize { diff --git a/src/test/ui/suggestions/issue-46756-consider-borrowing-cast-or-binexpr.stderr b/src/test/ui/suggestions/issue-46756-consider-borrowing-cast-or-binexpr.stderr index e89e9dce94d..9c492751ca1 100644 --- a/src/test/ui/suggestions/issue-46756-consider-borrowing-cast-or-binexpr.stderr +++ b/src/test/ui/suggestions/issue-46756-consider-borrowing-cast-or-binexpr.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-46756-consider-borrowing-cast-or-binexpr.rs:20:42 + --> $DIR/issue-46756-consider-borrowing-cast-or-binexpr.rs:22:42 | LL | light_flows_our_war_of_mocking_words(behold as usize); | ^^^^^^^^^^^^^^^ @@ -11,7 +11,7 @@ LL | light_flows_our_war_of_mocking_words(behold as usize); found type `usize` error[E0308]: mismatched types - --> $DIR/issue-46756-consider-borrowing-cast-or-binexpr.rs:22:42 + --> $DIR/issue-46756-consider-borrowing-cast-or-binexpr.rs:24:42 | LL | light_flows_our_war_of_mocking_words(with_tears + 4); | ^^^^^^^^^^^^^^ diff --git a/src/test/ui/suggestions/missing-comma-in-match.fixed b/src/test/ui/suggestions/missing-comma-in-match.fixed new file mode 100644 index 00000000000..4832f35f42d --- /dev/null +++ b/src/test/ui/suggestions/missing-comma-in-match.fixed @@ -0,0 +1,21 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix + +fn main() { + match &Some(3) { + &None => 1, + &Some(2) => { 3 } + //~^ ERROR expected one of `,`, `.`, `?`, `}`, or an operator, found `=>` + //~| NOTE expected one of `,`, `.`, `?`, `}`, or an operator here + _ => 2 + }; +} diff --git a/src/test/ui/suggestions/missing-comma-in-match.rs b/src/test/ui/suggestions/missing-comma-in-match.rs index 6f86cdea3cf..e39b20e77ea 100644 --- a/src/test/ui/suggestions/missing-comma-in-match.rs +++ b/src/test/ui/suggestions/missing-comma-in-match.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// run-rustfix + fn main() { match &Some(3) { &None => 1 diff --git a/src/test/ui/suggestions/missing-comma-in-match.stderr b/src/test/ui/suggestions/missing-comma-in-match.stderr index b71a50b6631..77935934107 100644 --- a/src/test/ui/suggestions/missing-comma-in-match.stderr +++ b/src/test/ui/suggestions/missing-comma-in-match.stderr @@ -1,5 +1,5 @@ error: expected one of `,`, `.`, `?`, `}`, or an operator, found `=>` - --> $DIR/missing-comma-in-match.rs:14:18 + --> $DIR/missing-comma-in-match.rs:16:18 | LL | &None => 1 | - help: missing a comma here to end this `match` arm diff --git a/src/test/ui/suggestions/str-as-char.fixed b/src/test/ui/suggestions/str-as-char.fixed new file mode 100644 index 00000000000..c0dad38e436 --- /dev/null +++ b/src/test/ui/suggestions/str-as-char.fixed @@ -0,0 +1,16 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix + +fn main() { + println!("●●"); + //~^ ERROR character literal may only contain one codepoint +} diff --git a/src/test/ui/suggestions/str-as-char.rs b/src/test/ui/suggestions/str-as-char.rs index 09aca61147d..b5a5df0af7f 100644 --- a/src/test/ui/suggestions/str-as-char.rs +++ b/src/test/ui/suggestions/str-as-char.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// run-rustfix + fn main() { println!('●●'); //~^ ERROR character literal may only contain one codepoint diff --git a/src/test/ui/suggestions/str-as-char.stderr b/src/test/ui/suggestions/str-as-char.stderr index d881becf00c..60eb182adf1 100644 --- a/src/test/ui/suggestions/str-as-char.stderr +++ b/src/test/ui/suggestions/str-as-char.stderr @@ -1,5 +1,5 @@ error: character literal may only contain one codepoint - --> $DIR/str-as-char.rs:12:14 + --> $DIR/str-as-char.rs:14:14 | LL | println!('●●'); | ^^^^ diff --git a/src/test/ui/suggestions/tuple-float-index.fixed b/src/test/ui/suggestions/tuple-float-index.fixed new file mode 100644 index 00000000000..55bc2f77dad --- /dev/null +++ b/src/test/ui/suggestions/tuple-float-index.fixed @@ -0,0 +1,16 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix +// compile-flags: -Z parse-only + +fn main () { + ((1, (2, 3)).1).1; //~ ERROR unexpected token: `1.1` +} diff --git a/src/test/ui/suggestions/tuple-float-index.rs b/src/test/ui/suggestions/tuple-float-index.rs index 0a188305a92..d569ca4cb86 100644 --- a/src/test/ui/suggestions/tuple-float-index.rs +++ b/src/test/ui/suggestions/tuple-float-index.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// run-rustfix // compile-flags: -Z parse-only fn main () { diff --git a/src/test/ui/suggestions/tuple-float-index.stderr b/src/test/ui/suggestions/tuple-float-index.stderr index 4a1e34890f4..15af0834f03 100644 --- a/src/test/ui/suggestions/tuple-float-index.stderr +++ b/src/test/ui/suggestions/tuple-float-index.stderr @@ -1,5 +1,5 @@ error: unexpected token: `1.1` - --> $DIR/tuple-float-index.rs:14:17 + --> $DIR/tuple-float-index.rs:15:17 | LL | (1, (2, 3)).1.1; //~ ERROR unexpected token: `1.1` | ------------^^^ diff --git a/src/test/ui/update-references.sh b/src/test/ui/update-references.sh index 4fc11daaa3a..47a85352b00 100755 --- a/src/test/ui/update-references.sh +++ b/src/test/ui/update-references.sh @@ -26,7 +26,6 @@ if [[ "$1" == "--help" || "$1" == "-h" || "$1" == "" || "$2" == "" ]]; then echo " $0 ../../../build/x86_64-apple-darwin/test/ui *.rs */*.rs" fi -MYDIR=$(dirname $0) BUILD_DIR="$1" shift @@ -34,7 +33,8 @@ shift shopt -s nullglob while [[ "$1" != "" ]]; do - for EXT in "stderr" "stdout"; do + MYDIR=$(dirname $1) + for EXT in "stderr" "stdout" "fixed"; do for OUT_NAME in $BUILD_DIR/${1%.rs}.*$EXT; do OUT_BASE=`basename "$OUT_NAME"` if ! (diff $OUT_NAME $MYDIR/$OUT_BASE >& /dev/null); then diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 733fc1f16d2..2df52816599 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -32,7 +32,6 @@ pub enum Mode { RunMake, Ui, MirOpt, - Rustfix, } impl Mode { @@ -68,7 +67,6 @@ impl FromStr for Mode { "run-make" => Ok(RunMake), "ui" => Ok(Ui), "mir-opt" => Ok(MirOpt), - "rustfix" => Ok(Rustfix), _ => Err(()), } } @@ -92,7 +90,6 @@ impl fmt::Display for Mode { RunMake => "run-make", Ui => "ui", MirOpt => "mir-opt", - Rustfix => "rustfix", }; fmt::Display::fmt(s, f) } diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 73dd079cf0c..7ac3f5b5b25 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -236,6 +236,7 @@ pub struct TestProps { pub normalize_stdout: Vec<(String, String)>, pub normalize_stderr: Vec<(String, String)>, pub failure_status: i32, + pub run_rustfix: bool, } impl TestProps { @@ -267,6 +268,7 @@ impl TestProps { normalize_stdout: vec![], normalize_stderr: vec![], failure_status: 101, + run_rustfix: false, } } @@ -403,6 +405,10 @@ impl TestProps { if let Some(code) = config.parse_failure_status(ln) { self.failure_status = code; } + + if !self.run_rustfix { + self.run_rustfix = config.parse_run_rustfix(ln); + } }); for key in &["RUST_TEST_NOCAPTURE", "RUST_TEST_THREADS"] { @@ -642,6 +648,10 @@ impl Config { None } + + fn parse_run_rustfix(&self, line: &str) -> bool { + self.parse_name_directive(line, "run-rustfix") + } } pub fn lldb_version_to_int(version_string: &str) -> isize { diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index ea1863b2fd1..fae75c352da 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -11,7 +11,7 @@ use common::{Config, TestPaths}; use common::{CompileFail, ParseFail, Pretty, RunFail, RunPass, RunPassValgrind}; use common::{Codegen, CodegenUnits, DebugInfoGdb, DebugInfoLldb, Rustdoc}; -use common::{Incremental, MirOpt, RunMake, Ui, Rustfix}; +use common::{Incremental, MirOpt, RunMake, Ui}; use common::{expected_output_path, UI_STDERR, UI_STDOUT, UI_FIXED}; use common::CompareMode; use diff; @@ -242,7 +242,6 @@ impl<'test> TestCx<'test> { CodegenUnits => self.run_codegen_units_test(), Incremental => self.run_incremental_test(), RunMake => self.run_rmake_test(), - Rustfix => self.run_rustfix_test(), Ui => self.run_ui_test(), MirOpt => self.run_mir_opt_test(), } @@ -1689,7 +1688,6 @@ impl<'test> TestCx<'test> { rustc.arg(dir_opt); } - Rustfix | RunPass | RunFail | RunPassValgrind | @@ -2555,6 +2553,7 @@ impl<'test> TestCx<'test> { let expected_stderr = self.load_expected_output(UI_STDERR); let expected_stdout = self.load_expected_output(UI_STDOUT); + let expected_fixed = self.load_expected_output(UI_FIXED); let normalized_stdout = self.normalize_output(&proc_res.stdout, &self.props.normalize_stdout); @@ -2571,6 +2570,21 @@ impl<'test> TestCx<'test> { errors += self.compare_output("stdout", &normalized_stdout, &expected_stdout); errors += self.compare_output("stderr", &normalized_stderr, &expected_stderr); + if self.config.compare_mode.is_some() { + // don't test rustfix with nll right now + } else if self.props.run_rustfix { + // Apply suggestions from rustc to the code itself + let unfixed_code = self.load_expected_output_from_path(&self.testpaths.file) + .unwrap(); + let suggestions = get_suggestions_from_json(&proc_res.stderr, &HashSet::new()).unwrap(); + let fixed_code = apply_suggestions(&unfixed_code, &suggestions); + + errors += self.compare_output("fixed", &fixed_code, &expected_fixed); + } else if !expected_fixed.is_empty() { + panic!("the `// run-rustfix` directive wasn't found but a `*.fixed` \ + file was found"); + } + if errors > 0 { println!("To update references, run this command from build directory:"); let relative_path_to_file = self.testpaths @@ -2606,6 +2620,23 @@ impl<'test> TestCx<'test> { self.check_error_patterns(&proc_res.stderr, &proc_res); } } + + if self.props.run_rustfix && self.config.compare_mode.is_none() { + // And finally, compile the fixed code and make sure it both + // succeeds and has no diagnostics. + let mut rustc = self.make_compile_args( + &self.testpaths.file.with_extension(UI_FIXED), + TargetLocation::ThisFile(self.make_exe_name()), + ); + rustc.arg("-L").arg(&self.aux_output_dir_name()); + let res = self.compose_and_run_compiler(rustc, None); + if !res.status.success() { + self.fatal_proc_rec("failed to compile fixed code", &res); + } + if !res.stderr.is_empty() { + self.fatal_proc_rec("fixed code is still producing diagnostics", &res); + } + } } fn run_mir_opt_test(&self) { @@ -2930,62 +2961,6 @@ impl<'test> TestCx<'test> { println!("Actual {} saved to {}", kind, output_file.display()); 1 } - - fn run_rustfix_test(&self) { - // First up, compile the test with --error-format=json - let mut rustc = self.make_compile_args( - &self.testpaths.file, - TargetLocation::ThisFile(self.make_exe_name()), - ); - rustc.arg("--error-format").arg("json") - .arg("-L").arg(&self.aux_output_dir_name()); - let proc_res = self.compose_and_run_compiler(rustc, None); - - // Now apply suggestions from rustc to the code itself - let unfixed_code = self.load_expected_output_from_path(&self.testpaths.file) - .unwrap(); - let suggestions = get_suggestions_from_json(&proc_res.stderr, &HashSet::new()).unwrap(); - let fixed_code = apply_suggestions(&unfixed_code, &suggestions); - - // Load up what the expected result of fixing should be - let fixture_path = expected_output_path(&self.testpaths, None, &None, UI_FIXED); - let expected_fixed = self.load_expected_output_from_path(&fixture_path) - .unwrap_or(String::new()); - - // Make sure our fixed code is the same as what we're expecting - let errors = self.compare_output(UI_FIXED, &fixed_code, &expected_fixed); - if errors > 0 { - println!("To update references, run this command from build directory:"); - let relative_path_to_file = self.testpaths - .relative_dir - .join(self.testpaths.file.file_name().unwrap()); - println!( - "{}/update-references.sh '{}' '{}'", - self.config.src_base.display(), - self.config.build_base.display(), - relative_path_to_file.display() - ); - self.fatal_proc_rec( - &format!("{} errors occurred comparing output.", errors), - &proc_res, - ); - } - - // And finally, compile the fixed code and make sure it both succeeds - // and has no diagnostics. - let mut rustc = self.make_compile_args( - &self.testpaths.file.with_extension(UI_FIXED), - TargetLocation::ThisFile(self.make_exe_name()), - ); - rustc.arg("-L").arg(&self.aux_output_dir_name()); - let res = self.compose_and_run_compiler(rustc, None); - if !res.status.success() { - self.fatal_proc_rec("failed to compile fixed code", &res); - } - if !res.stderr.is_empty() { - self.fatal_proc_rec("fixed code is still producing diagnostics", &res); - } - } } struct ProcArgs { -- cgit 1.4.1-3-g733a5 From c338bd539ea9ab1d33c0af8c6deed0cf4738b70c Mon Sep 17 00:00:00 2001 From: John Kåre Alsaker Date: Tue, 20 Mar 2018 01:18:08 +0100 Subject: Fix libtest-json test --- src/test/run-make-fulldeps/libtest-json/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/test/run-make-fulldeps/libtest-json/Makefile b/src/test/run-make-fulldeps/libtest-json/Makefile index ec91ddfb9f9..a0bc8cf6688 100644 --- a/src/test/run-make-fulldeps/libtest-json/Makefile +++ b/src/test/run-make-fulldeps/libtest-json/Makefile @@ -6,7 +6,7 @@ OUTPUT_FILE := $(TMPDIR)/libtest-json-output.json all: $(RUSTC) --test f.rs - $(call RUN,f) -Z unstable-options --test-threads=1 --format=json > $(OUTPUT_FILE) || true + RUST_BACKTRACE=0 $(call RUN,f) -Z unstable-options --test-threads=1 --format=json > $(OUTPUT_FILE) || true cat $(OUTPUT_FILE) | "$(PYTHON)" validate_json.py -- cgit 1.4.1-3-g733a5 From 2b4675b1fcb3bd50224cf8d7127870f316c05e5b Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 1 May 2018 09:46:11 -0400 Subject: add `Location::START` const --- src/librustc/mir/mod.rs | 5 +++++ src/librustc_mir/borrow_check/nll/type_check/input_output.rs | 4 ++-- src/librustc_mir/transform/elaborate_drops.rs | 4 ++-- 3 files changed, 9 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 55bfbed0b39..37f6d47ff84 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1978,6 +1978,11 @@ impl fmt::Debug for Location { } impl Location { + pub const START: Location = Location { + block: START_BLOCK, + statement_index: 0, + }; + /// Returns the location immediately after this one within the enclosing block. /// /// Note that if this location represents a terminator, then the diff --git a/src/librustc_mir/borrow_check/nll/type_check/input_output.rs b/src/librustc_mir/borrow_check/nll/type_check/input_output.rs index b1aeae0b76b..beb1a26ae70 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/input_output.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/input_output.rs @@ -112,7 +112,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { let anon_defn_ty = anon_defn_ty.subst(tcx, anon_decl.substs); let anon_defn_ty = renumber::renumber_regions( cx.infcx, - TyContext::Location(start_position), + TyContext::Location(Location::START), &anon_defn_ty, ); debug!( @@ -134,7 +134,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { }).unwrap_or_else(|terr| { span_mirbug!( self, - start_position, + Location::START, "equate_inputs_and_outputs: `{:?}=={:?}` failed with `{:?}`", output_ty, mir_output_ty, diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs index 8b771fcf493..5397d18cdd7 100644 --- a/src/librustc_mir/transform/elaborate_drops.rs +++ b/src/librustc_mir/transform/elaborate_drops.rs @@ -550,7 +550,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { } fn drop_flags_on_init(&mut self) { - let loc = Location { block: START_BLOCK, statement_index: 0 }; + let loc = Location::START; let span = self.patch.source_info_for_location(self.mir, loc).span; let false_ = self.constant_bool(span, false); for flag in self.drop_flags.values() { @@ -576,7 +576,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { } fn drop_flags_for_args(&mut self) { - let loc = Location { block: START_BLOCK, statement_index: 0 }; + let loc = Location::START; dataflow::drop_flag_effects_for_function_entry( self.tcx, self.mir, self.env, |path, ds| { self.set_drop_flag(loc, path, ds); -- cgit 1.4.1-3-g733a5 From 81905a15c1f466fa6f57cf62d5277efcd01fbb9b Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 1 May 2018 10:48:04 -0400 Subject: use `crate` visibility modifier --- src/librustc_mir/borrow_check/nll/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index 3ca1bd23e86..a42ce3a2d3b 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -29,10 +29,10 @@ use self::mir_util::PassWhere; mod constraint_generation; pub mod explain_borrow; -pub(crate) mod region_infer; +crate mod region_infer; mod renumber; mod subtype_constraint_generation; -pub(crate) mod type_check; +crate mod type_check; mod universal_regions; use self::region_infer::RegionInferenceContext; -- cgit 1.4.1-3-g733a5 From 53eb9e582f41d39e8f320c6e5a959605ec9daf5f Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 1 May 2018 10:50:05 -0400 Subject: add `Locations::All` as a concept In particular, type annotations given by the user must hold at all points in the program. This doesn't affect current analysis but will affect fact generation later. --- src/librustc_mir/borrow_check/nll/mod.rs | 1 - .../nll/subtype_constraint_generation.rs | 23 +++---- .../borrow_check/nll/type_check/input_output.rs | 27 ++++---- .../borrow_check/nll/type_check/mod.rs | 73 ++++++++++++++++------ 4 files changed, 74 insertions(+), 50 deletions(-) (limited to 'src') diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index a42ce3a2d3b..411bf5b55ed 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -38,7 +38,6 @@ mod universal_regions; use self::region_infer::RegionInferenceContext; use self::universal_regions::UniversalRegions; - /// Rewrites the regions in the MIR to use NLL variables, also /// scraping out the set of universal regions (e.g., region parameters) /// declared on the function. That set will need to be given to diff --git a/src/librustc_mir/borrow_check/nll/subtype_constraint_generation.rs b/src/librustc_mir/borrow_check/nll/subtype_constraint_generation.rs index 32728145b29..05b61f25a39 100644 --- a/src/librustc_mir/borrow_check/nll/subtype_constraint_generation.rs +++ b/src/librustc_mir/borrow_check/nll/subtype_constraint_generation.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc::mir::Mir; +use rustc::mir::{Location, Mir}; use rustc::infer::region_constraints::Constraint; use rustc::infer::region_constraints::RegionConstraintData; use rustc::infer::region_constraints::{Verify, VerifyBound}; @@ -65,7 +65,11 @@ impl<'cx, 'tcx> SubtypeConstraintGenerator<'cx, 'tcx> { givens, } = data; - let span = self.mir.source_info(locations.from_location).span; + let span = self.mir + .source_info(locations.from_location().unwrap_or(Location::START)) + .span; + + let at_location = locations.at_location().unwrap_or(Location::START); for constraint in constraints.keys() { debug!("generate: constraint: {:?}", constraint); @@ -83,8 +87,7 @@ impl<'cx, 'tcx> SubtypeConstraintGenerator<'cx, 'tcx> { // reverse direction, because `regioncx` talks about // "outlives" (`>=`) whereas the region constraints // talk about `<=`. - self.regioncx - .add_outlives(span, b_vid, a_vid, locations.at_location); + self.regioncx.add_outlives(span, b_vid, a_vid, at_location); } for verify in verifys { @@ -109,7 +112,7 @@ impl<'cx, 'tcx> SubtypeConstraintGenerator<'cx, 'tcx> { let lower_bound = self.to_region_vid(verify.region); - let point = locations.at_location; + let point = locations.at_location().unwrap_or(Location::START); let test = self.verify_bound_to_region_test(&verify.bound); @@ -149,14 +152,6 @@ impl<'cx, 'tcx> SubtypeConstraintGenerator<'cx, 'tcx> { } fn to_region_vid(&self, r: ty::Region<'tcx>) -> ty::RegionVid { - // Every region that we see in the constraints came from the - // MIR or from the parameter environment. If the former, it - // will be a region variable. If the latter, it will be in - // the set of universal regions *somewhere*. - if let ty::ReVar(vid) = r { - *vid - } else { - self.regioncx.to_region_vid(r) - } + self.regioncx.to_region_vid(r) } } diff --git a/src/librustc_mir/borrow_check/nll/type_check/input_output.rs b/src/librustc_mir/borrow_check/nll/type_check/input_output.rs index beb1a26ae70..2b1878c33e9 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/input_output.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/input_output.rs @@ -29,7 +29,7 @@ use rustc::traits::PredicateObligations; use rustc_data_structures::indexed_vec::Idx; -use super::{AtLocation, TypeChecker}; +use super::{Locations, TypeChecker}; impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { pub(super) fn equate_inputs_and_outputs( @@ -47,26 +47,21 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } = universal_regions; let infcx = self.infcx; - let start_position = Location { - block: START_BLOCK, - statement_index: 0, - }; - // Equate expected input tys with those in the MIR. let argument_locals = (1..).map(Local::new); for (&unnormalized_input_ty, local) in unnormalized_input_tys.iter().zip(argument_locals) { - let input_ty = self.normalize(&unnormalized_input_ty, start_position); + let input_ty = self.normalize(&unnormalized_input_ty, Locations::All); let mir_input_ty = mir.local_decls[local].ty; - self.equate_normalized_input_or_output(start_position, input_ty, mir_input_ty); + self.equate_normalized_input_or_output(input_ty, mir_input_ty); } assert!( mir.yield_ty.is_some() && universal_regions.yield_ty.is_some() || mir.yield_ty.is_none() && universal_regions.yield_ty.is_none() - ); + ); if let Some(mir_yield_ty) = mir.yield_ty { let ur_yield_ty = universal_regions.yield_ty.unwrap(); - self.equate_normalized_input_or_output(start_position, ur_yield_ty, mir_yield_ty); + self.equate_normalized_input_or_output(ur_yield_ty, mir_yield_ty); } // Return types are a bit more complex. They may contain existential `impl Trait` @@ -75,13 +70,13 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { "equate_inputs_and_outputs: unnormalized_output_ty={:?}", unnormalized_output_ty ); - let output_ty = self.normalize(&unnormalized_output_ty, start_position); + let output_ty = self.normalize(&unnormalized_output_ty, Locations::All); debug!( "equate_inputs_and_outputs: normalized output_ty={:?}", output_ty ); let mir_output_ty = mir.local_decls[RETURN_PLACE].ty; - let anon_type_map = self.fully_perform_op(start_position.at_self(), |cx| { + let anon_type_map = self.fully_perform_op(Locations::All, |cx| { let mut obligations = ObligationAccumulator::default(); let (output_ty, anon_type_map) = obligations.add(infcx.instantiate_anon_types( @@ -148,7 +143,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { // prove that `T: Iterator` where `T` is the type we // instantiated it with). if let Some(anon_type_map) = anon_type_map { - self.fully_perform_op(start_position.at_self(), |_cx| { + self.fully_perform_op(Locations::All, |_cx| { infcx.constrain_anon_types(&anon_type_map, universal_regions); Ok(InferOk { value: (), @@ -158,13 +153,13 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } } - fn equate_normalized_input_or_output(&mut self, location: Location, a: Ty<'tcx>, b: Ty<'tcx>) { + fn equate_normalized_input_or_output(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) { debug!("equate_normalized_input_or_output(a={:?}, b={:?})", a, b); - if let Err(terr) = self.eq_types(a, b, location.at_self()) { + if let Err(terr) = self.eq_types(a, b, Locations::All) { span_mirbug!( self, - location, + Location::START, "equate_normalized_input_or_output: `{:?}=={:?}` failed with `{:?}`", a, b, diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index a21b9196bad..ec98a0a02c0 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -619,16 +619,35 @@ pub struct OutlivesSet<'tcx> { } #[derive(Copy, Clone, Debug)] -pub struct Locations { - /// The location in the MIR that generated these constraints. - /// This is intended for error reporting and diagnosis; the - /// constraints may *take effect* at a distinct spot. - pub from_location: Location, - - /// The constraints must be met at this location. In terms of the - /// NLL RFC, when you have a constraint `R1: R2 @ P`, this field - /// is the `P` value. - pub at_location: Location, +pub enum Locations { + All, + Pair { + /// The location in the MIR that generated these constraints. + /// This is intended for error reporting and diagnosis; the + /// constraints may *take effect* at a distinct spot. + from_location: Location, + + /// The constraints must be met at this location. In terms of the + /// NLL RFC, when you have a constraint `R1: R2 @ P`, this field + /// is the `P` value. + at_location: Location, + } +} + +impl Locations { + pub fn from_location(&self) -> Option { + match self { + Locations::All => None, + Locations::Pair { from_location, .. } => Some(*from_location), + } + } + + pub fn at_location(&self) -> Option { + match self { + Locations::All => None, + Locations::Pair { at_location, .. } => Some(*at_location), + } + } } impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { @@ -770,7 +789,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { "check_stmt: user_assert_ty ty={:?} local_ty={:?}", ty, local_ty ); - if let Err(terr) = self.eq_types(ty, local_ty, location.at_self()) { + if let Err(terr) = self.eq_types(ty, local_ty, Locations::All) { span_mirbug!( self, stmt, @@ -820,7 +839,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { let place_ty = location.ty(mir, tcx).to_ty(tcx); let rv_ty = value.ty(mir, tcx); - let locations = Locations { + let locations = Locations::Pair { from_location: term_location, at_location: target.start_location(), }; @@ -839,7 +858,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { // *both* blocks, so we need to ensure that it holds // at both locations. if let Some(unwind) = unwind { - let locations = Locations { + let locations = Locations::Pair { from_location: term_location, at_location: unwind.start_location(), }; @@ -971,7 +990,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { match *destination { Some((ref dest, target_block)) => { let dest_ty = dest.ty(mir, tcx).to_ty(tcx); - let locations = Locations { + let locations = Locations::Pair { from_location: term_location, at_location: target_block.start_location(), }; @@ -1375,7 +1394,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { }; let operand_ty = operand.ty(mir, tcx); if let Err(terr) = - self.sub_types(operand_ty, field_ty, location.at_successor_within_block()) + self.sub_types(operand_ty, field_ty, location.at_self()) { span_mirbug!( self, @@ -1514,12 +1533,12 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } } - fn normalize(&mut self, value: &T, location: Location) -> T + fn normalize(&mut self, value: &T, location: impl ToLocations) -> T where T: fmt::Debug + TypeFoldable<'tcx>, { debug!("normalize(value={:?}, location={:?})", value, location); - self.fully_perform_op(location.at_self(), |this| { + self.fully_perform_op(location.to_locations(), |this| { let Normalized { value, obligations } = this.infcx .at(&this.misc(this.last_span), this.param_env) .normalize(value) @@ -1585,16 +1604,32 @@ trait AtLocation { impl AtLocation for Location { fn at_self(self) -> Locations { - Locations { + Locations::Pair { from_location: self, at_location: self, } } fn at_successor_within_block(self) -> Locations { - Locations { + Locations::Pair { from_location: self, at_location: self.successor_within_block(), } } } + +trait ToLocations: fmt::Debug + Copy { + fn to_locations(self) -> Locations; +} + +impl ToLocations for Locations { + fn to_locations(self) -> Locations { + self + } +} + +impl ToLocations for Location { + fn to_locations(self) -> Locations { + self.at_self() + } +} -- cgit 1.4.1-3-g733a5 From 74bb9171cc50cbe560b2e780dbb1a1c2285d7886 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 1 May 2018 10:03:36 -0400 Subject: add location table This will be used in fact generation. --- src/librustc_mir/borrow_check/location.rs | 126 ++++++++++++++++++++++++++++++ src/librustc_mir/borrow_check/mod.rs | 4 + src/librustc_mir/borrow_check/nll/mod.rs | 2 + 3 files changed, 132 insertions(+) create mode 100644 src/librustc_mir/borrow_check/location.rs (limited to 'src') diff --git a/src/librustc_mir/borrow_check/location.rs b/src/librustc_mir/borrow_check/location.rs new file mode 100644 index 00000000000..e09f0ee9e2a --- /dev/null +++ b/src/librustc_mir/borrow_check/location.rs @@ -0,0 +1,126 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(dead_code)] // TODO -- will be used in a later commit, remove then + +use rustc::mir::{BasicBlock, Location, Mir}; +use rustc_data_structures::indexed_vec::{Idx, IndexVec}; + +/// Maps between a MIR Location, which identifies the a particular +/// statement within a basic block, to a "rich location", which +/// identifies at a finer granularity. In particular, we distinguish +/// the *start* of a statement and the *mid-point*. The mid-point is +/// the point *just* before the statement takes effect; in particular, +/// for an assignment `A = B`, it is the point where B is about to be +/// written into A. This mid-point is a kind of hack to work around +/// our inability to track the position information at sufficient +/// granularity through outlives relations; however, the rich location +/// table serves another purpose: it compresses locations from +/// multiple words into a single u32. +crate struct LocationTable { + num_points: usize, + statements_before_block: IndexVec, +} + +newtype_index!(LocationIndex { DEBUG_FORMAT = "LocationIndex({})" }); + +#[derive(Copy, Clone, Debug)] +crate enum RichLocation { + Start(Location), + Mid(Location), +} + +impl LocationTable { + crate fn new(mir: &Mir<'_>) -> Self { + let mut num_points = 0; + let statements_before_block = mir.basic_blocks() + .iter() + .map(|block_data| { + let v = num_points; + num_points += (block_data.statements.len() + 1) * 2; + v + }) + .collect(); + + debug!( + "LocationTable(statements_before_block={:#?})", + statements_before_block + ); + debug!("LocationTable: num_points={:#?}", num_points); + + Self { + num_points, + statements_before_block, + } + } + + #[allow(dead_code)] // TODO + crate fn all_points(&self) -> impl Iterator { + (0..self.num_points).map(LocationIndex::new) + } + + crate fn start_index(&self, location: Location) -> LocationIndex { + let Location { + block, + statement_index, + } = location; + let start_index = self.statements_before_block[block]; + LocationIndex::new(start_index + statement_index * 2) + } + + crate fn mid_index(&self, location: Location) -> LocationIndex { + let Location { + block, + statement_index, + } = location; + let start_index = self.statements_before_block[block]; + LocationIndex::new(start_index + statement_index * 2 + 1) + } + + crate fn to_location(&self, index: LocationIndex) -> RichLocation { + let point_index = index.index(); + + // Find the basic block. We have a vector with the + // starting index of the statement in each block. Imagine + // we have statement #22, and we have a vector like: + // + // [0, 10, 20] + // + // In that case, this represents point_index 2 of + // basic block BB2. We know this because BB0 accounts for + // 0..10, BB1 accounts for 11..20, and BB2 accounts for + // 20... + // + // To compute this, we could do a binary search, but + // because I am lazy we instead iterate through to find + // the last point where the "first index" (0, 10, or 20) + // was less than the statement index (22). In our case, this will + // be (BB2, 20). + let (block, &first_index) = self.statements_before_block + .iter_enumerated() + .filter(|(_, first_index)| **first_index <= point_index) + .last() + .unwrap(); + + let statement_index = (point_index - first_index) / 2; + if index.is_start() { + RichLocation::Start(Location { block, statement_index }) + } else { + RichLocation::Mid(Location { block, statement_index }) + } + } +} + +impl LocationIndex { + fn is_start(&self) -> bool { + // even indices are start points; odd indices are mid points + (self.index() % 2) == 0 + } +} diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index c619f350f58..3e3f510e308 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -50,12 +50,14 @@ use std::iter; use self::borrow_set::{BorrowSet, BorrowData}; use self::flows::Flows; +use self::location::LocationTable; use self::prefixes::PrefixSet; use self::MutateMode::{JustWrite, WriteAndRead}; crate mod borrow_set; mod error_reporting; mod flows; +mod location; crate mod place_ext; mod prefixes; @@ -110,6 +112,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( let mut mir: Mir<'tcx> = input_mir.clone(); let free_regions = nll::replace_regions_in_mir(infcx, def_id, param_env, &mut mir); let mir = &mir; // no further changes + let location_table = &LocationTable::new(mir); let move_data: MoveData<'tcx> = match MoveData::gather_moves(mir, tcx) { Ok(move_data) => move_data, @@ -199,6 +202,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( def_id, free_regions, mir, + location_table, param_env, &mut flow_inits, &mdpe.move_data, diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index 411bf5b55ed..80ad3ecb9f8 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -9,6 +9,7 @@ // except according to those terms. use borrow_check::borrow_set::BorrowSet; +use borrow_check::location::LocationTable; use rustc::hir::def_id::DefId; use rustc::mir::{ClosureRegionRequirements, ClosureOutlivesSubject, Mir}; use rustc::infer::InferCtxt; @@ -70,6 +71,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>( def_id: DefId, universal_regions: UniversalRegions<'tcx>, mir: &Mir<'tcx>, + _location_table: &LocationTable, param_env: ty::ParamEnv<'gcx>, flow_inits: &mut FlowAtLocation>, move_data: &MoveData<'tcx>, -- cgit 1.4.1-3-g733a5 From eaac10ec0d7426b53386c053981de02a3aec2fed Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 1 May 2018 10:49:11 -0400 Subject: add `-Znll-facts` switch that dumps facts for new analysis --- src/librustc/session/config.rs | 2 + src/librustc_mir/borrow_check/location.rs | 2 - .../borrow_check/nll/constraint_generation.rs | 187 ++++++++++++++++---- src/librustc_mir/borrow_check/nll/facts.rs | 194 +++++++++++++++++++++ src/librustc_mir/borrow_check/nll/mod.rs | 59 +++++-- .../nll/subtype_constraint_generation.rs | 50 +++++- src/librustc_mir/lib.rs | 1 + 7 files changed, 441 insertions(+), 54 deletions(-) create mode 100644 src/librustc_mir/borrow_check/nll/facts.rs (limited to 'src') diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index dc97c941567..0beda679e69 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1250,6 +1250,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "choose which RELRO level to use"), nll_subminimal_causes: bool = (false, parse_bool, [UNTRACKED], "when tracking region error causes, accept subminimal results for faster execution."), + nll_facts: bool = (false, parse_bool, [UNTRACKED], + "dump facts from NLL analysis into side files"), disable_nll_user_type_assert: bool = (false, parse_bool, [UNTRACKED], "disable user provided type assertion in NLL"), trans_time_graph: bool = (false, parse_bool, [UNTRACKED], diff --git a/src/librustc_mir/borrow_check/location.rs b/src/librustc_mir/borrow_check/location.rs index e09f0ee9e2a..1284a5b0e2a 100644 --- a/src/librustc_mir/borrow_check/location.rs +++ b/src/librustc_mir/borrow_check/location.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(dead_code)] // TODO -- will be used in a later commit, remove then - use rustc::mir::{BasicBlock, Location, Mir}; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; diff --git a/src/librustc_mir/borrow_check/nll/constraint_generation.rs b/src/librustc_mir/borrow_check/nll/constraint_generation.rs index afaedecdf0a..d34e9434fbf 100644 --- a/src/librustc_mir/borrow_check/nll/constraint_generation.rs +++ b/src/librustc_mir/borrow_check/nll/constraint_generation.rs @@ -8,28 +8,37 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use borrow_check::borrow_set::BorrowSet; +use borrow_check::location::LocationTable; +use borrow_check::nll::facts::AllFacts; use rustc::hir; -use rustc::mir::{BasicBlock, BasicBlockData, Location, Place, Mir, Rvalue}; +use rustc::infer::InferCtxt; +use rustc::mir::visit::TyContext; use rustc::mir::visit::Visitor; use rustc::mir::Place::Projection; -use rustc::mir::{Local, PlaceProjection, ProjectionElem}; -use rustc::mir::visit::TyContext; -use rustc::infer::InferCtxt; -use rustc::ty::{self, CanonicalTy, ClosureSubsts}; -use rustc::ty::subst::Substs; +use rustc::mir::{BasicBlock, BasicBlockData, Location, Mir, Place, Rvalue}; +use rustc::mir::{Local, PlaceProjection, ProjectionElem, Statement, Terminator}; use rustc::ty::fold::TypeFoldable; +use rustc::ty::subst::Substs; +use rustc::ty::{self, CanonicalTy, ClosureSubsts}; +use super::region_infer::{Cause, RegionInferenceContext}; use super::ToRegionVid; -use super::region_infer::{RegionInferenceContext, Cause}; pub(super) fn generate_constraints<'cx, 'gcx, 'tcx>( infcx: &InferCtxt<'cx, 'gcx, 'tcx>, regioncx: &mut RegionInferenceContext<'tcx>, + all_facts: &mut Option, + location_table: &LocationTable, mir: &Mir<'tcx>, + borrow_set: &BorrowSet<'tcx>, ) { let mut cg = ConstraintGeneration { + borrow_set, infcx, regioncx, + location_table, + all_facts, mir, }; @@ -41,8 +50,11 @@ pub(super) fn generate_constraints<'cx, 'gcx, 'tcx>( /// 'cg = the duration of the constraint generation process itself. struct ConstraintGeneration<'cg, 'cx: 'cg, 'gcx: 'tcx, 'tcx: 'cx> { infcx: &'cg InferCtxt<'cx, 'gcx, 'tcx>, + all_facts: &'cg mut Option, + location_table: &'cg LocationTable, regioncx: &'cg mut RegionInferenceContext<'tcx>, mir: &'cg Mir<'tcx>, + borrow_set: &'cg BorrowSet<'tcx>, } impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx, 'tcx> { @@ -68,12 +80,14 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx /// call. Make them live at the location where they appear. fn visit_ty(&mut self, ty: &ty::Ty<'tcx>, ty_context: TyContext) { match ty_context { - TyContext::ReturnTy(source_info) | - TyContext::YieldTy(source_info) | - TyContext::LocalDecl { source_info, .. } => { - span_bug!(source_info.span, - "should not be visiting outside of the CFG: {:?}", - ty_context); + TyContext::ReturnTy(source_info) + | TyContext::YieldTy(source_info) + | TyContext::LocalDecl { source_info, .. } => { + span_bug!( + source_info.span, + "should not be visiting outside of the CFG: {:?}", + ty_context + ); } TyContext::Location(location) => { self.add_regular_live_constraint(*ty, location, Cause::LiveOther(location)); @@ -90,25 +104,117 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx self.super_closure_substs(substs); } + fn visit_statement( + &mut self, + block: BasicBlock, + statement: &Statement<'tcx>, + location: Location, + ) { + if let Some(all_facts) = self.all_facts { + all_facts.cfg_edge.push(( + self.location_table.start_index(location), + self.location_table.mid_index(location), + )); + + all_facts.cfg_edge.push(( + self.location_table.mid_index(location), + self.location_table + .start_index(location.successor_within_block()), + )); + } + + self.super_statement(block, statement, location); + } + + fn visit_assign( + &mut self, + block: BasicBlock, + place: &Place<'tcx>, + rvalue: &Rvalue<'tcx>, + location: Location, + ) { + // When we see `X = ...`, then kill borrows of + // `(*X).foo` and so forth. + if let Some(all_facts) = self.all_facts { + if let Place::Local(temp) = place { + if let Some(borrow_indices) = self.borrow_set.local_map.get(temp) { + for &borrow_index in borrow_indices { + let location_index = self.location_table.mid_index(location); + all_facts.killed.push((borrow_index, location_index)); + } + } + } + } + + self.super_assign(block, place, rvalue, location); + } + + fn visit_terminator( + &mut self, + block: BasicBlock, + terminator: &Terminator<'tcx>, + location: Location, + ) { + if let Some(all_facts) = self.all_facts { + all_facts.cfg_edge.push(( + self.location_table.start_index(location), + self.location_table.mid_index(location), + )); + + for successor_block in terminator.successors() { + all_facts.cfg_edge.push(( + self.location_table.mid_index(location), + self.location_table + .start_index(successor_block.start_location()), + )); + } + } + + self.super_terminator(block, terminator, location); + } + fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) { debug!("visit_rvalue(rvalue={:?}, location={:?})", rvalue, location); - // Look for an rvalue like: - // - // & L - // - // where L is the path that is borrowed. In that case, we have - // to add the reborrow constraints (which don't fall out - // naturally from the type-checker). - if let Rvalue::Ref(region, _bk, ref borrowed_lv) = *rvalue { - self.add_reborrow_constraint(location, region, borrowed_lv); + match rvalue { + Rvalue::Ref(region, _borrow_kind, borrowed_place) => { + // In some cases, e.g. when borrowing from an unsafe + // place, we don't bother to create a loan, since + // there are no conditions to validate. + if let Some(all_facts) = self.all_facts { + if let Some(borrow_index) = self.borrow_set.location_map.get(&location) { + let region_vid = region.to_region_vid(); + all_facts.borrow_region.push(( + region_vid, + *borrow_index, + self.location_table.mid_index(location), + )); + } + } + + // Look for an rvalue like: + // + // & L + // + // where L is the path that is borrowed. In that case, we have + // to add the reborrow constraints (which don't fall out + // naturally from the type-checker). + self.add_reborrow_constraint(location, region, borrowed_place); + } + + _ => { } } self.super_rvalue(rvalue, location); } - fn visit_user_assert_ty(&mut self, _c_ty: &CanonicalTy<'tcx>, - _local: &Local, _location: Location) { } + fn visit_user_assert_ty( + &mut self, + _c_ty: &CanonicalTy<'tcx>, + _local: &Local, + _location: Location, + ) { + } } impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> { @@ -122,8 +228,7 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> { { debug!( "add_regular_live_constraint(live_ty={:?}, location={:?})", - live_ty, - location + live_ty, location ); self.infcx @@ -144,8 +249,10 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> { ) { let mut borrowed_place = borrowed_place; - debug!("add_reborrow_constraint({:?}, {:?}, {:?})", - location, borrow_region, borrowed_place); + debug!( + "add_reborrow_constraint({:?}, {:?}, {:?})", + location, borrow_region, borrowed_place + ); while let Projection(box PlaceProjection { base, elem }) = borrowed_place { debug!("add_reborrow_constraint - iteration {:?}", borrowed_place); @@ -165,12 +272,20 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> { location.successor_within_block(), ); + if let Some(all_facts) = self.all_facts { + all_facts.outlives.push(( + ref_region.to_region_vid(), + borrow_region.to_region_vid(), + self.location_table.mid_index(location), + )); + } + match mutbl { hir::Mutability::MutImmutable => { // Immutable reference. We don't need the base // to be valid for the entire lifetime of // the borrow. - break + break; } hir::Mutability::MutMutable => { // Mutable reference. We *do* need the base @@ -199,19 +314,19 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> { } ty::TyRawPtr(..) => { // deref of raw pointer, guaranteed to be valid - break + break; } ty::TyAdt(def, _) if def.is_box() => { // deref of `Box`, need the base to be valid - propagate } - _ => bug!("unexpected deref ty {:?} in {:?}", base_ty, borrowed_place) + _ => bug!("unexpected deref ty {:?} in {:?}", base_ty, borrowed_place), } } - ProjectionElem::Field(..) | - ProjectionElem::Downcast(..) | - ProjectionElem::Index(..) | - ProjectionElem::ConstantIndex { .. } | - ProjectionElem::Subslice { .. } => { + ProjectionElem::Field(..) + | ProjectionElem::Downcast(..) + | ProjectionElem::Index(..) + | ProjectionElem::ConstantIndex { .. } + | ProjectionElem::Subslice { .. } => { // other field access } } diff --git a/src/librustc_mir/borrow_check/nll/facts.rs b/src/librustc_mir/borrow_check/nll/facts.rs new file mode 100644 index 00000000000..2802aa0dff4 --- /dev/null +++ b/src/librustc_mir/borrow_check/nll/facts.rs @@ -0,0 +1,194 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use borrow_check::location::{LocationIndex, LocationTable}; +use dataflow::indexes::BorrowIndex; +use rustc::ty::RegionVid; +use std::error::Error; +use std::fmt::Debug; +use std::fs::{self, File}; +use std::io::Write; +use std::path::Path; + +/// The "facts" which are the basis of the NLL borrow analysis. +#[derive(Default)] +crate struct AllFacts { + // `borrow_region(R, B, P)` -- the region R may refer to data from borrow B + // starting at the point P (this is usually the point *after* a borrow rvalue) + crate borrow_region: Vec<(RegionVid, BorrowIndex, LocationIndex)>, + + // universal_region(R) -- this is a "free region" within fn body + crate universal_region: Vec, + + // `cfg_edge(P,Q)` for each edge P -> Q in the control flow + crate cfg_edge: Vec<(LocationIndex, LocationIndex)>, + + // `killed(B,P)` when some prefix of the path borrowed at B is assigned at point P + crate killed: Vec<(BorrowIndex, LocationIndex)>, + + // `outlives(R1, R2, P)` when we require `R1@P: R2@P` + crate outlives: Vec<(RegionVid, RegionVid, LocationIndex)>, + + // `region_live_at(R, P)` when the region R appears in a live variable at P + crate region_live_at: Vec<(RegionVid, LocationIndex)>, +} + +impl AllFacts { + crate fn write_to_dir( + &self, + dir: impl AsRef, + location_table: &LocationTable, + ) -> Result<(), Box> { + let dir: &Path = dir.as_ref(); + fs::create_dir_all(dir)?; + let wr = FactWriter { location_table, dir }; + macro_rules! write_facts_to_path { + ($wr:ident . write_facts_to_path($this:ident . [ + $($field:ident,)* + ])) => { + $( + $wr.write_facts_to_path( + &$this.$field, + &format!("{}.facts", stringify!($field)) + )?; + )* + } + } + write_facts_to_path! { + wr.write_facts_to_path(self.[ + borrow_region, + universal_region, + cfg_edge, + killed, + outlives, + region_live_at, + ]) + } + Ok(()) + } +} + +struct FactWriter<'w> { + location_table: &'w LocationTable, + dir: &'w Path, +} + +impl<'w> FactWriter<'w> { + fn write_facts_to_path( + &self, + rows: &Vec, + file_name: &str, + ) -> Result<(), Box> + where + T: FactRow, + { + let file = &self.dir.join(file_name); + let mut file = File::create(file)?; + for row in rows { + row.write(&mut file, self.location_table)?; + } + Ok(()) + } +} + +trait FactRow { + fn write( + &self, + out: &mut File, + location_table: &LocationTable, + ) -> Result<(), Box>; +} + +impl FactRow for RegionVid { + fn write( + &self, + out: &mut File, + location_table: &LocationTable, + ) -> Result<(), Box> { + write_row(out, location_table, &[self]) + } +} + +impl FactRow for (A, B) +where + A: FactCell, + B: FactCell, +{ + fn write( + &self, + out: &mut File, + location_table: &LocationTable, + ) -> Result<(), Box> { + write_row(out, location_table, &[&self.0, &self.1]) + } +} + +impl FactRow for (A, B, C) +where + A: FactCell, + B: FactCell, + C: FactCell, +{ + fn write( + &self, + out: &mut File, + location_table: &LocationTable, + ) -> Result<(), Box> { + write_row(out, location_table, &[&self.0, &self.1, &self.2]) + } +} + +impl FactRow for (A, B, C, D) +where + A: FactCell, + B: FactCell, + C: FactCell, + D: FactCell, +{ + fn write( + &self, + out: &mut File, + location_table: &LocationTable, + ) -> Result<(), Box> { + write_row(out, location_table, &[&self.0, &self.1, &self.2, &self.3]) + } +} + +fn write_row( + out: &mut dyn Write, + location_table: &LocationTable, + columns: &[&dyn FactCell], +) -> Result<(), Box> { + for (index, c) in columns.iter().enumerate() { + let tail = if index == columns.len() - 1 { + "\n" + } else { + "\t" + }; + write!(out, "{:?}{}", c.to_string(location_table), tail)?; + } + Ok(()) +} + +trait FactCell { + fn to_string(&self, location_table: &LocationTable) -> String; +} + +impl FactCell for A { + default fn to_string(&self, _location_table: &LocationTable) -> String { + format!("{:?}", self) + } +} + +impl FactCell for LocationIndex { + fn to_string(&self, location_table: &LocationTable) -> String { + format!("{:?}", location_table.to_location(*self)) + } +} diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index 80ad3ecb9f8..0b1729294d8 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -10,32 +10,35 @@ use borrow_check::borrow_set::BorrowSet; use borrow_check::location::LocationTable; +use dataflow::move_paths::MoveData; +use dataflow::FlowAtLocation; +use dataflow::MaybeInitializedPlaces; use rustc::hir::def_id::DefId; -use rustc::mir::{ClosureRegionRequirements, ClosureOutlivesSubject, Mir}; use rustc::infer::InferCtxt; +use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Mir}; use rustc::ty::{self, RegionKind, RegionVid}; use rustc::util::nodemap::FxHashMap; use std::collections::BTreeSet; use std::fmt::Debug; use std::io; +use std::path::PathBuf; use transform::MirSource; use util::liveness::{LivenessResults, LocalSet}; -use dataflow::FlowAtLocation; -use dataflow::MaybeInitializedPlaces; -use dataflow::move_paths::MoveData; +use self::mir_util::PassWhere; use util as mir_util; use util::pretty::{self, ALIGN}; -use self::mir_util::PassWhere; mod constraint_generation; pub mod explain_borrow; +mod facts; crate mod region_infer; mod renumber; mod subtype_constraint_generation; crate mod type_check; mod universal_regions; +use self::facts::AllFacts; use self::region_infer::RegionInferenceContext; use self::universal_regions::UniversalRegions; @@ -71,11 +74,11 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>( def_id: DefId, universal_regions: UniversalRegions<'tcx>, mir: &Mir<'tcx>, - _location_table: &LocationTable, + location_table: &LocationTable, param_env: ty::ParamEnv<'gcx>, flow_inits: &mut FlowAtLocation>, move_data: &MoveData<'tcx>, - _borrow_set: &BorrowSet<'tcx>, + borrow_set: &BorrowSet<'tcx>, ) -> ( RegionInferenceContext<'tcx>, Option>, @@ -93,15 +96,47 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>( move_data, ); + let mut all_facts = if infcx.tcx.sess.opts.debugging_opts.nll_facts { + Some(AllFacts::default()) + } else { + None + }; + + if let Some(all_facts) = &mut all_facts { + all_facts + .universal_region + .extend(universal_regions.universal_regions()); + } + // Create the region inference context, taking ownership of the region inference // data that was contained in `infcx`. let var_origins = infcx.take_region_var_origins(); - let mut regioncx = RegionInferenceContext::new(var_origins, universal_regions, mir); - subtype_constraint_generation::generate(&mut regioncx, mir, constraint_sets); - + let mut regioncx = + RegionInferenceContext::new(var_origins, universal_regions, mir); + + // Generate various constraints. + subtype_constraint_generation::generate( + &mut regioncx, + &mut all_facts, + location_table, + mir, + constraint_sets, + ); + constraint_generation::generate_constraints( + infcx, + &mut regioncx, + &mut all_facts, + location_table, + &mir, + borrow_set, + ); - // Generate non-subtyping constraints. - constraint_generation::generate_constraints(infcx, &mut regioncx, &mir); + // Dump facts if requested. + if let Some(all_facts) = all_facts { + let def_path = infcx.tcx.hir.def_path(def_id); + let dir_path = PathBuf::from("nll-facts").join(def_path.to_filename_friendly_no_crate()); + all_facts.write_to_dir(dir_path, location_table).unwrap(); + } // Solve the region constraints. let closure_region_requirements = regioncx.solve(infcx, &mir, def_id); diff --git a/src/librustc_mir/borrow_check/nll/subtype_constraint_generation.rs b/src/librustc_mir/borrow_check/nll/subtype_constraint_generation.rs index 05b61f25a39..9db19085a39 100644 --- a/src/librustc_mir/borrow_check/nll/subtype_constraint_generation.rs +++ b/src/librustc_mir/borrow_check/nll/subtype_constraint_generation.rs @@ -8,14 +8,17 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use rustc::mir::{Location, Mir}; +use borrow_check::location::LocationTable; +use borrow_check::nll::facts::AllFacts; use rustc::infer::region_constraints::Constraint; use rustc::infer::region_constraints::RegionConstraintData; use rustc::infer::region_constraints::{Verify, VerifyBound}; +use rustc::mir::{Location, Mir}; use rustc::ty; +use std::iter; use syntax::codemap::Span; -use super::region_infer::{TypeTest, RegionInferenceContext, RegionTest}; +use super::region_infer::{RegionInferenceContext, RegionTest, TypeTest}; use super::type_check::Locations; use super::type_check::MirTypeckRegionConstraints; use super::type_check::OutlivesSet; @@ -27,19 +30,30 @@ use super::type_check::OutlivesSet; /// them into the NLL `RegionInferenceContext`. pub(super) fn generate<'tcx>( regioncx: &mut RegionInferenceContext<'tcx>, + all_facts: &mut Option, + location_table: &LocationTable, mir: &Mir<'tcx>, constraints: &MirTypeckRegionConstraints<'tcx>, ) { - SubtypeConstraintGenerator { regioncx, mir }.generate(constraints); + SubtypeConstraintGenerator { + regioncx, + location_table, + mir, + }.generate(constraints, all_facts); } struct SubtypeConstraintGenerator<'cx, 'tcx: 'cx> { regioncx: &'cx mut RegionInferenceContext<'tcx>, + location_table: &'cx LocationTable, mir: &'cx Mir<'tcx>, } impl<'cx, 'tcx> SubtypeConstraintGenerator<'cx, 'tcx> { - fn generate(&mut self, constraints: &MirTypeckRegionConstraints<'tcx>) { + fn generate( + &mut self, + constraints: &MirTypeckRegionConstraints<'tcx>, + all_facts: &mut Option, + ) { let MirTypeckRegionConstraints { liveness_set, outlives_sets, @@ -57,6 +71,17 @@ impl<'cx, 'tcx> SubtypeConstraintGenerator<'cx, 'tcx> { self.regioncx.add_live_point(region_vid, *location, &cause); } + if let Some(all_facts) = all_facts { + all_facts + .region_live_at + .extend(liveness_set.into_iter().flat_map(|(region, location, _)| { + let r = self.to_region_vid(region); + let p1 = self.location_table.start_index(*location); + let p2 = self.location_table.mid_index(*location); + iter::once((r, p1)).chain(iter::once((r, p2))) + })); + } + for OutlivesSet { locations, data } in outlives_sets { debug!("generate: constraints at: {:#?}", locations); let RegionConstraintData { @@ -88,6 +113,23 @@ impl<'cx, 'tcx> SubtypeConstraintGenerator<'cx, 'tcx> { // "outlives" (`>=`) whereas the region constraints // talk about `<=`. self.regioncx.add_outlives(span, b_vid, a_vid, at_location); + + // In the new analysis, all outlives relations etc + // "take effect" at the mid point of the statement + // that requires them, so ignore the `at_location`. + if let Some(all_facts) = all_facts { + if let Some(from_location) = locations.from_location() { + all_facts.outlives.push(( + b_vid, + a_vid, + self.location_table.mid_index(from_location), + )); + } else { + for location in self.location_table.all_points() { + all_facts.outlives.push((b_vid, a_vid, location)); + } + } + } } for verify in verifys { diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index 95cf3b8ddc6..2545ba3a94a 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -34,6 +34,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! #![feature(inclusive_range_methods)] #![feature(crate_visibility_modifier)] #![feature(never_type)] +#![feature(specialization)] #![cfg_attr(stage0, feature(try_trait))] extern crate arena; -- cgit 1.4.1-3-g733a5 From 9788479784a22af8e7c1008c7c63026d7c9338ca Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 1 May 2018 15:00:31 -0400 Subject: remove `#[allow(dead_code)]` --- src/librustc_mir/borrow_check/location.rs | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/librustc_mir/borrow_check/location.rs b/src/librustc_mir/borrow_check/location.rs index 1284a5b0e2a..28da1b2d733 100644 --- a/src/librustc_mir/borrow_check/location.rs +++ b/src/librustc_mir/borrow_check/location.rs @@ -59,7 +59,6 @@ impl LocationTable { } } - #[allow(dead_code)] // TODO crate fn all_points(&self) -> impl Iterator { (0..self.num_points).map(LocationIndex::new) } -- cgit 1.4.1-3-g733a5 From b36cbcb0c4ab342fdc575e323535965ce6711d37 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 4 May 2018 14:26:53 -0400 Subject: add a comment about Locations::All --- .../borrow_check/nll/type_check/mod.rs | 36 ++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'src') diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index ec98a0a02c0..42a1745addf 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -618,9 +618,45 @@ pub struct OutlivesSet<'tcx> { pub data: RegionConstraintData<'tcx>, } +/// The `Locations` type summarizes *where* region constraints are +/// required to hold. Normally, this is at a particular point which +/// created the obligation, but for constraints that the user gave, we +/// want the constraint to hold at all points. #[derive(Copy, Clone, Debug)] pub enum Locations { + /// Indicates that a type constraint should always be true. This + /// is particularly important in the new borrowck analysis for + /// things like the type of the return slot. Consider this + /// example: + /// + /// ``` + /// fn foo<'a>(x: &'a u32) -> &'a u32 { + /// let y = 22; + /// return &y; // error + /// } + /// ``` + /// + /// Here, we wind up with the signature from the return type being + /// something like `&'1 u32` where `'1` is a universal region. But + /// the type of the return slot `_0` is something like `&'2 u32` + /// where `'2` is an existential region variable. The type checker + /// requires that `&'2 u32 = &'1 u32` -- but at what point? In the + /// older NLL analysis, we required this only at the entry point + /// to the function. By the nature of the constraints, this wound + /// up propagating to all points reachable from start (because + /// `'1` -- as a universal region -- is live everywhere). In the + /// newer analysis, though, this doesn't work: `_0` is considered + /// dead at the start (it has no usable value) and hence this type + /// equality is basically a no-op. Then, later on, when we do `_0 + /// = &'3 y`, that region `'3` never winds up related to the + /// universal region `'1` and hence no error occurs. Therefore, we + /// use Locations::All instead, which ensures that the `'1` and + /// `'2` are equal everything. We also use this for other + /// user-given type annotations; e.g., if the user wrote `let mut + /// x: &'static u32 = ...`, we would ensure that all values + /// assigned to `x` are of `'static` lifetime. All, + Pair { /// The location in the MIR that generated these constraints. /// This is intended for error reporting and diagnosis; the -- cgit 1.4.1-3-g733a5 From 1e38eee63b0a0a3429a59dd756c852116b4d3615 Mon Sep 17 00:00:00 2001 From: Kornel Date: Fri, 4 May 2018 12:43:52 +0100 Subject: Suggest more helpful formatting string --- src/libcore/fmt/mod.rs | 11 ++++++----- src/test/ui/on-unimplemented/no-debug.stderr | 11 +++++++---- 2 files changed, 13 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 99e3012c9bf..5820fe58932 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -542,10 +542,10 @@ impl<'a> Display for Arguments<'a> { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_on_unimplemented( - on(crate_local, label="`{Self}` cannot be formatted using `:?`; \ - add `#[derive(Debug)]` or manually implement `{Debug}`"), + on(crate_local, label="`{Self}` cannot be formatted using `{{:?}}`", + note="add `#[derive(Debug)]` or manually implement `{Debug}`"), message="`{Self}` doesn't implement `{Debug}`", - label="`{Self}` cannot be formatted using `:?` because it doesn't implement `{Debug}`", + label="`{Self}` cannot be formatted using `{{:?}}` because it doesn't implement `{Debug}`", )] #[doc(alias = "{:?}")] #[lang = "debug_trait"] @@ -610,8 +610,9 @@ pub trait Debug { /// ``` #[rustc_on_unimplemented( message="`{Self}` doesn't implement `{Display}`", - label="`{Self}` cannot be formatted with the default formatter; \ - try using `:?` instead if you are using a format string", + label="`{Self}` cannot be formatted with the default formatter", + note="in format strings you may be able to use `{{:?}}` \ + (or {{:#?}} for pretty-print) instead", )] #[doc(alias = "{}")] #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/test/ui/on-unimplemented/no-debug.stderr b/src/test/ui/on-unimplemented/no-debug.stderr index 5d8f80e57b0..275cd91a435 100644 --- a/src/test/ui/on-unimplemented/no-debug.stderr +++ b/src/test/ui/on-unimplemented/no-debug.stderr @@ -2,16 +2,17 @@ error[E0277]: `Foo` doesn't implement `std::fmt::Debug` --> $DIR/no-debug.rs:20:27 | LL | println!("{:?} {:?}", Foo, Bar); - | ^^^ `Foo` cannot be formatted using `:?`; add `#[derive(Debug)]` or manually implement `std::fmt::Debug` + | ^^^ `Foo` cannot be formatted using `{:?}` | = help: the trait `std::fmt::Debug` is not implemented for `Foo` + = note: add `#[derive(Debug)]` or manually implement `std::fmt::Debug` = note: required by `std::fmt::Debug::fmt` error[E0277]: `no_debug::Bar` doesn't implement `std::fmt::Debug` --> $DIR/no-debug.rs:20:32 | LL | println!("{:?} {:?}", Foo, Bar); - | ^^^ `no_debug::Bar` cannot be formatted using `:?` because it doesn't implement `std::fmt::Debug` + | ^^^ `no_debug::Bar` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug` | = help: the trait `std::fmt::Debug` is not implemented for `no_debug::Bar` = note: required by `std::fmt::Debug::fmt` @@ -20,18 +21,20 @@ error[E0277]: `Foo` doesn't implement `std::fmt::Display` --> $DIR/no-debug.rs:21:23 | LL | println!("{} {}", Foo, Bar); - | ^^^ `Foo` cannot be formatted with the default formatter; try using `:?` instead if you are using a format string + | ^^^ `Foo` cannot be formatted with the default formatter | = help: the trait `std::fmt::Display` is not implemented for `Foo` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead = note: required by `std::fmt::Display::fmt` error[E0277]: `no_debug::Bar` doesn't implement `std::fmt::Display` --> $DIR/no-debug.rs:21:28 | LL | println!("{} {}", Foo, Bar); - | ^^^ `no_debug::Bar` cannot be formatted with the default formatter; try using `:?` instead if you are using a format string + | ^^^ `no_debug::Bar` cannot be formatted with the default formatter | = help: the trait `std::fmt::Display` is not implemented for `no_debug::Bar` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead = note: required by `std::fmt::Display::fmt` error: aborting due to 4 previous errors -- cgit 1.4.1-3-g733a5 From 1733f5e1c0a69c853adebf718fc7b4f81a1d257b Mon Sep 17 00:00:00 2001 From: kennytm Date: Sun, 6 May 2018 00:04:06 +0800 Subject: Added `./x.py test --no-doc` option. This enables `./x.py test --stage 0 src/libstd --no-doc` and ensures the stage2-rustc and rustdoc need to be built. --- src/bootstrap/builder.rs | 8 +++++--- src/bootstrap/flags.rs | 19 +++++++++++++------ src/bootstrap/lib.rs | 12 +++++++++++- src/bootstrap/test.rs | 12 +++++++++--- 4 files changed, 38 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 08bb8ab4815..408e61ef548 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -25,7 +25,7 @@ use compile; use install; use dist; use util::{exe, libdir, add_lib_path}; -use {Build, Mode}; +use {Build, Mode, DocTestsOption}; use cache::{INTERNER, Interned, Cache}; use check; use test; @@ -591,6 +591,8 @@ impl<'a> Builder<'a> { format!("{} {}", env::var("RUSTFLAGS").unwrap_or_default(), extra_args)); } + let want_rustdoc = self.doc_tests != DocTestsOption::No; + // Customize the compiler we're running. Specify the compiler to cargo // as our shim and then pass it some various options used to configure // how the actual compiler itself is called. @@ -607,7 +609,7 @@ impl<'a> Builder<'a> { .env("RUSTC_LIBDIR", self.rustc_libdir(compiler)) .env("RUSTC_RPATH", self.config.rust_rpath.to_string()) .env("RUSTDOC", self.out.join("bootstrap/debug/rustdoc")) - .env("RUSTDOC_REAL", if cmd == "doc" || cmd == "test" { + .env("RUSTDOC_REAL", if cmd == "doc" || (cmd == "test" && want_rustdoc) { self.rustdoc(compiler.host) } else { PathBuf::from("/path/to/nowhere/rustdoc/not/required") @@ -624,7 +626,7 @@ impl<'a> Builder<'a> { if let Some(ref error_format) = self.config.rustc_error_format { cargo.env("RUSTC_ERROR_FORMAT", error_format); } - if cmd != "build" && cmd != "check" { + if cmd != "build" && cmd != "check" && want_rustdoc { cargo.env("RUSTDOC_LIBDIR", self.rustc_libdir(self.compiler(2, self.config.build))); } diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 3eb9dca2aa8..fb7c8ba1351 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -19,7 +19,7 @@ use std::process; use getopts::Options; -use Build; +use {Build, DocTestsOption}; use config::Config; use metadata; use builder::Builder; @@ -62,7 +62,7 @@ pub enum Subcommand { test_args: Vec, rustc_args: Vec, fail_fast: bool, - doc_tests: bool, + doc_tests: DocTestsOption, }, Bench { paths: Vec, @@ -171,7 +171,8 @@ To learn more about a subcommand, run `./x.py -h`"); "extra options to pass the compiler when running tests", "ARGS", ); - opts.optflag("", "doc", "run doc tests"); + opts.optflag("", "no-doc", "do not run doc tests"); + opts.optflag("", "doc", "only run doc tests"); }, "bench" => { opts.optmulti("", "test-args", "extra arguments", "ARGS"); }, "clean" => { opts.optflag("", "all", "clean all build artifacts"); }, @@ -324,7 +325,13 @@ Arguments: test_args: matches.opt_strs("test-args"), rustc_args: matches.opt_strs("rustc-args"), fail_fast: !matches.opt_present("no-fail-fast"), - doc_tests: matches.opt_present("doc"), + doc_tests: if matches.opt_present("doc") { + DocTestsOption::Only + } else if matches.opt_present("no-doc") { + DocTestsOption::No + } else { + DocTestsOption::Yes + } } } "bench" => { @@ -411,10 +418,10 @@ impl Subcommand { } } - pub fn doc_tests(&self) -> bool { + pub fn doc_tests(&self) -> DocTestsOption { match *self { Subcommand::Test { doc_tests, .. } => doc_tests, - _ => false, + _ => DocTestsOption::Yes, } } } diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 0a7f0e5ff4e..624319485be 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -210,6 +210,16 @@ pub struct Compiler { host: Interned, } +#[derive(PartialEq, Eq, Copy, Clone, Debug)] +pub enum DocTestsOption { + // Default, run normal tests and doc tests. + Yes, + // Do not run any doc tests. + No, + // Only run doc tests. + Only, +} + /// Global configuration for the build system. /// /// This structure transitively contains all configuration for the build system. @@ -233,7 +243,7 @@ pub struct Build { rustfmt_info: channel::GitInfo, local_rebuild: bool, fail_fast: bool, - doc_tests: bool, + doc_tests: DocTestsOption, verbosity: usize, // Targets for which to build. diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index e8c40dfdb0a..0d430c30036 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -32,7 +32,7 @@ use dist; use native; use tool::{self, Tool}; use util::{self, dylib_path, dylib_path_var}; -use Mode; +use {Mode, DocTestsOption}; use toolstate::ToolState; const ADB_TEST_DIR: &str = "/data/tmp/work"; @@ -1519,8 +1519,14 @@ impl Step for Crate { if test_kind.subcommand() == "test" && !builder.fail_fast { cargo.arg("--no-fail-fast"); } - if builder.doc_tests { - cargo.arg("--doc"); + match builder.doc_tests { + DocTestsOption::Only => { + cargo.arg("--doc"); + } + DocTestsOption::No => { + cargo.args(&["--lib", "--bins", "--examples", "--tests", "--benches"]); + } + DocTestsOption::Yes => {} } cargo.arg("-p").arg(krate); -- cgit 1.4.1-3-g733a5 From be9d6690b22c7bdf46dda7f83ca61b69f58ce78b Mon Sep 17 00:00:00 2001 From: kennytm Date: Sun, 6 May 2018 02:33:01 +0800 Subject: Added test case. --- src/bootstrap/builder.rs | 35 +++++++++++++++++++++++++++++++++++ src/bootstrap/lib.rs | 2 +- src/bootstrap/test.rs | 14 +++++++------- 3 files changed, 43 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 408e61ef548..da12fbdb942 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -1405,4 +1405,39 @@ mod __test { }, ]); } + + #[test] + fn test_with_no_doc_stage0() { + let mut config = configure(&[], &[]); + config.stage = Some(0); + config.cmd = Subcommand::Test { + paths: vec!["src/libstd".into()], + test_args: vec![], + rustc_args: vec![], + fail_fast: true, + doc_tests: DocTestsOption::No, + }; + + let build = Build::new(config); + let mut builder = Builder::new(&build); + + let host = INTERNER.intern_str("A"); + + builder.run_step_descriptions( + &[StepDescription::from::()], + &["src/libstd".into()], + ); + + // Ensure we don't build any compiler artifacts. + assert!(builder.cache.all::().is_empty()); + assert_eq!(first(builder.cache.all::()), &[ + test::Crate { + compiler: Compiler { host, stage: 0 }, + target: host, + mode: Mode::Libstd, + test_kind: test::TestKind::Test, + krate: INTERNER.intern_str("std"), + }, + ]); + } } diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 624319485be..ff9a262e2cc 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -304,7 +304,7 @@ impl Crate { /// /// These entries currently correspond to the various output directories of the /// build system, with each mod generating output in a different directory. -#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] pub enum Mode { /// Build the standard library, placing output in the "stageN-std" directory. Libstd, diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 0d430c30036..2f0e3868f89 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -38,7 +38,7 @@ use toolstate::ToolState; const ADB_TEST_DIR: &str = "/data/tmp/work"; /// The two modes of the test runner; tests or benchmarks. -#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)] +#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, PartialOrd, Ord)] pub enum TestKind { /// Run `cargo test` Test, @@ -1407,13 +1407,13 @@ impl Step for CrateNotDefault { } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Crate { - compiler: Compiler, - target: Interned, - mode: Mode, - test_kind: TestKind, - krate: Interned, + pub compiler: Compiler, + pub target: Interned, + pub mode: Mode, + pub test_kind: TestKind, + pub krate: Interned, } impl Step for Crate { -- cgit 1.4.1-3-g733a5 From 3ddd67ba5356b96806f039e1e8997af63c3a6ee1 Mon Sep 17 00:00:00 2001 From: Lukas Kalbertodt Date: Tue, 1 May 2018 13:43:05 +0200 Subject: Move libcore/time tests from `time.rs` to `tests/time.rs` All other tests of libcore reside in the tests/ directory, too. Apparently the tests of `time.rs` weren't run before, at least not by `x.py test src/libcore`. --- src/libcore/tests/lib.rs | 1 + src/libcore/tests/time.rs | 122 ++++++++++++++++++++++++++++++++++++++++++++++ src/libcore/time.rs | 116 ------------------------------------------- 3 files changed, 123 insertions(+), 116 deletions(-) create mode 100644 src/libcore/tests/time.rs (limited to 'src') diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index f6750c590b3..340879c6b85 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -74,4 +74,5 @@ mod result; mod slice; mod str; mod str_lossy; +mod time; mod tuple; diff --git a/src/libcore/tests/time.rs b/src/libcore/tests/time.rs new file mode 100644 index 00000000000..9e6f284859c --- /dev/null +++ b/src/libcore/tests/time.rs @@ -0,0 +1,122 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use core::time::Duration; + +#[test] +fn creation() { + assert!(Duration::from_secs(1) != Duration::from_secs(0)); + assert_eq!(Duration::from_secs(1) + Duration::from_secs(2), + Duration::from_secs(3)); + assert_eq!(Duration::from_millis(10) + Duration::from_secs(4), + Duration::new(4, 10 * 1_000_000)); + assert_eq!(Duration::from_millis(4000), Duration::new(4, 0)); +} + +#[test] +fn secs() { + assert_eq!(Duration::new(0, 0).as_secs(), 0); + assert_eq!(Duration::from_secs(1).as_secs(), 1); + assert_eq!(Duration::from_millis(999).as_secs(), 0); + assert_eq!(Duration::from_millis(1001).as_secs(), 1); +} + +#[test] +fn nanos() { + assert_eq!(Duration::new(0, 0).subsec_nanos(), 0); + assert_eq!(Duration::new(0, 5).subsec_nanos(), 5); + assert_eq!(Duration::new(0, 1_000_000_001).subsec_nanos(), 1); + assert_eq!(Duration::from_secs(1).subsec_nanos(), 0); + assert_eq!(Duration::from_millis(999).subsec_nanos(), 999 * 1_000_000); + assert_eq!(Duration::from_millis(1001).subsec_nanos(), 1 * 1_000_000); +} + +#[test] +fn add() { + assert_eq!(Duration::new(0, 0) + Duration::new(0, 1), + Duration::new(0, 1)); + assert_eq!(Duration::new(0, 500_000_000) + Duration::new(0, 500_000_001), + Duration::new(1, 1)); +} + +#[test] +fn checked_add() { + assert_eq!(Duration::new(0, 0).checked_add(Duration::new(0, 1)), + Some(Duration::new(0, 1))); + assert_eq!(Duration::new(0, 500_000_000).checked_add(Duration::new(0, 500_000_001)), + Some(Duration::new(1, 1))); + assert_eq!(Duration::new(1, 0).checked_add(Duration::new(::core::u64::MAX, 0)), None); +} + +#[test] +fn sub() { + assert_eq!(Duration::new(0, 1) - Duration::new(0, 0), + Duration::new(0, 1)); + assert_eq!(Duration::new(0, 500_000_001) - Duration::new(0, 500_000_000), + Duration::new(0, 1)); + assert_eq!(Duration::new(1, 0) - Duration::new(0, 1), + Duration::new(0, 999_999_999)); +} + +#[test] +fn checked_sub() { + let zero = Duration::new(0, 0); + let one_nano = Duration::new(0, 1); + let one_sec = Duration::new(1, 0); + assert_eq!(one_nano.checked_sub(zero), Some(Duration::new(0, 1))); + assert_eq!(one_sec.checked_sub(one_nano), + Some(Duration::new(0, 999_999_999))); + assert_eq!(zero.checked_sub(one_nano), None); + assert_eq!(zero.checked_sub(one_sec), None); +} + +#[test] #[should_panic] +fn sub_bad1() { + Duration::new(0, 0) - Duration::new(0, 1); +} + +#[test] #[should_panic] +fn sub_bad2() { + Duration::new(0, 0) - Duration::new(1, 0); +} + +#[test] +fn mul() { + assert_eq!(Duration::new(0, 1) * 2, Duration::new(0, 2)); + assert_eq!(Duration::new(1, 1) * 3, Duration::new(3, 3)); + assert_eq!(Duration::new(0, 500_000_001) * 4, Duration::new(2, 4)); + assert_eq!(Duration::new(0, 500_000_001) * 4000, + Duration::new(2000, 4000)); +} + +#[test] +fn checked_mul() { + assert_eq!(Duration::new(0, 1).checked_mul(2), Some(Duration::new(0, 2))); + assert_eq!(Duration::new(1, 1).checked_mul(3), Some(Duration::new(3, 3))); + assert_eq!(Duration::new(0, 500_000_001).checked_mul(4), Some(Duration::new(2, 4))); + assert_eq!(Duration::new(0, 500_000_001).checked_mul(4000), + Some(Duration::new(2000, 4000))); + assert_eq!(Duration::new(::core::u64::MAX - 1, 0).checked_mul(2), None); +} + +#[test] +fn div() { + assert_eq!(Duration::new(0, 1) / 2, Duration::new(0, 0)); + assert_eq!(Duration::new(1, 1) / 3, Duration::new(0, 333_333_333)); + assert_eq!(Duration::new(99, 999_999_000) / 100, + Duration::new(0, 999_999_990)); +} + +#[test] +fn checked_div() { + assert_eq!(Duration::new(2, 0).checked_div(2), Some(Duration::new(1, 0))); + assert_eq!(Duration::new(1, 0).checked_div(2), Some(Duration::new(0, 500_000_000))); + assert_eq!(Duration::new(2, 0).checked_div(0), None); +} diff --git a/src/libcore/time.rs b/src/libcore/time.rs index e22fe450bb1..8e8b1691c65 100644 --- a/src/libcore/time.rs +++ b/src/libcore/time.rs @@ -481,119 +481,3 @@ impl<'a> Sum<&'a Duration> for Duration { iter.fold(Duration::new(0, 0), |a, b| a + *b) } } - -#[cfg(test)] -mod tests { - use super::Duration; - - #[test] - fn creation() { - assert!(Duration::from_secs(1) != Duration::from_secs(0)); - assert_eq!(Duration::from_secs(1) + Duration::from_secs(2), - Duration::from_secs(3)); - assert_eq!(Duration::from_millis(10) + Duration::from_secs(4), - Duration::new(4, 10 * 1_000_000)); - assert_eq!(Duration::from_millis(4000), Duration::new(4, 0)); - } - - #[test] - fn secs() { - assert_eq!(Duration::new(0, 0).as_secs(), 0); - assert_eq!(Duration::from_secs(1).as_secs(), 1); - assert_eq!(Duration::from_millis(999).as_secs(), 0); - assert_eq!(Duration::from_millis(1001).as_secs(), 1); - } - - #[test] - fn nanos() { - assert_eq!(Duration::new(0, 0).subsec_nanos(), 0); - assert_eq!(Duration::new(0, 5).subsec_nanos(), 5); - assert_eq!(Duration::new(0, 1_000_000_001).subsec_nanos(), 1); - assert_eq!(Duration::from_secs(1).subsec_nanos(), 0); - assert_eq!(Duration::from_millis(999).subsec_nanos(), 999 * 1_000_000); - assert_eq!(Duration::from_millis(1001).subsec_nanos(), 1 * 1_000_000); - } - - #[test] - fn add() { - assert_eq!(Duration::new(0, 0) + Duration::new(0, 1), - Duration::new(0, 1)); - assert_eq!(Duration::new(0, 500_000_000) + Duration::new(0, 500_000_001), - Duration::new(1, 1)); - } - - #[test] - fn checked_add() { - assert_eq!(Duration::new(0, 0).checked_add(Duration::new(0, 1)), - Some(Duration::new(0, 1))); - assert_eq!(Duration::new(0, 500_000_000).checked_add(Duration::new(0, 500_000_001)), - Some(Duration::new(1, 1))); - assert_eq!(Duration::new(1, 0).checked_add(Duration::new(::u64::MAX, 0)), None); - } - - #[test] - fn sub() { - assert_eq!(Duration::new(0, 1) - Duration::new(0, 0), - Duration::new(0, 1)); - assert_eq!(Duration::new(0, 500_000_001) - Duration::new(0, 500_000_000), - Duration::new(0, 1)); - assert_eq!(Duration::new(1, 0) - Duration::new(0, 1), - Duration::new(0, 999_999_999)); - } - - #[test] - fn checked_sub() { - let zero = Duration::new(0, 0); - let one_nano = Duration::new(0, 1); - let one_sec = Duration::new(1, 0); - assert_eq!(one_nano.checked_sub(zero), Some(Duration::new(0, 1))); - assert_eq!(one_sec.checked_sub(one_nano), - Some(Duration::new(0, 999_999_999))); - assert_eq!(zero.checked_sub(one_nano), None); - assert_eq!(zero.checked_sub(one_sec), None); - } - - #[test] #[should_panic] - fn sub_bad1() { - Duration::new(0, 0) - Duration::new(0, 1); - } - - #[test] #[should_panic] - fn sub_bad2() { - Duration::new(0, 0) - Duration::new(1, 0); - } - - #[test] - fn mul() { - assert_eq!(Duration::new(0, 1) * 2, Duration::new(0, 2)); - assert_eq!(Duration::new(1, 1) * 3, Duration::new(3, 3)); - assert_eq!(Duration::new(0, 500_000_001) * 4, Duration::new(2, 4)); - assert_eq!(Duration::new(0, 500_000_001) * 4000, - Duration::new(2000, 4000)); - } - - #[test] - fn checked_mul() { - assert_eq!(Duration::new(0, 1).checked_mul(2), Some(Duration::new(0, 2))); - assert_eq!(Duration::new(1, 1).checked_mul(3), Some(Duration::new(3, 3))); - assert_eq!(Duration::new(0, 500_000_001).checked_mul(4), Some(Duration::new(2, 4))); - assert_eq!(Duration::new(0, 500_000_001).checked_mul(4000), - Some(Duration::new(2000, 4000))); - assert_eq!(Duration::new(::u64::MAX - 1, 0).checked_mul(2), None); - } - - #[test] - fn div() { - assert_eq!(Duration::new(0, 1) / 2, Duration::new(0, 0)); - assert_eq!(Duration::new(1, 1) / 3, Duration::new(0, 333_333_333)); - assert_eq!(Duration::new(99, 999_999_000) / 100, - Duration::new(0, 999_999_990)); - } - - #[test] - fn checked_div() { - assert_eq!(Duration::new(2, 0).checked_div(2), Some(Duration::new(1, 0))); - assert_eq!(Duration::new(1, 0).checked_div(2), Some(Duration::new(0, 500_000_000))); - assert_eq!(Duration::new(2, 0).checked_div(0), None); - } -} -- cgit 1.4.1-3-g733a5 From 10ab98da8c8e53ab7b89eff489e09d352522889e Mon Sep 17 00:00:00 2001 From: Lukas Kalbertodt Date: Tue, 1 May 2018 15:07:15 +0200 Subject: Fix warning in `core::time` tests --- src/libcore/tests/time.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/libcore/tests/time.rs b/src/libcore/tests/time.rs index 9e6f284859c..042c523f25f 100644 --- a/src/libcore/tests/time.rs +++ b/src/libcore/tests/time.rs @@ -77,14 +77,16 @@ fn checked_sub() { assert_eq!(zero.checked_sub(one_sec), None); } -#[test] #[should_panic] +#[test] +#[should_panic] fn sub_bad1() { - Duration::new(0, 0) - Duration::new(0, 1); + let _ = Duration::new(0, 0) - Duration::new(0, 1); } -#[test] #[should_panic] +#[test] +#[should_panic] fn sub_bad2() { - Duration::new(0, 0) - Duration::new(1, 0); + let _ = Duration::new(0, 0) - Duration::new(1, 0); } #[test] -- cgit 1.4.1-3-g733a5 From 13e07a4e180e964717a0f71f0fc40260bab7d84a Mon Sep 17 00:00:00 2001 From: kennytm Date: Sun, 6 May 2018 00:53:48 +0800 Subject: Move the tests in src/libcore/slice/memchr.rs as well. --- src/libcore/slice/memchr.rs | 82 ------------------------------------------ src/libcore/tests/slice.rs | 86 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 82 deletions(-) (limited to 'src') diff --git a/src/libcore/slice/memchr.rs b/src/libcore/slice/memchr.rs index 469404f7f6b..7b62e7b0620 100644 --- a/src/libcore/slice/memchr.rs +++ b/src/libcore/slice/memchr.rs @@ -135,85 +135,3 @@ pub fn memrchr(x: u8, text: &[u8]) -> Option { // find the byte before the point the body loop stopped text[..offset].iter().rposition(|elt| *elt == x) } - -// test fallback implementations on all platforms -#[test] -fn matches_one() { - assert_eq!(Some(0), memchr(b'a', b"a")); -} - -#[test] -fn matches_begin() { - assert_eq!(Some(0), memchr(b'a', b"aaaa")); -} - -#[test] -fn matches_end() { - assert_eq!(Some(4), memchr(b'z', b"aaaaz")); -} - -#[test] -fn matches_nul() { - assert_eq!(Some(4), memchr(b'\x00', b"aaaa\x00")); -} - -#[test] -fn matches_past_nul() { - assert_eq!(Some(5), memchr(b'z', b"aaaa\x00z")); -} - -#[test] -fn no_match_empty() { - assert_eq!(None, memchr(b'a', b"")); -} - -#[test] -fn no_match() { - assert_eq!(None, memchr(b'a', b"xyz")); -} - -#[test] -fn matches_one_reversed() { - assert_eq!(Some(0), memrchr(b'a', b"a")); -} - -#[test] -fn matches_begin_reversed() { - assert_eq!(Some(3), memrchr(b'a', b"aaaa")); -} - -#[test] -fn matches_end_reversed() { - assert_eq!(Some(0), memrchr(b'z', b"zaaaa")); -} - -#[test] -fn matches_nul_reversed() { - assert_eq!(Some(4), memrchr(b'\x00', b"aaaa\x00")); -} - -#[test] -fn matches_past_nul_reversed() { - assert_eq!(Some(0), memrchr(b'z', b"z\x00aaaa")); -} - -#[test] -fn no_match_empty_reversed() { - assert_eq!(None, memrchr(b'a', b"")); -} - -#[test] -fn no_match_reversed() { - assert_eq!(None, memrchr(b'a', b"xyz")); -} - -#[test] -fn each_alignment_reversed() { - let mut data = [1u8; 64]; - let needle = 2; - let pos = 40; - data[pos] = needle; - for start in 0..16 { - assert_eq!(Some(pos - start), memrchr(needle, &data[start..])); - } -} diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs index 53fdfa06827..c81e5e97cbb 100644 --- a/src/libcore/tests/slice.rs +++ b/src/libcore/tests/slice.rs @@ -550,3 +550,89 @@ fn sort_unstable() { v.sort_unstable(); assert!(v == [0xDEADBEEF]); } + +pub mod memchr { + use core::slice::memchr::{memchr, memrchr}; + + // test fallback implementations on all platforms + #[test] + fn matches_one() { + assert_eq!(Some(0), memchr(b'a', b"a")); + } + + #[test] + fn matches_begin() { + assert_eq!(Some(0), memchr(b'a', b"aaaa")); + } + + #[test] + fn matches_end() { + assert_eq!(Some(4), memchr(b'z', b"aaaaz")); + } + + #[test] + fn matches_nul() { + assert_eq!(Some(4), memchr(b'\x00', b"aaaa\x00")); + } + + #[test] + fn matches_past_nul() { + assert_eq!(Some(5), memchr(b'z', b"aaaa\x00z")); + } + + #[test] + fn no_match_empty() { + assert_eq!(None, memchr(b'a', b"")); + } + + #[test] + fn no_match() { + assert_eq!(None, memchr(b'a', b"xyz")); + } + + #[test] + fn matches_one_reversed() { + assert_eq!(Some(0), memrchr(b'a', b"a")); + } + + #[test] + fn matches_begin_reversed() { + assert_eq!(Some(3), memrchr(b'a', b"aaaa")); + } + + #[test] + fn matches_end_reversed() { + assert_eq!(Some(0), memrchr(b'z', b"zaaaa")); + } + + #[test] + fn matches_nul_reversed() { + assert_eq!(Some(4), memrchr(b'\x00', b"aaaa\x00")); + } + + #[test] + fn matches_past_nul_reversed() { + assert_eq!(Some(0), memrchr(b'z', b"z\x00aaaa")); + } + + #[test] + fn no_match_empty_reversed() { + assert_eq!(None, memrchr(b'a', b"")); + } + + #[test] + fn no_match_reversed() { + assert_eq!(None, memrchr(b'a', b"xyz")); + } + + #[test] + fn each_alignment_reversed() { + let mut data = [1u8; 64]; + let needle = 2; + let pos = 40; + data[pos] = needle; + for start in 0..16 { + assert_eq!(Some(pos - start), memrchr(needle, &data[start..])); + } + } +} -- cgit 1.4.1-3-g733a5 From f24915b67fafe33e87e685d884ff63389b6967cb Mon Sep 17 00:00:00 2001 From: kennytm Date: Sun, 6 May 2018 00:54:12 +0800 Subject: Added a tidy test to ensure libcore cannot contain any tests. --- src/tools/tidy/src/lib.rs | 1 + src/tools/tidy/src/libcoretest.rs | 34 ++++++++++++++++++++++++++++++++++ src/tools/tidy/src/main.rs | 1 + 3 files changed, 36 insertions(+) create mode 100644 src/tools/tidy/src/libcoretest.rs (limited to 'src') diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index fa227436640..022ef57503a 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -51,6 +51,7 @@ pub mod pal; pub mod deps; pub mod ui_tests; pub mod unstable_book; +pub mod libcoretest; fn filter_dirs(path: &Path) -> bool { let skip = [ diff --git a/src/tools/tidy/src/libcoretest.rs b/src/tools/tidy/src/libcoretest.rs new file mode 100644 index 00000000000..ef8b55186b1 --- /dev/null +++ b/src/tools/tidy/src/libcoretest.rs @@ -0,0 +1,34 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Tidy check to ensure `#[test]` is not used directly inside `libcore`. +//! +//! `#![no_core]` libraries cannot be tested directly due to duplicating lang +//! item. All tests must be written externally in `libcore/tests`. + +use std::path::Path; +use std::fs::read_to_string; + +pub fn check(path: &Path, bad: &mut bool) { + let libcore_path = path.join("libcore"); + super::walk( + &libcore_path, + &mut |subpath| t!(subpath.strip_prefix(&libcore_path)).starts_with("tests"), + &mut |subpath| { + if t!(read_to_string(subpath)).contains("#[test]") { + tidy_error!( + bad, + "{} contains #[test]; libcore tests must be placed inside `src/libcore/tests/`", + subpath.display() + ); + } + }, + ); +} diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index 24974192795..7b86650823a 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -41,6 +41,7 @@ fn main() { features::check(&path, &mut bad, quiet); pal::check(&path, &mut bad); unstable_book::check(&path, &mut bad); + libcoretest::check(&path, &mut bad); if !args.iter().any(|s| *s == "--no-vendor") { deps::check(&path, &mut bad); } -- cgit 1.4.1-3-g733a5 From 02f6a0335f99378b2e7d630e00aabdeb57a5bd25 Mon Sep 17 00:00:00 2001 From: kennytm Date: Sun, 6 May 2018 01:02:05 +0800 Subject: Some final touches to ensure `./x.py test --stage 0 src/lib*` works --- src/libcore/lib.rs | 1 + src/libcore/tests/lib.rs | 1 + src/libcore/tests/num/uint_macros.rs | 1 + src/libstd/lib.rs | 4 ++-- 4 files changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 04dd42583d4..37f9dcc7e32 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -50,6 +50,7 @@ // Since libcore defines many fundamental lang items, all tests live in a // separate crate, libcoretest, to avoid bizarre issues. +#![cfg(not(test))] #![stable(feature = "core", since = "1.6.0")] #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 340879c6b85..5e98e40e0d5 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -46,6 +46,7 @@ #![feature(reverse_bits)] #![feature(inclusive_range_methods)] #![feature(iterator_find_map)] +#![feature(slice_internals)] extern crate core; extern crate test; diff --git a/src/libcore/tests/num/uint_macros.rs b/src/libcore/tests/num/uint_macros.rs index ca6906f7310..257f6ea20d4 100644 --- a/src/libcore/tests/num/uint_macros.rs +++ b/src/libcore/tests/num/uint_macros.rs @@ -98,6 +98,7 @@ mod tests { } #[test] + #[cfg(not(stage0))] fn test_reverse_bits() { assert_eq!(A.reverse_bits().reverse_bits(), A); assert_eq!(B.reverse_bits().reverse_bits(), B); diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index fc05833e285..d41739ab02c 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -330,10 +330,10 @@ // with a rustc without jemalloc. // FIXME(#44236) shouldn't need MSVC logic #![cfg_attr(all(not(target_env = "msvc"), - any(stage0, feature = "force_alloc_system")), + any(all(stage0, not(test)), feature = "force_alloc_system")), feature(global_allocator))] #[cfg(all(not(target_env = "msvc"), - any(stage0, feature = "force_alloc_system")))] + any(all(stage0, not(test)), feature = "force_alloc_system")))] #[global_allocator] static ALLOC: alloc_system::System = alloc_system::System; -- cgit 1.4.1-3-g733a5 From e24cbe2da07f1a713bd50a8f30792b145633795e Mon Sep 17 00:00:00 2001 From: John Kåre Alsaker Date: Sun, 8 Apr 2018 13:44:29 +0200 Subject: Misc tweaks --- config.toml.example | 3 +++ src/Cargo.lock | 1 + src/bootstrap/bin/rustc.rs | 7 +++++++ src/bootstrap/builder.rs | 4 ++++ src/bootstrap/config.rs | 3 +++ src/bootstrap/job.rs | 10 ++++------ src/librustc/util/common.rs | 11 +++++++++++ src/librustc_plugin/lib.rs | 1 - src/librustc_plugin/registry.rs | 2 -- src/tools/compiletest/Cargo.toml | 1 + src/tools/compiletest/src/main.rs | 3 +++ src/tools/compiletest/src/runtest.rs | 36 ++++++++++++++++++++++++++++++++++-- src/tools/tidy/src/deps.rs | 1 + 13 files changed, 72 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/config.toml.example b/config.toml.example index effe0084381..34fcc755b3a 100644 --- a/config.toml.example +++ b/config.toml.example @@ -346,6 +346,9 @@ # Whether to deny warnings in crates #deny-warnings = true +# Print backtrace on internal compiler errors during bootstrap +#backtrace-on-ice = false + # ============================================================================= # Options for specific targets # diff --git a/src/Cargo.lock b/src/Cargo.lock index 0f08eaf596a..a2767bd290d 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -390,6 +390,7 @@ dependencies = [ "env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index b6ae824c376..3f97accaa4d 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -107,6 +107,13 @@ fn main() { env::join_paths(&dylib_path).unwrap()); let mut maybe_crate = None; + // Print backtrace in case of ICE + if env::var("RUSTC_BACKTRACE_ON_ICE").is_ok() && env::var("RUST_BACKTRACE").is_err() { + cmd.env("RUST_BACKTRACE", "1"); + } + + cmd.env("RUSTC_BREAK_ON_ICE", "1"); + if let Some(target) = target { // The stage0 compiler has a special sysroot distinct from what we // actually downloaded, so we just always pass the `--sysroot` option. diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 08bb8ab4815..43387e28565 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -706,6 +706,10 @@ impl<'a> Builder<'a> { cargo.env("RUSTC_PRINT_STEP_TIMINGS", "1"); } + if self.config.backtrace_on_ice { + cargo.env("RUSTC_BACKTRACE_ON_ICE", "1"); + } + cargo.env("RUSTC_VERBOSE", format!("{}", self.verbosity)); // in std, we want to avoid denying warnings for stage 0 as that makes cfg's painful. diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 7175f6a6764..6dd6291be23 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -72,6 +72,7 @@ pub struct Config { pub dry_run: bool, pub deny_warnings: bool, + pub backtrace_on_ice: bool, // llvm codegen options pub llvm_enabled: bool, @@ -306,6 +307,7 @@ struct Rust { wasm_syscall: Option, lld: Option, deny_warnings: Option, + backtrace_on_ice: Option, } /// TOML representation of how each build target is configured. @@ -531,6 +533,7 @@ impl Config { config.musl_root = rust.musl_root.clone().map(PathBuf::from); config.save_toolstates = rust.save_toolstates.clone().map(PathBuf::from); set(&mut config.deny_warnings, rust.deny_warnings.or(flags.warnings)); + set(&mut config.backtrace_on_ice, rust.backtrace_on_ice); if let Some(ref backends) = rust.codegen_backends { config.rust_codegen_backends = backends.iter() diff --git a/src/bootstrap/job.rs b/src/bootstrap/job.rs index fa3ba02482f..6445ce8da33 100644 --- a/src/bootstrap/job.rs +++ b/src/bootstrap/job.rs @@ -122,12 +122,10 @@ struct JOBOBJECT_BASIC_LIMIT_INFORMATION { } pub unsafe fn setup(build: &mut Build) { - // Tell Windows to not show any UI on errors (such as not finding a required dll - // during startup or terminating abnormally). This is important for running tests, - // since some of them use abnormal termination by design. - // This mode is inherited by all child processes. - let mode = SetErrorMode(SEM_NOGPFAULTERRORBOX); // read inherited flags - SetErrorMode(mode | SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX); + // Enable the Windows Error Reporting dialog which msys disables, + // so we can JIT debug rustc + let mode = SetErrorMode(0); + SetErrorMode(mode & !SEM_NOGPFAULTERRORBOX); // Create a new job object for us to use let job = CreateJobObjectW(0 as *mut _, 0 as *const _); diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index c74e42263ef..85533caffce 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -58,6 +58,17 @@ fn panic_hook(info: &panic::PanicInfo) { if backtrace { TyCtxt::try_print_query_stack(); } + + #[cfg(windows)] + unsafe { + if env::var("RUSTC_BREAK_ON_ICE").is_ok() { + extern "system" { + fn DebugBreak(); + } + // Trigger a debugger if we crashed during bootstrap + DebugBreak(); + } + } } } diff --git a/src/librustc_plugin/lib.rs b/src/librustc_plugin/lib.rs index 622d8e51a6c..348aa6a7cef 100644 --- a/src/librustc_plugin/lib.rs +++ b/src/librustc_plugin/lib.rs @@ -65,7 +65,6 @@ html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(rustc_diagnostic_macros)] -#![feature(staged_api)] #[macro_use] extern crate syntax; diff --git a/src/librustc_plugin/registry.rs b/src/librustc_plugin/registry.rs index ebfd8785a0a..7e3c411c1d2 100644 --- a/src/librustc_plugin/registry.rs +++ b/src/librustc_plugin/registry.rs @@ -128,8 +128,6 @@ impl<'a> Registry<'a> { /// This can be used in place of `register_syntax_extension` to register legacy custom derives /// (i.e. attribute syntax extensions whose name begins with `derive_`). Legacy custom /// derives defined by this function do not trigger deprecation warnings when used. - #[unstable(feature = "rustc_private", issue = "27812")] - #[rustc_deprecated(since = "1.15.0", reason = "replaced by macros 1.1 (RFC 1861)")] pub fn register_custom_derive(&mut self, name: ast::Name, extension: SyntaxExtension) { assert!(name.as_str().starts_with("derive_")); self.whitelisted_custom_derives.push(name); diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml index 77554f244c8..45cb147fbbc 100644 --- a/src/tools/compiletest/Cargo.toml +++ b/src/tools/compiletest/Cargo.toml @@ -19,5 +19,6 @@ rustfix = "0.2" libc = "0.2" [target.'cfg(windows)'.dependencies] +lazy_static = "1.0" miow = "0.3" winapi = { version = "0.3", features = ["winerror"] } diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index a7849d53c3d..e2b446c99dc 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -23,6 +23,9 @@ extern crate libc; extern crate log; extern crate regex; #[macro_use] +#[cfg(windows)] +extern crate lazy_static; +#[macro_use] extern crate serde_derive; extern crate serde_json; extern crate test; diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index fae75c352da..1bac9ef66bb 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -38,6 +38,39 @@ use std::str; use extract_gdb_version; +#[cfg(windows)] +fn disable_error_reporting R, R>(f: F) -> R { + use std::sync::Mutex; + const SEM_NOGPFAULTERRORBOX: u32 = 0x0002; + extern "system" { + fn SetErrorMode(mode: u32) -> u32; + } + + lazy_static! { + static ref LOCK: Mutex<()> = { + Mutex::new(()) + }; + } + // Error mode is a global variable, so lock it so only one thread will change it + let _lock = LOCK.lock().unwrap(); + + // Tell Windows to not show any UI on errors (such as terminating abnormally). + // This is important for running tests, since some of them use abnormal + // termination by design. This mode is inherited by all child processes. + unsafe { + let old_mode = SetErrorMode(SEM_NOGPFAULTERRORBOX); // read inherited flags + SetErrorMode(old_mode | SEM_NOGPFAULTERRORBOX); + let r = f(); + SetErrorMode(old_mode); + r + } +} + +#[cfg(not(windows))] +fn disable_error_reporting R, R>(f: F) -> R { + f() +} + /// The name of the environment variable that holds dynamic library locations. pub fn dylib_env_var() -> &'static str { if cfg!(windows) { @@ -1578,8 +1611,7 @@ impl<'test> TestCx<'test> { let newpath = env::join_paths(&path).unwrap(); command.env(dylib_env_var(), newpath); - let mut child = command - .spawn() + let mut child = disable_error_reporting(|| command.spawn()) .expect(&format!("failed to exec `{:?}`", &command)); if let Some(input) = input { child diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 8caf39fc27b..9a87fcb00d5 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -73,6 +73,7 @@ static WHITELIST: &'static [Crate] = &[ Crate("flate2"), Crate("fuchsia-zircon"), Crate("fuchsia-zircon-sys"), + Crate("getopts"), Crate("humantime"), Crate("jobserver"), Crate("kernel32-sys"), -- cgit 1.4.1-3-g733a5 From 169f58b712e793ea43b90a6008a21b777bf4102f Mon Sep 17 00:00:00 2001 From: kennytm Date: Sun, 6 May 2018 03:29:19 +0800 Subject: Added some simple documentation. --- src/bootstrap/README.md | 4 ++++ src/libcore/lib.rs | 8 ++++++++ 2 files changed, 12 insertions(+) (limited to 'src') diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md index 9ff681ac680..98c353eb6ec 100644 --- a/src/bootstrap/README.md +++ b/src/bootstrap/README.md @@ -64,6 +64,10 @@ The script accepts commands, flags, and arguments to determine what to do: # execute tests in the standard library in stage0 ./x.py test --stage 0 src/libstd + # execute tests in the core and standard library in stage0, + # without running doc tests (thus avoid depending on building the compiler) + ./x.py test --stage 0 --no-doc src/libcore src/libstd + # execute all doc tests ./x.py test src/doc ``` diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 37f9dcc7e32..54f35d17974 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -50,6 +50,14 @@ // Since libcore defines many fundamental lang items, all tests live in a // separate crate, libcoretest, to avoid bizarre issues. +// +// Here we explicitly #[cfg]-out this whole crate when testing. If we don't do +// this, both the generated test artifact and the linked libtest (which +// transitively includes libcore) will both define the same set of lang items, +// and this will cause the E0152 "duplicate lang item found" error. See +// discussion in #50466 for details. +// +// This cfg won't affect doc tests. #![cfg(not(test))] #![stable(feature = "core", since = "1.6.0")] -- cgit 1.4.1-3-g733a5 From 05af55bd8052576bc172d635f8eb9207ccedfd29 Mon Sep 17 00:00:00 2001 From: kennytm Date: Sun, 6 May 2018 03:30:42 +0800 Subject: s/DocTestsOption/DocTests/g --- src/bootstrap/builder.rs | 6 +++--- src/bootstrap/flags.rs | 14 +++++++------- src/bootstrap/lib.rs | 4 ++-- src/bootstrap/test.rs | 8 ++++---- 4 files changed, 16 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index da12fbdb942..10027640272 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -25,7 +25,7 @@ use compile; use install; use dist; use util::{exe, libdir, add_lib_path}; -use {Build, Mode, DocTestsOption}; +use {Build, Mode, DocTests}; use cache::{INTERNER, Interned, Cache}; use check; use test; @@ -591,7 +591,7 @@ impl<'a> Builder<'a> { format!("{} {}", env::var("RUSTFLAGS").unwrap_or_default(), extra_args)); } - let want_rustdoc = self.doc_tests != DocTestsOption::No; + let want_rustdoc = self.doc_tests != DocTests::No; // Customize the compiler we're running. Specify the compiler to cargo // as our shim and then pass it some various options used to configure @@ -1415,7 +1415,7 @@ mod __test { test_args: vec![], rustc_args: vec![], fail_fast: true, - doc_tests: DocTestsOption::No, + doc_tests: DocTests::No, }; let build = Build::new(config); diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index fb7c8ba1351..5315a3028ff 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -19,7 +19,7 @@ use std::process; use getopts::Options; -use {Build, DocTestsOption}; +use {Build, DocTests}; use config::Config; use metadata; use builder::Builder; @@ -62,7 +62,7 @@ pub enum Subcommand { test_args: Vec, rustc_args: Vec, fail_fast: bool, - doc_tests: DocTestsOption, + doc_tests: DocTests, }, Bench { paths: Vec, @@ -326,11 +326,11 @@ Arguments: rustc_args: matches.opt_strs("rustc-args"), fail_fast: !matches.opt_present("no-fail-fast"), doc_tests: if matches.opt_present("doc") { - DocTestsOption::Only + DocTests::Only } else if matches.opt_present("no-doc") { - DocTestsOption::No + DocTests::No } else { - DocTestsOption::Yes + DocTests::Yes } } } @@ -418,10 +418,10 @@ impl Subcommand { } } - pub fn doc_tests(&self) -> DocTestsOption { + pub fn doc_tests(&self) -> DocTests { match *self { Subcommand::Test { doc_tests, .. } => doc_tests, - _ => DocTestsOption::Yes, + _ => DocTests::Yes, } } } diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index ff9a262e2cc..e53fef06786 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -211,7 +211,7 @@ pub struct Compiler { } #[derive(PartialEq, Eq, Copy, Clone, Debug)] -pub enum DocTestsOption { +pub enum DocTests { // Default, run normal tests and doc tests. Yes, // Do not run any doc tests. @@ -243,7 +243,7 @@ pub struct Build { rustfmt_info: channel::GitInfo, local_rebuild: bool, fail_fast: bool, - doc_tests: DocTestsOption, + doc_tests: DocTests, verbosity: usize, // Targets for which to build. diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 2f0e3868f89..cbb952bab61 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -32,7 +32,7 @@ use dist; use native; use tool::{self, Tool}; use util::{self, dylib_path, dylib_path_var}; -use {Mode, DocTestsOption}; +use {Mode, DocTests}; use toolstate::ToolState; const ADB_TEST_DIR: &str = "/data/tmp/work"; @@ -1520,13 +1520,13 @@ impl Step for Crate { cargo.arg("--no-fail-fast"); } match builder.doc_tests { - DocTestsOption::Only => { + DocTests::Only => { cargo.arg("--doc"); } - DocTestsOption::No => { + DocTests::No => { cargo.args(&["--lib", "--bins", "--examples", "--tests", "--benches"]); } - DocTestsOption::Yes => {} + DocTests::Yes => {} } cargo.arg("-p").arg(krate); -- cgit 1.4.1-3-g733a5 From 7364d26921e6f7a852930c80cb52f961234579ed Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Sat, 5 May 2018 19:02:13 -0400 Subject: Update books for the next release. --- src/doc/book | 2 +- src/doc/nomicon | 2 +- src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/doc/book b/src/doc/book index 6237a75790c..f51127530d4 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 6237a75790cd2e0ca22961b55f64a83319e73464 +Subproject commit f51127530d46b9acbf4747c859da185e771cfcf3 diff --git a/src/doc/nomicon b/src/doc/nomicon index 3c56329d1bd..748a5e6742d 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit 3c56329d1bd9038e5341f1962bcd8d043312a712 +Subproject commit 748a5e6742db4a21c4c630a58087f818828e8a0a diff --git a/src/doc/reference b/src/doc/reference index 76296346e97..134f419ee62 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 76296346e97c3702974d3398fdb94af9e10111a2 +Subproject commit 134f419ee62714590b04712fe6072253bc2a7822 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index d5ec87eabe5..eebda16e4b4 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit d5ec87eabe5733cc2348c7dada89fc67c086f391 +Subproject commit eebda16e4b45f2eed4310cf7b9872cc752278163 -- cgit 1.4.1-3-g733a5