[[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)",
"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)",
"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)",
"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"
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),
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,
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";
);
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;
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.
--- /dev/null
+[book]
+authors = ["The Rust Project Developers"]
+multilingual = false
+src = "src"
+title = "The rustc book"
--- /dev/null
+# 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
--- /dev/null
+# 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.
--- /dev/null
+# 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.
--- /dev/null
+# 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
--- /dev/null
+# 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
--- /dev/null
+# 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.
--- /dev/null
+# 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.
--- /dev/null
+# 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 <https://github.com/rust-lang/rust/issues/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<Trait>) {
+}
+```
+
+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<Trait>) {
+ | ^^^^^ 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<dyn Trait>) {
+}
+```
+
+## box-pointers
+
+This lints use of the Box type. Some example code that triggers this lint:
+
+```rust
+struct Foo {
+ x: Box<isize>,
+}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: type uses owned (Box type) pointers: std::boxed::Box<isize>
+ --> src/lib.rs:6:5
+ |
+6 | x: Box<isize> //~ ERROR type uses owned
+ | ^^^^^^^^^^^^^
+ |
+```
+
+This lint is mostly historical, and not particularly useful. `Box<T>` 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>() -> T { panic!() }
+
+fn main() {
+ foo::<usize>();
+}
+```
+
+When set to 'deny', this will produce:
+
+```text
+error: unused result
+ --> src/main.rs:6:5
+ |
+6 | foo::<usize>();
+ | ^^^^^^^^^^^^^^^
+ |
+```
+
+## 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
+ | ^^^^^^^^^^^^^^^^
+ |
+```
--- /dev/null
+# 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=i32>(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=i32>(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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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 <https://github.com/rust-lang/rust/issues/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"]
+ | ^^^^^^^^^^^^^^^^^^^^
+ |
+```
--- /dev/null
+# 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
--- /dev/null
+# 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 <https://github.com/rust-lang/rust/issues/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<X> {
+ type Output;
+}
+
+pub trait Trait2<X> {}
+
+pub struct A;
+
+impl<X, T> Trait1<X> for T where T: Trait2<X> {
+ type Output = ();
+}
+
+impl<X> Trait1<Box<X>> for A {
+ type Output = i32;
+}
+```
+
+This will produce:
+
+```text
+warning: conflicting implementations of trait `Trait1<std::boxed::Box<_>>` for type `A`: (E0119)
+ --> src/main.rs:13:1
+ |
+9 | impl<X, T> Trait1<X> for T where T: Trait2<X> {
+ | --------------------------------------------- first implementation here
+...
+13 | impl<X> Trait1<Box<X>> 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 <https://github.com/rust-lang/rust/issues/46205>
+ = note: downstream crates may implement trait `Trait2<std::boxed::Box<_>>` 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 <https://github.com/rust-lang/rust/issues/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: 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: 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 <https://github.com/rust-lang/rust/issues/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<T>(pub T);
+
+pub struct Foo {
+ start: u8,
+ data: Unaligned<u32>,
+}
+
+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 <https://github.com/rust-lang/rust/issues/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<T: Send> = Vec<T>;
+```
+
+This will produce:
+
+```text
+warning: type alias is never used: `SendVec`
+ --> src/main.rs:1:1
+ |
+1 | type SendVec<T: Send> = Vec<T>;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+```
+
+## 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 <https://github.com/rust-lang/rust/issues/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`
+ |
+```
--- /dev/null
+# 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
--- /dev/null
+# 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
--- /dev/null
+# 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
+```
--- /dev/null
+# 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
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)]
}
}
-#[cfg_attr(not(test), lang = "box_free")]
+#[cfg(stage0)]
+#[lang = "box_free"]
+#[inline]
+unsafe fn old_box_free<T: ?Sized>(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<T: ?Sized>(ptr: *mut T) {
+pub(crate) unsafe fn box_free<T: ?Sized>(ptr: Unique<T>) {
+ let ptr = ptr.as_ptr();
let size = size_of_val(&*ptr);
let align = min_align_of_val(&*ptr);
// We do not allocate for Box<T> when T is ZST, so deallocation is also not necessary.
fn from_box(v: Box<T>) -> Arc<T> {
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);
value_size);
// Free the allocation without dropping its contents
- box_free(bptr);
+ box_free(box_unique);
Arc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData }
}
#[unstable(feature = "ptr_internals", issue = "0", reason = "use into_raw_non_null instead")]
#[inline]
+ #[doc(hidden)]
pub fn into_unique(b: Box<T>) -> Unique<T> {
let unique = b.0;
mem::forget(b);
fn from_box(v: Box<T>) -> Rc<T> {
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);
value_size);
// Free the allocation without dropping its contents
- box_free(bptr);
+ box_free(box_unique);
Rc { ptr: NonNull::new_unchecked(ptr), phantom: PhantomData }
}
/// ```
#[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<Rhs: ?Sized = Self> {
/// This method tests for `self` and `other` values to be equal, and is used
/// }
/// impl Eq for Book {}
/// ```
+#[doc(alias = "==")]
+#[doc(alias = "!=")]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Eq: PartialEq<Self> {
// this method is used solely by #[deriving] to assert
/// }
/// ```
#[lang = "ord"]
+#[doc(alias = "<")]
+#[doc(alias = ">")]
+#[doc(alias = "<=")]
+#[doc(alias = ">=")]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Ord: Eq + PartialOrd<Self> {
/// This method returns an `Ordering` between `self` and `other`.
/// ```
#[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<Rhs: ?Sized = Self>: PartialEq<Rhs> {
/// This method returns an ordering between `self` and `other` values if one exists.
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.
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.
/// 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}`")]
/// 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}`")]
/// 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}`")]
/// 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}`")]
/// 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}`")]
/// 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}`")]
/// 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}`")]
/// 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}`")]
/// 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}`")]
/// 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}`")]
/// 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.
/// assert_eq!('b', *x);
/// ```
#[lang = "deref_mut"]
+#[doc(alias = "*")]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait DerefMut: Deref {
/// Mutably dereferences the value.
/// [`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;
/// 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<Idx> {
/// ```
///
/// [`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<Idx> {
/// [`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<Idx> {
/// 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<Idx> {
/// [`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<Idx> {
reason = "use NonNull instead and consider PhantomData<T> \
(if you also use #[may_dangle]), Send, and/or Sync")]
#[allow(deprecated)]
+#[doc(hidden)]
pub struct Unique<T: ?Sized> {
pointer: NonZero<*const T>,
// NOTE: this marker has no consequences for variance, but is necessary
/// `self` was generated from, if any.
#[unstable(feature = "proc_macro", issue = "38356")]
pub fn parent(&self) -> Option<Span> {
- 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
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;
[] NormalizeProjectionTy(CanonicalProjectionGoal<'tcx>),
[] NormalizeTyAfterErasingRegions(ParamEnvAnd<'tcx, Ty<'tcx>>),
[] DropckOutlives(CanonicalTyGoal<'tcx>),
+ [] EvaluateObligation(CanonicalPredicateGoal<'tcx>),
[] SubstituteNormalizeAndTestPredicates { key: (DefId, &'tcx Substs<'tcx>) },
ForeignMod,
Expression,
Statement,
+ Closure,
Other,
}
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();
}
}
}
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(
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,
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,
}
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(
// 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(..) => {
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| {
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);
}
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);
}
}
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);
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
);
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
);
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),
};
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),
};
Typeof => "{{typeof}}",
};
- Symbol::intern(s).as_str()
+ Symbol::intern(s).as_interned_str()
}
pub fn to_string(&self) -> String {
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
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,
}
};
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;
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a>,
hasher: &mut StableHasher<W>) {
- let s: &str = &**self;
- s.hash_stable(hcx, hasher);
+ self.with(|s| s.hash_stable(hcx, hasher))
}
}
}
}
+impl<'a> HashStable<StableHashingContext<'a>> for LocalInternedString {
+ #[inline]
+ fn hash_stable<W: StableHasherResult>(&self,
+ hcx: &mut StableHashingContext<'a>,
+ hasher: &mut StableHasher<W>) {
+ let s: &str = &**self;
+ s.hash_stable(hcx, hasher);
+ }
+}
+
+impl<'a> ToStableHashKey<StableHashingContext<'a>> for LocalInternedString {
+ type KeyType = LocalInternedString;
+
+ #[inline]
+ fn to_stable_hash_key(&self,
+ _: &StableHashingContext<'a>)
+ -> LocalInternedString {
+ self.clone()
+ }
+}
+
impl<'a> HashStable<StableHashingContext<'a>> for ast::Name {
#[inline]
fn hash_stable<W: StableHasherResult>(&self,
fn to_stable_hash_key(&self,
_: &StableHashingContext<'a>)
-> InternedString {
- self.as_str()
+ self.as_interned_str()
}
}
#![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))]
#![feature(nonzero)]
#![feature(proc_macro_internals)]
#![feature(quote)]
+#![feature(optin_builtin_traits)]
#![feature(refcell_replace_swap)]
#![feature(rustc_diagnostic_macros)]
#![feature(slice_patterns)]
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);
SelectionContext,
SelectionError,
ObjectSafetyViolation,
+ Overflow,
};
use errors::DiagnosticBuilder;
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 \
}
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();
.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: _ }) =
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 == '&');
cleaned_pred.to_predicate()
);
- selcx.evaluate_obligation(&obligation)
+ self.predicate_may_hold(&obligation)
})
}
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.
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![]))
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;
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
ty::error::TypeError<'tcx>),
TraitNotObjectSafe(DefId),
ConstEvalFailure(ConstEvalErr<'tcx>),
+ Overflow,
}
pub struct FulfillmentError<'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);
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 {
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<Self, ErrorReported>
{
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) => {
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 })
+ }
}
}
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+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
+ }
+}
use ty::{self, Ty};
pub mod dropck_outlives;
+pub mod evaluate_obligation;
pub mod normalize;
pub mod normalize_erasing_regions;
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;
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;
/// 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)]
/// 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
}
impl EvaluationResult {
- fn may_apply(self) -> bool {
+ pub fn may_apply(self) -> bool {
match self {
EvaluatedToOk |
EvaluatedToAmbig |
}
}
+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<OverflowError> for SelectionError<'tcx> {
+ fn from(OverflowError: OverflowError) -> SelectionError<'tcx> {
+ SelectionError::Overflow
+ }
+}
+
#[derive(Clone)]
pub struct EvaluationCache<'tcx> {
hashmap: RefCell<FxHashMap<ty::PolyTraitRef<'tcx>, WithDepNode<EvaluationResult>>>
intercrate: None,
intercrate_ambiguity_causes: None,
allow_negative_impls: false,
+ query_mode: TraitQueryMode::Standard,
}
}
intercrate: Some(mode),
intercrate_ambiguity_causes: None,
allow_negative_impls: false,
+ query_mode: TraitQueryMode::Standard,
}
}
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,
}
}
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))
+ }
}
///////////////////////////////////////////////////////////////////////////
// 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<EvaluationResult, OverflowError>
{
- debug!("evaluate_obligation_conservatively({:?})",
- obligation);
-
self.probe(|this, _| {
this.evaluate_predicate_recursively(TraitObligationStackList::empty(), obligation)
- == EvaluatedToOk
})
}
fn evaluate_predicates_recursively<'a,'o,I>(&mut self,
stack: TraitObligationStackList<'o, 'tcx>,
predicates: I)
- -> EvaluationResult
+ -> Result<EvaluationResult, OverflowError>
where I : IntoIterator<Item=&'a PredicateObligation<'tcx>>, '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<EvaluationResult, OverflowError>
{
debug!("evaluate_predicate_recursively({:?})",
obligation);
// 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),
}
}
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)
}
}
result
}
Ok(None) => {
- EvaluatedToAmbig
+ Ok(EvaluatedToAmbig)
}
Err(_) => {
- EvaluatedToErr
+ Ok(EvaluatedToErr)
}
}
}
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)
}
}
}
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)
}
}
}
fn evaluate_trait_predicate_recursively<'o>(&mut self,
previous_stack: TraitObligationStackList<'o, 'tcx>,
mut obligation: TraitObligation<'tcx>)
- -> EvaluationResult
+ -> Result<EvaluationResult, OverflowError>
{
debug!("evaluate_trait_predicate_recursively({:?})",
obligation);
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<EvaluationResult, OverflowError>
{
// In intercrate mode, whenever any of the types are unbound,
// there can always be an impl. Even if there are no impls in
}
}
}
- return EvaluatedToAmbig;
+ return Ok(EvaluatedToAmbig);
}
if unbound_input_types &&
stack.iter().skip(1).any(
{
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
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)
}
}
fn evaluate_candidate<'o>(&mut self,
stack: &TraitObligationStack<'o, 'tcx>,
candidate: &SelectionCandidate<'tcx>)
- -> EvaluationResult
+ -> Result<EvaluationResult, OverflowError>
{
debug!("evaluate_candidate: depth={} candidate={:?}",
stack.obligation.recursion_depth, candidate);
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,
// 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
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::<Result<Vec<_>, 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();
}
// 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<Vec<Option<EvaluatedCandidate>>, _> = 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<EvaluatedCandidate> =
+ candidates?.into_iter().filter_map(|c| c).collect();
// If there are STILL multiple candidate, we can further
// reduce the list by dropping duplicates -- including
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);
fn evaluate_where_clause<'o>(&mut self,
stack: &TraitObligationStack<'o, 'tcx>,
where_clause_trait_ref: ty::PolyTraitRef<'tcx>)
- -> EvaluationResult
+ -> Result<EvaluationResult, OverflowError>
{
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)
}
})
}
super::ConstEvalFailure(ref err) => {
tcx.lift(err).map(super::ConstEvalFailure)
}
+ super::Overflow => bug!() // FIXME: ape ConstEvalFailure?
}
}
}
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;
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))
}
}
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> {
use middle::cstore::{ExternCrate, ExternCrateSource};
use syntax::ast;
use syntax::symbol::Symbol;
-use syntax::symbol::InternedString;
+use syntax::symbol::LocalInternedString;
use std::cell::Cell;
{
let visible_parent_map = self.visible_parent_map(LOCAL_CRATE);
- let (mut cur_def, mut cur_path) = (external_def_id, Vec::<InternedString>::new());
+ let (mut cur_def, mut cur_path) = (external_def_id, Vec::<LocalInternedString>::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.
}
let data = cur_def_key.disambiguated_data.data;
- let symbol =
- data.get_opt_name().unwrap_or_else(|| Symbol::intern("<unnamed>").as_str());
+ let symbol = data.get_opt_name().map(|n| n.as_str()).unwrap_or_else(|| {
+ Symbol::intern("<unnamed>").as_str()
+ });
cur_path.push(symbol);
match visible_parent_map.get(&cur_def) {
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();
// 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.)
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));
}
// 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 };
// 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;
}
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<u8> 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)],
// 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<StableHashingContext<'a>>;
+
+ 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<QueryMap<'tcx, Self>>;
+
+ 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]
}
}
-impl<'tcx, M: QueryConfig<Key=DefId>> 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))
}
}
+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)
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<QueryJob<'tcx>>),
- /// 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,
}
//! 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;
DUMMY_SP
}
}
+
+impl<'tcx> Key for CanonicalPredicateGoal<'tcx> {
+ fn map_crate(&self) -> CrateNum {
+ LOCAL_CRATE
+ }
+
+ fn default_span(&self, _tcx: TyCtxt) -> Span {
+ DUMMY_SP
+ }
+}
// 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};
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;
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;
mod job;
pub use self::job::{QueryJob, QueryInfo};
-use self::job::QueryResult;
mod keys;
pub use self::keys::Key;
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<traits::EvaluationResult, traits::OverflowError>,
+
[] fn substitute_normalize_and_test_predicates:
substitute_normalize_and_test_predicates_node((DefId, &'tcx Substs<'tcx>)) -> bool,
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;
encode_query_results::<specialization_graph_of, _>(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());
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,
{
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
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<D::Key, QueryResult<'tcx, QueryValue<D::Value>>>,
+pub struct QueryMap<'tcx, D: QueryConfig<'tcx> + ?Sized> {
+ pub(super) results: FxHashMap<D::Key, QueryValue<D::Value>>,
+ pub(super) active: FxHashMap<D::Key, QueryResult<'tcx>>,
}
pub(super) struct QueryValue<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<QueryMap<'tcx, Q>>,
+ key: Q::Key,
+ job: Lrc<QueryJob<'tcx>>,
+}
+
+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<Diagnostic>)
+ 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)]
}
/// 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> {
}
}
}
-}
-// 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)
+ fn try_get_with<Q: QueryDescription<'gcx>>(
+ self,
+ span: Span,
+ key: Q::Key)
+ -> Result<Q::Value, CycleError<'gcx>>
+ {
+ 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::<Q>(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::<Q>(key,
+ job,
+ dep_node_index,
+ &dep_node)
+ }
+ }
+
+ match self.force_query_with_job::<Q>(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<Q: QueryDescription<'gcx>>(
+ self,
+ key: Q::Key,
+ job: JobOwner<'a, 'gcx, Q>,
+ dep_node_index: DepNodeIndex,
+ dep_node: &DepNode
+ ) -> Result<Q::Value, CycleError<'gcx>>
+ {
+ // 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<Q: QueryDescription<'gcx>>(
+ 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<Q: QueryDescription<'gcx>>(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::<Q>(DUMMY_SP, key);
+ }
+ }
+
+ #[allow(dead_code)]
+ fn force_query<Q: QueryDescription<'gcx>>(
+ 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::<Q>(key, job, dep_node)
+ }
+
+ pub fn try_get_query<Q: QueryDescription<'gcx>>(
+ self,
+ span: Span,
+ key: Q::Key
+ ) -> Result<Q::Value, DiagnosticBuilder<'a>> {
+ match self.try_get_with::<Q>(span, key) {
+ Ok(e) => Ok(e),
+ Err(e) => Err(self.report_cycle(e)),
+ }
+ }
+
+ pub fn get_query<Q: QueryDescription<'gcx>>(self, span: Span, key: Q::Key) -> Q::Value {
+ self.try_get_query::<Q>(span, key).unwrap_or_else(|mut e| {
+ e.emit();
+ Q::handle_cycle_error(self)
+ })
}
}
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)*]) => {
$($(#[$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,
$($(#[$attr])* $name($K)),*
}
- #[allow(bad_style)]
- #[derive(Clone, Debug, PartialEq, Eq)]
- pub enum QueryMsg {
- $($name(Option<String>)),*
- }
-
impl<$tcx> Query<$tcx> {
pub fn name(&self) -> &'static str {
match *self {
})*
}
- $(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<QueryMap<$tcx, Self>> {
+ &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.
///
///
/// 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<F, R>(tcx: TyCtxt<'_, $tcx, 'lcx>,
- span: Span,
- key: $K,
- mut map: LockGuard<'_, QueryMap<$tcx, Self>>,
- compute: F)
- -> Result<((R, Vec<Diagnostic>), Lrc<QueryJob<$tcx>>), 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<QueryJob> = 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::<queries::$name>(key);
}
})*
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::<queries::$name>(self.span, key)
})*
}
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
{
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();
DepKind::NormalizeProjectionTy |
DepKind::NormalizeTyAfterErasingRegions |
DepKind::DropckOutlives |
+ DepKind::EvaluateObligation |
DepKind::SubstituteNormalizeAndTestPredicates |
DepKind::InstanceDefSizeEstimate |
DepKind::ProgramClausesForEnv |
impl<'tcx> Value<'tcx> for ty::SymbolName {
fn from_cycle_error<'a>(_: TyCtxt<'a, 'tcx, 'tcx>) -> Self {
- ty::SymbolName { name: Symbol::intern("<error>").as_str() }
+ ty::SymbolName { name: Symbol::intern("<error>").as_interned_str() }
}
}
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;
/// 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::<queries::adt_sized_constraint>(DUMMY_SP, self.did) {
Ok(tys) => tys,
Err(mut bug) => {
debug!("adt_sized_constraint: {:?} is recursive", self);
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.
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 {
}
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 {
}
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
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::<ty::queries::needs_drop_raw>(DUMMY_SP, param_env.and(ty)) {
Ok(v) => v,
Err(mut bug) => {
// Cycles should be reported as an error by `check_representable`.
use std::sync::mpsc::{Sender};
use syntax_pos::{SpanData};
-use ty::maps::{QueryMsg};
use ty::TyCtxt;
use dep_graph::{DepNode};
use proc_macro;
pub dump_profq_msg_log:bool,
}
+#[allow(bad_style)]
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct QueryMsg {
+ pub query: &'static str,
+ pub msg: Option<String>,
+}
+
/// 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)]
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
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;
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,
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));
pub fn provide_extern<$lt>(providers: &mut Providers<$lt>) {
$(fn $name<'a, $lt:$lt, T>($tcx: TyCtxt<'a, $lt, $lt>, def_id_arg: T)
-> <ty::queries::$name<$lt> as
- QueryConfig>::Value
+ QueryConfig<$lt>>::Value
where T: IntoArgs,
{
#[allow(unused_variables)]
.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(),
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};
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(),
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,
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 });
};
ty::AssociatedItem {
- name: Symbol::intern(&name),
+ name: name.as_symbol(),
kind,
vis: item.visibility.decode(self),
defaultness: container.defaultness(),
self.entry(id)
.children
.decode(self)
- .map(|index| Symbol::intern(&self.item_name(index)))
+ .map(|index| self.item_name(index).as_symbol())
.collect()
}
DefKey {
parent: Some(CRATE_DEF_INDEX),
disambiguated_data: DisambiguatedDefPathData {
- data: DefPathData::MacroDef(name.as_str()),
+ data: DefPathData::MacroDef(name.as_interned_str()),
disambiguator: 0,
}
}
));
}
- 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, ..
}
}
- 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;
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
}
) -> 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);
(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 {
}
}
- if log_enabled!(::log::Level::Trace) {
- self.dump_local(dest);
- }
+ self.dump_local(dest);
Ok(())
}
) -> 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 { .. } => {},
pub fn try_read_value(&self, ptr: Pointer, ptr_align: Align, ty: Ty<'tcx>) -> EvalResult<'tcx, Option<Value>> {
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 => {
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();
/// 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<AllocId>) {
+ if !log_enabled!(::log::Level::Trace) {
+ return;
+ }
use std::fmt::Write;
allocs.sort();
allocs.dedup();
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),
}
}
}
};
- if log_enabled!(::log::Level::Trace) {
- self.dump_local(place);
- }
+ self.dump_local(place);
Ok(place)
}
#![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)]
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()
}
}
}
}
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,
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()
}
}
}
}) {
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 {
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>,
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("<no hash>");
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),
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)
}], &[]);
}
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)
}], &[]);
}
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,
}], &[]);
}
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) => {
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) {
lint_node_id,
source_info.span,
&format!("{} requires unsafe function or \
- block (error E0133)", &description[..]));
+ block (error E0133)", &description.as_str()[..]));
}
}
}
(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;
continue;
}
- let callee_mir = match ty::queries::optimized_mir::try_get(self.tcx,
+ let callee_mir = match self.tcx.try_get_query::<ty::queries::optimized_mir>(
callsite.location.span,
callsite.callee) {
Ok(callee_mir) if self.should_inline(callsite, callee_mir) => {
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());
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 {
}
}
- 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<Operand<'tcx>>,
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") => {
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;
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),
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)
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)
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)
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};
}
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);
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+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<EvaluationResult, OverflowError> {
+ 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)
+ })
+}
extern crate syntax_pos;
mod dropck_outlives;
+mod evaluate_obligation;
mod normalize_projection_ty;
mod normalize_erasing_regions;
mod util;
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
};
}
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| {
use std::ffi::CString;
use std::ptr;
+use attributes;
use libc::c_uint;
use rustc::middle::allocator::AllocatorKind;
use rustc::ty::TyCtxt;
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,
}
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
})
.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
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",
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.
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;
// 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;
// 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());
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) {
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
pub vtables: RefCell<FxHashMap<(Ty<'tcx>,
Option<ty::PolyExistentialTraitRef<'tcx>>), ValueRef>>,
/// Cache of constant strings,
- pub const_cstr_cache: RefCell<FxHashMap<InternedString, ValueRef>>,
+ pub const_cstr_cache: RefCell<FxHashMap<LocalInternedString, ValueRef>>,
/// Reverse-direction for const ptrs cast from globals.
/// Key is a ValueRef holding a *T,
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 {
(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 {
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),
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();
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());
}
}
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);
// 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[..]);
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;
/// 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 { .. } => {},
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,
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;
}
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;
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);
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>)
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 {
{
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);
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).
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(
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,
/// 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();
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)
};
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.
}
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
// 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);
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;
self.body_id,
self.param_env,
poly_trait_ref.to_predicate());
- SelectionContext::new(self).evaluate_obligation(&obligation)
+ self.predicate_may_hold(&obligation)
})
})
}
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};
// Return an hint about the closest match in field names
fn suggest_field_name(variant: &'tcx ty::VariantDef,
field: &Spanned<ast::Name>,
- skip: Vec<InternedString>)
+ skip: Vec<LocalInternedString>)
-> Option<Symbol> {
let name = field.node.as_str();
let names = variant.fields.iter().filter_map(|field| {
// 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()[..]);
}
}
}
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 {
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,
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,
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:
// add a dummy parameter for the closure kind
types.push(ty::TypeParameterDef {
index: type_start,
- name: Symbol::intern("<closure_kind>").as_str(),
+ name: Symbol::intern("<closure_kind>").as_interned_str(),
def_id,
has_default: false,
object_lifetime_default: rl::Set1::Empty,
// add a dummy parameter for the closure signature
types.push(ty::TypeParameterDef {
index: type_start + 1,
- name: Symbol::intern("<closure_signature>").as_str(),
+ name: Symbol::intern("<closure_signature>").as_interned_str(),
def_id,
has_default: false,
object_lifetime_default: rl::Set1::Empty,
tcx.with_freevars(node_id, |fv| {
types.extend(fv.iter().zip(2..).map(|(_, i)| ty::TypeParameterDef {
index: type_start + i,
- name: Symbol::intern("<upvar>").as_str(),
+ name: Symbol::intern("<upvar>").as_interned_str(),
def_id,
has_default: false,
object_lifetime_default: rl::Set1::Empty,
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;
// Collect the predicates that were written inline by the user on each
// type parameter (e.g., `<T:Foo>`).
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,
#![allow(non_camel_case_types)]
+#![cfg_attr(stage0, feature(dyn_trait))]
+
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(crate_visibility_modifier)]
#![feature(rustc_diagnostic_macros)]
#![feature(slice_patterns)]
#![feature(slice_sort_by_cached_key)]
-#![feature(dyn_trait)]
#![feature(never_type)]
#[macro_use] extern crate log;
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 {
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())
]),
}),
)),
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 {
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);
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,
}
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,
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 {
});
}
- 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,
window.rootPath = \"{root_path}\";\
window.currentCrate = \"{krate}\";\
</script>\
+ <script src=\"{root_path}aliases.js\"></script>\
<script src=\"{root_path}main{suffix}.js\"></script>\
<script defer src=\"{root_path}search-index.js\"></script>\
- <script defer src=\"{root_path}aliases.js\"></script>\
</body>\
</html>",
css_extension = if css_file_extension {
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,
'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]);
return '<span>' + path.replace(/::/g, '::</span><span>');
}
+ 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) {
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 += '<tr class="' + type + ' result"><td>' +
'<a href="' + href + '">' +
}
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;
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");
collapseDocs(e.previousSibling.childNodes[0], "toggle");
}
}
- })
+ });
autoCollapseAllImpls(getPageId());
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)]
#![feature(test)]
#![feature(vec_remove_item)]
#![feature(entry_and_modify)]
-#![feature(dyn_trait)]
extern crate arena;
extern crate getopts;
// 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)),
(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
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)
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).
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::<Mark>();
+ 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 {
})
}
+ /// 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;
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<Span> {
+ self.ctxt().outer().expn_info().map(|i| i.call_site)
+ }
+
/// Return the source callee.
///
/// Returns None if the supplied span has no expansion trace,
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)]
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))
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
}
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<U: ?Sized> ::std::convert::AsRef<U> for InternedString where str: ::std::convert::AsRef<U> {
+impl LocalInternedString {
+ pub fn as_interned_str(self) -> InternedString {
+ InternedString {
+ symbol: Symbol::intern(self.string)
+ }
+ }
+}
+
+impl<U: ?Sized> ::std::convert::AsRef<U> for LocalInternedString
+where
+ str: ::std::convert::AsRef<U>
+{
fn as_ref(&self) -> &U {
self.string.as_ref()
}
}
-impl<T: ::std::ops::Deref<Target = str>> ::std::cmp::PartialEq<T> for InternedString {
+impl<T: ::std::ops::Deref<Target = str>> ::std::cmp::PartialEq<T> for LocalInternedString {
fn eq(&self, other: &T) -> bool {
self.string == other.deref()
}
}
-impl ::std::cmp::PartialEq<InternedString> for str {
- fn eq(&self, other: &InternedString) -> bool {
+impl ::std::cmp::PartialEq<LocalInternedString> for str {
+ fn eq(&self, other: &LocalInternedString) -> bool {
self == other.string
}
}
-impl<'a> ::std::cmp::PartialEq<InternedString> for &'a str {
- fn eq(&self, other: &InternedString) -> bool {
+impl<'a> ::std::cmp::PartialEq<LocalInternedString> for &'a str {
+ fn eq(&self, other: &LocalInternedString) -> bool {
*self == other.string
}
}
-impl ::std::cmp::PartialEq<InternedString> for String {
- fn eq(&self, other: &InternedString) -> bool {
+impl ::std::cmp::PartialEq<LocalInternedString> for String {
+ fn eq(&self, other: &LocalInternedString) -> bool {
self == other.string
}
}
-impl<'a> ::std::cmp::PartialEq<InternedString> for &'a String {
- fn eq(&self, other: &InternedString) -> bool {
+impl<'a> ::std::cmp::PartialEq<LocalInternedString> 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: Decoder>(d: &mut D) -> Result<LocalInternedString, D::Error> {
+ Ok(Symbol::intern(&d.read_str()?).as_str())
+ }
+}
+
+impl Encodable for LocalInternedString {
+ fn encode<S: Encoder>(&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<F: FnOnce(&str) -> 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<H: Hasher>(&self, state: &mut H) {
+ self.with(|str| str.hash(state))
+ }
+}
+
+impl PartialOrd<InternedString> for InternedString {
+ fn partial_cmp(&self, other: &InternedString) -> Option<Ordering> {
+ 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<T: ::std::ops::Deref<Target = str>> PartialEq<T> for InternedString {
+ fn eq(&self, other: &T) -> bool {
+ self.with(|string| string == other.deref())
+ }
+}
+
+impl PartialEq<InternedString> for InternedString {
+ fn eq(&self, other: &InternedString) -> bool {
+ self.symbol == other.symbol
+ }
+}
+
+impl PartialEq<InternedString> for str {
+ fn eq(&self, other: &InternedString) -> bool {
+ other.with(|string| self == string)
+ }
+}
+
+impl<'a> PartialEq<InternedString> for &'a str {
+ fn eq(&self, other: &InternedString) -> bool {
+ other.with(|string| *self == string)
+ }
+}
+
+impl PartialEq<InternedString> for String {
+ fn eq(&self, other: &InternedString) -> bool {
+ other.with(|string| self == string)
+ }
+}
+
+impl<'a> PartialEq<InternedString> for &'a String {
+ fn eq(&self, other: &InternedString) -> bool {
+ other.with(|string| *self == string)
+ }
+}
+
+impl ::std::convert::From<InternedString> 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: Decoder>(d: &mut D) -> Result<InternedString, D::Error> {
- Ok(Symbol::intern(&d.read_str()?).as_str())
+ Ok(Symbol::intern(&d.read_str()?).as_interned_str())
}
}
impl Encodable for InternedString {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
- s.emit_str(self.string)
+ self.with(|string| s.emit_str(string))
}
}
# 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
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 {
// 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
}
x
}
+// CHECK: { i16, i16 } @enum_id_1(i16 %x.0, i16 %x.1)
+#[no_mangle]
+pub fn enum_id_1(x: Option<Result<u16, u16>>) -> Option<Result<u16, u16>> {
+ x
+}
+
+// CHECK: i16 @enum_id_2(i16)
+#[no_mangle]
+pub fn enum_id_2(x: Option<u8>) -> Option<u8> {
+ x
+}
+
// CHECK: noalias i8* @allocator()
#[no_mangle]
#[allocator]
let b = &Some(a);
&b; // keep variable in an alloca
-// CHECK: [[S_b:%[0-9]+]] = bitcast %"core::option::Option<i32>"** %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<i32>"* %_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<i32>"** %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<i32>"* %_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]])
}
#[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() {}
// 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
//~^ 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() {}
//! A simple test for testing many permutations of allowedness of
//! impl Trait
-#![feature(dyn_trait)]
use std::fmt::Debug;
// Allowed
// ignore-tidy-linelength
+//~^^^^^^^^^^^^ ERROR
+
#![feature(optin_builtin_traits)]
unsafe auto trait Trait {
fn main() {
// ICE
call_method(());
- //~^ ERROR
}
// 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
}
#[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;
#[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
// compile-flags: -Z borrowck=mir
#![allow(dead_code)]
-#![feature(dyn_trait)]
use std::fmt::Debug;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(dyn_trait)]
#![allow(bare_trait_object)]
struct Foo;
}
#[derive(Copy, Clone)]
+#[repr(u8)]
enum SingleVariant {
TheOnlyVariant
}
// compile-pass
// failure-status: 1
-#![feature(dyn_trait)]
-
use std::error::Error;
use std::io;
// ignore-pretty `dyn ::foo` parses differently in the current edition
-#![feature(dyn_trait)]
-
use std::fmt::Display;
static BYTE: u8 = 33;
#![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);
+}
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(stmt_expr_attributes)]
+
+pub fn main() {
+ let _x = #[inline(always)] || {};
+ let _y = #[inline(never)] || {};
+ let _z = #[inline] || {};
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// 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<Item = ()> {
+ Some(()).into_iter().flat_map(|_| vec![])
+}
// 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<dyn Error>> {
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 (), !),
assert_eq!(size_of::<e3>(), 4 as usize);
assert_eq!(size_of::<ReorderedStruct>(), 4);
assert_eq!(size_of::<ReorderedEnum>(), 6);
+
+ assert_eq!(size_of::<EnumEmpty>(), 0);
+ assert_eq!(size_of::<EnumSingle1>(), 0);
+ assert_eq!(size_of::<EnumSingle2>(), 0);
+ assert_eq!(size_of::<EnumSingle3>(), 0);
+ assert_eq!(size_of::<EnumSingle4>(), 1);
+ assert_eq!(size_of::<EnumSingle5>(), 1);
+
assert_eq!(size_of::<NicheFilledEnumWithInhabitedVariant>(), size_of::<&'static ()>());
}
-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
+++ /dev/null
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-trait Trait {}
-type A = Box<dyn Trait>; //~ ERROR `dyn Trait` syntax is unstable
-
-fn main() {}
+++ /dev/null
-error[E0658]: `dyn Trait` syntax is unstable (see issue #44662)
- --> $DIR/feature-gate-dyn-trait.rs:12:14
- |
-LL | type A = Box<dyn Trait>; //~ 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`.
#![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() {}
-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
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
|
|
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
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(dyn_trait)]
-
use std::fmt::Debug;
use std::option;
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) -> <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 | -> <impl Iterator as Iterator>::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<impl Debug> 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 | -> <dyn Iterator<Item = impl Debug> 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) -> <impl Iterator>::Item {
| ^^^^^^^^^^^^^^^^^^^^^ ambiguous associated type
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
| ^^^^^^^^^^^^^
#![allow(warnings)]
-#![feature(dyn_trait)]
#![feature(in_band_lifetimes)]
use std::fmt::Debug;
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<dyn Debug + 'a>) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// Iterator>::Item`, to be exact).
#![allow(warnings)]
-#![feature(dyn_trait)]
#![feature(rustc_attrs)]
trait Anything { }
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()))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: where <T as std::iter::Iterator>::Item: '_#2r
error[E0309]: the associated type `<T as std::iter::Iterator>::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()))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: consider adding an explicit lifetime bound `<T as std::iter::Iterator>::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<T>) -> Box<dyn Anything + 'a>
LL | | where
]
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()))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: where <T as std::iter::Iterator>::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<T>) -> Box<dyn Anything + 'a>
LL | | where
]
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()))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: where <T as std::iter::Iterator>::Item: '_#3r
error[E0309]: the associated type `<T as std::iter::Iterator>::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()))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: consider adding an explicit lifetime bound `<T as std::iter::Iterator>::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<T>) -> Box<dyn Anything + 'a>
LL | | where
]
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()))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: where <T as std::iter::Iterator>::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<T>) -> Box<dyn Anything + 'a>
LL | | where
// compile-flags:-Zborrowck=mir -Zverbose
#![allow(warnings)]
-#![feature(dyn_trait)]
trait Anything { }
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 `<T as std::iter::Iterator>::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())
| ^^^^^^^^^^^^^^^^^^
= help: consider adding an explicit lifetime bound `<T as std::iter::Iterator>::Item: ReEarlyBound(0, 'a)`...
error[E0309]: the associated type `<T as std::iter::Iterator>::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())
| ^^^^^^^^^^^^^^^^^^
// compile-flags:-Zborrowck=mir -Zverbose
#![allow(warnings)]
-#![feature(dyn_trait)]
#![feature(rustc_attrs)]
use std::cell::Cell;
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));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= 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));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= 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
]
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));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= 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));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= 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
]
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));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= 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));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= 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
]
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));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= 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
// compile-flags:-Zborrowck=mir -Zverbose
#![allow(warnings)]
-#![feature(dyn_trait)]
#![feature(rustc_attrs)]
use std::cell::Cell;
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));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= 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
]
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));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= 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
]
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));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= 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
]
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));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= 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
]
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));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= 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
// compile-pass
#![allow(warnings)]
-#![feature(dyn_trait)]
#![feature(rustc_attrs)]
use std::cell::Cell;
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));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
]
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
]
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));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
]
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
]
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));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
]
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
]
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));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
]
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
]
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));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
]
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
// compile-flags:-Zborrowck=mir -Zverbose
#![allow(warnings)]
-#![feature(dyn_trait)]
#![feature(rustc_attrs)]
use std::cell::Cell;
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));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: where <T as Anything<ReClosureBound('_#1r), ReClosureBound('_#2r)>>::AssocType: '_#3r
error[E0309]: the associated type `<T as Anything<'_#5r, '_#6r>>::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));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: consider adding an explicit lifetime bound `<T as Anything<'_#5r, '_#6r>>::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
]
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));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#3r)>>::AssocType: '_#4r
error[E0309]: the associated type `<T as Anything<'_#6r, '_#7r>>::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));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: consider adding an explicit lifetime bound `<T as Anything<'_#6r, '_#7r>>::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
]
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));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#3r)>>::AssocType: '_#4r
error[E0309]: the associated type `<T as Anything<'_#6r, '_#7r>>::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));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= help: consider adding an explicit lifetime bound `<T as Anything<'_#6r, '_#7r>>::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
]
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));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#3r)>>::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
]
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));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#3r)>>::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
]
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));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: where <T as Anything<ReClosureBound('_#1r), ReClosureBound('_#1r)>>::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
]
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));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: where <T as Anything<ReClosureBound('_#2r), ReClosureBound('_#2r)>>::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
]
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));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: where <T as Anything<ReClosureBound('_#1r), ReClosureBound('_#1r)>>::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
// compile-flags:-Zborrowck=mir -Zverbose
#![allow(warnings)]
-#![feature(dyn_trait)]
#![feature(rustc_attrs)]
use std::cell::Cell;
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));
| ^^^^^^^^^^^^^^^^^^^
= 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<T>(value: T) {
LL | | let cell = Cell::new(&());
]
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));
| ^^^^^^^^^^^^^^^^^^^
= 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));
| ^^^^^^^^^^^^^^^^^^^
= 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));
// compile-flags:-Zborrowck=mir -Zverbose
#![allow(warnings)]
-#![feature(dyn_trait)]
#![feature(rustc_attrs)]
use std::fmt::Debug;
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)
| ^^^^^
= 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)
| ^^^^^
= 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<T>) -> Box<dyn Debug + 'a>
LL | | where
]
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
| ^
// compile-flags:-Zborrowck=mir -Zverbose
#![allow(warnings)]
-#![feature(dyn_trait)]
#![feature(rustc_attrs)]
use std::cell::Cell;
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| {
| __________________________^
= 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| {
| __________________________^
= 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| {
]
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| {
| __________________________^
= 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
]
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| {
| __________________________^
= 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| {
| __________________________^
= 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
]
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| {
| __________________________^
= 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
#![feature(nll)]
#![allow(warnings)]
-#![feature(dyn_trait)]
use std::cell::Cell;
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)
| ^^^^^^^^^^^^^^^^^
// function body.
#![allow(warnings)]
-#![feature(dyn_trait)]
use std::cell::Cell;
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)
| ^^^^^^^^^^^^^^^^^
// compile-flags:-Zborrowck=mir
#![allow(warnings)]
-#![feature(dyn_trait)]
use std::fmt::Debug;
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
| ^
= 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
| ^
// compile-flags: -Z parse-only
-#![feature(dyn_trait)]
#![feature(raw_identifiers)]
fn test_if() {
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
//
// cc #48468
-#![feature(dyn_trait)]
-
use std::fmt::Debug;
struct Foo {
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<dyn Debug + '_>, //~ 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<dyn Debug + '_>, //~ ERROR missing lifetime specifier
| ^^^^^^^^^^^^^^
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<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
| ____________________________________________________^
//
// cc #48468
-#![feature(dyn_trait)]
-
fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
// ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static`
Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime
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<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
LL | | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static`
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
| ^^^^^
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);
}
}
}