From: kennytm Date: Fri, 27 Apr 2018 20:51:00 +0000 (+0800) Subject: Rollup merge of #50257 - estebank:fix-49560, r=nikomatsakis X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=dc6b167e224f3a782fa7b1e6f5cff21f5238f97e;hp=d92d1935cb01cfa469a725f041e4c1d8a2ee9564;p=rust.git Rollup merge of #50257 - estebank:fix-49560, r=nikomatsakis Don't ICE on tuple struct ctor with incorrect arg count Fix #49560. --- 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" diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index b9c82127342..08bb8ab4815 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -323,7 +323,7 @@ macro_rules! describe { 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, test::RustdocUi), @@ -331,7 +331,7 @@ macro_rules! describe { 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 ae22260c564..16f4b29dcce 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -71,6 +71,7 @@ fn run(self, builder: &Builder) { 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 08bbd68c756..e8c40dfdb0a 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1212,6 +1212,7 @@ fn run(self, builder: &Builder) { 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; 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. 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..8adc05c5137 --- /dev/null +++ b/src/doc/rustc/book.toml @@ -0,0 +1,5 @@ +[book] +authors = ["The Rust Project Developers"] +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..e4c0939fd46 --- /dev/null +++ b/src/doc/rustc/src/SUMMARY.md @@ -0,0 +1,16 @@ +# The Rustc Book + +- [What is rustc?](what-is-rustc.md) +- [Command-line arguments](command-line-arguments.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) +- [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/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md new file mode 100644 index 00000000000..eff09428902 --- /dev/null +++ b/src/doc/rustc/src/codegen-options/index.md @@ -0,0 +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 +parallelism](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. 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..e2b001832fe --- /dev/null +++ b/src/doc/rustc/src/command-line-arguments.md @@ -0,0 +1,116 @@ +# Command-line arguments + +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 + +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`/`--version`: 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 + +This flag lets you control the format of errors. + +## `--color`: configure coloring of output + +This flag lets you control color settings of the output. diff --git a/src/doc/rustc/src/contributing.md b/src/doc/rustc/src/contributing.md new file mode 100644 index 00000000000..fcb8e6b27db --- /dev/null +++ b/src/doc/rustc/src/contributing.md @@ -0,0 +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 diff --git a/src/doc/rustc/src/lints/groups.md b/src/doc/rustc/src/lints/groups.md new file mode 100644 index 00000000000..46b717f3387 --- /dev/null +++ b/src/doc/rustc/src/lints/groups.md @@ -0,0 +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 new file mode 100644 index 00000000000..bf345a24389 --- /dev/null +++ b/src/doc/rustc/src/lints/index.md @@ -0,0 +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: + +```bash +$ 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. diff --git a/src/doc/rustc/src/lints/levels.md b/src/doc/rustc/src/lints/levels.md new file mode 100644 index 00000000000..19bb6707d22 --- /dev/null +++ b/src/doc/rustc/src/lints/levels.md @@ -0,0 +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: + +```bash +$ 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: + +```console +$ 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,ignore +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,ignore +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. 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..e1a3f96a6fe --- /dev/null +++ b/src/doc/rustc/src/lints/listing/allowed-by-default.md @@ -0,0 +1,453 @@ +# 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,ignore +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}; + +pub mod test { + pub struct A; +} +# fn main() {} +``` + +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,no_run +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]), +} +``` + +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 + | ^^^^^^^^^^^^^^^^ + | +``` 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..e7ec6af8be1 --- /dev/null +++ b/src/doc/rustc/src/lints/listing/deny-by-default.md @@ -0,0 +1,241 @@ +# Deny-by-default lints + +These lints are all set to the 'deny' level by default. + +## exceeding-bitshifts + +This lint detects that a shift exceeds the type's number of bits. Some +example code that triggers this lint: + +```rust,ignore +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,ignore +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,ignore +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,ignore +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,ignore +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,ignore +#[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,ignore +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,ignore +#![crate_type="lol"] +``` + +This will produce: + +```text +error: invalid `crate_type` value + --> src/lib.rs:1:1 + | +1 | #![crate_type="lol"] + | ^^^^^^^^^^^^^^^^^^^^ + | +``` 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..18cd2fe32a3 --- /dev/null +++ b/src/doc/rustc/src/lints/listing/index.md @@ -0,0 +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 new file mode 100644 index 00000000000..1171f75caa1 --- /dev/null +++ b/src/doc/rustc/src/lints/listing/warn-by-default.md @@ -0,0 +1,1039 @@ +# Warn-by-default lints + +These lints are all set to the 'warn' level by default. + +## const-err + +This lint detects an erroneous expression while doing constant evaluation. Some +example code that triggers this lint: + +```rust,ignore +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,ignore +#![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,ignore +pub trait Trait { + type A; +} + +pub struct S; + +mod foo { + struct Z; + + impl ::Trait for ::S { + type A = Z; + } +} +# fn main() {} +``` + +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,ignore +#[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,no_run +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,no_run +while true { + +} +``` + +This will produce: + +```text +warning: denote infinite loops with `loop { ... }` + --> src/main.rs:2:5 + | +2 | while true { + | ^^^^^^^^^^ help: use `loop` + | +``` 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..8620346e5b7 --- /dev/null +++ b/src/doc/rustc/src/targets/built-in.md @@ -0,0 +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 new file mode 100644 index 00000000000..0691afc60ea --- /dev/null +++ b/src/doc/rustc/src/targets/custom.md @@ -0,0 +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 new file mode 100644 index 00000000000..07e3a79471f --- /dev/null +++ b/src/doc/rustc/src/targets/index.md @@ -0,0 +1,13 @@ +# 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. + +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 +``` 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..bed1b71c24e --- /dev/null +++ b/src/doc/rustc/src/what-is-rustc.md @@ -0,0 +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 diff --git a/src/liballoc/alloc.rs b/src/liballoc/alloc.rs index c0372d24ed5..f59c9f7fd61 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)] @@ -152,9 +152,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 e52a0216dd3..d0950bff9ce 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -566,7 +566,8 @@ unsafe fn allocate_for_ptr(ptr: *const T) -> *mut ArcInner { 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 @@ fn from_box(v: Box) -> 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/boxed.rs b/src/liballoc/boxed.rs index 5ebd2cc6146..1b4f86dcfac 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -184,6 +184,7 @@ pub fn into_raw_non_null(b: Box) -> NonNull { #[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); diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 8fb8e111754..d0188c6e828 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -681,7 +681,8 @@ unsafe fn allocate_for_ptr(ptr: *const T) -> *mut RcBox { 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 @@ fn from_box(v: Box) -> 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/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 @@ /// ``` #[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 @@ fn ne(&self, other: &Rhs) -> bool { !self.eq(other) } /// } /// 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 @@ fn cmp(&self, other: &Reverse) -> Ordering { /// } /// ``` #[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 @@ fn partial_cmp(&self, other: &Ordering) -> Option { /// ``` #[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 @@ fn fmt(&self, fmt: &mut Formatter) -> Result { 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 @@ fn not(self) -> $t { !self } /// 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 @@ fn bitand(self, rhs: $t) -> $t { self & rhs } /// 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 @@ fn bitor(self, rhs: $t) -> $t { self | rhs } /// 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 @@ fn bitxor(self, other: $t) -> $t { self ^ other } /// 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 @@ macro_rules! shl_impl_all { /// 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 @@ macro_rules! shr_impl_all { /// 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 @@ fn bitand_assign(&mut self, other: $t) { *self &= other } /// 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 @@ fn bitor_assign(&mut self, other: $t) { *self |= other } /// 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 @@ fn bitxor_assign(&mut self, other: $t) { *self ^= other } /// 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 @@ macro_rules! shl_assign_impl_all { /// 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 @@ fn deref(&self) -> &T { *self } /// 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 @@ /// [`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 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { /// 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 @@ pub fn is_empty(&self) -> bool { /// ``` /// /// [`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 @@ pub fn contains(&self, item: &U) -> bool /// [`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 @@ pub fn contains(&self, item: &U) -> bool /// 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 @@ pub fn is_empty(&self) -> bool { /// [`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 { diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 74bb264cc67..c61bdfc9c4f 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -2513,6 +2513,7 @@ fn ge(&self, other: &*mut T) -> bool { *self >= *other } 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 diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index e171216523a..f51dbc3772f 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -270,7 +270,7 @@ pub fn source_file(&self) -> SourceFile { /// `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(Span) } /// The span for the origin source code that `self` was generated from. If 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 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 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool { [] 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/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 @@ fn check_attributes(&self, item: &hir::Item, target: Target) { 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 @@ fn check_stmt_attributes(&self, stmt: &hir::Stmt) { } 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/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 4023521147e..e4b9fc1385d 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -655,7 +655,7 @@ fn collect_in_band_defs( 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 @@ fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) { 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, @@ -4107,15 +4107,13 @@ fn new_implicit_lifetime(&mut self, span: Span) -> hir::Lifetime { } 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/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 @@ fn visit_item(&mut self, i: &'a Item) { // 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 @@ fn visit_item(&mut self, i: &'a Item) { 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 @@ fn visit_item(&mut self, i: &'a Item) { 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 @@ fn visit_item(&mut self, i: &'a Item) { 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 @@ fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) { } 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 @@ fn visit_generic_param(&mut self, param: &'a GenericParam) { 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 @@ fn visit_generic_param(&mut self, param: &'a GenericParam) { 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 @@ fn visit_generic_param(&mut self, param: &'a GenericParam) { 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 @@ fn visit_trait_item(&mut self, ti: &'a TraitItem) { 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 @@ pub fn as_interned_str(&self) -> InternedString { Typeof => "{{typeof}}", }; - Symbol::intern(s).as_str() + Symbol::intern(s).as_interned_str() } pub fn to_string(&self) -> String { @@ -731,7 +731,7 @@ fn allocate_def_indices(definitions: &mut Definitions) { 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 @@ pub fn def_index(&self, def_path_table: &DefPathTable) -> DefIndex { 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 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 @@ fn to_stable_hash_key(&self, } } +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..24892dfcc8f 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))] @@ -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/coherence.rs b/src/librustc/traits/coherence.rs index 31f8af1f968..5a626e7b82c 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -154,7 +154,10 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>, recursion_depth: 0, predicate: p }) .chain(obligations) - .find(|o| !selcx.evaluate_obligation(o)); + .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). 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 3eb45439001..047d4bb8930 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -24,6 +24,7 @@ SelectionContext, SelectionError, ObjectSafetyViolation, + Overflow, }; use errors::DiagnosticBuilder; @@ -659,8 +660,7 @@ pub fn report_selection_error(&self, 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 \ @@ -830,6 +830,10 @@ pub fn report_selection_error(&self, } 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(); @@ -872,7 +876,6 @@ fn suggest_remove_reference(&self, .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: _ }) = @@ -886,7 +889,7 @@ fn suggest_remove_reference(&self, 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 == '&'); @@ -1328,7 +1331,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'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..6e201507181 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -112,7 +112,7 @@ fn select(&mut self, selcx: &mut SelectionContext<'a, 'gcx, '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. @@ -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 728d9f1a027..dd5208e908e 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -41,7 +41,7 @@ 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; @@ -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 @@ -349,6 +362,7 @@ pub enum SelectionError<'tcx> { ty::error::TypeError<'tcx>), TraitNotObjectSafe(DefId), ConstEvalFailure(ConstEvalErr<'tcx>), + Overflow, } pub struct FulfillmentError<'tcx> { @@ -550,8 +564,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/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 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 @@ pub fn evaluate(&self, 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/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/query/evaluate_obligation.rs b/src/librustc/traits/query/evaluate_obligation.rs new file mode 100644 index 00000000000..4e028cac49a --- /dev/null +++ b/src/librustc/traits/query/evaluate_obligation.rs @@ -0,0 +1,70 @@ +// 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, SelectionContext, + TraitQueryMode, OverflowError}; +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 { + self.evaluate_obligation(obligation).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 { + 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)); + // 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") + } + } + } +} + +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 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 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 f43f5cf3e3f..4ba3655bb64 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -17,12 +17,12 @@ 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}; 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; @@ -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)] @@ -319,7 +324,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 +390,7 @@ enum EvaluationResult { } impl EvaluationResult { - fn may_apply(self) -> bool { + pub fn may_apply(self) -> bool { match self { EvaluatedToOk | EvaluatedToAmbig | @@ -408,6 +413,26 @@ fn is_stack_dependent(self) -> bool { } } +impl_stable_hash_for!(enum self::EvaluationResult { + EvaluatedToOk, + EvaluatedToAmbig, + EvaluatedToUnknown, + EvaluatedToRecur, + EvaluatedToErr +}); + +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +/// 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 + } +} + #[derive(Clone)] pub struct EvaluationCache<'tcx> { hashmap: RefCell, WithDepNode>> @@ -421,6 +446,7 @@ pub fn new(infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>) -> SelectionContext<'cx, 'gcx intercrate: None, intercrate_ambiguity_causes: None, allow_negative_impls: false, + query_mode: TraitQueryMode::Standard, } } @@ -433,6 +459,7 @@ pub fn intercrate(infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>, intercrate: Some(mode), intercrate_ambiguity_causes: None, allow_negative_impls: false, + query_mode: TraitQueryMode::Standard, } } @@ -445,6 +472,20 @@ pub fn with_negative(infcx: &'cx InferCtxt<'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, } } @@ -528,12 +569,27 @@ pub fn select(&mut self, obligation: &TraitObligation<'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) => { + // 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 }; - Ok(ret) + match self.confirm_candidate(obligation, candidate) { + Err(SelectionError::Overflow) => { + assert!(self.query_mode == TraitQueryMode::Canonical); + return Err(SelectionError::Overflow); + }, + Err(e) => Err(e), + Ok(candidate) => Ok(Some(candidate)) + } } /////////////////////////////////////////////////////////////////////////// @@ -547,32 +603,30 @@ pub fn select(&mut self, obligation: &TraitObligation<'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); - self.probe(|this, _| { - this.evaluate_predicate_recursively(TraitObligationStackList::empty(), obligation) - .may_apply() - }) + // 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 `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 + /// Evaluates whether the obligation `obligation` can be satisfied and returns + /// an `EvaluationResult`. + pub fn evaluate_obligation_recursively(&mut self, + obligation: &PredicateObligation<'tcx>) + -> Result { - debug!("evaluate_obligation_conservatively({:?})", - obligation); - self.probe(|this, _| { this.evaluate_predicate_recursively(TraitObligationStackList::empty(), obligation) - == EvaluatedToOk }) } @@ -582,29 +636,29 @@ pub fn evaluate_obligation_conservatively(&mut self, 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 +674,10 @@ fn evaluate_predicate_recursively<'o>(&mut self, // 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 +689,21 @@ fn evaluate_predicate_recursively<'o>(&mut self, 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 +721,10 @@ fn evaluate_predicate_recursively<'o>(&mut self, result } Ok(None) => { - EvaluatedToAmbig + Ok(EvaluatedToAmbig) } Err(_) => { - EvaluatedToErr + Ok(EvaluatedToErr) } } } @@ -680,13 +733,13 @@ fn evaluate_predicate_recursively<'o>(&mut self, 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 +760,16 @@ fn evaluate_predicate_recursively<'o>(&mut self, 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 +779,7 @@ fn evaluate_predicate_recursively<'o>(&mut self, 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 +798,23 @@ fn evaluate_trait_predicate_recursively<'o>(&mut self, 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 +869,7 @@ fn evaluate_stack<'o>(&mut self, } } } - return EvaluatedToAmbig; + return Ok(EvaluatedToAmbig); } if unbound_input_types && stack.iter().skip(1).any( @@ -825,7 +879,7 @@ fn evaluate_stack<'o>(&mut self, { 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 +914,19 @@ fn evaluate_stack<'o>(&mut self, 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) => Err(OverflowError), + Err(..) => Ok(EvaluatedToErr) } } @@ -909,7 +964,7 @@ fn coinductive_predicate(&self, predicate: ty::Predicate<'tcx>) -> bool { 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 +976,12 @@ fn evaluate_candidate<'o>(&mut self, 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 +1055,14 @@ fn candidate_from_obligation<'o>(&mut self, // 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); + match self.query_mode { + TraitQueryMode::Standard => { + self.infcx().report_overflow_error(&stack.obligation, true); + }, + TraitQueryMode::Canonical => { + return Err(Overflow); + }, + } } // Check the cache. Note that we skolemize the trait-ref @@ -1081,9 +1143,15 @@ fn candidate_from_obligation_no_cache<'o>(&mut self, 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 +1219,21 @@ fn candidate_from_obligation_no_cache<'o>(&mut self, } // 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) => Err(Overflow), + }) + .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 +1608,14 @@ fn assemble_candidates_from_caller_bounds<'o>(&mut self, 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 +1625,14 @@ fn assemble_candidates_from_caller_bounds<'o>(&mut self, 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..d7e42655bbb 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -177,6 +177,7 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { tcx.lift(err).map(super::ConstEvalFailure) } + super::Overflow => bug!() // FIXME: ape ConstEvalFailure? } } } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 4f49b159ad3..c28fcfe8805 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -34,7 +34,7 @@ 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; @@ -2328,7 +2328,15 @@ pub fn mk_foreign(self, def_id: DefId) -> Ty<'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)) } @@ -2471,7 +2479,7 @@ pub fn mk_param(self, } 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 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 @@ pub fn try_push_visible_item_path(self, buffer: &mut T, external_def_id: DefI { 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 @@ pub fn try_push_visible_item_path(self, buffer: &mut T, external_def_id: DefI } 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 @@ pub fn push_item_path(self, buffer: &mut T, def_id: DefId) 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/layout.rs b/src/librustc/ty/layout.rs index 942cfdb36b8..55137e28911 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -727,11 +727,7 @@ enum StructKind { // Only one variant is inhabited. (inh_second.is_none() && // Representation optimizations are allowed. - !def.repr.inhibit_enum_layout_opt() && - // Inhabited variant either has data ... - (!variants[inh_first.unwrap()].is_empty() || - // ... or there other, uninhabited, variants. - variants.len() > 1)); + !def.repr.inhibit_enum_layout_opt()); if is_struct { // Struct, or univariant enum equivalent to a struct. // (Typechecking will reject discriminant-sizing attrs.) @@ -765,6 +761,9 @@ enum StructKind { return Ok(tcx.intern_layout(st)); } + // The current code for niche-filling relies on variant indices + // instead of actual discriminants, so dataful enums with + // explicit discriminants (RFC #2363) would misbehave. let no_explicit_discriminants = def.variants.iter().enumerate() .all(|(i, v)| v.discr == ty::VariantDiscr::Relative(i)); @@ -898,7 +897,7 @@ enum StructKind { } // 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 }; @@ -959,7 +958,7 @@ enum StructKind { // 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; } @@ -986,15 +985,80 @@ enum StructKind { 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/librustc/ty/maps/config.rs b/src/librustc/ty/maps/config.rs index 735fe06560f..57c8c4f34e7 100644 --- a/src/librustc/ty/maps/config.rs +++ b/src/librustc/ty/maps/config.rs @@ -9,24 +9,45 @@ // 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::{CanonicalProjectionGoal, CanonicalTyGoal}; +use traits::query::{CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal}; 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 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 { - type Key: Eq + Hash + Clone; - type Value; +pub trait QueryConfig<'tcx> { + const NAME: &'static str; + + type Key: Eq + Hash + Clone + Debug; + 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; } -pub(super) trait QueryDescription<'tcx>: QueryConfig { +pub trait QueryDescription<'tcx>: QueryConfig<'tcx> { fn describe(tcx: TyCtxt, key: Self::Key) -> String; #[inline] @@ -41,7 +62,7 @@ fn try_load_from_disk(_: TyCtxt<'_, 'tcx, 'tcx>, } } -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)) @@ -73,6 +94,12 @@ fn describe(_tcx: TyCtxt, goal: ParamEnvAnd<'tcx, Ty<'tcx>>) -> String { } } +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/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 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/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 @@ fn default_span(&self, _tcx: TyCtxt) -> Span { 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..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}; @@ -32,8 +31,9 @@ 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; @@ -42,7 +42,7 @@ 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; @@ -67,7 +67,6 @@ mod job; pub use self::job::{QueryJob, QueryInfo}; -use self::job::QueryResult; mod keys; pub use self::keys::Key; @@ -433,6 +432,12 @@ NoSolution, >, + /// Do not call this query directly: invoke `infcx.predicate_may_hold()` or + /// `infcx.predicate_must_hold()` instead. + [] 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/ty/maps/on_disk_cache.rs b/src/librustc/ty/maps/on_disk_cache.rs index f88e33c708e..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_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; @@ -239,14 +238,12 @@ pub fn serialize<'a, 'tcx, E>(&self, 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; + 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()); @@ -1124,7 +1121,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,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::get_cache_internal(tcx).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 61a4eb58531..37950463f74 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -15,21 +15,29 @@ 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, QueryMsg}; + 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; +use syntax::codemap::DUMMY_SP; -pub(super) struct QueryMap<'tcx, D: QueryDescription<'tcx>> { - phantom: PhantomData<(D, &'tcx ())>, - pub(super) map: FxHashMap>>, +pub struct QueryMap<'tcx, D: QueryConfig<'tcx> + ?Sized> { + pub(super) results: FxHashMap>, + pub(super) active: FxHashMap>, } pub(super) struct QueryValue { @@ -48,18 +56,166 @@ pub(super) fn new(value: T, } } -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(), + results: FxHashMap(), + active: FxHashMap(), + } + } +} + +// 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_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 }; + QueryMsg { + query: $query, + msg, + } + }} +} + +/// 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(); + 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::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); + { + let mut lock = map.borrow_mut(); + lock.active.remove(&key); + lock.results.insert(key, 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 |current_icx| { + // Update the ImplicitCtxt to point to our new query job + let new_icx = tls::ImplicitCtxt { + tcx, + query: Some(self.job.clone()), + layout_depth: current_icx.layout_depth, + task: current_icx.task, + }; + + // Use the ImplicitCtxt while we execute the query + tls::enter_context(&new_icx, |_| { + compute(tcx) + }) + }); + + // Extract the diagnostic from the job + let diagnostics = mem::replace(&mut *self.job.diagnostics.lock(), Vec::new()); + + (r, diagnostics) } } -pub(super) trait GetCacheInternal<'tcx>: QueryDescription<'tcx> + Sized { - fn get_cache_internal<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> LockGuard<'a, QueryMap<'tcx, Self>>; +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().active.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 +226,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> { @@ -180,28 +336,277 @@ pub(super) fn try_mark_green_and_read(self, dep_node: &DepNode) -> Option { - if cfg!(debug_assertions) { - if $tcx.sess.profile_queries() { - profq_msg($tcx.sess, $msg) + 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) } } -} -// 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 } + 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) + }) } } @@ -210,7 +615,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)*]) => { @@ -223,12 +628,7 @@ macro_rules! define_maps { $($(#[$attr:meta])* [$($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, @@ -251,12 +651,6 @@ pub enum Query<$tcx> { $($(#[$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 { @@ -303,162 +697,38 @@ pub struct $name<$tcx> { })* } - $(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() + const NAME: &'static str = stringify!($name); + + fn query(key: Self::Key) -> Query<'tcx> { + Query::$name(key) } - } - impl<'a, $tcx, 'lcx> queries::$name<$tcx> { + fn query_map<'a>(tcx: TyCtxt<'a, $tcx, '_>) -> &'a Lock> { + &tcx.maps.$name + } #[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)) } - /// 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 compute(tcx: TyCtxt<'_, 'tcx, '_>, key: Self::Key) -> Self::Value { + let provider = tcx.maps.providers[key.map_crate()].$name; + provider(tcx.global_tcx(), 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)) - ) - ); - - /// 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!(); - - // 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) - .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 = Self::start_job(tcx, span, key, lock, |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; - - 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(); - - 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, - dep_node_index, - &dep_node) - } - lock = get_lock_or_return!(); - } - - match Self::force_with_lock(tcx, key, span, lock, 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. /// @@ -467,282 +737,7 @@ macro_rules! get_lock_or_return { /// /// 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); - } - } - - /// 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) - } - - fn load_from_disk_and_cache_in_memory(tcx: TyCtxt<'a, $tcx, 'lcx>, - key: $K, - span: Span, - 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, job) = if let Some(result) = result { - (result, None) - } 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) = Self::start_job(tcx, - span, - key, - tcx.maps.$name.borrow_mut(), - |tcx| { - // The dep-graph for this computation is already in - // place - tcx.dep_graph.with_ignore(|| { - Self::compute_result(tcx, key) - }) - })?; - (result, Some(job)) - }; - - // 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); - } - - 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()); - - 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 lock = match Self::try_get_lock(tcx, span, &key) { - TryGetLock::NotYetStarted(lock) => lock, - TryGetLock::JobCompleted(result) => return result, - }; - Self::force_with_lock(tcx, - key, - span, - lock, - dep_node) - } - - fn force_with_lock(tcx: TyCtxt<'a, $tcx, 'lcx>, - key: $K, - span: Span, - map: LockGuard<'_, QueryMap<$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 = Self::start_job(tcx, - span, - key, - map, - |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), job) = 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); - } - - 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(); - - 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); } })* @@ -778,10 +773,7 @@ pub fn $name(self, key: $K) -> $V { 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) })* } @@ -872,7 +864,6 @@ fn default() -> Self { 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 @@ -915,23 +906,14 @@ macro_rules! force { { 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(); @@ -977,6 +959,7 @@ macro_rules! force { DepKind::NormalizeProjectionTy | DepKind::NormalizeTyAfterErasingRegions | DepKind::DropckOutlives | + DepKind::EvaluateObligation | DepKind::SubstituteNormalizeAndTestPredicates | DepKind::InstanceDefSizeEstimate | DepKind::ProgramClausesForEnv | 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 @@ fn from_cycle_error<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> 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..5a121d3edbe 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -51,7 +51,7 @@ 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; @@ -2031,7 +2031,7 @@ pub fn destructor(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option { /// 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); @@ -2463,7 +2463,7 @@ pub fn adt_def_id_of_variant(self, variant_def: &'tcx VariantDef) -> DefId { 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 @@ pub struct 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..e9c1e87676b 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -864,7 +864,7 @@ pub fn new(index: u32, name: InternedString) -> 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 { @@ -876,8 +876,10 @@ pub fn to_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> { } 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 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::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/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 @@ fn name_by_region_index(index: usize) -> InternedString { 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/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_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 @@ pub fn t_pair(&self, ty1: Ty<'tcx>, ty2: Ty<'tcx>) -> Ty<'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 @@ fn check_attr(&self, attr: &ast::Attribute) { 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..fdfe2a98bf9 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)] @@ -535,7 +535,7 @@ fn load_macro_untracked(&self, id: DefId, sess: &Session) -> LoadedMacro { .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 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 @@ fn get_variant(&self, item: &Entry, index: DefIndex) -> ty::VariantDef { 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 @@ pub fn each_child_of_item(&self, id: DefIndex, mut callback: F, sess: &Sessio 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 @@ pub fn each_child_of_item(&self, id: DefIndex, mut callback: F, sess: &Sessio 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 @@ pub fn get_associated_item(&self, id: DefIndex) -> ty::AssociatedItem { }; ty::AssociatedItem { - name: Symbol::intern(&name), + name: name.as_symbol(), kind, vis: item.visibility.decode(self), defaultness: container.defaultness(), @@ -914,7 +914,7 @@ pub fn get_struct_field_names(&self, id: DefIndex) -> Vec { 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 @@ pub fn def_key(&self, index: DefIndex) -> DefKey { 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/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index ec7ee466008..0ed95a319f7 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 @@ fn check_terminator( )); } - 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 @@ fn check_call_inputs( } } - 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; 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 @@ pub fn into_expr(&mut self, 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 @@ fn call_intrinsic<'a>( ) -> 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/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 42f0e38af1f..f6e9994b5da 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -671,6 +671,23 @@ pub(super) fn eval_rvalue_into_place( (Value::ByVal(_), _) => bug!("expected fat ptr"), } } else { + let src_layout = self.layout_of(src.ty)?; + match src_layout.variants { + layout::Variants::Single { index } => { + if let Some(def) = src.ty.ty_adt_def() { + let discr_val = def + .discriminant_for_variant(*self.tcx, index) + .val; + return self.write_primval( + dest, + PrimVal::Bytes(discr_val), + dest_ty); + } + } + layout::Variants::Tagged { .. } | + layout::Variants::NicheFilling { .. } => {}, + } + let src_val = self.value_to_primval(src)?; let dest_val = self.cast_primval(src_val, src.ty, dest_ty)?; let valty = ValTy { @@ -751,9 +768,7 @@ pub(super) fn eval_rvalue_into_place( } } - if log_enabled!(::log::Level::Trace) { - self.dump_local(dest); - } + self.dump_local(dest); Ok(()) } @@ -852,10 +867,16 @@ pub fn read_discriminant_value( ) -> EvalResult<'tcx, u128> { let layout = self.layout_of(ty)?; trace!("read_discriminant_value {:#?}", layout); + if layout.abi == layout::Abi::Uninhabited { + return Ok(0); + } match layout.variants { layout::Variants::Single { index } => { - return Ok(index as u128); + let discr_val = ty.ty_adt_def().map_or( + index as u128, + |def| def.discriminant_for_variant(*self.tcx, index).val); + return Ok(discr_val); } layout::Variants::Tagged { .. } | layout::Variants::NicheFilling { .. } => {}, @@ -1318,6 +1339,15 @@ pub(crate) fn read_ptr( pub fn try_read_value(&self, ptr: Pointer, ptr_align: Align, ty: Ty<'tcx>) -> EvalResult<'tcx, Option> { 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)?; + + if layout.size.bytes() == 0 { + return Ok(Some(Value::ByVal(PrimVal::Undef))); + } + let ptr = ptr.to_ptr()?; let val = match ty.sty { ty::TyBool => { @@ -1540,6 +1570,9 @@ fn unsize_into( 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 @@ pub fn get_alloc_kind(&self, id: AllocId) -> Option> /// 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..d03204bfab1 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -136,6 +136,7 @@ pub fn read_field( let val = [a, b][field_index]; Ok(Some((Value::ByVal(val), field.ty))) }, + // FIXME(oli-obk): figure out whether we should be calling `try_read_value` here _ => Ok(None), } } @@ -218,9 +219,7 @@ pub fn eval_place(&mut self, mir_place: &mir::Place<'tcx>) -> EvalResult<'tcx, P } }; - if log_enabled!(::log::Level::Trace) { - self.dump_local(place); - } + self.dump_local(place); Ok(place) } diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index 399892522a3..75b7a10097d 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -24,7 +24,7 @@ #![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_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 @@ fn symbol_name(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::SymbolName { 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 @@ fn items(&self) -> &FxHashMap, (Linkage, Visibility)> { } 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/shim.rs b/src/librustc_mir/shim.rs index af60a83a4a2..699a5b17435 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/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 @@ fn visit_place(&mut self, 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 @@ fn visit_place(&mut self, 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 @@ fn require_unsafe(&mut self, 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/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 @@ fn run_pass<'a, 'tcx>(&self, (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/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 2b491385d66..2e2f8494146 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -126,7 +126,7 @@ fn run_pass(&self, caller_mir: &mut Mir<'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) => { @@ -379,8 +379,6 @@ fn inline_call(&self, 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 @@ fn dest_needs_borrow(place: &Place) -> bool { 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 @@ fn dest_needs_borrow(place: &Place) -> bool { } } - 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/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 @@ fn visit_terminator_kind(&mut self, 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_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index 19f33ef5d45..4b7c581d3c8 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -13,6 +13,7 @@ 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 @@ fn move_paths_for_fields(&self, 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), @@ -337,18 +339,19 @@ fn open_drop_for_tuple<'a>(&mut self, tys: &[Ty<'tcx>]) 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 +794,12 @@ fn open_drop<'a>(&mut self) -> BasicBlock { 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,28 +862,34 @@ fn elaborated_drop_block<'a>(&mut self) -> BasicBlock { 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 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 call = TerminatorKind::Call { func: Operand::function_handle(tcx, free_func, substs, self.source_info.span), - args: vec![Operand::Move(self.place.clone())], + args: args, destination: Some((unit_temp, target)), cleanup: None }; // FIXME(#43234) 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::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 @@ pub fn get_module(&mut self, def_id: DefId) -> Module<'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_traits/evaluate_obligation.rs b/src/librustc_traits/evaluate_obligation.rs new file mode 100644 index 00000000000..21259bbcd38 --- /dev/null +++ b/src/librustc_traits/evaluate_obligation.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. + +use rustc::traits::{EvaluationResult, Obligation, ObligationCause, + OverflowError, SelectionContext, TraitQueryMode}; +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>, +) -> Result { + 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::with_query_mode(&infcx, TraitQueryMode::Canonical); + let obligation = Obligation::new(ObligationCause::dummy(), param_env, predicate); + + selcx.evaluate_obligation_recursively(&obligation) + }) +} 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_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 }; } 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 @@ 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| { 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, diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs index f9a8473464d..ea3f5b40860 100644 --- a/src/librustc_trans/back/linker.rs +++ b/src/librustc_trans/back/linker.rs @@ -959,7 +959,11 @@ fn no_position_independent_executable(&mut self) { } 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 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 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::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 @@ pub fn new(tcx: TyCtxt<'a, 'tcx, '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 @@ fn get_template_parameters<'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 @@ fn push_item_name(cx: &CodegenCx, 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 @@ fn trans_terminator(&mut self, // 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/mir/place.rs b/src/librustc_trans/mir/place.rs index b340d91b027..b8b0c019ca6 100644 --- a/src/librustc_trans/mir/place.rs +++ b/src/librustc_trans/mir/place.rs @@ -16,7 +16,7 @@ use rustc_data_structures::indexed_vec::Idx; use base; use builder::Builder; -use common::{CodegenCx, C_usize, C_u8, C_u32, C_uint, C_int, C_null, C_uint_big}; +use common::{CodegenCx, C_undef, C_usize, C_u8, C_u32, C_uint, C_null, C_uint_big}; use consts; use type_of::LayoutLlvmExt; use type_::Type; @@ -264,9 +264,15 @@ pub fn project_field(self, bx: &Builder<'a, 'tcx>, ix: usize) -> PlaceRef<'tcx> /// Obtain the actual discriminant of a value. pub fn trans_get_discr(self, bx: &Builder<'a, 'tcx>, cast_to: Ty<'tcx>) -> ValueRef { let cast_to = bx.cx.layout_of(cast_to).immediate_llvm_type(bx.cx); + if self.layout.abi == layout::Abi::Uninhabited { + return C_undef(cast_to); + } match self.layout.variants { layout::Variants::Single { index } => { - return C_uint(cast_to, index as u64); + let discr_val = self.layout.ty.ty_adt_def().map_or( + index as u128, + |def| def.discriminant_for_variant(bx.cx.tcx, index).val); + return C_uint_big(cast_to, discr_val); } layout::Variants::Tagged { .. } | layout::Variants::NicheFilling { .. } => {}, @@ -328,9 +334,11 @@ pub fn trans_set_discr(&self, bx: &Builder<'a, 'tcx>, variant_index: usize) { let ptr = self.project_field(bx, 0); let to = self.layout.ty.ty_adt_def().unwrap() .discriminant_for_variant(bx.tcx(), variant_index) - .val as u64; - bx.store(C_int(ptr.layout.llvm_type(bx.cx), to as i64), - ptr.llval, ptr.align); + .val; + bx.store( + C_uint_big(ptr.layout.llvm_type(bx.cx), to), + ptr.llval, + ptr.align); } layout::Variants::NicheFilling { dataful_variant, diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index 93702bfbbf3..c932777402e 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -22,7 +22,7 @@ use builder::Builder; use callee; use common::{self, val_ty}; -use common::{C_bool, C_u8, C_i32, C_u32, C_u64, C_null, C_usize, C_uint, C_uint_big}; +use common::{C_bool, C_u8, C_i32, C_u32, C_u64, C_undef, C_null, C_usize, C_uint, C_uint_big}; use consts; use monomorphize; use type_::Type; @@ -267,11 +267,33 @@ pub fn trans_rvalue_operand(&mut self, } mir::CastKind::Misc => { assert!(cast.is_llvm_immediate()); + let ll_t_out = cast.immediate_llvm_type(bx.cx); + if operand.layout.abi == layout::Abi::Uninhabited { + return (bx, OperandRef { + val: OperandValue::Immediate(C_undef(ll_t_out)), + layout: cast, + }); + } let r_t_in = CastTy::from_ty(operand.layout.ty) .expect("bad input type for cast"); let r_t_out = CastTy::from_ty(cast.ty).expect("bad output type for cast"); let ll_t_in = operand.layout.immediate_llvm_type(bx.cx); - let ll_t_out = cast.immediate_llvm_type(bx.cx); + match operand.layout.variants { + layout::Variants::Single { index } => { + if let Some(def) = operand.layout.ty.ty_adt_def() { + let discr_val = def + .discriminant_for_variant(bx.cx.tcx, index) + .val; + let discr = C_uint_big(ll_t_out, discr_val); + return (bx, OperandRef { + val: OperandValue::Immediate(discr), + layout: cast, + }); + } + } + layout::Variants::Tagged { .. } | + layout::Variants::NicheFilling { .. } => {}, + } let llval = operand.immediate(); let mut signed = false; 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 @@ fn predefine(&self, 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 @@ fn from_interned(symbol: ty::SymbolName) -> Self { 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 @@ pub fn ast_region_to_region(&self, { 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 @@ pub fn def_to_ty(&self, 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/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 @@ fn overloaded_deref_ty(&mut self, ty: Ty<'tcx>) -> Option> { 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/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index c9e53fa7674..91264849cad 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -732,8 +732,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/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/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 @@ pub fn lookup_method_in_trait(&self, 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 @@ fn consider_probe(&self, 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 @@ fn consider_probe(&self, // 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_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 @@ fn is_fn_ty(&self, ty: &Ty<'tcx>, span: Span) -> bool { 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/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::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 @@ fn check_field(&self, // 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/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 23fe91ffdeb..958960d3a36 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -71,6 +71,8 @@ #![allow(non_camel_case_types)] +#![cfg_attr(stage0, feature(dyn_trait))] + #![feature(box_patterns)] #![feature(box_syntax)] #![feature(crate_visibility_modifier)] @@ -81,7 +83,6 @@ #![feature(rustc_diagnostic_macros)] #![feature(slice_patterns)] #![feature(slice_sort_by_cached_key)] -#![feature(dyn_trait)] #![feature(never_type)] #[macro_use] extern crate log; 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 @@ fn generics_to_path_params(&self, generics: ty::Generics) -> hir::PathParameters 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 @@ fn ty_param_to_ty(&self, param: ty::TypeParameterDef) -> hir::Ty { 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 @@ fn clean(&self, cx: &DocContext) -> Type { 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 @@ fn clean(&self, cx: &DocContext) -> Type { } 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 @@ fn clean(&self, cx: &DocContext) -> Type { 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 @@ fn clean(&self, cx: &DocContext) -> Type { }); } - 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/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 { diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 82449e9b5f9..4e9781cc560 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1595,6 +1595,8 @@ pub fn new(root_path: &'a str, suffix: &'a str) -> 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()); diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 614386a583a..8efb51bccd8 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)] @@ -23,7 +25,6 @@ #![feature(test)] #![feature(vec_remove_item)] #![feature(entry_and_modify)] -#![feature(dyn_trait)] extern crate arena; extern crate getopts; diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 0331e90164f..a4a83712a08 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -375,9 +375,6 @@ pub fn walk_feature_fields(&self, mut f: F) // 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 @@ pub fn walk_feature_fields(&self, mut f: F) (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.27.0", Some(44662), None), ); // If you change this, please modify src/doc/unstable-book as well. You must @@ -1657,10 +1656,6 @@ fn visit_ty(&mut self, ty: &'a ast::Ty) { 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/libsyntax_pos/hygiene.rs b/src/libsyntax_pos/hygiene.rs index 5e96b5ce673..658408519b9 100644 --- a/src/libsyntax_pos/hygiene.rs +++ b/src/libsyntax_pos/hygiene.rs @@ -21,6 +21,7 @@ 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 @@ pub fn is_descendant_of(mut self, ancestor: Mark) -> bool { 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 la = least_ancestor(a, b); + /// assert!(a.is_descendant_of(la)) + /// assert!(b.is_descendant_of(la)) + /// ``` + 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::(); + 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 { @@ -238,6 +265,22 @@ fn apply_mark_internal(self, mark: Mark) -> 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; diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 9a7d1fd8ee6..8d37b4aa396 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -291,6 +291,12 @@ pub fn source_callsite(self) -> 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, 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 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 @@ pub const fn with_empty_ctxt(name: Symbol) -> 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 @@ pub fn gensymed(self) -> Self { 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)) } } 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 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]]) } 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/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 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 @@ fn bar(&self, _: &impl Debug) { } //~^ 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() {} diff --git a/src/test/compile-fail/impl-trait/where-allowed.rs b/src/test/compile-fail/impl-trait/where-allowed.rs index 038eacaf110..2891cd59e3e 100644 --- a/src/test/compile-fail/impl-trait/where-allowed.rs +++ b/src/test/compile-fail/impl-trait/where-allowed.rs @@ -10,7 +10,6 @@ //! A simple test for testing many permutations of allowedness of //! impl Trait -#![feature(dyn_trait)] use std::fmt::Debug; // Allowed 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 } 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 foo() {} #[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/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/debuginfo/c-style-enum.rs b/src/test/debuginfo/c-style-enum.rs index 1f1f42e2dec..2dbac8e3d9e 100644 --- a/src/test/debuginfo/c-style-enum.rs +++ b/src/test/debuginfo/c-style-enum.rs @@ -151,6 +151,7 @@ enum ManualDiscriminant { } #[derive(Copy, Clone)] +#[repr(u8)] enum SingleVariant { TheOnlyVariant } 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/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/run-pass/issue-23304-2.rs b/src/test/run-pass/issue-23304-2.rs index 79712f7c25e..5989b7e9c6a 100644 --- a/src/test/run-pass/issue-23304-2.rs +++ b/src/test/run-pass/issue-23304-2.rs @@ -10,8 +10,13 @@ #![allow(dead_code)] -enum X { A = 0 as isize } +enum X { A = 42 as isize } enum Y { A = X::A as isize } -fn main() { } +fn main() { + let x = X::A; + let x = x as isize; + assert_eq!(x, 42); + assert_eq!(Y::A as isize, 42); +} 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/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![]) +} 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/run-pass/type-sizes.rs b/src/test/run-pass/type-sizes.rs index 7bd9a1703ee..a47f082b9c3 100644 --- a/src/test/run-pass/type-sizes.rs +++ b/src/test/run-pass/type-sizes.rs @@ -43,6 +43,31 @@ enum ReorderedEnum { B(u8, u16, u8), } +enum EnumEmpty {} + +enum EnumSingle1 { + A, +} + +enum EnumSingle2 { + A = 42 as isize, +} + +enum EnumSingle3 { + A, + B(!), +} + +#[repr(u8)] +enum EnumSingle4 { + A, +} + +#[repr(u8)] +enum EnumSingle5 { + A = 42 as u8, +} + enum NicheFilledEnumWithInhabitedVariant { A(&'static ()), B(&'static (), !), @@ -74,5 +99,13 @@ pub fn main() { assert_eq!(size_of::(), 4 as usize); assert_eq!(size_of::(), 4); assert_eq!(size_of::(), 6); + + assert_eq!(size_of::(), 0); + assert_eq!(size_of::(), 0); + assert_eq!(size_of::(), 0); + assert_eq!(size_of::(), 0); + assert_eq!(size_of::(), 1); + assert_eq!(size_of::(), 1); + assert_eq!(size_of::(), size_of::<&'static ()>()); } 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-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/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`. 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 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 | diff --git a/src/test/ui/impl_trait_projections.rs b/src/test/ui/impl_trait_projections.rs index 6a727942271..57a0040600a 100644 --- a/src/test/ui/impl_trait_projections.rs +++ b/src/test/ui/impl_trait_projections.rs @@ -7,8 +7,6 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(dyn_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 9b38de614fc..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:23: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:30: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:37: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:44:29 + --> $DIR/impl_trait_projections.rs:42:29 | LL | -> as Iterator>::Item | ^^^^^^^^^^ error[E0223]: ambiguous associated type - --> $DIR/impl_trait_projections.rs:23: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/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/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.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-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.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-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.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-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.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-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.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-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.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/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.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-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.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-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.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-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.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-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.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-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.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; 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.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/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.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-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.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> { | ____________________________________________________^ 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 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 | ^^^^^ diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 85434bb8a69..d1dac370c9e 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1168,6 +1168,8 @@ fn check_no_compiler_crash(&self, proc_res: &ProcRes) { 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); } } }