Auto merge of #57721 - ehuss:update-cargo, r=alexcrichton
Update cargo
Unblocks #56884 cc @euclio
6 commits in 2b4a5f1f0bb6e13759e88ea9512527b0beba154f..ffe65875fd05018599ad07e7389e99050c7915be
2019-01-12 04:13:12 +0000 to 2019-01-17 23:57:50 +0000
- Better error message for bad manifest with `cargo install`. (rust-lang/cargo#6560)
- relax rustdoc output assertion (rust-lang/cargo#6559)
- touch some files when we use them (rust-lang/cargo#6477)
- Add documentation for new package/publish feature flags. (rust-lang/cargo#6553)
- Update chat link to Discord. (rust-lang/cargo#6554)
- Fix typo (rust-lang/cargo#6552)
r? @alexcrichton
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 65cdfe6..9924055 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -19,9 +19,16 @@
As a reminder, all contributors are expected to follow our [Code of Conduct][coc].
+The [rustc-guide] is your friend! It describes how the compiler works and how
+to contribute to it in more detail than this document.
+
+If this is your first time contributing, the [walkthrough] chapter of the guide
+can give you a good example of how a typical contribution would go.
+
[pound-rust-internals]: https://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust-internals
[internals]: https://internals.rust-lang.org
[coc]: https://www.rust-lang.org/conduct.html
+[walkthrough]: https://rust-lang.github.io/rustc-guide/walkthrough.html
## Feature Requests
[feature-requests]: #feature-requests
@@ -89,222 +96,14 @@
```
## The Build System
-[the-build-system]: #the-build-system
-Rust's build system allows you to bootstrap the compiler, run tests &
-benchmarks, generate documentation, install a fresh build of Rust, and more.
-It's your best friend when working on Rust, allowing you to compile & test
-your contributions before submission.
+For info on how to configure and build the compiler, please see [this
+chapter][rustcguidebuild] of the rustc-guide. This chapter contains info for
+contributions to the compiler and the standard library. It also lists some
+really useful commands to the build system (`./x.py`), which could save you a
+lot of time.
-The build system lives in [the `src/bootstrap` directory][bootstrap] in the
-project root. Our build system is itself written in Rust and is based on Cargo
-to actually build all the compiler's crates. If you have questions on the build
-system internals, try asking in [`#rust-internals`][pound-rust-internals].
-
-[bootstrap]: https://github.com/rust-lang/rust/tree/master/src/bootstrap/
-
-### Configuration
-[configuration]: #configuration
-
-Before you can start building the compiler you need to configure the build for
-your system. In most cases, that will just mean using the defaults provided
-for Rust.
-
-To change configuration, you must copy the file `config.toml.example`
-to `config.toml` in the directory from which you will be running the build, and
-change the settings provided.
-
-There are large number of options provided in this config file that will alter the
-configuration used in the build process. Some options to note:
-
-#### `[llvm]`:
-- `assertions = true` = This enables LLVM assertions, which makes LLVM misuse cause an assertion failure instead of weird misbehavior. This also slows down the compiler's runtime by ~20%.
-- `ccache = true` - Use ccache when building llvm
-
-#### `[build]`:
-- `compiler-docs = true` - Build compiler documentation
-
-#### `[rust]`:
-- `debuginfo = true` - Build a compiler with debuginfo. Makes building rustc slower, but then you can use a debugger to debug `rustc`.
-- `debuginfo-lines = true` - An alternative to `debuginfo = true` that doesn't let you use a debugger, but doesn't make building rustc slower and still gives you line numbers in backtraces.
-- `debuginfo-tools = true` - Build the extended tools with debuginfo.
-- `debug-assertions = true` - Makes the log output of `debug!` work.
-- `optimize = false` - Disable optimizations to speed up compilation of stage1 rust, but makes the stage1 compiler x100 slower.
-
-For more options, the `config.toml` file contains commented out defaults, with
-descriptions of what each option will do.
-
-Note: Previously the `./configure` script was used to configure this
-project. It can still be used, but it's recommended to use a `config.toml`
-file. If you still have a `config.mk` file in your directory - from
-`./configure` - you may need to delete it for `config.toml` to work.
-
-### Building
-[building]: #building
-
-A default configuration requires around 3.5 GB of disk space, whereas building a debug configuration may require more than 30 GB.
-
-Dependencies
-- [build dependencies](README.md#building-from-source)
-- `gdb` 6.2.0 minimum, 7.1 or later recommended for test builds
-
-The build system uses the `x.py` script to control the build process. This script
-is used to build, test, and document various parts of the compiler. You can
-execute it as:
-
-```sh
-python x.py build
-```
-
-On some systems you can also use the shorter version:
-
-```sh
-./x.py build
-```
-
-To learn more about the driver and top-level targets, you can execute:
-
-```sh
-python x.py --help
-```
-
-The general format for the driver script is:
-
-```sh
-python x.py <command> [<directory>]
-```
-
-Some example commands are `build`, `test`, and `doc`. These will build, test,
-and document the specified directory. The second argument, `<directory>`, is
-optional and defaults to working over the entire compiler. If specified,
-however, only that specific directory will be built. For example:
-
-```sh
-# build the entire compiler
-python x.py build
-
-# build all documentation
-python x.py doc
-
-# run all test suites
-python x.py test
-
-# build only the standard library
-python x.py build src/libstd
-
-# test only one particular test suite
-python x.py test src/test/rustdoc
-
-# build only the stage0 libcore library
-python x.py build src/libcore --stage 0
-```
-
-You can explore the build system through the various `--help` pages for each
-subcommand. For example to learn more about a command you can run:
-
-```
-python x.py build --help
-```
-
-To learn about all possible rules you can execute, run:
-
-```
-python x.py build --help --verbose
-```
-
-Note: Previously `./configure` and `make` were used to build this project.
-They are still available, but `x.py` is the recommended build system.
-
-### Useful commands
-[useful-commands]: #useful-commands
-
-Some common invocations of `x.py` are:
-
-- `x.py build --help` - show the help message and explain the subcommand
-- `x.py build src/libtest --stage 1` - build up to (and including) the first
- stage. For most cases we don't need to build the stage2 compiler, so we can
- save time by not building it. The stage1 compiler is a fully functioning
- compiler and (probably) will be enough to determine if your change works as
- expected.
-- `x.py build src/rustc --stage 1` - This will build just rustc, without libstd.
- This is the fastest way to recompile after you changed only rustc source code.
- Note however that the resulting rustc binary won't have a stdlib to link
- against by default. You can build libstd once with `x.py build src/libstd`,
- but it is only guaranteed to work if recompiled, so if there are any issues
- recompile it.
-- `x.py test` - build the full compiler & run all tests (takes a while). This
- is what gets run by the continuous integration system against your pull
- request. You should run this before submitting to make sure your tests pass
- & everything builds in the correct manner.
-- `x.py test src/libstd --stage 1` - test the standard library without
- recompiling stage 2.
-- `x.py test src/test/run-pass --test-args TESTNAME` - Run a matching set of
- tests.
- - `TESTNAME` should be a substring of the tests to match against e.g. it could
- be the fully qualified test name, or just a part of it.
- `TESTNAME=collections::hash::map::test_map::test_capacity_not_less_than_len`
- or `TESTNAME=test_capacity_not_less_than_len`.
-- `x.py test src/test/run-pass --stage 1 --test-args <substring-of-test-name>` -
- Run a single rpass test with the stage1 compiler (this will be quicker than
- running the command above as we only build the stage1 compiler, not the entire
- thing). You can also leave off the directory argument to run all stage1 test
- types.
-- `x.py test src/libcore --stage 1` - Run stage1 tests in `libcore`.
-- `x.py test src/tools/tidy` - Check that the source code is in compliance with
- Rust's style guidelines. There is no official document describing Rust's full
- guidelines as of yet, but basic rules like 4 spaces for indentation and no
- more than 99 characters in a single line should be kept in mind when writing
- code.
-
-### Using your local build
-[using-local-build]: #using-local-build
-
-If you use Rustup to manage your rust install, it has a feature called ["custom
-toolchains"][toolchain-link] that you can use to access your newly-built compiler
-without having to install it to your system or user PATH. If you've run `python
-x.py build`, then you can add your custom rustc to a new toolchain like this:
-
-[toolchain-link]: https://github.com/rust-lang-nursery/rustup.rs#working-with-custom-toolchains-and-local-builds
-
-```
-rustup toolchain link <name> build/<host-triple>/stage2
-```
-
-Where `<host-triple>` is the build triple for the host (the triple of your
-computer, by default), and `<name>` is the name for your custom toolchain. (If you
-added `--stage 1` to your build command, the compiler will be in the `stage1`
-folder instead.) You'll only need to do this once - it will automatically point
-to the latest build you've done.
-
-Once this is set up, you can use your custom toolchain just like any other. For
-example, if you've named your toolchain `local`, running `cargo +local build` will
-compile a project with your custom rustc, setting `rustup override set local` will
-override the toolchain for your current directory, and `cargo +local doc` will use
-your custom rustc and rustdoc to generate docs. (If you do this with a `--stage 1`
-build, you'll need to build rustdoc specially, since it's not normally built in
-stage 1. `python x.py build --stage 1 src/libstd src/tools/rustdoc` will build
-rustdoc and libstd, which will allow rustdoc to be run with that toolchain.)
-
-### Out-of-tree builds
-[out-of-tree-builds]: #out-of-tree-builds
-
-Rust's `x.py` script fully supports out-of-tree builds - it looks for
-the Rust source code from the directory `x.py` was found in, but it
-reads the `config.toml` configuration file from the directory it's
-run in, and places all build artifacts within a subdirectory named `build`.
-
-This means that if you want to do an out-of-tree build, you can just do it:
-```
-$ cd my/build/dir
-$ cp ~/my-config.toml config.toml # Or fill in config.toml otherwise
-$ path/to/rust/x.py build
-...
-$ # This will use the Rust source code in `path/to/rust`, but build
-$ # artifacts will now be in ./build
-```
-
-It's absolutely fine to have multiple build directories with different
-`config.toml` configurations using the same code.
+[rustcguidebuild]: https://rust-lang.github.io/rustc-guide/how-to-build-and-run.html
## Pull Requests
[pull-requests]: #pull-requests
@@ -320,26 +119,13 @@
Please make pull requests against the `master` branch.
-Compiling all of `./x.py test` can take a while. When testing your pull request,
-consider using one of the more specialized `./x.py` targets to cut down on the
-amount of time you have to wait. You need to have built the compiler at least
-once before running these will work, but that’s only one full build rather than
-one each time.
-
- $ python x.py test --stage 1
-
-is one such example, which builds just `rustc`, and then runs the tests. If
-you’re adding something to the standard library, try
-
- $ python x.py test src/libstd --stage 1
-
Please make sure your pull request is in compliance with Rust's style
guidelines by running
$ python x.py test src/tools/tidy
Make this check before every pull request (and every new commit in a pull
-request) ; you can add [git hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks)
+request); you can add [git hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks)
before every push to make sure you never forget to make this check.
All pull requests are reviewed by another person. We have a bot,
@@ -532,6 +318,12 @@
reference to `doc/reference.html`. The CSS might be messed up, but you can
verify that the HTML is right.
+Additionally, contributions to the [rustc-guide] are always welcome. Contributions
+can be made directly at [the
+rust-lang/rustc-guide](https://github.com/rust-lang/rustc-guide) repo. The issue
+tracker in that repo is also a great way to find things that need doing. There
+are issues for beginners and advanced compiler devs alike!
+
## Issue Triage
[issue-triage]: #issue-triage
@@ -627,7 +419,7 @@
more seasoned developers, some useful places to look for information
are:
-* The [rustc guide] contains information about how various parts of the compiler work
+* The [rustc guide] contains information about how various parts of the compiler work and how to contribute to the compiler
* [Rust Forge][rustforge] contains additional documentation, including write-ups of how to achieve common tasks
* The [Rust Internals forum][rif], a place to ask questions and
discuss Rust's internals
diff --git a/README.md b/README.md
index cb1f062..514e420 100644
--- a/README.md
+++ b/README.md
@@ -13,9 +13,13 @@
["Installation"]: https://doc.rust-lang.org/book/ch01-01-installation.html
[The Book]: https://doc.rust-lang.org/book/index.html
-## Building from Source
+## Installing from Source
[building-from-source]: #building-from-source
+_Note: If you wish to contribute to the compiler, you should read
+[this chapter](https://rust-lang.github.io/rustc-guide/how-to-build-and-run.html)
+of the rustc-guide instead._
+
### Building on *nix
1. Make sure you have installed the dependencies:
diff --git a/config.toml.example b/config.toml.example
index 23943d3..24293fc 100644
--- a/config.toml.example
+++ b/config.toml.example
@@ -90,6 +90,11 @@
# with clang-cl, so this is special in that it only compiles LLVM with clang-cl
#clang-cl = '/path/to/clang-cl.exe'
+# Pass extra compiler and linker flags to the LLVM CMake build.
+#cflags = "-fextra-flag"
+#cxxflags = "-fextra-flag"
+#ldflags = "-Wl,extra-flag"
+
# Use libc++ when building LLVM instead of libstdc++. This is the default on
# platforms already use libc++ as the default C++ library, but this option
# allows you to use libc++ even on platforms when it's not. You need to ensure
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 9421817..a2989f0 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -82,6 +82,9 @@
pub lldb_enabled: bool,
pub llvm_tools_enabled: bool,
+ pub llvm_cflags: Option<String>,
+ pub llvm_cxxflags: Option<String>,
+ pub llvm_ldflags: Option<String>,
pub llvm_use_libcxx: bool,
// rust codegen options
@@ -254,6 +257,9 @@
link_shared: Option<bool>,
version_suffix: Option<String>,
clang_cl: Option<String>,
+ cflags: Option<String>,
+ cxxflags: Option<String>,
+ ldflags: Option<String>,
use_libcxx: Option<bool>,
}
@@ -516,6 +522,10 @@
config.llvm_link_jobs = llvm.link_jobs;
config.llvm_version_suffix = llvm.version_suffix.clone();
config.llvm_clang_cl = llvm.clang_cl.clone();
+
+ config.llvm_cflags = llvm.cflags.clone();
+ config.llvm_cxxflags = llvm.cxxflags.clone();
+ config.llvm_ldflags = llvm.ldflags.clone();
set(&mut config.llvm_use_libcxx, llvm.use_libcxx);
}
diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py
index b0c3c970..7b70236 100755
--- a/src/bootstrap/configure.py
+++ b/src/bootstrap/configure.py
@@ -64,6 +64,10 @@
o("missing-tools", "dist.missing-tools", "allow failures when building tools")
o("use-libcxx", "llvm.use_libcxx", "build LLVM with libc++")
+o("cflags", "llvm.cflags", "build LLVM with these extra compiler flags")
+o("cxxflags", "llvm.cxxflags", "build LLVM with these extra compiler flags")
+o("ldflags", "llvm.ldflags", "build LLVM with these extra linker flags")
+
# Optimization and debugging options. These may be overridden by the release
# channel, etc.
o("optimize", "rust.optimize", "build optimized rust code")
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index cb9c86d..f5bacd6 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -358,7 +358,11 @@
}
cfg.build_arg("-j").build_arg(builder.jobs().to_string());
- cfg.define("CMAKE_C_FLAGS", builder.cflags(target, GitRepo::Llvm).join(" "));
+ let mut cflags = builder.cflags(target, GitRepo::Llvm).join(" ");
+ if let Some(ref s) = builder.config.llvm_cxxflags {
+ cflags.push_str(&format!(" {}", s));
+ }
+ cfg.define("CMAKE_C_FLAGS", cflags);
let mut cxxflags = builder.cflags(target, GitRepo::Llvm).join(" ");
if builder.config.llvm_static_stdcpp &&
!target.contains("windows") &&
@@ -366,6 +370,9 @@
{
cxxflags.push_str(" -static-libstdc++");
}
+ if let Some(ref s) = builder.config.llvm_cxxflags {
+ cxxflags.push_str(&format!(" {}", s));
+ }
cfg.define("CMAKE_CXX_FLAGS", cxxflags);
if let Some(ar) = builder.ar(target) {
if ar.is_absolute() {
@@ -383,6 +390,12 @@
}
}
+ if let Some(ref s) = builder.config.llvm_ldflags {
+ cfg.define("CMAKE_SHARED_LINKER_FLAGS", s);
+ cfg.define("CMAKE_MODULE_LINKER_FLAGS", s);
+ cfg.define("CMAKE_EXE_LINKER_FLAGS", s);
+ }
+
if env::var_os("SCCACHE_ERROR_LOG").is_some() {
cfg.env("RUST_LOG", "sccache=warn");
}
diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md
index 94f2104..a616409 100644
--- a/src/doc/rustc/src/codegen-options/index.md
+++ b/src/doc/rustc/src/codegen-options/index.md
@@ -187,7 +187,7 @@
This flag lets you control the optimization level.
-* `0`: no optimizations
+* `0`: no optimizations, also turn on `cfg(debug_assertions)`.
* `1`: basic optimizations
* `2`: some optimizations
* `3`: all optimizations
diff --git a/src/doc/rustc/src/contributing.md b/src/doc/rustc/src/contributing.md
index 3a1cafe..25a5c97 100644
--- a/src/doc/rustc/src/contributing.md
+++ b/src/doc/rustc/src/contributing.md
@@ -1,6 +1,12 @@
# Contributing to rustc
We'd love to have your help improving `rustc`! To that end, we've written [a
-whole book](https://rust-lang.github.io/rustc-guide/) on its
+whole book][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.
+
+If you would like to contribute to _this_ book, you can find its source in the
+rustc source at [src/doc/rustc][rustc_book].
+
+[rustc_guide]: https://rust-lang.github.io/rustc-guide/
+[rustc_book]: https://github.com/rust-lang/rust/tree/master/src/doc/rustc
diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md
index 905b064..d3eb8cb 100644
--- a/src/doc/rustdoc/src/unstable-features.md
+++ b/src/doc/rustdoc/src/unstable-features.md
@@ -417,3 +417,15 @@
(grouping of crate docs generated into the same output directory, like with `cargo doc`). Per-crate
files like the search index will still load from the documentation root, but anything that gets
renamed with `--resource-suffix` will load from the given path.
+
+### `--persist-doctests`: persist doctest executables after running
+
+Using this flag looks like this:
+
+```bash
+$ rustdoc src/lib.rs --test -Z unstable-options --persist-doctests target/rustdoctest
+```
+
+This flag allows you to keep doctest executables around after they're compiled or run.
+Usually, rustdoc will immediately discard a compiled doctest after it's been tested, but
+with this option, you can keep those binaries around for farther testing.
\ No newline at end of file
diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs
index 86f28a9..d43a5c1 100644
--- a/src/libcore/cmp.rs
+++ b/src/libcore/cmp.rs
@@ -91,6 +91,8 @@
/// For example, let's tweak our previous code a bit:
///
/// ```
+/// // The derive implements <BookFormat> == <BookFormat> comparisons
+/// #[derive(PartialEq)]
/// enum BookFormat {
/// Paperback,
/// Hardback,
@@ -102,31 +104,34 @@
/// format: BookFormat,
/// }
///
+/// // Implement <Book> == <BookFormat> comparisons
/// impl PartialEq<BookFormat> for Book {
/// fn eq(&self, other: &BookFormat) -> bool {
-/// match (&self.format, other) {
-/// (BookFormat::Paperback, BookFormat::Paperback) => true,
-/// (BookFormat::Hardback, BookFormat::Hardback) => true,
-/// (BookFormat::Ebook, BookFormat::Ebook) => true,
-/// (_, _) => false,
-/// }
+/// self.format == *other
+/// }
+/// }
+///
+/// // Implement <BookFormat> == <Book> comparisons
+/// impl PartialEq<Book> for BookFormat {
+/// fn eq(&self, other: &Book) -> bool {
+/// *self == other.format
/// }
/// }
///
/// let b1 = Book { isbn: 3, format: BookFormat::Paperback };
///
/// assert!(b1 == BookFormat::Paperback);
-/// assert!(b1 != BookFormat::Ebook);
+/// assert!(BookFormat::Ebook != b1);
/// ```
///
/// By changing `impl PartialEq for Book` to `impl PartialEq<BookFormat> for Book`,
-/// we've changed what type we can use on the right side of the `==` operator.
-/// This lets us use it in the `assert!` statements at the bottom.
+/// we allow `BookFormat`s to be compared with `Book`s.
///
/// You can also combine these implementations to let the `==` operator work with
/// two different types:
///
/// ```
+/// #[derive(PartialEq)]
/// enum BookFormat {
/// Paperback,
/// Hardback,
@@ -140,12 +145,13 @@
///
/// impl PartialEq<BookFormat> for Book {
/// fn eq(&self, other: &BookFormat) -> bool {
-/// match (&self.format, other) {
-/// (&BookFormat::Paperback, &BookFormat::Paperback) => true,
-/// (&BookFormat::Hardback, &BookFormat::Hardback) => true,
-/// (&BookFormat::Ebook, &BookFormat::Ebook) => true,
-/// (_, _) => false,
-/// }
+/// self.format == *other
+/// }
+/// }
+///
+/// impl PartialEq<Book> for BookFormat {
+/// fn eq(&self, other: &Book) -> bool {
+/// *self == other.format
/// }
/// }
///
@@ -159,7 +165,7 @@
/// let b2 = Book { isbn: 3, format: BookFormat::Ebook };
///
/// assert!(b1 == BookFormat::Paperback);
-/// assert!(b1 != BookFormat::Ebook);
+/// assert!(BookFormat::Ebook != b1);
/// assert!(b1 == b2);
/// ```
///
diff --git a/src/libcore/ffi.rs b/src/libcore/ffi.rs
index 0717a88..644380c 100644
--- a/src/libcore/ffi.rs
+++ b/src/libcore/ffi.rs
@@ -12,24 +12,27 @@
/// and `*mut c_void` is equivalent to C's `void*`. That said, this is
/// *not* the same as C's `void` return type, which is Rust's `()` type.
///
-/// Ideally, this type would be equivalent to [`!`], but currently it may
-/// be more ideal to use `c_void` for FFI purposes.
+/// To model pointers to opaque types in FFI, until `extern type` is
+/// stabilized, it is recommended to use a newtype wrapper around an empty
+/// byte array. See the [Nomicon] for details.
///
-/// [`!`]: ../../std/primitive.never.html
/// [pointer]: ../../std/primitive.pointer.html
+/// [Nomicon]: https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs
// N.B., for LLVM to recognize the void pointer type and by extension
// functions like malloc(), we need to have it represented as i8* in
// LLVM bitcode. The enum used here ensures this and prevents misuse
-// of the "raw" type by only having private variants.. We need two
+// of the "raw" type by only having private variants. We need two
// variants, because the compiler complains about the repr attribute
-// otherwise.
+// otherwise and we need at least one variant as otherwise the enum
+// would be uninhabited and at least dereferencing such pointers would
+// be UB.
#[repr(u8)]
#[stable(feature = "raw_os", since = "1.1.0")]
pub enum c_void {
- #[unstable(feature = "c_void_variant", reason = "should not have to exist",
+ #[unstable(feature = "c_void_variant", reason = "temporary implementation detail",
issue = "0")]
#[doc(hidden)] __variant1,
- #[unstable(feature = "c_void_variant", reason = "should not have to exist",
+ #[unstable(feature = "c_void_variant", reason = "temporary implementation detail",
issue = "0")]
#[doc(hidden)] __variant2,
}
@@ -49,7 +52,7 @@
#[unstable(feature = "c_variadic",
reason = "the `c_variadic` feature has not been properly tested on \
all supported platforms",
- issue = "27745")]
+ issue = "44930")]
extern {
type VaListImpl;
}
@@ -74,7 +77,7 @@
#[unstable(feature = "c_variadic",
reason = "the `c_variadic` feature has not been properly tested on \
all supported platforms",
- issue = "27745")]
+ issue = "44930")]
struct VaListImpl {
stack: *mut (),
gr_top: *mut (),
@@ -90,7 +93,7 @@
#[unstable(feature = "c_variadic",
reason = "the `c_variadic` feature has not been properly tested on \
all supported platforms",
- issue = "27745")]
+ issue = "44930")]
struct VaListImpl {
gpr: u8,
fpr: u8,
@@ -106,7 +109,7 @@
#[unstable(feature = "c_variadic",
reason = "the `c_variadic` feature has not been properly tested on \
all supported platforms",
- issue = "27745")]
+ issue = "44930")]
struct VaListImpl {
gp_offset: i32,
fp_offset: i32,
@@ -120,7 +123,7 @@
#[unstable(feature = "c_variadic",
reason = "the `c_variadic` feature has not been properly tested on \
all supported platforms",
- issue = "27745")]
+ issue = "44930")]
#[repr(transparent)]
pub struct VaList<'a>(&'a mut VaListImpl);
@@ -140,7 +143,7 @@
#[unstable(feature = "c_variadic",
reason = "the `c_variadic` feature has not been properly tested on \
all supported platforms",
- issue = "27745")]
+ issue = "44930")]
pub trait VaArgSafe {}
}
@@ -150,7 +153,7 @@
#[unstable(feature = "c_variadic",
reason = "the `c_variadic` feature has not been properly tested on \
all supported platforms",
- issue = "27745")]
+ issue = "44930")]
impl sealed_trait::VaArgSafe for $t {}
)+
}
@@ -163,12 +166,12 @@
#[unstable(feature = "c_variadic",
reason = "the `c_variadic` feature has not been properly tested on \
all supported platforms",
- issue = "27745")]
+ issue = "44930")]
impl<T> sealed_trait::VaArgSafe for *mut T {}
#[unstable(feature = "c_variadic",
reason = "the `c_variadic` feature has not been properly tested on \
all supported platforms",
- issue = "27745")]
+ issue = "44930")]
impl<T> sealed_trait::VaArgSafe for *const T {}
impl<'a> VaList<'a> {
@@ -176,7 +179,7 @@
#[unstable(feature = "c_variadic",
reason = "the `c_variadic` feature has not been properly tested on \
all supported platforms",
- issue = "27745")]
+ issue = "44930")]
pub unsafe fn arg<T: sealed_trait::VaArgSafe>(&mut self) -> T {
va_arg(self)
}
@@ -185,7 +188,7 @@
#[unstable(feature = "c_variadic",
reason = "the `c_variadic` feature has not been properly tested on \
all supported platforms",
- issue = "27745")]
+ issue = "44930")]
pub unsafe fn copy<F, R>(&self, f: F) -> R
where F: for<'copy> FnOnce(VaList<'copy>) -> R {
#[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"),
diff --git a/src/libcore/hint.rs b/src/libcore/hint.rs
index 9e57a4e..ad5a207 100644
--- a/src/libcore/hint.rs
+++ b/src/libcore/hint.rs
@@ -49,3 +49,26 @@
pub unsafe fn unreachable_unchecked() -> ! {
intrinsics::unreachable()
}
+
+/// Save power or switch hyperthreads in a busy-wait spin-loop.
+///
+/// This function is deliberately more primitive than
+/// [`std::thread::yield_now`](../../std/thread/fn.yield_now.html) and
+/// does not directly yield to the system's scheduler.
+/// In some cases it might be useful to use a combination of both functions.
+/// Careful benchmarking is advised.
+///
+/// On some platforms this function may not do anything at all.
+#[inline]
+#[unstable(feature = "renamed_spin_loop", issue = "55002")]
+pub fn spin_loop() {
+ #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+ unsafe {
+ asm!("pause" ::: "memory" : "volatile");
+ }
+
+ #[cfg(target_arch = "aarch64")]
+ unsafe {
+ asm!("yield" ::: "memory" : "volatile");
+ }
+}
diff --git a/src/libcore/ops/index.rs b/src/libcore/ops/index.rs
index 4f55c68..6cfa367 100644
--- a/src/libcore/ops/index.rs
+++ b/src/libcore/ops/index.rs
@@ -51,6 +51,21 @@
/// ```
#[lang = "index"]
#[rustc_on_unimplemented(
+ on(
+ _Self="&str",
+ note="you can use `.chars().nth()` or `.bytes().nth()`
+see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
+ ),
+ on(
+ _Self="str",
+ note="you can use `.chars().nth()` or `.bytes().nth()`
+see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
+ ),
+ on(
+ _Self="std::string::String",
+ note="you can use `.chars().nth()` or `.bytes().nth()`
+see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
+ ),
message="the type `{Self}` cannot be indexed by `{Idx}`",
label="`{Self}` cannot be indexed by `{Idx}`",
)]
@@ -141,6 +156,21 @@
/// ```
#[lang = "index_mut"]
#[rustc_on_unimplemented(
+ on(
+ _Self="&str",
+ note="you can use `.chars().nth()` or `.bytes().nth()`
+see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
+ ),
+ on(
+ _Self="str",
+ note="you can use `.chars().nth()` or `.bytes().nth()`
+see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
+ ),
+ on(
+ _Self="std::string::String",
+ note="you can use `.chars().nth()` or `.bytes().nth()`
+see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
+ ),
message="the type `{Self}` cannot be mutably indexed by `{Idx}`",
label="`{Self}` cannot be mutably indexed by `{Idx}`",
)]
diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs
index 762e075..7c09a36 100644
--- a/src/libcore/pin.rs
+++ b/src/libcore/pin.rs
@@ -99,6 +99,7 @@
use fmt;
use marker::{Sized, Unpin};
+use cmp::{self, PartialEq, PartialOrd};
use ops::{Deref, DerefMut, Receiver, CoerceUnsized, DispatchFromDyn};
/// A pinned pointer.
@@ -112,16 +113,57 @@
/// [`Unpin`]: ../../std/marker/trait.Unpin.html
/// [`pin` module]: ../../std/pin/index.html
//
-// Note: the derives below are allowed because they all only use `&P`, so they
-// cannot move the value behind `pointer`.
+// Note: the derives below, and the explicit `PartialEq` and `PartialOrd`
+// implementations, are allowed because they all only use `&P`, so they cannot move
+// the value behind `pointer`.
#[stable(feature = "pin", since = "1.33.0")]
#[fundamental]
#[repr(transparent)]
-#[derive(Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
+#[derive(Copy, Clone, Hash, Eq, Ord)]
pub struct Pin<P> {
pointer: P,
}
+#[stable(feature = "pin_partialeq_partialord_impl_applicability", since = "1.34.0")]
+impl<P, Q> PartialEq<Pin<Q>> for Pin<P>
+where
+ P: PartialEq<Q>,
+{
+ fn eq(&self, other: &Pin<Q>) -> bool {
+ self.pointer == other.pointer
+ }
+
+ fn ne(&self, other: &Pin<Q>) -> bool {
+ self.pointer != other.pointer
+ }
+}
+
+#[stable(feature = "pin_partialeq_partialord_impl_applicability", since = "1.34.0")]
+impl<P, Q> PartialOrd<Pin<Q>> for Pin<P>
+where
+ P: PartialOrd<Q>,
+{
+ fn partial_cmp(&self, other: &Pin<Q>) -> Option<cmp::Ordering> {
+ self.pointer.partial_cmp(&other.pointer)
+ }
+
+ fn lt(&self, other: &Pin<Q>) -> bool {
+ self.pointer < other.pointer
+ }
+
+ fn le(&self, other: &Pin<Q>) -> bool {
+ self.pointer <= other.pointer
+ }
+
+ fn gt(&self, other: &Pin<Q>) -> bool {
+ self.pointer > other.pointer
+ }
+
+ fn ge(&self, other: &Pin<Q>) -> bool {
+ self.pointer >= other.pointer
+ }
+}
+
impl<P: Deref> Pin<P>
where
P::Target: Unpin,
diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs
index 99e6365..8992e51 100644
--- a/src/libcore/sync/atomic.rs
+++ b/src/libcore/sync/atomic.rs
@@ -84,6 +84,8 @@
use cell::UnsafeCell;
use fmt;
+use hint::spin_loop;
+
/// Save power or switch hyperthreads in a busy-wait spin-loop.
///
/// This function is deliberately more primitive than
@@ -96,15 +98,7 @@
#[inline]
#[stable(feature = "spin_loop_hint", since = "1.24.0")]
pub fn spin_loop_hint() {
- #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
- unsafe {
- asm!("pause" ::: "memory" : "volatile");
- }
-
- #[cfg(target_arch = "aarch64")]
- unsafe {
- asm!("yield" ::: "memory" : "volatile");
- }
+ spin_loop()
}
/// A boolean type which can be safely shared between threads.
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index 427fe51..4cfebaa 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -476,6 +476,9 @@
[] CheckModLoops(DefId),
[] CheckModUnstableApiUsage(DefId),
[] CheckModItemTypes(DefId),
+ [] CheckModPrivacy(DefId),
+ [] CheckModIntrinsics(DefId),
+ [] CheckModLiveness(DefId),
[] CollectModItemTypes(DefId),
[] Reachability,
@@ -583,6 +586,7 @@
[] CheckImplItemWellFormed(DefId),
[] ReachableNonGenerics(CrateNum),
[] NativeLibraries(CrateNum),
+ [] EntryFn(CrateNum),
[] PluginRegistrarFn(CrateNum),
[] ProcMacroDeclsStatic(CrateNum),
[input] CrateDisambiguator(CrateNum),
@@ -630,6 +634,7 @@
[input] Freevars(DefId),
[input] MaybeUnusedTraitImport(DefId),
[input] MaybeUnusedExternCrates,
+ [input] NamesImportedByGlobUse(DefId),
[eval_always] StabilityIndex,
[eval_always] AllTraits,
[input] AllCrateNums,
diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs
index 501ef01..a9e80dd 100644
--- a/src/librustc/dep_graph/graph.rs
+++ b/src/librustc/dep_graph/graph.rs
@@ -3,7 +3,7 @@
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
use smallvec::SmallVec;
-use rustc_data_structures::sync::{Lrc, Lock};
+use rustc_data_structures::sync::{Lrc, Lock, AtomicU32, Ordering};
use std::env;
use std::hash::Hash;
use std::collections::hash_map::Entry;
@@ -58,7 +58,7 @@
/// nodes and edges as well as all fingerprints of nodes that have them.
previous: PreviousDepGraph,
- colors: Lock<DepNodeColorMap>,
+ colors: DepNodeColorMap,
/// When we load, there may be `.o` files, cached mir, or other such
/// things available to us. If we find that they are not dirty, we
@@ -84,7 +84,7 @@
dep_node_debug: Default::default(),
current: Lock::new(CurrentDepGraph::new(prev_graph_node_count)),
previous: prev_graph,
- colors: Lock::new(DepNodeColorMap::new(prev_graph_node_count)),
+ colors: DepNodeColorMap::new(prev_graph_node_count),
loaded_from_cache: Default::default(),
})),
}
@@ -282,12 +282,11 @@
DepNodeColor::Red
};
- let mut colors = data.colors.borrow_mut();
- debug_assert!(colors.get(prev_index).is_none(),
+ debug_assert!(data.colors.get(prev_index).is_none(),
"DepGraph::with_task() - Duplicate DepNodeColor \
insertion for {:?}", key);
- colors.insert(prev_index, color);
+ data.colors.insert(prev_index, color);
}
(result, dep_node_index)
@@ -502,7 +501,7 @@
pub fn node_color(&self, dep_node: &DepNode) -> Option<DepNodeColor> {
if let Some(ref data) = self.data {
if let Some(prev_index) = data.previous.node_to_index_opt(dep_node) {
- return data.colors.borrow().get(prev_index)
+ return data.colors.get(prev_index)
} else {
// This is a node that did not exist in the previous compilation
// session, so we consider it to be red.
@@ -513,56 +512,89 @@
None
}
- pub fn try_mark_green<'tcx>(&self,
- tcx: TyCtxt<'_, 'tcx, 'tcx>,
- dep_node: &DepNode)
- -> Option<DepNodeIndex> {
- debug!("try_mark_green({:?}) - BEGIN", dep_node);
- let data = self.data.as_ref().unwrap();
+ /// Try to read a node index for the node dep_node.
+ /// A node will have an index, when it's already been marked green, or when we can mark it
+ /// green. This function will mark the current task as a reader of the specified node, when
+ /// a node index can be found for that node.
+ pub fn try_mark_green_and_read(
+ &self,
+ tcx: TyCtxt<'_, '_, '_>,
+ dep_node: &DepNode
+ ) -> Option<(SerializedDepNodeIndex, DepNodeIndex)> {
+ self.try_mark_green(tcx, dep_node).map(|(prev_index, dep_node_index)| {
+ debug_assert!(self.is_green(&dep_node));
+ self.read_index(dep_node_index);
+ (prev_index, dep_node_index)
+ })
+ }
- #[cfg(not(parallel_queries))]
- debug_assert!(!data.current.borrow().node_to_node_index.contains_key(dep_node));
+ pub fn try_mark_green(
+ &self,
+ tcx: TyCtxt<'_, '_, '_>,
+ dep_node: &DepNode
+ ) -> Option<(SerializedDepNodeIndex, DepNodeIndex)> {
+ debug_assert!(!dep_node.kind.is_input());
- if dep_node.kind.is_input() {
- // We should only hit try_mark_green() for inputs that do not exist
- // anymore in the current compilation session. Existing inputs are
- // eagerly marked as either red/green before any queries are
- // executed.
- debug_assert!(dep_node.extract_def_id(tcx).is_none());
- debug!("try_mark_green({:?}) - END - DepNode is deleted input", dep_node);
- return None;
- }
+ // Return None if the dep graph is disabled
+ let data = self.data.as_ref()?;
- let (prev_deps, prev_dep_node_index) = match data.previous.edges_from(dep_node) {
- Some(prev) => {
+ // Return None if the dep node didn't exist in the previous session
+ let prev_index = data.previous.node_to_index_opt(dep_node)?;
+
+ match data.colors.get(prev_index) {
+ Some(DepNodeColor::Green(dep_node_index)) => Some((prev_index, dep_node_index)),
+ Some(DepNodeColor::Red) => None,
+ None => {
// This DepNode and the corresponding query invocation existed
// in the previous compilation session too, so we can try to
// mark it as green by recursively marking all of its
// dependencies green.
- prev
+ self.try_mark_previous_green(
+ tcx.global_tcx(),
+ data,
+ prev_index,
+ &dep_node
+ ).map(|dep_node_index| {
+ (prev_index, dep_node_index)
+ })
}
- None => {
- // This DepNode did not exist in the previous compilation session,
- // so we cannot mark it as green.
- debug!("try_mark_green({:?}) - END - DepNode does not exist in \
- current compilation session anymore", dep_node);
- return None
- }
- };
+ }
+ }
- debug_assert!(data.colors.borrow().get(prev_dep_node_index).is_none());
+ /// Try to mark a dep-node which existed in the previous compilation session as green
+ fn try_mark_previous_green<'tcx>(
+ &self,
+ tcx: TyCtxt<'_, 'tcx, 'tcx>,
+ data: &DepGraphData,
+ prev_dep_node_index: SerializedDepNodeIndex,
+ dep_node: &DepNode
+ ) -> Option<DepNodeIndex> {
+ debug!("try_mark_previous_green({:?}) - BEGIN", dep_node);
+
+ #[cfg(not(parallel_queries))]
+ {
+ debug_assert!(!data.current.borrow().node_to_node_index.contains_key(dep_node));
+ debug_assert!(data.colors.get(prev_dep_node_index).is_none());
+ }
+
+ // We never try to mark inputs as green
+ debug_assert!(!dep_node.kind.is_input());
+
+ debug_assert_eq!(data.previous.index_to_node(prev_dep_node_index), *dep_node);
+
+ let prev_deps = data.previous.edge_targets_from(prev_dep_node_index);
let mut current_deps = SmallVec::new();
for &dep_dep_node_index in prev_deps {
- let dep_dep_node_color = data.colors.borrow().get(dep_dep_node_index);
+ let dep_dep_node_color = data.colors.get(dep_dep_node_index);
match dep_dep_node_color {
Some(DepNodeColor::Green(node_index)) => {
// This dependency has been marked as green before, we are
// still fine and can continue with checking the other
// dependencies.
- debug!("try_mark_green({:?}) --- found dependency {:?} to \
+ debug!("try_mark_previous_green({:?}) --- found dependency {:?} to \
be immediately green",
dep_node,
data.previous.index_to_node(dep_dep_node_index));
@@ -573,7 +605,7 @@
// compared to the previous compilation session. We cannot
// mark the DepNode as green and also don't need to bother
// with checking any of the other dependencies.
- debug!("try_mark_green({:?}) - END - dependency {:?} was \
+ debug!("try_mark_previous_green({:?}) - END - dependency {:?} was \
immediately red",
dep_node,
data.previous.index_to_node(dep_dep_node_index));
@@ -585,12 +617,18 @@
// We don't know the state of this dependency. If it isn't
// an input node, let's try to mark it green recursively.
if !dep_dep_node.kind.is_input() {
- debug!("try_mark_green({:?}) --- state of dependency {:?} \
+ debug!("try_mark_previous_green({:?}) --- state of dependency {:?} \
is unknown, trying to mark it green", dep_node,
dep_dep_node);
- if let Some(node_index) = self.try_mark_green(tcx, dep_dep_node) {
- debug!("try_mark_green({:?}) --- managed to MARK \
+ let node_index = self.try_mark_previous_green(
+ tcx,
+ data,
+ dep_dep_node_index,
+ dep_dep_node
+ );
+ if let Some(node_index) = node_index {
+ debug!("try_mark_previous_green({:?}) --- managed to MARK \
dependency {:?} as green", dep_node, dep_dep_node);
current_deps.push(node_index);
continue;
@@ -600,7 +638,7 @@
DepKind::Hir |
DepKind::HirBody |
DepKind::CrateMetadata => {
- if dep_node.extract_def_id(tcx).is_none() {
+ if dep_dep_node.extract_def_id(tcx).is_none() {
// If the node does not exist anymore, we
// just fail to mark green.
return None
@@ -620,20 +658,20 @@
}
// We failed to mark it green, so we try to force the query.
- debug!("try_mark_green({:?}) --- trying to force \
+ debug!("try_mark_previous_green({:?}) --- trying to force \
dependency {:?}", dep_node, dep_dep_node);
if ::ty::query::force_from_dep_node(tcx, dep_dep_node) {
- let dep_dep_node_color = data.colors.borrow().get(dep_dep_node_index);
+ let dep_dep_node_color = data.colors.get(dep_dep_node_index);
match dep_dep_node_color {
Some(DepNodeColor::Green(node_index)) => {
- debug!("try_mark_green({:?}) --- managed to \
+ debug!("try_mark_previous_green({:?}) --- managed to \
FORCE dependency {:?} to green",
dep_node, dep_dep_node);
current_deps.push(node_index);
}
Some(DepNodeColor::Red) => {
- debug!("try_mark_green({:?}) - END - \
+ debug!("try_mark_previous_green({:?}) - END - \
dependency {:?} was red after forcing",
dep_node,
dep_dep_node);
@@ -641,7 +679,7 @@
}
None => {
if !tcx.sess.has_errors() {
- bug!("try_mark_green() - Forcing the DepNode \
+ bug!("try_mark_previous_green() - Forcing the DepNode \
should have set its color")
} else {
// If the query we just forced has resulted
@@ -653,7 +691,7 @@
}
} else {
// The DepNode could not be forced.
- debug!("try_mark_green({:?}) - END - dependency {:?} \
+ debug!("try_mark_previous_green({:?}) - END - dependency {:?} \
could not be forced", dep_node, dep_dep_node);
return None
}
@@ -705,16 +743,15 @@
}
// ... and finally storing a "Green" entry in the color map.
- let mut colors = data.colors.borrow_mut();
// Multiple threads can all write the same color here
#[cfg(not(parallel_queries))]
- debug_assert!(colors.get(prev_dep_node_index).is_none(),
- "DepGraph::try_mark_green() - Duplicate DepNodeColor \
+ debug_assert!(data.colors.get(prev_dep_node_index).is_none(),
+ "DepGraph::try_mark_previous_green() - Duplicate DepNodeColor \
insertion for {:?}", dep_node);
- colors.insert(prev_dep_node_index, DepNodeColor::Green(dep_node_index));
+ data.colors.insert(prev_dep_node_index, DepNodeColor::Green(dep_node_index));
- debug!("try_mark_green({:?}) - END - successfully marked as green", dep_node);
+ debug!("try_mark_previous_green({:?}) - END - successfully marked as green", dep_node);
Some(dep_node_index)
}
@@ -735,9 +772,8 @@
pub fn exec_cache_promotions<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) {
let green_nodes: Vec<DepNode> = {
let data = self.data.as_ref().unwrap();
- let colors = data.colors.borrow();
- colors.values.indices().filter_map(|prev_index| {
- match colors.get(prev_index) {
+ data.colors.values.indices().filter_map(|prev_index| {
+ match data.colors.get(prev_index) {
Some(DepNodeColor::Green(_)) => {
let dep_node = data.previous.index_to_node(prev_index);
if dep_node.cache_on_disk(tcx) {
@@ -1035,7 +1071,7 @@
// A data structure that stores Option<DepNodeColor> values as a contiguous
// array, using one u32 per entry.
struct DepNodeColorMap {
- values: IndexVec<SerializedDepNodeIndex, u32>,
+ values: IndexVec<SerializedDepNodeIndex, AtomicU32>,
}
const COMPRESSED_NONE: u32 = 0;
@@ -1045,12 +1081,12 @@
impl DepNodeColorMap {
fn new(size: usize) -> DepNodeColorMap {
DepNodeColorMap {
- values: IndexVec::from_elem_n(COMPRESSED_NONE, size)
+ values: (0..size).map(|_| AtomicU32::new(COMPRESSED_NONE)).collect(),
}
}
fn get(&self, index: SerializedDepNodeIndex) -> Option<DepNodeColor> {
- match self.values[index] {
+ match self.values[index].load(Ordering::Acquire) {
COMPRESSED_NONE => None,
COMPRESSED_RED => Some(DepNodeColor::Red),
value => Some(DepNodeColor::Green(DepNodeIndex::from_u32(
@@ -1059,10 +1095,10 @@
}
}
- fn insert(&mut self, index: SerializedDepNodeIndex, color: DepNodeColor) {
- self.values[index] = match color {
+ fn insert(&self, index: SerializedDepNodeIndex, color: DepNodeColor) {
+ self.values[index].store(match color {
DepNodeColor::Red => COMPRESSED_RED,
DepNodeColor::Green(index) => index.as_u32() + COMPRESSED_FIRST_GREEN,
- }
+ }, Ordering::Release)
}
}
diff --git a/src/librustc/dep_graph/prev.rs b/src/librustc/dep_graph/prev.rs
index 76d2954..ea5350a 100644
--- a/src/librustc/dep_graph/prev.rs
+++ b/src/librustc/dep_graph/prev.rs
@@ -19,14 +19,11 @@
}
#[inline]
- pub fn edges_from(&self,
- dep_node: &DepNode)
- -> Option<(&[SerializedDepNodeIndex], SerializedDepNodeIndex)> {
- self.index
- .get(dep_node)
- .map(|&node_index| {
- (self.data.edge_targets_from(node_index), node_index)
- })
+ pub fn edge_targets_from(
+ &self,
+ dep_node_index: SerializedDepNodeIndex
+ ) -> &[SerializedDepNodeIndex] {
+ self.data.edge_targets_from(dep_node_index)
}
#[inline]
diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs
index f633703..041291e 100644
--- a/src/librustc/hir/intravisit.rs
+++ b/src/librustc/hir/intravisit.rs
@@ -35,11 +35,9 @@
use syntax_pos::Span;
use hir::*;
use hir::def::Def;
-use hir::map::{self, Map};
+use hir::map::Map;
use super::itemlikevisit::DeepVisitor;
-use std::cmp;
-
#[derive(Copy, Clone)]
pub enum FnKind<'a> {
/// `#[xxx] pub async/const/extern "Abi" fn foo()`
@@ -1133,57 +1131,3 @@
// the right thing to do, should content be added in the future,
// would be to walk it.
}
-
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)]
-pub struct IdRange {
- pub min: NodeId,
- pub max: NodeId,
-}
-
-impl IdRange {
- pub fn max() -> IdRange {
- IdRange {
- min: NodeId::MAX,
- max: NodeId::from_u32(0),
- }
- }
-
- pub fn empty(&self) -> bool {
- self.min >= self.max
- }
-
- pub fn contains(&self, id: NodeId) -> bool {
- id >= self.min && id < self.max
- }
-
- pub fn add(&mut self, id: NodeId) {
- self.min = cmp::min(self.min, id);
- self.max = cmp::max(self.max, NodeId::from_u32(id.as_u32() + 1));
- }
-}
-
-
-pub struct IdRangeComputingVisitor<'a, 'hir: 'a> {
- result: IdRange,
- map: &'a map::Map<'hir>,
-}
-
-impl<'a, 'hir> IdRangeComputingVisitor<'a, 'hir> {
- pub fn new(map: &'a map::Map<'hir>) -> IdRangeComputingVisitor<'a, 'hir> {
- IdRangeComputingVisitor { result: IdRange::max(), map: map }
- }
-
- pub fn result(&self) -> IdRange {
- self.result
- }
-}
-
-impl<'a, 'hir> Visitor<'hir> for IdRangeComputingVisitor<'a, 'hir> {
- fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'hir> {
- NestedVisitorMap::OnlyBodies(&self.map)
- }
-
- fn visit_id(&mut self, id: NodeId) {
- self.result.add(id);
- }
-}
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index 8badcbf..8cdc493 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -3775,7 +3775,7 @@
let ohs = P(self.lower_expr(ohs));
hir::ExprKind::Unary(op, ohs)
}
- ExprKind::Lit(ref l) => hir::ExprKind::Lit(P((*l).clone())),
+ ExprKind::Lit(ref l) => hir::ExprKind::Lit((*l).clone()),
ExprKind::Cast(ref expr, ref ty) => {
let expr = P(self.lower_expr(expr));
hir::ExprKind::Cast(expr, self.lower_ty(ty, ImplTraitContext::disallowed()))
diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs
index bc0a64a..c9b4b2b 100644
--- a/src/librustc/hir/map/def_collector.rs
+++ b/src/librustc/hir/map/def_collector.rs
@@ -120,10 +120,10 @@
let def_data = match i.node {
ItemKind::Impl(..) => DefPathData::Impl,
ItemKind::Trait(..) => DefPathData::Trait(i.ident.as_interned_str()),
+ ItemKind::TraitAlias(..) => DefPathData::TraitAlias(i.ident.as_interned_str()),
ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) |
- ItemKind::TraitAlias(..) | ItemKind::Existential(..) |
- ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::Ty(..) =>
- DefPathData::TypeNs(i.ident.as_interned_str()),
+ ItemKind::Existential(..) | ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) |
+ ItemKind::Ty(..) => DefPathData::TypeNs(i.ident.as_interned_str()),
ItemKind::Mod(..) if i.ident == keywords::Invalid.ident() => {
return visit::walk_item(self, i);
}
diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs
index 6b707dd..1b74451 100644
--- a/src/librustc/hir/map/definitions.rs
+++ b/src/librustc/hir/map/definitions.rs
@@ -373,7 +373,9 @@
/// GlobalMetaData identifies a piece of crate metadata that is global to
/// a whole crate (as opposed to just one item). GlobalMetaData components
/// are only supposed to show up right below the crate root.
- GlobalMetaData(InternedString)
+ GlobalMetaData(InternedString),
+ /// A trait alias.
+ TraitAlias(InternedString),
}
#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug,
@@ -615,6 +617,7 @@
match *self {
TypeNs(name) |
Trait(name) |
+ TraitAlias(name) |
AssocTypeInTrait(name) |
AssocTypeInImpl(name) |
AssocExistentialInImpl(name) |
@@ -642,6 +645,7 @@
let s = match *self {
TypeNs(name) |
Trait(name) |
+ TraitAlias(name) |
AssocTypeInTrait(name) |
AssocTypeInImpl(name) |
AssocExistentialInImpl(name) |
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index 869baef..d9ca37c 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -509,6 +509,21 @@
&self.forest.krate.attrs
}
+ pub fn get_module(&self, module: DefId) -> (&'hir Mod, Span, NodeId)
+ {
+ let node_id = self.as_local_node_id(module).unwrap();
+ self.read(node_id);
+ match self.find_entry(node_id).unwrap().node {
+ Node::Item(&Item {
+ span,
+ node: ItemKind::Mod(ref m),
+ ..
+ }) => (m, span, node_id),
+ Node::Crate => (&self.forest.krate.module, self.forest.krate.span, node_id),
+ _ => panic!("not a module")
+ }
+ }
+
pub fn visit_item_likes_in_module<V>(&self, module: DefId, visitor: &mut V)
where V: ItemLikeVisitor<'hir>
{
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index fc4bd05..4fc50bc 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -10,6 +10,7 @@
pub use self::UnOp::*;
pub use self::UnsafeSource::*;
+use errors::FatalError;
use hir::def::Def;
use hir::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX};
use util::nodemap::{NodeMap, FxHashSet};
@@ -19,7 +20,7 @@
use syntax::source_map::{self, Spanned};
use rustc_target::spec::abi::Abi;
use syntax::ast::{self, CrateSugar, Ident, Name, NodeId, DUMMY_NODE_ID, AsmDialect};
-use syntax::ast::{Attribute, Lit, StrStyle, FloatTy, IntTy, UintTy};
+use syntax::ast::{Attribute, Label, Lit, StrStyle, FloatTy, IntTy, UintTy};
use syntax::attr::InlineAttr;
use syntax::ext::hygiene::SyntaxContext;
use syntax::ptr::P;
@@ -143,17 +144,6 @@
pub const DUMMY_ITEM_LOCAL_ID: ItemLocalId = ItemLocalId::MAX;
#[derive(Clone, RustcEncodable, RustcDecodable, Copy)]
-pub struct Label {
- pub ident: Ident,
-}
-
-impl fmt::Debug for Label {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "label({:?})", self.ident)
- }
-}
-
-#[derive(Clone, RustcEncodable, RustcDecodable, Copy)]
pub struct Lifetime {
pub id: NodeId,
pub span: Span,
@@ -1466,7 +1456,7 @@
/// A unary operation (For example: `!x`, `*x`)
Unary(UnOp, P<Expr>),
/// A literal (For example: `1`, `"foo"`)
- Lit(P<Lit>),
+ Lit(Lit),
/// A cast (`foo as f64`)
Cast(P<Expr>, P<Ty>),
Type(P<Expr>, P<Ty>),
@@ -2066,6 +2056,20 @@
pub hir_ref_id: HirId,
}
+impl TraitRef {
+ /// Get the `DefId` of the referenced trait. It _must_ actually be a trait or trait alias.
+ pub fn trait_def_id(&self) -> DefId {
+ match self.path.def {
+ Def::Trait(did) => did,
+ Def::TraitAlias(did) => did,
+ Def::Err => {
+ FatalError.raise();
+ }
+ _ => unreachable!(),
+ }
+ }
+}
+
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct PolyTraitRef {
/// The `'a` in `<'a> Foo<&'a T>`
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index 8ff60e5..f48059b 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -153,7 +153,7 @@
Error,
});
-impl_stable_hash_for!(struct hir::Label {
+impl_stable_hash_for!(struct ast::Label {
ident
});
diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs
index 70ec72d..de56718 100644
--- a/src/librustc/ich/impls_syntax.rs
+++ b/src/librustc/ich/impls_syntax.rs
@@ -258,7 +258,7 @@
tokenstream::TokenTree::Delimited(span, delim, ref tts) => {
span.hash_stable(hcx, hasher);
std_hash::Hash::hash(&delim, hasher);
- for sub_tt in tts.stream().trees() {
+ for sub_tt in tts.trees() {
sub_tt.hash_stable(hcx, hasher);
}
}
diff --git a/src/librustc/infer/lexical_region_resolve/mod.rs b/src/librustc/infer/lexical_region_resolve/mod.rs
index 39ce8cc..545192a 100644
--- a/src/librustc/infer/lexical_region_resolve/mod.rs
+++ b/src/librustc/infer/lexical_region_resolve/mod.rs
@@ -186,34 +186,39 @@
}
fn expansion(&self, var_values: &mut LexicalRegionResolutions<'tcx>) {
- self.iterate_until_fixed_point("Expansion", |constraint, origin| {
- debug!("expansion: constraint={:?} origin={:?}", constraint, origin);
- match *constraint {
+ self.iterate_until_fixed_point("Expansion", |constraint| {
+ debug!("expansion: constraint={:?}", constraint);
+ let (a_region, b_vid, b_data, retain) = match *constraint {
Constraint::RegSubVar(a_region, b_vid) => {
let b_data = var_values.value_mut(b_vid);
- (self.expand_node(a_region, b_vid, b_data), false)
+ (a_region, b_vid, b_data, false)
}
Constraint::VarSubVar(a_vid, b_vid) => match *var_values.value(a_vid) {
- VarValue::ErrorValue => (false, false),
+ VarValue::ErrorValue => return (false, false),
VarValue::Value(a_region) => {
- let b_node = var_values.value_mut(b_vid);
- let changed = self.expand_node(a_region, b_vid, b_node);
- let retain = match *b_node {
+ let b_data = var_values.value_mut(b_vid);
+ let retain = match *b_data {
VarValue::Value(ReStatic) | VarValue::ErrorValue => false,
_ => true
};
- (changed, retain)
+ (a_region, b_vid, b_data, retain)
}
},
Constraint::RegSubReg(..) | Constraint::VarSubReg(..) => {
// These constraints are checked after expansion
// is done, in `collect_errors`.
- (false, false)
+ return (false, false)
}
- }
+ };
+
+ let changed = self.expand_node(a_region, b_vid, b_data);
+ (changed, retain)
})
}
+ // This function is very hot in some workloads. There's a single callsite
+ // so always inlining is ok even though it's large.
+ #[inline(always)]
fn expand_node(
&self,
a_region: Region<'tcx>,
@@ -722,18 +727,17 @@
}
fn iterate_until_fixed_point<F>(&self, tag: &str, mut body: F)
- where
- F: FnMut(&Constraint<'tcx>, &SubregionOrigin<'tcx>) -> (bool, bool),
+ where F: FnMut(&Constraint<'tcx>) -> (bool, bool),
{
- let mut constraints: SmallVec<[_; 16]> = self.data.constraints.iter().collect();
+ let mut constraints: SmallVec<[_; 16]> = self.data.constraints.keys().collect();
let mut iteration = 0;
let mut changed = true;
while changed {
changed = false;
iteration += 1;
debug!("---- {} Iteration {}{}", "#", tag, iteration);
- constraints.retain(|(constraint, origin)| {
- let (edge_changed, retain) = body(constraint, origin);
+ constraints.retain(|constraint| {
+ let (edge_changed, retain) = body(constraint);
if edge_changed {
debug!("Updated due to constraint {:?}", constraint);
changed = true;
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index c8d137a..a0bd4f0 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -368,6 +368,12 @@
report_in_external_macro: true
}
+declare_lint! {
+ pub AMBIGUOUS_ASSOCIATED_ITEMS,
+ Warn,
+ "ambiguous associated items"
+}
+
/// Does nothing as a lint pass, but registers some `Lint`s
/// that are used by other parts of the compiler.
#[derive(Copy, Clone)]
@@ -433,6 +439,7 @@
parser::QUESTION_MARK_MACRO_SEP,
parser::ILL_FORMED_ATTRIBUTE_INPUT,
DEPRECATED_IN_FUTURE,
+ AMBIGUOUS_ASSOCIATED_ITEMS,
)
}
}
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index 0c769c9..abbf0ae 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -409,7 +409,7 @@
}
}).chain(
// Seed entry point
- tcx.sess.entry_fn.borrow().map(|(id, _, _)| id)
+ tcx.entry_fn(LOCAL_CRATE).map(|(def_id, _)| tcx.hir().as_local_node_id(def_id).unwrap())
).collect::<Vec<_>>();
// Seed implemented trait items
diff --git a/src/librustc/middle/entry.rs b/src/librustc/middle/entry.rs
index 6b593a1..218ca3b 100644
--- a/src/librustc/middle/entry.rs
+++ b/src/librustc/middle/entry.rs
@@ -1,5 +1,5 @@
use hir::map as hir_map;
-use hir::def_id::{CRATE_DEF_INDEX};
+use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE};
use session::{config, Session};
use session::config::EntryFnType;
use syntax::ast::NodeId;
@@ -8,6 +8,8 @@
use syntax_pos::Span;
use hir::{Item, ItemKind, ImplItem, TraitItem};
use hir::itemlikevisit::ItemLikeVisitor;
+use ty::TyCtxt;
+use ty::query::Providers;
struct EntryContext<'a, 'tcx: 'a> {
session: &'a Session,
@@ -45,36 +47,34 @@
}
}
-pub fn find_entry_point(session: &Session,
- hir_map: &hir_map::Map<'_>,
- crate_name: &str) {
- let any_exe = session.crate_types.borrow().iter().any(|ty| {
+fn entry_fn(tcx: TyCtxt<'_, '_, '_>, cnum: CrateNum) -> Option<(DefId, EntryFnType)> {
+ assert_eq!(cnum, LOCAL_CRATE);
+
+ let any_exe = tcx.sess.crate_types.borrow().iter().any(|ty| {
*ty == config::CrateType::Executable
});
if !any_exe {
// No need to find a main function
- session.entry_fn.set(None);
- return
+ return None;
}
// If the user wants no main function at all, then stop here.
- if attr::contains_name(&hir_map.krate().attrs, "no_main") {
- session.entry_fn.set(None);
- return
+ if attr::contains_name(&tcx.hir().krate().attrs, "no_main") {
+ return None;
}
let mut ctxt = EntryContext {
- session,
- map: hir_map,
+ session: tcx.sess,
+ map: tcx.hir(),
main_fn: None,
attr_main_fn: None,
start_fn: None,
non_main_fns: Vec::new(),
};
- hir_map.krate().visit_all_item_likes(&mut ctxt);
+ tcx.hir().krate().visit_all_item_likes(&mut ctxt);
- configure_main(&mut ctxt, crate_name);
+ configure_main(tcx, &ctxt)
}
// Beware, this is duplicated in `libsyntax/entry.rs`, so make sure to keep
@@ -135,43 +135,58 @@
.span_label(item.span, "multiple `start` functions")
.emit();
}
- },
- EntryPointType::None => ()
+ }
+ EntryPointType::None => (),
}
}
-fn configure_main(this: &mut EntryContext<'_, '_>, crate_name: &str) {
- if let Some((node_id, span)) = this.start_fn {
- this.session.entry_fn.set(Some((node_id, span, EntryFnType::Start)));
- } else if let Some((node_id, span)) = this.attr_main_fn {
- this.session.entry_fn.set(Some((node_id, span, EntryFnType::Main)));
- } else if let Some((node_id, span)) = this.main_fn {
- this.session.entry_fn.set(Some((node_id, span, EntryFnType::Main)));
+fn configure_main(
+ tcx: TyCtxt<'_, '_, '_>,
+ visitor: &EntryContext<'_, '_>,
+) -> Option<(DefId, EntryFnType)> {
+ if let Some((node_id, _)) = visitor.start_fn {
+ Some((tcx.hir().local_def_id(node_id), EntryFnType::Start))
+ } else if let Some((node_id, _)) = visitor.attr_main_fn {
+ Some((tcx.hir().local_def_id(node_id), EntryFnType::Main))
+ } else if let Some((node_id, _)) = visitor.main_fn {
+ Some((tcx.hir().local_def_id(node_id), EntryFnType::Main))
} else {
// No main function
- this.session.entry_fn.set(None);
- let mut err = struct_err!(this.session, E0601,
- "`main` function not found in crate `{}`", crate_name);
- if !this.non_main_fns.is_empty() {
+ let mut err = struct_err!(tcx.sess, E0601,
+ "`main` function not found in crate `{}`", tcx.crate_name(LOCAL_CRATE));
+ if !visitor.non_main_fns.is_empty() {
// There were some functions named 'main' though. Try to give the user a hint.
err.note("the main function must be defined at the crate level \
but you have one or more functions named 'main' that are not \
defined at the crate level. Either move the definition or \
attach the `#[main]` attribute to override this behavior.");
- for &(_, span) in &this.non_main_fns {
+ for &(_, span) in &visitor.non_main_fns {
err.span_note(span, "here is a function named 'main'");
}
err.emit();
- this.session.abort_if_errors();
+ tcx.sess.abort_if_errors();
} else {
- if let Some(ref filename) = this.session.local_crate_source_file {
+ if let Some(ref filename) = tcx.sess.local_crate_source_file {
err.note(&format!("consider adding a `main` function to `{}`", filename.display()));
}
- if this.session.teach(&err.get_code().unwrap()) {
+ if tcx.sess.teach(&err.get_code().unwrap()) {
err.note("If you don't know the basics of Rust, you can go look to the Rust Book \
to get started: https://doc.rust-lang.org/book/");
}
err.emit();
}
+
+ None
}
}
+
+pub fn find_entry_point(tcx: TyCtxt<'_, '_, '_>) -> Option<(DefId, EntryFnType)> {
+ tcx.entry_fn(LOCAL_CRATE)
+}
+
+pub fn provide(providers: &mut Providers<'_>) {
+ *providers = Providers {
+ entry_fn,
+ ..*providers
+ };
+}
diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs
index 1716daa..a0f7954 100644
--- a/src/librustc/middle/intrinsicck.rs
+++ b/src/librustc/middle/intrinsicck.rs
@@ -2,6 +2,7 @@
use hir::def_id::DefId;
use ty::{self, Ty, TyCtxt};
use ty::layout::{LayoutError, Pointer, SizeSkeleton, VariantIdx};
+use ty::query::{Providers, queries};
use rustc_target::spec::abi::Abi::RustIntrinsic;
use rustc_data_structures::indexed_vec::Idx;
@@ -10,10 +11,23 @@
use hir;
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
- let mut visitor = ItemVisitor {
- tcx,
+ for &module in tcx.hir().krate().modules.keys() {
+ queries::check_mod_intrinsics::ensure(tcx, tcx.hir().local_def_id(module));
+ }
+}
+
+fn check_mod_intrinsics<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
+ tcx.hir().visit_item_likes_in_module(
+ module_def_id,
+ &mut ItemVisitor { tcx }.as_deep_visitor()
+ );
+}
+
+pub fn provide(providers: &mut Providers<'_>) {
+ *providers = Providers {
+ check_mod_intrinsics,
+ ..*providers
};
- tcx.hir().krate().visit_all_item_likes(&mut visitor.as_deep_visitor());
}
struct ItemVisitor<'a, 'tcx: 'a> {
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index a78cf1a..e73677d 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -100,6 +100,7 @@
use hir::def::*;
use hir::Node;
use ty::{self, TyCtxt};
+use ty::query::{Providers, queries};
use lint;
use errors::Applicability;
use util::nodemap::{NodeMap, HirIdMap, HirIdSet};
@@ -114,8 +115,9 @@
use syntax::symbol::keywords;
use syntax_pos::Span;
-use hir::{Expr, HirId};
use hir;
+use hir::{Expr, HirId};
+use hir::def_id::DefId;
use hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap};
/// For use with `propagate_through_loop`.
@@ -179,11 +181,24 @@
fn visit_arm(&mut self, a: &'tcx hir::Arm) { visit_arm(self, a); }
}
+fn check_mod_liveness<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
+ tcx.hir().visit_item_likes_in_module(module_def_id, &mut IrMaps::new(tcx).as_deep_visitor());
+}
+
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
- tcx.hir().krate().visit_all_item_likes(&mut IrMaps::new(tcx).as_deep_visitor());
+ for &module in tcx.hir().krate().modules.keys() {
+ queries::check_mod_liveness::ensure(tcx, tcx.hir().local_def_id(module));
+ }
tcx.sess.abort_if_errors();
}
+pub fn provide(providers: &mut Providers<'_>) {
+ *providers = Providers {
+ check_mod_liveness,
+ ..*providers
+ };
+}
+
impl fmt::Debug for LiveNode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "ln({})", self.get())
@@ -911,17 +926,8 @@
}
fn compute(&mut self, body: &hir::Expr) -> LiveNode {
- // if there is a `break` or `again` at the top level, then it's
- // effectively a return---this only occurs in `for` loops,
- // where the body is really a closure.
-
debug!("compute: using id for body, {}", self.ir.tcx.hir().node_to_pretty_string(body.id));
- let exit_ln = self.s.exit_ln;
-
- self.break_ln.insert(body.id, exit_ln);
- self.cont_ln.insert(body.id, exit_ln);
-
// the fallthrough exit is only for those cases where we do not
// explicitly return:
let s = self.s;
@@ -1024,19 +1030,10 @@
self.propagate_through_expr(&e, succ)
}
- hir::ExprKind::Closure(.., blk_id, _, _) => {
+ hir::ExprKind::Closure(..) => {
debug!("{} is an ExprKind::Closure",
self.ir.tcx.hir().node_to_pretty_string(expr.id));
- // The next-node for a break is the successor of the entire
- // loop. The next-node for a continue is the top of this loop.
- let node = self.live_node(expr.hir_id, expr.span);
-
- let break_ln = succ;
- let cont_ln = node;
- self.break_ln.insert(blk_id.node_id, break_ln);
- self.cont_ln.insert(blk_id.node_id, cont_ln);
-
// the construction of a closure itself is not important,
// but we have to consider the closed over variables.
let caps = self.ir.capture_info_map.get(&expr.id).cloned().unwrap_or_else(||
@@ -1407,15 +1404,16 @@
debug!("propagate_through_loop: using id for loop body {} {}",
expr.id, self.ir.tcx.hir().node_to_pretty_string(body.id));
- let break_ln = succ;
- let cont_ln = ln;
- self.break_ln.insert(expr.id, break_ln);
- self.cont_ln.insert(expr.id, cont_ln);
+
+ self.break_ln.insert(expr.id, succ);
let cond_ln = match kind {
LoopLoop => ln,
WhileLoop(ref cond) => self.propagate_through_expr(&cond, ln),
};
+
+ self.cont_ln.insert(expr.id, cond_ln);
+
let body_ln = self.propagate_through_block(body, cond_ln);
// repeat until fixed point is reached:
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 42adc6a..cdbef56 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -6,7 +6,7 @@
use session::{early_error, early_warn, Session};
use session::search_paths::SearchPath;
-use rustc_target::spec::{LinkerFlavor, PanicStrategy, RelroLevel};
+use rustc_target::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, RelroLevel};
use rustc_target::spec::{Target, TargetTriple};
use lint;
use middle::cstore;
@@ -649,15 +649,15 @@
}
}
-// The type of entry function, so
-// users can have their own entry
-// functions
-#[derive(Copy, Clone, PartialEq)]
+// The type of entry function, so users can have their own entry functions
+#[derive(Copy, Clone, PartialEq, Hash, Debug)]
pub enum EntryFnType {
Main,
Start,
}
+impl_stable_hash_via_hash!(EntryFnType);
+
#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug)]
pub enum CrateType {
Executable,
@@ -808,13 +808,16 @@
pub const parse_cross_lang_lto: Option<&str> =
Some("either a boolean (`yes`, `no`, `on`, `off`, etc), \
or the path to the linker plugin");
+ pub const parse_merge_functions: Option<&str> =
+ Some("one of: `disabled`, `trampolines`, or `aliases`");
}
#[allow(dead_code)]
mod $mod_set {
use super::{$struct_name, Passes, Sanitizer, LtoCli, CrossLangLto};
- use rustc_target::spec::{LinkerFlavor, PanicStrategy, RelroLevel};
+ use rustc_target::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, RelroLevel};
use std::path::PathBuf;
+ use std::str::FromStr;
$(
pub fn $opt(cg: &mut $struct_name, v: Option<&str>) -> bool {
@@ -1046,6 +1049,14 @@
};
true
}
+
+ fn parse_merge_functions(slot: &mut Option<MergeFunctions>, v: Option<&str>) -> bool {
+ match v.and_then(|s| MergeFunctions::from_str(s).ok()) {
+ Some(mergefunc) => *slot = Some(mergefunc),
+ _ => return false,
+ }
+ true
+ }
}
) }
@@ -1342,10 +1353,15 @@
unpretty: Option<String> = (None, parse_unpretty, [UNTRACKED],
"Present the input source, unstable (and less-pretty) variants;
valid types are any of the types for `--pretty`, as well as:
+ `expanded`, `expanded,identified`,
+ `expanded,hygiene` (with internal representations),
`flowgraph=<nodeid>` (graphviz formatted flowgraph for node),
+ `flowgraph,unlabelled=<nodeid>` (unlabelled graphviz formatted flowgraph for node),
`everybody_loops` (all function bodies replaced with `loop {}`),
- `hir` (the HIR), `hir,identified`, or
- `hir,typed` (HIR with types for each node)."),
+ `hir` (the HIR), `hir,identified`,
+ `hir,typed` (HIR with types for each node),
+ `hir-tree` (dump the raw HIR),
+ `mir` (the MIR), or `mir-cfg` (graphviz formatted MIR)"),
run_dsymutil: Option<bool> = (None, parse_opt_bool, [TRACKED],
"run `dsymutil` and delete intermediate object files"),
ui_testing: bool = (false, parse_bool, [UNTRACKED],
@@ -1376,6 +1392,9 @@
"whether to use the PLT when calling into shared libraries;
only has effect for PIC code on systems with ELF binaries
(default: PLT is disabled if full relro is enabled)"),
+ merge_functions: Option<MergeFunctions> = (None, parse_merge_functions, [TRACKED],
+ "control the operation of the MergeFunctions LLVM pass, taking
+ the same values as the target option of the same name"),
}
pub fn default_lib_output() -> CrateType {
@@ -2394,7 +2413,7 @@
use super::{CrateType, DebugInfo, ErrorOutputType, OptLevel, OutputTypes,
Passes, Sanitizer, LtoCli, CrossLangLto};
use syntax::feature_gate::UnstableFeatures;
- use rustc_target::spec::{PanicStrategy, RelroLevel, TargetTriple};
+ use rustc_target::spec::{MergeFunctions, PanicStrategy, RelroLevel, TargetTriple};
use syntax::edition::Edition;
pub trait DepTrackingHash {
@@ -2437,12 +2456,14 @@
impl_dep_tracking_hash_via_hash!(Option<usize>);
impl_dep_tracking_hash_via_hash!(Option<String>);
impl_dep_tracking_hash_via_hash!(Option<(String, u64)>);
+ impl_dep_tracking_hash_via_hash!(Option<MergeFunctions>);
impl_dep_tracking_hash_via_hash!(Option<PanicStrategy>);
impl_dep_tracking_hash_via_hash!(Option<RelroLevel>);
impl_dep_tracking_hash_via_hash!(Option<lint::Level>);
impl_dep_tracking_hash_via_hash!(Option<PathBuf>);
impl_dep_tracking_hash_via_hash!(Option<cstore::NativeLibraryKind>);
impl_dep_tracking_hash_via_hash!(CrateType);
+ impl_dep_tracking_hash_via_hash!(MergeFunctions);
impl_dep_tracking_hash_via_hash!(PanicStrategy);
impl_dep_tracking_hash_via_hash!(RelroLevel);
impl_dep_tracking_hash_via_hash!(Passes);
@@ -2528,7 +2549,7 @@
use std::iter::FromIterator;
use std::path::PathBuf;
use super::{Externs, OutputType, OutputTypes};
- use rustc_target::spec::{PanicStrategy, RelroLevel};
+ use rustc_target::spec::{MergeFunctions, PanicStrategy, RelroLevel};
use syntax::symbol::Symbol;
use syntax::edition::{Edition, DEFAULT_EDITION};
use syntax;
@@ -3183,6 +3204,10 @@
opts = reference.clone();
opts.debugging_opts.cross_lang_lto = CrossLangLto::LinkerPluginAuto;
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
+
+ opts = reference.clone();
+ opts.debugging_opts.merge_functions = Some(MergeFunctions::Disabled);
+ assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
}
#[test]
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index 7363b8b..cf00bf3 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -67,8 +67,6 @@
/// This is `None` if the host and target are the same.
pub target_tlib_path: Option<SearchPath>,
pub parse_sess: ParseSess,
- /// For a library crate, this is always none
- pub entry_fn: Once<Option<(NodeId, Span, config::EntryFnType)>>,
pub sysroot: PathBuf,
/// The name of the root source file of the crate, in the local file system.
/// `None` means that there is no source file.
@@ -1173,8 +1171,6 @@
host_tlib_path,
target_tlib_path,
parse_sess: p_s,
- // For a library crate, this is always none
- entry_fn: Once::new(),
sysroot,
local_crate_source_file,
working_dir,
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 6db6fe3..9a0610f 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -42,7 +42,7 @@
use rustc_data_structures::sync::Lock;
use rustc_target::spec::abi::Abi;
use std::cmp;
-use std::fmt;
+use std::fmt::{self, Display};
use std::iter;
use std::rc::Rc;
use util::nodemap::{FxHashMap, FxHashSet};
@@ -629,7 +629,8 @@
obligation: &PredicateObligation<'tcx>,
) -> Result<EvaluationResult, OverflowError> {
self.evaluation_probe(|this| {
- this.evaluate_predicate_recursively(TraitObligationStackList::empty(), obligation)
+ this.evaluate_predicate_recursively(TraitObligationStackList::empty(),
+ obligation.clone())
})
}
@@ -655,12 +656,12 @@
predicates: I,
) -> Result<EvaluationResult, OverflowError>
where
- I: IntoIterator<Item = &'a PredicateObligation<'tcx>>,
+ I: IntoIterator<Item = 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.clone())?;
debug!(
"evaluate_predicate_recursively({:?}) = {:?}",
obligation, eval
@@ -679,9 +680,19 @@
fn evaluate_predicate_recursively<'o>(
&mut self,
previous_stack: TraitObligationStackList<'o, 'tcx>,
- obligation: &PredicateObligation<'tcx>,
+ obligation: PredicateObligation<'tcx>,
) -> Result<EvaluationResult, OverflowError> {
- debug!("evaluate_predicate_recursively({:?})", obligation);
+ debug!("evaluate_predicate_recursively(previous_stack={:?}, obligation={:?})",
+ previous_stack.head(), obligation);
+
+ // Previous_stack stores a TraitObligatiom, while 'obligation' is
+ // a PredicateObligation. These are distinct types, so we can't
+ // use any Option combinator method that would force them to be
+ // the same
+ match previous_stack.head() {
+ Some(h) => self.check_recursion_limit(&obligation, h.obligation)?,
+ None => self.check_recursion_limit(&obligation, &obligation)?
+ }
match obligation.predicate {
ty::Predicate::Trait(ref t) => {
@@ -695,8 +706,9 @@
match self.infcx
.subtype_predicate(&obligation.cause, obligation.param_env, p)
{
- Some(Ok(InferOk { obligations, .. })) => {
- self.evaluate_predicates_recursively(previous_stack, &obligations)
+ Some(Ok(InferOk { mut obligations, .. })) => {
+ self.add_depth(obligations.iter_mut(), obligation.recursion_depth);
+ self.evaluate_predicates_recursively(previous_stack,obligations.into_iter())
}
Some(Err(_)) => Ok(EvaluatedToErr),
None => Ok(EvaluatedToAmbig),
@@ -710,8 +722,9 @@
ty,
obligation.cause.span,
) {
- Some(obligations) => {
- self.evaluate_predicates_recursively(previous_stack, obligations.iter())
+ Some(mut obligations) => {
+ self.add_depth(obligations.iter_mut(), obligation.recursion_depth);
+ self.evaluate_predicates_recursively(previous_stack, obligations.into_iter())
}
None => Ok(EvaluatedToAmbig),
},
@@ -733,10 +746,11 @@
ty::Predicate::Projection(ref data) => {
let project_obligation = obligation.with(data.clone());
match project::poly_project_and_unify_type(self, &project_obligation) {
- Ok(Some(subobligations)) => {
+ Ok(Some(mut subobligations)) => {
+ self.add_depth(subobligations.iter_mut(), obligation.recursion_depth);
let result = self.evaluate_predicates_recursively(
previous_stack,
- subobligations.iter(),
+ subobligations.into_iter(),
);
if let Some(key) =
ProjectionCacheKey::from_poly_projection_predicate(self, data)
@@ -1005,7 +1019,7 @@
match this.confirm_candidate(stack.obligation, candidate) {
Ok(selection) => this.evaluate_predicates_recursively(
stack.list(),
- selection.nested_obligations().iter(),
+ selection.nested_obligations().into_iter()
),
Err(..) => Ok(EvaluatedToErr),
}
@@ -1080,6 +1094,45 @@
.insert(trait_ref, WithDepNode::new(dep_node, result));
}
+ // For various reasons, it's possible for a subobligation
+ // to have a *lower* recursion_depth than the obligation used to create it.
+ // Projection sub-obligations may be returned from the projection cache,
+ // which results in obligations with an 'old' recursion_depth.
+ // Additionally, methods like ty::wf::obligations and
+ // InferCtxt.subtype_predicate produce subobligations without
+ // taking in a 'parent' depth, causing the generated subobligations
+ // to have a recursion_depth of 0
+ //
+ // To ensure that obligation_depth never decreasees, we force all subobligations
+ // to have at least the depth of the original obligation.
+ fn add_depth<T: 'cx, I: Iterator<Item = &'cx mut Obligation<'tcx, T>>>(&self, it: I,
+ min_depth: usize) {
+ it.for_each(|o| o.recursion_depth = cmp::max(min_depth, o.recursion_depth) + 1);
+ }
+
+ // Check that the recursion limit has not been exceeded.
+ //
+ // The weird return type of this function allows it to be used with the 'try' (?)
+ // operator within certain functions
+ fn check_recursion_limit<T: Display + TypeFoldable<'tcx>, V: Display + TypeFoldable<'tcx>>(
+ &self,
+ obligation: &Obligation<'tcx, T>,
+ error_obligation: &Obligation<'tcx, V>
+ ) -> Result<(), OverflowError> {
+ let recursion_limit = *self.infcx.tcx.sess.recursion_limit.get();
+ if obligation.recursion_depth >= recursion_limit {
+ match self.query_mode {
+ TraitQueryMode::Standard => {
+ self.infcx().report_overflow_error(error_obligation, true);
+ }
+ TraitQueryMode::Canonical => {
+ return Err(OverflowError);
+ }
+ }
+ }
+ Ok(())
+ }
+
///////////////////////////////////////////////////////////////////////////
// CANDIDATE ASSEMBLY
//
@@ -1096,17 +1149,8 @@
) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
// Watch out for overflow. This intentionally bypasses (and does
// not update) the cache.
- let recursion_limit = *self.infcx.tcx.sess.recursion_limit.get();
- if stack.obligation.recursion_depth >= recursion_limit {
- match self.query_mode {
- TraitQueryMode::Standard => {
- self.infcx().report_overflow_error(&stack.obligation, true);
- }
- TraitQueryMode::Canonical => {
- return Err(Overflow);
- }
- }
- }
+ self.check_recursion_limit(&stack.obligation, &stack.obligation)?;
+
// Check the cache. Note that we freshen the trait-ref
// separately rather than using `stack.fresh_trait_ref` --
@@ -1767,7 +1811,7 @@
self.evaluation_probe(|this| {
match this.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) {
Ok(obligations) => {
- this.evaluate_predicates_recursively(stack.list(), obligations.iter())
+ this.evaluate_predicates_recursively(stack.list(), obligations.into_iter())
}
Err(()) => Ok(EvaluatedToErr),
}
@@ -2154,7 +2198,7 @@
let def_id = obligation.predicate.def_id();
- if ty::is_trait_alias(self.tcx(), def_id) {
+ if self.tcx().is_trait_alias(def_id) {
candidates.vec.push(TraitAliasCandidate(def_id.clone()));
}
@@ -3802,6 +3846,10 @@
fn with(r: &'o TraitObligationStack<'o, 'tcx>) -> TraitObligationStackList<'o, 'tcx> {
TraitObligationStackList { head: Some(r) }
}
+
+ fn head(&self) -> Option<&'o TraitObligationStack<'o, 'tcx>> {
+ self.head
+ }
}
impl<'o, 'tcx> Iterator for TraitObligationStackList<'o, 'tcx> {
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index d69219e..e37eab6 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -983,6 +983,9 @@
maybe_unused_trait_imports: FxHashSet<DefId>,
maybe_unused_extern_crates: Vec<(DefId, Span)>,
+ /// A map of glob use to a set of names it actually imports. Currently only
+ /// used in save-analysis.
+ glob_map: FxHashMap<DefId, FxHashSet<ast::Name>>,
/// Extern prelude entries. The value is `true` if the entry was introduced
/// via `extern crate` item and not `--extern` option or compiler built-in.
pub extern_prelude: FxHashMap<ast::Name, bool>,
@@ -1232,6 +1235,9 @@
.into_iter()
.map(|(id, sp)| (hir.local_def_id(id), sp))
.collect(),
+ glob_map: resolutions.glob_map.into_iter().map(|(id, names)| {
+ (hir.local_def_id(id), names)
+ }).collect(),
extern_prelude: resolutions.extern_prelude,
hir_map: hir,
def_path_hash_to_def_id,
@@ -2972,6 +2978,10 @@
assert_eq!(cnum, LOCAL_CRATE);
Lrc::new(tcx.maybe_unused_extern_crates.clone())
};
+ providers.names_imported_by_glob_use = |tcx, id| {
+ assert_eq!(id.krate, LOCAL_CRATE);
+ Lrc::new(tcx.glob_map.get(&id).cloned().unwrap_or_default())
+ };
providers.stability_index = |tcx, cnum| {
assert_eq!(cnum, LOCAL_CRATE);
diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs
index 417e140..9328de4 100644
--- a/src/librustc/ty/item_path.rs
+++ b/src/librustc/ty/item_path.rs
@@ -311,6 +311,7 @@
data @ DefPathData::Misc |
data @ DefPathData::TypeNs(..) |
data @ DefPathData::Trait(..) |
+ data @ DefPathData::TraitAlias(..) |
data @ DefPathData::AssocTypeInTrait(..) |
data @ DefPathData::AssocTypeInImpl(..) |
data @ DefPathData::AssocExistentialInImpl(..) |
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 26b4735..dd315cf 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -4,7 +4,7 @@
pub use self::IntVarValue::*;
pub use self::fold::TypeFoldable;
-use hir::{map as hir_map, FreevarMap, TraitMap};
+use hir::{map as hir_map, FreevarMap, GlobMap, TraitMap};
use hir::Node;
use hir::def::{Def, CtorKind, ExportMap};
use hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
@@ -115,16 +115,6 @@
// Data types
-/// The complete set of all analyses described in this module. This is
-/// produced by the driver and fed to codegen and later passes.
-///
-/// N.B., these contents are being migrated into queries using the
-/// *on-demand* infrastructure.
-#[derive(Clone)]
-pub struct CrateAnalysis {
- pub glob_map: hir::GlobMap,
-}
-
#[derive(Clone)]
pub struct Resolutions {
pub freevars: FreevarMap,
@@ -132,6 +122,7 @@
pub maybe_unused_trait_imports: NodeSet,
pub maybe_unused_extern_crates: Vec<(NodeId, Span)>,
pub export_map: ExportMap,
+ pub glob_map: GlobMap,
/// Extern prelude entries. The value is `true` if the entry was introduced
/// via `extern crate` item and not `--extern` option or compiler built-in.
pub extern_prelude: FxHashMap<Name, bool>,
@@ -3179,18 +3170,6 @@
None
}
-/// Returns `true` if `def_id` is a trait alias.
-pub fn is_trait_alias(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> bool {
- if let Some(node_id) = tcx.hir().as_local_node_id(def_id) {
- if let Node::Item(item) = tcx.hir().get(node_id) {
- if let hir::ItemKind::TraitAlias(..) = item.node {
- return true;
- }
- }
- }
- false
-}
-
/// See `ParamEnv` struct definition for details.
fn param_env<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId)
diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs
index ca5d1f6..ae41ca0 100644
--- a/src/librustc/ty/query/config.rs
+++ b/src/librustc/ty/query/config.rs
@@ -109,6 +109,33 @@
}
}
+impl<'tcx> QueryDescription<'tcx> for queries::check_mod_privacy<'tcx> {
+ fn describe(
+ tcx: TyCtxt<'_, '_, '_>,
+ key: DefId,
+ ) -> Cow<'static, str> {
+ format!("checking privacy in {}", key.describe_as_module(tcx)).into()
+ }
+}
+
+impl<'tcx> QueryDescription<'tcx> for queries::check_mod_intrinsics<'tcx> {
+ fn describe(
+ tcx: TyCtxt<'_, '_, '_>,
+ key: DefId,
+ ) -> Cow<'static, str> {
+ format!("checking intrinsics in {}", key.describe_as_module(tcx)).into()
+ }
+}
+
+impl<'tcx> QueryDescription<'tcx> for queries::check_mod_liveness<'tcx> {
+ fn describe(
+ tcx: TyCtxt<'_, '_, '_>,
+ key: DefId,
+ ) -> Cow<'static, str> {
+ format!("checking liveness of variables in {}", key.describe_as_module(tcx)).into()
+ }
+}
+
impl<'tcx> QueryDescription<'tcx> for queries::collect_mod_item_types<'tcx> {
fn describe(
tcx: TyCtxt<'_, '_, '_>,
@@ -629,6 +656,12 @@
}
}
+impl<'tcx> QueryDescription<'tcx> for queries::entry_fn<'tcx> {
+ fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+ "looking up the entry function of a crate".into()
+ }
+}
+
impl<'tcx> QueryDescription<'tcx> for queries::plugin_registrar_fn<'tcx> {
fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
"looking up the plugin registrar for a crate".into()
diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs
index 39d76ce..10f3571 100644
--- a/src/librustc/ty/query/mod.rs
+++ b/src/librustc/ty/query/mod.rs
@@ -22,7 +22,7 @@
use mir;
use mir::interpret::GlobalId;
use session::{CompileResult, CrateDisambiguator};
-use session::config::OutputFilenames;
+use session::config::{EntryFnType, OutputFilenames};
use traits::{self, Vtable};
use traits::query::{
CanonicalPredicateGoal, CanonicalProjectionGoal,
@@ -264,6 +264,12 @@
[] fn check_mod_item_types: CheckModItemTypes(DefId) -> (),
+ [] fn check_mod_privacy: CheckModPrivacy(DefId) -> (),
+
+ [] fn check_mod_intrinsics: CheckModIntrinsics(DefId) -> (),
+
+ [] fn check_mod_liveness: CheckModLiveness(DefId) -> (),
+
[] fn collect_mod_item_types: CollectModItemTypes(DefId) -> (),
/// Caches CoerceUnsized kinds for impls on custom types.
@@ -476,6 +482,9 @@
[] fn foreign_modules: ForeignModules(CrateNum) -> Lrc<Vec<ForeignModule>>,
+ /// Identifies the entry-point (e.g. the `main` function) for a given
+ /// crate, returning `None` if there is no entry point (such as for library crates).
+ [] fn entry_fn: EntryFn(CrateNum) -> Option<(DefId, EntryFnType)>,
[] fn plugin_registrar_fn: PluginRegistrarFn(CrateNum) -> Option<DefId>,
[] fn proc_macro_decls_static: ProcMacroDeclsStatic(CrateNum) -> Option<DefId>,
[] fn crate_disambiguator: CrateDisambiguator(CrateNum) -> CrateDisambiguator,
@@ -541,6 +550,8 @@
[] fn maybe_unused_trait_import: MaybeUnusedTraitImport(DefId) -> bool,
[] fn maybe_unused_extern_crates: maybe_unused_extern_crates_node(CrateNum)
-> Lrc<Vec<(DefId, Span)>>,
+ [] fn names_imported_by_glob_use: NamesImportedByGlobUse(DefId)
+ -> Lrc<FxHashSet<ast::Name>>,
[] fn stability_index: stability_index_node(CrateNum) -> Lrc<stability::Index<'tcx>>,
[] fn all_crate_nums: all_crate_nums_node(CrateNum) -> Lrc<Vec<CrateNum>>,
diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs
index 562cd75..1cc9bbd 100644
--- a/src/librustc/ty/query/plumbing.rs
+++ b/src/librustc/ty/query/plumbing.rs
@@ -2,7 +2,7 @@
//! that generate the actual methods on tcx which find and execute the
//! provider, manage the caches, and so forth.
-use dep_graph::{DepNodeIndex, DepNode, DepKind, DepNodeColor};
+use dep_graph::{DepNodeIndex, DepNode, DepKind, SerializedDepNodeIndex};
use errors::DiagnosticBuilder;
use errors::Level;
use errors::Diagnostic;
@@ -335,40 +335,6 @@
eprintln!("end of query stack");
}
- /// Try to read a node index for the node dep_node.
- /// A node will have an index, when it's already been marked green, or when we can mark it
- /// green. This function will mark the current task as a reader of the specified node, when
- /// a node index can be found for that node.
- pub(super) fn try_mark_green_and_read(self, dep_node: &DepNode) -> Option<DepNodeIndex> {
- match self.dep_graph.node_color(dep_node) {
- Some(DepNodeColor::Green(dep_node_index)) => {
- self.dep_graph.read_index(dep_node_index);
- Some(dep_node_index)
- }
- Some(DepNodeColor::Red) => {
- None
- }
- None => {
- // try_mark_green (called below) will panic when full incremental
- // compilation is disabled. If that's the case, we can't try to mark nodes
- // as green anyway, so we can safely return None here.
- if !self.dep_graph.is_fully_enabled() {
- return None;
- }
- match self.dep_graph.try_mark_green(self.global_tcx(), &dep_node) {
- Some(dep_node_index) => {
- debug_assert!(self.dep_graph.is_green(&dep_node));
- self.dep_graph.read_index(dep_node_index);
- Some(dep_node_index)
- }
- None => {
- None
- }
- }
- }
- }
- }
-
#[inline(never)]
fn try_get_with<Q: QueryDescription<'gcx>>(
self,
@@ -435,10 +401,13 @@
}
if !dep_node.kind.is_input() {
- if let Some(dep_node_index) = self.try_mark_green_and_read(&dep_node) {
+ if let Some((prev_dep_node_index,
+ dep_node_index)) = self.dep_graph.try_mark_green_and_read(self,
+ &dep_node) {
return Ok(self.load_from_disk_and_cache_in_memory::<Q>(
key,
job,
+ prev_dep_node_index,
dep_node_index,
&dep_node
))
@@ -454,6 +423,7 @@
self,
key: Q::Key,
job: JobOwner<'a, 'gcx, Q>,
+ prev_dep_node_index: SerializedDepNodeIndex,
dep_node_index: DepNodeIndex,
dep_node: &DepNode
) -> Q::Value
@@ -466,10 +436,7 @@
// 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);
+ 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.
@@ -624,7 +591,7 @@
// 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() {
+ if self.dep_graph.try_mark_green_and_read(self, &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
@@ -1281,6 +1248,9 @@
DepKind::CheckModLoops => { force!(check_mod_loops, def_id!()); }
DepKind::CheckModUnstableApiUsage => { force!(check_mod_unstable_api_usage, def_id!()); }
DepKind::CheckModItemTypes => { force!(check_mod_item_types, def_id!()); }
+ DepKind::CheckModPrivacy => { force!(check_mod_privacy, def_id!()); }
+ DepKind::CheckModIntrinsics => { force!(check_mod_intrinsics, def_id!()); }
+ DepKind::CheckModLiveness => { force!(check_mod_liveness, def_id!()); }
DepKind::CollectModItemTypes => { force!(collect_mod_item_types, def_id!()); }
DepKind::Reachability => { force!(reachable_set, LOCAL_CRATE); }
DepKind::MirKeys => { force!(mir_keys, LOCAL_CRATE); }
@@ -1362,6 +1332,7 @@
DepKind::CheckImplItemWellFormed => { force!(check_impl_item_well_formed, def_id!()); }
DepKind::ReachableNonGenerics => { force!(reachable_non_generics, krate!()); }
DepKind::NativeLibraries => { force!(native_libraries, krate!()); }
+ DepKind::EntryFn => { force!(entry_fn, krate!()); }
DepKind::PluginRegistrarFn => { force!(plugin_registrar_fn, krate!()); }
DepKind::ProcMacroDeclsStatic => { force!(proc_macro_decls_static, krate!()); }
DepKind::CrateDisambiguator => { force!(crate_disambiguator, krate!()); }
@@ -1413,6 +1384,7 @@
DepKind::MaybeUnusedTraitImport => {
force!(maybe_unused_trait_import, def_id!());
}
+ DepKind::NamesImportedByGlobUse => { force!(names_imported_by_glob_use, def_id!()); }
DepKind::MaybeUnusedExternCrates => { force!(maybe_unused_extern_crates, LOCAL_CRATE); }
DepKind::StabilityIndex => { force!(stability_index, LOCAL_CRATE); }
DepKind::AllTraits => { force!(all_traits, LOCAL_CRATE); }
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index e989ef8..75fc0f7 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -526,6 +526,15 @@
}
}
+ /// True if `def_id` refers to a trait alias (i.e., `trait Foo = ...;`).
+ pub fn is_trait_alias(self, def_id: DefId) -> bool {
+ if let DefPathData::TraitAlias(_) = self.def_key(def_id).disambiguated_data.data {
+ true
+ } else {
+ false
+ }
+ }
+
/// True if this def-id refers to the implicit constructor for
/// a tuple struct like `struct Foo(u32)`.
pub fn is_struct_constructor(self, def_id: DefId) -> bool {
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 04e5718..51e9192 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -409,6 +409,7 @@
DefPathData::AssocTypeInImpl(_) |
DefPathData::AssocExistentialInImpl(_) |
DefPathData::Trait(_) |
+ DefPathData::TraitAlias(_) |
DefPathData::Impl |
DefPathData::TypeNs(_) => {
break;
diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs
index 66303ab..72963cb 100644
--- a/src/librustc_borrowck/borrowck/mod.rs
+++ b/src/librustc_borrowck/borrowck/mod.rs
@@ -39,7 +39,6 @@
use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
use rustc::hir;
-use rustc::hir::intravisit::{self, Visitor};
use dataflow::{DataFlowContext, BitwiseOperator, DataFlowOperator, KillFrom};
@@ -157,12 +156,6 @@
where F: FnOnce(&mut BorrowckCtxt<'a, 'tcx>) -> &'c cfg::CFG
{
// Check the body of fn items.
- let tcx = this.tcx;
- let id_range = {
- let mut visitor = intravisit::IdRangeComputingVisitor::new(&tcx.hir());
- visitor.visit_body(this.body);
- visitor.result()
- };
let (all_loans, move_data) =
gather_loans::gather_loans_in_fn(this, body_id);
@@ -184,7 +177,6 @@
Some(this.body),
cfg,
LoanDataFlowOperator,
- id_range,
all_loans.len());
for (loan_idx, loan) in all_loans.iter().enumerate() {
loan_dfcx.add_gen(loan.gen_scope.item_local_id(), loan_idx);
@@ -198,7 +190,6 @@
let flowed_moves = move_data::FlowedMoveData::new(move_data,
this,
cfg,
- id_range,
this.body);
Some(AnalysisData { all_loans,
diff --git a/src/librustc_borrowck/borrowck/move_data.rs b/src/librustc_borrowck/borrowck/move_data.rs
index c5bee87..56c9f92 100644
--- a/src/librustc_borrowck/borrowck/move_data.rs
+++ b/src/librustc_borrowck/borrowck/move_data.rs
@@ -15,7 +15,6 @@
use std::usize;
use syntax_pos::Span;
use rustc::hir;
-use rustc::hir::intravisit::IdRange;
#[derive(Default)]
pub struct MoveData<'tcx> {
@@ -559,7 +558,6 @@
pub fn new(move_data: MoveData<'tcx>,
bccx: &BorrowckCtxt<'a, 'tcx>,
cfg: &cfg::CFG,
- id_range: IdRange,
body: &hir::Body)
-> FlowedMoveData<'a, 'tcx> {
let tcx = bccx.tcx;
@@ -570,7 +568,6 @@
Some(body),
cfg,
MoveDataFlowOperator,
- id_range,
move_data.moves.borrow().len());
let mut dfcx_assign =
DataFlowContext::new(tcx,
@@ -578,7 +575,6 @@
Some(body),
cfg,
AssignDataFlowOperator,
- id_range,
move_data.var_assignments.borrow().len());
move_data.add_gen_kills(bccx,
diff --git a/src/librustc_borrowck/dataflow.rs b/src/librustc_borrowck/dataflow.rs
index 56e25bd..8cf6205 100644
--- a/src/librustc_borrowck/dataflow.rs
+++ b/src/librustc_borrowck/dataflow.rs
@@ -15,7 +15,7 @@
use rustc::util::nodemap::FxHashMap;
use rustc::hir;
-use rustc::hir::intravisit::{self, IdRange};
+use rustc::hir::intravisit;
use rustc::hir::print as pprust;
@@ -230,16 +230,15 @@
body: Option<&hir::Body>,
cfg: &cfg::CFG,
oper: O,
- id_range: IdRange,
bits_per_id: usize) -> DataFlowContext<'a, 'tcx, O> {
let usize_bits = mem::size_of::<usize>() * 8;
let words_per_id = (bits_per_id + usize_bits - 1) / usize_bits;
let num_nodes = cfg.graph.all_nodes().len();
- debug!("DataFlowContext::new(analysis_name: {}, id_range={:?}, \
+ debug!("DataFlowContext::new(analysis_name: {}, \
bits_per_id={}, words_per_id={}) \
num_nodes: {}",
- analysis_name, id_range, bits_per_id, words_per_id,
+ analysis_name, bits_per_id, words_per_id,
num_nodes);
let entry = if oper.initial_value() { usize::MAX } else {0};
diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs
index 2eab626..b504aa5 100644
--- a/src/librustc_codegen_llvm/debuginfo/mod.rs
+++ b/src/librustc_codegen_llvm/debuginfo/mod.rs
@@ -14,7 +14,7 @@
use llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilder, DISubprogram, DIArray, DIFlags,
DILexicalBlock};
use rustc::hir::CodegenFnAttrFlags;
-use rustc::hir::def_id::{DefId, CrateNum};
+use rustc::hir::def_id::{DefId, CrateNum, LOCAL_CRATE};
use rustc::ty::subst::{Substs, UnpackedKind};
use abi::Abi;
@@ -290,9 +290,8 @@
let mut flags = DIFlags::FlagPrototyped;
- let local_id = self.tcx().hir().as_local_node_id(def_id);
- if let Some((id, _, _)) = *self.sess().entry_fn.borrow() {
- if local_id == Some(id) {
+ if let Some((id, _)) = self.tcx.entry_fn(LOCAL_CRATE) {
+ if id == def_id {
flags |= DIFlags::FlagMainSubprogram;
}
}
diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs
index ad9ebbc..dc70ebc 100644
--- a/src/librustc_codegen_llvm/llvm_util.rs
+++ b/src/librustc_codegen_llvm/llvm_util.rs
@@ -3,6 +3,7 @@
use llvm;
use rustc::session::Session;
use rustc::session::config::PrintRequest;
+use rustc_target::spec::MergeFunctions;
use libc::c_int;
use std::ffi::CString;
use syntax::feature_gate::UnstableFeatures;
@@ -61,7 +62,14 @@
add("-disable-preinline");
}
if llvm::LLVMRustIsRustLLVM() {
- add("-mergefunc-use-aliases");
+ match sess.opts.debugging_opts.merge_functions
+ .unwrap_or(sess.target.target.options.merge_functions) {
+ MergeFunctions::Disabled |
+ MergeFunctions::Trampolines => {}
+ MergeFunctions::Aliases => {
+ add("-mergefunc-use-aliases");
+ }
+ }
}
// HACK(eddyb) LLVM inserts `llvm.assume` calls to preserve align attributes
diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs
index bf69089..c372892 100644
--- a/src/librustc_codegen_ssa/back/symbol_export.rs
+++ b/src/librustc_codegen_ssa/back/symbol_export.rs
@@ -194,7 +194,7 @@
})
.collect();
- if tcx.sess.entry_fn.borrow().is_some() {
+ if tcx.entry_fn(LOCAL_CRATE).is_some() {
let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new("main"));
symbols.push((exported_symbol, SymbolExportLevel::C));
diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs
index fb3e7ea..39bdc70 100644
--- a/src/librustc_codegen_ssa/back/write.rs
+++ b/src/librustc_codegen_ssa/back/write.rs
@@ -24,6 +24,7 @@
use rustc_data_structures::svh::Svh;
use rustc_errors::{Handler, Level, DiagnosticBuilder, FatalError, DiagnosticId};
use rustc_errors::emitter::{Emitter};
+use rustc_target::spec::MergeFunctions;
use syntax::attr;
use syntax::ext::hygiene::Mark;
use syntax_pos::MultiSpan;
@@ -152,8 +153,24 @@
sess.opts.optimize == config::OptLevel::Aggressive &&
!sess.target.target.options.is_like_emscripten;
- self.merge_functions = sess.opts.optimize == config::OptLevel::Default ||
- sess.opts.optimize == config::OptLevel::Aggressive;
+ // Some targets (namely, NVPTX) interact badly with the MergeFunctions
+ // pass. This is because MergeFunctions can generate new function calls
+ // which may interfere with the target calling convention; e.g. for the
+ // NVPTX target, PTX kernels should not call other PTX kernels.
+ // MergeFunctions can also be configured to generate aliases instead,
+ // but aliases are not supported by some backends (again, NVPTX).
+ // Therefore, allow targets to opt out of the MergeFunctions pass,
+ // but otherwise keep the pass enabled (at O2 and O3) since it can be
+ // useful for reducing code size.
+ self.merge_functions = match sess.opts.debugging_opts.merge_functions
+ .unwrap_or(sess.target.target.options.merge_functions) {
+ MergeFunctions::Disabled => false,
+ MergeFunctions::Trampolines |
+ MergeFunctions::Aliases => {
+ sess.opts.optimize == config::OptLevel::Default ||
+ sess.opts.optimize == config::OptLevel::Aggressive
+ }
+ };
}
pub fn bitcode_needed(&self) -> bool {
diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs
index b88ec07..38caacb 100644
--- a/src/librustc_codegen_ssa/base.rs
+++ b/src/librustc_codegen_ssa/base.rs
@@ -441,10 +441,8 @@
pub fn maybe_create_entry_wrapper<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
cx: &'a Bx::CodegenCx
) {
- let (main_def_id, span) = match *cx.sess().entry_fn.borrow() {
- Some((id, span, _)) => {
- (cx.tcx().hir().local_def_id(id), span)
- }
+ let (main_def_id, span) = match cx.tcx().entry_fn(LOCAL_CRATE) {
+ Some((def_id, _)) => { (def_id, cx.tcx().def_span(def_id)) },
None => return,
};
@@ -458,7 +456,7 @@
let main_llfn = cx.get_fn(instance);
- let et = cx.sess().entry_fn.get().map(|e| e.2);
+ let et = cx.tcx().entry_fn(LOCAL_CRATE).map(|e| e.1);
match et {
Some(EntryFnType::Main) => create_entry_fn::<Bx>(cx, span, main_llfn, main_def_id, true),
Some(EntryFnType::Start) => create_entry_fn::<Bx>(cx, span, main_llfn, main_def_id, false),
diff --git a/src/librustc_codegen_utils/lib.rs b/src/librustc_codegen_utils/lib.rs
index b59bca0..5f61852 100644
--- a/src/librustc_codegen_utils/lib.rs
+++ b/src/librustc_codegen_utils/lib.rs
@@ -31,6 +31,7 @@
#[macro_use] extern crate rustc_data_structures;
use rustc::ty::TyCtxt;
+use rustc::hir::def_id::LOCAL_CRATE;
pub mod link;
pub mod codegen_backend;
@@ -42,11 +43,9 @@
/// that actually test that compilation succeeds without
/// reporting an error.
pub fn check_for_rustc_errors_attr(tcx: TyCtxt) {
- if let Some((id, span, _)) = *tcx.sess.entry_fn.borrow() {
- let main_def_id = tcx.hir().local_def_id(id);
-
- if tcx.has_attr(main_def_id, "rustc_error") {
- tcx.sess.span_fatal(span, "compilation successful");
+ if let Some((def_id, _)) = tcx.entry_fn(LOCAL_CRATE) {
+ if tcx.has_attr(def_id, "rustc_error") {
+ tcx.sess.span_fatal(tcx.def_span(def_id), "compilation successful");
}
}
}
diff --git a/src/librustc_data_structures/sync.rs b/src/librustc_data_structures/sync.rs
index f9f94f0..0253eef 100644
--- a/src/librustc_data_structures/sync.rs
+++ b/src/librustc_data_structures/sync.rs
@@ -70,6 +70,7 @@
pub struct Atomic<T: Copy>(Cell<T>);
impl<T: Copy> Atomic<T> {
+ #[inline]
pub fn new(v: T) -> Self {
Atomic(Cell::new(v))
}
@@ -80,10 +81,12 @@
self.0.into_inner()
}
+ #[inline]
pub fn load(&self, _: Ordering) -> T {
self.0.get()
}
+ #[inline]
pub fn store(&self, val: T, _: Ordering) {
self.0.set(val)
}
@@ -118,6 +121,7 @@
pub type AtomicUsize = Atomic<usize>;
pub type AtomicBool = Atomic<bool>;
+ pub type AtomicU32 = Atomic<u32>;
pub type AtomicU64 = Atomic<u64>;
pub use self::serial_join as join;
@@ -223,7 +227,7 @@
pub use parking_lot::MutexGuard as LockGuard;
pub use parking_lot::MappedMutexGuard as MappedLockGuard;
- pub use std::sync::atomic::{AtomicBool, AtomicUsize, AtomicU64};
+ pub use std::sync::atomic::{AtomicBool, AtomicUsize, AtomicU32, AtomicU64};
pub use std::sync::Arc as Lrc;
pub use std::sync::Weak as Weak;
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index 1ecb8ef..d23d8b8 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -168,7 +168,6 @@
let ExpansionResult {
expanded_crate,
defs,
- analysis,
resolutions,
mut hir_forest,
} = {
@@ -251,7 +250,6 @@
output,
&cstore,
&hir_map,
- &analysis,
&resolutions,
&expanded_crate,
&hir_map.krate(),
@@ -277,12 +275,11 @@
sess,
cstore,
hir_map,
- analysis,
resolutions,
&mut arenas,
&crate_name,
&outputs,
- |tcx, analysis, rx, result| {
+ |tcx, rx, result| {
{
// Eventually, we will want to track plugins.
tcx.dep_graph.with_ignore(|| {
@@ -293,7 +290,6 @@
output,
opt_crate,
tcx.hir().krate(),
- &analysis,
tcx,
&crate_name,
);
@@ -527,7 +523,6 @@
pub hir_crate: Option<&'a hir::Crate>,
pub hir_map: Option<&'a hir_map::Map<'tcx>>,
pub resolutions: Option<&'a Resolutions>,
- pub analysis: Option<&'a ty::CrateAnalysis>,
pub tcx: Option<TyCtxt<'a, 'tcx, 'tcx>>,
}
@@ -547,7 +542,6 @@
hir_crate: None,
hir_map: None,
resolutions: None,
- analysis: None,
tcx: None,
}
}
@@ -595,7 +589,6 @@
out_file: &'a Option<PathBuf>,
cstore: &'tcx CStore,
hir_map: &'a hir_map::Map<'tcx>,
- analysis: &'a ty::CrateAnalysis,
resolutions: &'a Resolutions,
krate: &'a ast::Crate,
hir_crate: &'a hir::Crate,
@@ -606,7 +599,6 @@
crate_name: Some(crate_name),
cstore: Some(cstore),
hir_map: Some(hir_map),
- analysis: Some(analysis),
resolutions: Some(resolutions),
expanded_crate: Some(krate),
hir_crate: Some(hir_crate),
@@ -623,12 +615,10 @@
out_file: &'a Option<PathBuf>,
krate: Option<&'a ast::Crate>,
hir_crate: &'a hir::Crate,
- analysis: &'a ty::CrateAnalysis,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
crate_name: &'a str,
) -> Self {
CompileState {
- analysis: Some(analysis),
tcx: Some(tcx),
expanded_crate: krate,
hir_crate: Some(hir_crate),
@@ -711,7 +701,6 @@
pub struct ExpansionResult {
pub expanded_crate: ast::Crate,
pub defs: hir_map::Definitions,
- pub analysis: ty::CrateAnalysis,
pub resolutions: Resolutions,
pub hir_forest: hir_map::Forest,
}
@@ -772,16 +761,13 @@
freevars: resolver.freevars,
export_map: resolver.export_map,
trait_map: resolver.trait_map,
+ glob_map: resolver.glob_map,
maybe_unused_trait_imports: resolver.maybe_unused_trait_imports,
maybe_unused_extern_crates: resolver.maybe_unused_extern_crates,
extern_prelude: resolver.extern_prelude.iter().map(|(ident, entry)| {
(ident.name, entry.introduced_by_item)
}).collect(),
},
-
- analysis: ty::CrateAnalysis {
- glob_map: resolver.glob_map
- },
}),
Err(x) => Err(x),
}
@@ -1159,10 +1145,13 @@
ty::provide(providers);
traits::provide(providers);
stability::provide(providers);
+ middle::intrinsicck::provide(providers);
+ middle::liveness::provide(providers);
reachable::provide(providers);
rustc_passes::provide(providers);
rustc_traits::provide(providers);
middle::region::provide(providers);
+ middle::entry::provide(providers);
cstore::provide(providers);
lint::provide(providers);
}
@@ -1180,7 +1169,6 @@
sess: &'tcx Session,
cstore: &'tcx CStore,
hir_map: hir_map::Map<'tcx>,
- analysis: ty::CrateAnalysis,
resolutions: Resolutions,
arenas: &'tcx mut AllArenas<'tcx>,
name: &str,
@@ -1190,7 +1178,6 @@
where
F: for<'a> FnOnce(
TyCtxt<'a, 'tcx, 'tcx>,
- ty::CrateAnalysis,
mpsc::Receiver<Box<dyn Any + Send>>,
CompileResult,
) -> R,
@@ -1199,10 +1186,6 @@
rustc_incremental::load_query_result_cache(sess)
});
- time(sess, "looking for entry point", || {
- middle::entry::find_entry_point(sess, &hir_map, name)
- });
-
let mut local_providers = ty::query::Providers::default();
default_provide(&mut local_providers);
codegen_backend.provide(&mut local_providers);
@@ -1232,6 +1215,10 @@
// tcx available.
time(sess, "dep graph tcx init", || rustc_incremental::dep_graph_tcx_init(tcx));
+ time(sess, "looking for entry point", || {
+ middle::entry::find_entry_point(tcx)
+ });
+
time(sess, "looking for plugin registrar", || {
plugin::build::find_plugin_registrar(tcx)
});
@@ -1254,7 +1241,7 @@
match typeck::check_crate(tcx) {
Ok(x) => x,
Err(x) => {
- f(tcx, analysis, rx, Err(x));
+ f(tcx, rx, Err(x));
return Err(x);
}
}
@@ -1307,7 +1294,7 @@
// lint warnings and so on -- kindck used to do this abort, but
// kindck is gone now). -nmatsakis
if sess.err_count() > 0 {
- return Ok(f(tcx, analysis, rx, sess.compile_status()));
+ return Ok(f(tcx, rx, sess.compile_status()));
}
time(sess, "death checking", || middle::dead::check_crate(tcx));
@@ -1318,7 +1305,7 @@
time(sess, "lint checking", || lint::check_crate(tcx));
- return Ok(f(tcx, analysis, rx, tcx.sess.compile_status()));
+ return Ok(f(tcx, rx, tcx.sess.compile_status()));
},
)
}
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 010ac28..c8a5bbe 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -879,7 +879,6 @@
pretty::print_after_hir_lowering(state.session,
state.cstore.unwrap(),
state.hir_map.unwrap(),
- state.analysis.unwrap(),
state.resolutions.unwrap(),
state.input,
&state.expanded_crate.take().unwrap(),
@@ -940,7 +939,6 @@
time(state.session, "save analysis", || {
save::process_crate(state.tcx.unwrap(),
state.expanded_crate.unwrap(),
- state.analysis.unwrap(),
state.crate_name.unwrap(),
state.input,
None,
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index a9ec993..d980c5a 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -123,7 +123,8 @@
sess.fatal(&format!("argument to `unpretty` must be one of `normal`, \
`expanded`, `flowgraph[,unlabelled]=<nodeid>`, \
`identified`, `expanded,identified`, `everybody_loops`, \
- `hir`, `hir,identified`, `hir,typed`, or `mir`; got {}",
+ `hir`, `hir,identified`, `hir,typed`, `hir-tree`, \
+ `mir` or `mir-cfg`; got {}",
name));
} else {
sess.fatal(&format!("argument to `pretty` must be one of `normal`, `expanded`, \
@@ -190,7 +191,6 @@
sess: &'tcx Session,
cstore: &'tcx CStore,
hir_map: &hir_map::Map<'tcx>,
- analysis: &ty::CrateAnalysis,
resolutions: &Resolutions,
output_filenames: &OutputFilenames,
id: &str,
@@ -223,12 +223,11 @@
sess,
cstore,
hir_map.clone(),
- analysis.clone(),
resolutions.clone(),
&mut arenas,
id,
output_filenames,
- |tcx, _, _, _| {
+ |tcx, _, _| {
let empty_tables = ty::TypeckTables::empty(None);
let annotation = TypedAnnotation {
tcx,
@@ -959,7 +958,6 @@
pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session,
cstore: &'tcx CStore,
hir_map: &hir_map::Map<'tcx>,
- analysis: &ty::CrateAnalysis,
resolutions: &Resolutions,
input: &Input,
krate: &ast::Crate,
@@ -972,7 +970,6 @@
print_with_analysis(sess,
cstore,
hir_map,
- analysis,
resolutions,
crate_name,
output_filenames,
@@ -1010,7 +1007,6 @@
s.call_with_pp_support_hir(sess,
cstore,
hir_map,
- analysis,
resolutions,
output_filenames,
crate_name,
@@ -1033,7 +1029,6 @@
s.call_with_pp_support_hir(sess,
cstore,
hir_map,
- analysis,
resolutions,
output_filenames,
crate_name,
@@ -1048,7 +1043,6 @@
s.call_with_pp_support_hir(sess,
cstore,
hir_map,
- analysis,
resolutions,
output_filenames,
crate_name,
@@ -1081,7 +1075,6 @@
s.call_with_pp_support_hir(sess,
cstore,
hir_map,
- analysis,
resolutions,
output_filenames,
crate_name,
@@ -1103,13 +1096,12 @@
}
// In an ideal world, this would be a public function called by the driver after
-// analsysis is performed. However, we want to call `phase_3_run_analysis_passes`
+// analysis is performed. However, we want to call `phase_3_run_analysis_passes`
// with a different callback than the standard driver, so that isn't easy.
// Instead, we call that function ourselves.
fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session,
cstore: &'a CStore,
hir_map: &hir_map::Map<'tcx>,
- analysis: &ty::CrateAnalysis,
resolutions: &Resolutions,
crate_name: &str,
output_filenames: &OutputFilenames,
@@ -1134,12 +1126,11 @@
sess,
cstore,
hir_map.clone(),
- analysis.clone(),
resolutions.clone(),
&mut arenas,
crate_name,
output_filenames,
- |tcx, _, _, _| {
+ |tcx, _, _| {
match ppm {
PpmMir | PpmMirCFG => {
if let Some(nodeid) = nodeid {
diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs
index 7449b2b..736cca6 100644
--- a/src/librustc_errors/diagnostic_builder.rs
+++ b/src/librustc_errors/diagnostic_builder.rs
@@ -33,7 +33,11 @@
/// it easy to declare such methods on the builder.
macro_rules! forward {
// Forward pattern for &self -> &Self
- (pub fn $n:ident(&self, $($name:ident: $ty:ty),* $(,)*) -> &Self) => {
+ (
+ $(#[$attrs:meta])*
+ pub fn $n:ident(&self, $($name:ident: $ty:ty),* $(,)*) -> &Self
+ ) => {
+ $(#[$attrs])*
pub fn $n(&self, $($name: $ty),*) -> &Self {
#[allow(deprecated)]
self.diagnostic.$n($($name),*);
@@ -42,7 +46,11 @@
};
// Forward pattern for &mut self -> &mut Self
- (pub fn $n:ident(&mut self, $($name:ident: $ty:ty),* $(,)*) -> &mut Self) => {
+ (
+ $(#[$attrs:meta])*
+ pub fn $n:ident(&mut self, $($name:ident: $ty:ty),* $(,)*) -> &mut Self
+ ) => {
+ $(#[$attrs])*
pub fn $n(&mut self, $($name: $ty),*) -> &mut Self {
#[allow(deprecated)]
self.diagnostic.$n($($name),*);
@@ -52,10 +60,15 @@
// Forward pattern for &mut self -> &mut Self, with S: Into<MultiSpan>
// type parameter. No obvious way to make this more generic.
- (pub fn $n:ident<S: Into<MultiSpan>>(
- &mut self,
- $($name:ident: $ty:ty),*
- $(,)*) -> &mut Self) => {
+ (
+ $(#[$attrs:meta])*
+ pub fn $n:ident<S: Into<MultiSpan>>(
+ &mut self,
+ $($name:ident: $ty:ty),*
+ $(,)*
+ ) -> &mut Self
+ ) => {
+ $(#[$attrs])*
pub fn $n<S: Into<MultiSpan>>(&mut self, $($name: $ty),*) -> &mut Self {
#[allow(deprecated)]
self.diagnostic.$n($($name),*);
@@ -177,34 +190,43 @@
msg: &str,
) -> &mut Self);
- #[deprecated(note = "Use `span_suggestion_short_with_applicability`")]
- forward!(pub fn span_suggestion_short(
- &mut self,
- sp: Span,
- msg: &str,
- suggestion: String,
- ) -> &mut Self);
+ forward!(
+ #[deprecated(note = "Use `span_suggestion_short_with_applicability`")]
+ pub fn span_suggestion_short(
+ &mut self,
+ sp: Span,
+ msg: &str,
+ suggestion: String,
+ ) -> &mut Self
+ );
- #[deprecated(note = "Use `multipart_suggestion_with_applicability`")]
- forward!(pub fn multipart_suggestion(
- &mut self,
- msg: &str,
- suggestion: Vec<(Span, String)>,
- ) -> &mut Self);
+ forward!(
+ #[deprecated(note = "Use `multipart_suggestion_with_applicability`")]
+ pub fn multipart_suggestion(
+ &mut self,
+ msg: &str,
+ suggestion: Vec<(Span, String)>,
+ ) -> &mut Self
+ );
- #[deprecated(note = "Use `span_suggestion_with_applicability`")]
- forward!(pub fn span_suggestion(&mut self,
- sp: Span,
- msg: &str,
- suggestion: String,
- ) -> &mut Self);
+ forward!(
+ #[deprecated(note = "Use `span_suggestion_with_applicability`")]
+ pub fn span_suggestion(
+ &mut self,
+ sp: Span,
+ msg: &str,
+ suggestion: String,
+ ) -> &mut Self
+ );
- #[deprecated(note = "Use `span_suggestions_with_applicability`")]
- forward!(pub fn span_suggestions(&mut self,
- sp: Span,
- msg: &str,
- suggestions: Vec<String>,
- ) -> &mut Self);
+ forward!(
+ #[deprecated(note = "Use `span_suggestions_with_applicability`")]
+ pub fn span_suggestions(&mut self,
+ sp: Span,
+ msg: &str,
+ suggestions: Vec<String>,
+ ) -> &mut Self
+ );
pub fn multipart_suggestion_with_applicability(&mut self,
msg: &str,
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index a074441..3e25f98 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -135,10 +135,11 @@
if let Some(line) = line_opt {
if let Some(lo) = line.char_indices().map(|(i, _)| i).nth(lo) {
let hi_opt = hi_opt.and_then(|hi| line.char_indices().map(|(i, _)| i).nth(hi));
- buf.push_str(match hi_opt {
- Some(hi) => &line[lo..hi],
- None => &line[lo..],
- });
+ match hi_opt {
+ Some(hi) if hi > lo => buf.push_str(&line[lo..hi]),
+ Some(_) => (),
+ None => buf.push_str(&line[lo..]),
+ }
}
if let None = hi_opt {
buf.push('\n');
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index f895542..f6c381f 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -1474,7 +1474,7 @@
_ => {},
}
TokenTree::Delimited(_, _, tts) => {
- self.check_tokens(cx, tts.stream())
+ self.check_tokens(cx, tts)
},
}
}
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index 2d764d1..71c859d 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -341,6 +341,11 @@
reference: "issue #57571 <https://github.com/rust-lang/rust/issues/57571>",
edition: None,
},
+ FutureIncompatibleInfo {
+ id: LintId::of(AMBIGUOUS_ASSOCIATED_ITEMS),
+ reference: "issue #57644 <https://github.com/rust-lang/rust/issues/57644>",
+ edition: None,
+ },
]);
// Register renamed and removed lints.
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index dc8db5b..1f07e8f 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -418,6 +418,7 @@
EntryKind::Mod(_) => Def::Mod(did),
EntryKind::Variant(_) => Def::Variant(did),
EntryKind::Trait(_) => Def::Trait(did),
+ EntryKind::TraitAlias(_) => Def::TraitAlias(did),
EntryKind::Enum(..) => Def::Enum(did),
EntryKind::MacroDef(_) => Def::Macro(did, MacroKind::Bang),
EntryKind::ForeignType => Def::ForeignTy(did),
@@ -520,17 +521,26 @@
}
pub fn get_trait_def(&self, item_id: DefIndex, sess: &Session) -> ty::TraitDef {
- let data = match self.entry(item_id).kind {
- EntryKind::Trait(data) => data.decode((self, sess)),
- _ => bug!(),
- };
-
- ty::TraitDef::new(self.local_def_id(item_id),
- data.unsafety,
- data.paren_sugar,
- data.has_auto_impl,
- data.is_marker,
- self.def_path_table.def_path_hash(item_id))
+ match self.entry(item_id).kind {
+ EntryKind::Trait(data) => {
+ let data = data.decode((self, sess));
+ ty::TraitDef::new(self.local_def_id(item_id),
+ data.unsafety,
+ data.paren_sugar,
+ data.has_auto_impl,
+ data.is_marker,
+ self.def_path_table.def_path_hash(item_id))
+ },
+ EntryKind::TraitAlias(_) => {
+ ty::TraitDef::new(self.local_def_id(item_id),
+ hir::Unsafety::Normal,
+ false,
+ false,
+ false,
+ self.def_path_table.def_path_hash(item_id))
+ },
+ _ => bug!("def-index does not refer to trait or trait alias"),
+ }
}
fn get_variant(&self,
@@ -615,10 +625,13 @@
item_id: DefIndex,
tcx: TyCtxt<'a, 'tcx, 'tcx>)
-> ty::GenericPredicates<'tcx> {
- match self.entry(item_id).kind {
- EntryKind::Trait(data) => data.decode(self).super_predicates.decode((self, tcx)),
- _ => bug!(),
- }
+ let super_predicates = match self.entry(item_id).kind {
+ EntryKind::Trait(data) => data.decode(self).super_predicates,
+ EntryKind::TraitAlias(data) => data.decode(self).super_predicates,
+ _ => bug!("def-index does not refer to trait or trait alias"),
+ };
+
+ super_predicates.decode((self, tcx))
}
pub fn get_generics(&self,
@@ -1014,7 +1027,8 @@
}
def_key.parent.and_then(|parent_index| {
match self.entry(parent_index).kind {
- EntryKind::Trait(_) => Some(self.local_def_id(parent_index)),
+ EntryKind::Trait(_) |
+ EntryKind::TraitAlias(_) => Some(self.local_def_id(parent_index)),
_ => None,
}
})
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index 2de1637..afb0218 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -1128,8 +1128,7 @@
EntryKind::Impl(self.lazy(&data))
}
- hir::ItemKind::Trait(..) |
- hir::ItemKind::TraitAlias(..) => {
+ hir::ItemKind::Trait(..) => {
let trait_def = tcx.trait_def(def_id);
let data = TraitData {
unsafety: trait_def.unsafety,
@@ -1141,6 +1140,13 @@
EntryKind::Trait(self.lazy(&data))
}
+ hir::ItemKind::TraitAlias(..) => {
+ let data = TraitAliasData {
+ super_predicates: self.lazy(&tcx.super_predicates_of(def_id)),
+ };
+
+ EntryKind::TraitAlias(self.lazy(&data))
+ }
hir::ItemKind::ExternCrate(_) |
hir::ItemKind::Use(..) => bug!("cannot encode info for item {:?}", item),
};
@@ -1214,6 +1220,7 @@
hir::ItemKind::Impl(..) |
hir::ItemKind::Existential(..) |
hir::ItemKind::Trait(..) => Some(self.encode_generics(def_id)),
+ hir::ItemKind::TraitAlias(..) => Some(self.encode_generics(def_id)),
_ => None,
},
predicates: match item.node {
@@ -1226,7 +1233,8 @@
hir::ItemKind::Union(..) |
hir::ItemKind::Impl(..) |
hir::ItemKind::Existential(..) |
- hir::ItemKind::Trait(..) => Some(self.encode_predicates(def_id)),
+ hir::ItemKind::Trait(..) |
+ hir::ItemKind::TraitAlias(..) => Some(self.encode_predicates(def_id)),
_ => None,
},
@@ -1236,7 +1244,8 @@
// hack. (No reason not to expand it in the future if
// necessary.)
predicates_defined_on: match item.node {
- hir::ItemKind::Trait(..) => Some(self.encode_predicates_defined_on(def_id)),
+ hir::ItemKind::Trait(..) |
+ hir::ItemKind::TraitAlias(..) => Some(self.encode_predicates_defined_on(def_id)),
_ => None, // not *wrong* for other kinds of items, but not needed
},
diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs
index d35d649..1f00086 100644
--- a/src/librustc_metadata/native_libs.rs
+++ b/src/librustc_metadata/native_libs.rs
@@ -163,7 +163,7 @@
!self.tcx.features().static_nobundle {
feature_gate::emit_feature_err(&self.tcx.sess.parse_sess,
"static_nobundle",
- span.unwrap(),
+ span.unwrap_or_else(|| syntax_pos::DUMMY_SP),
GateIssue::Language,
"kind=\"static-nobundle\" is feature gated");
}
diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs
index 25f499b..f3ff974 100644
--- a/src/librustc_metadata/schema.rs
+++ b/src/librustc_metadata/schema.rs
@@ -316,6 +316,7 @@
AssociatedType(AssociatedContainer),
AssociatedExistential(AssociatedContainer),
AssociatedConst(AssociatedContainer, ConstQualif, Lazy<RenderedConst>),
+ TraitAlias(Lazy<TraitAliasData<'tcx>>),
}
impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for EntryKind<'gcx> {
@@ -370,6 +371,9 @@
EntryKind::Trait(ref trait_data) => {
trait_data.hash_stable(hcx, hasher);
}
+ EntryKind::TraitAlias(ref trait_alias_data) => {
+ trait_alias_data.hash_stable(hcx, hasher);
+ }
EntryKind::Impl(ref impl_data) => {
impl_data.hash_stable(hcx, hasher);
}
@@ -475,6 +479,15 @@
});
#[derive(RustcEncodable, RustcDecodable)]
+pub struct TraitAliasData<'tcx> {
+ pub super_predicates: Lazy<ty::GenericPredicates<'tcx>>,
+}
+
+impl_stable_hash_for!(struct TraitAliasData<'tcx> {
+ super_predicates
+});
+
+#[derive(RustcEncodable, RustcDecodable)]
pub struct ImplData<'tcx> {
pub polarity: hir::ImplPolarity,
pub defaultness: hir::Defaultness,
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
index 77c8a89..2a858bd 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
@@ -505,7 +505,7 @@
) {
let mut diag = infcx.tcx.sess.struct_span_err(
span,
- "unsatisfied lifetime constraints", // FIXME
+ "lifetime may not live long enough"
);
let counter = &mut 1;
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index a6a8fe5..eb49547 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -177,13 +177,13 @@
use rustc::hir::{self, CodegenFnAttrFlags};
use rustc::hir::itemlikevisit::ItemLikeVisitor;
-use rustc::hir::def_id::DefId;
+use rustc::hir::def_id::{DefId, LOCAL_CRATE};
use rustc::mir::interpret::{AllocId, ConstValue};
use rustc::middle::lang_items::{ExchangeMallocFnLangItem, StartFnLangItem};
use rustc::ty::subst::Substs;
use rustc::ty::{self, TypeFoldable, Ty, TyCtxt, GenericParamDefKind};
use rustc::ty::adjustment::CustomCoerceUnsized;
-use rustc::session::config;
+use rustc::session::config::EntryFnType;
use rustc::mir::{self, Location, Promoted};
use rustc::mir::visit::Visitor as MirVisitor;
use rustc::mir::mono::MonoItem;
@@ -321,9 +321,7 @@
let mut roots = Vec::new();
{
- let entry_fn = tcx.sess.entry_fn.borrow().map(|(node_id, _, _)| {
- tcx.hir().local_def_id(node_id)
- });
+ let entry_fn = tcx.entry_fn(LOCAL_CRATE);
debug!("collect_roots: entry_fn = {:?}", entry_fn);
@@ -924,7 +922,7 @@
tcx: TyCtxt<'a, 'tcx, 'tcx>,
mode: MonoItemCollectionMode,
output: &'b mut Vec<MonoItem<'tcx>>,
- entry_fn: Option<DefId>,
+ entry_fn: Option<(DefId, EntryFnType)>,
}
impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> {
@@ -1023,7 +1021,7 @@
true
}
MonoItemCollectionMode::Lazy => {
- self.entry_fn == Some(def_id) ||
+ self.entry_fn.map(|(id, _)| id) == Some(def_id) ||
self.tcx.is_reachable_non_generic(def_id) ||
self.tcx.codegen_fn_attrs(def_id).flags.contains(
CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
@@ -1048,14 +1046,9 @@
/// the return type of `main`. This is not needed when
/// the user writes their own `start` manually.
fn push_extra_entry_roots(&mut self) {
- if self.tcx.sess.entry_fn.get().map(|e| e.2) != Some(config::EntryFnType::Main) {
- return
- }
-
- let main_def_id = if let Some(def_id) = self.entry_fn {
- def_id
- } else {
- return
+ let main_def_id = match self.entry_fn {
+ Some((def_id, EntryFnType::Main)) => def_id,
+ _ => return,
};
let start_def_id = match self.tcx.lang_items().require(StartFnLangItem) {
diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs
index 7014f53..c831cbd 100644
--- a/src/librustc_mir/monomorphize/item.rs
+++ b/src/librustc_mir/monomorphize/item.rs
@@ -1,6 +1,6 @@
use monomorphize::Instance;
use rustc::hir;
-use rustc::hir::def_id::DefId;
+use rustc::hir::def_id::{DefId, LOCAL_CRATE};
use rustc::session::config::OptLevel;
use rustc::ty::{self, Ty, TyCtxt, ClosureSubsts, GeneratorSubsts};
use rustc::ty::subst::Substs;
@@ -75,8 +75,7 @@
match *self.as_mono_item() {
MonoItem::Fn(ref instance) => {
- let entry_def_id =
- tcx.sess.entry_fn.borrow().map(|(id, _, _)| tcx.hir().local_def_id(id));
+ let entry_def_id = tcx.entry_fn(LOCAL_CRATE).map(|(id, _)| id);
// If this function isn't inlined or otherwise has explicit
// linkage, then we'll be creating a globally shared version.
if self.explicit_linkage(tcx).is_some() ||
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 4890369..dcbb9ff 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -13,7 +13,7 @@
extern crate syntax_pos;
extern crate rustc_data_structures;
-use rustc::hir::{self, Node, PatKind};
+use rustc::hir::{self, Node, PatKind, AssociatedItemKind};
use rustc::hir::def::Def;
use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefId};
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
@@ -22,12 +22,12 @@
use rustc::middle::privacy::{AccessLevel, AccessLevels};
use rustc::ty::{self, TyCtxt, Ty, TraitRef, TypeFoldable, GenericParamDefKind};
use rustc::ty::fold::TypeVisitor;
-use rustc::ty::query::Providers;
+use rustc::ty::query::{Providers, queries};
use rustc::ty::subst::Substs;
use rustc::util::nodemap::NodeSet;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::sync::Lrc;
-use syntax::ast::{self, CRATE_NODE_ID, Ident};
+use syntax::ast::{self, DUMMY_NODE_ID, Ident};
use syntax::attr;
use syntax::symbol::keywords;
use syntax_pos::Span;
@@ -548,7 +548,7 @@
let mut reach = self.reach(trait_item_ref.id.node_id, item_level);
reach.generics().predicates();
- if trait_item_ref.kind == hir::AssociatedItemKind::Type &&
+ if trait_item_ref.kind == AssociatedItemKind::Type &&
!trait_item_ref.defaultness.has_value() {
// No type to visit.
} else {
@@ -782,6 +782,11 @@
NestedVisitorMap::All(&self.tcx.hir())
}
+ fn visit_mod(&mut self, _m: &'tcx hir::Mod, _s: Span, _n: ast::NodeId) {
+ // Don't visit nested modules, since we run a separate visitor walk
+ // for each module in `privacy_access_levels`
+ }
+
fn visit_nested_body(&mut self, body: hir::BodyId) {
let orig_tables = mem::replace(&mut self.tables, self.tcx.body_tables(body));
let body = self.tcx.hir().body(body);
@@ -917,6 +922,11 @@
NestedVisitorMap::All(&self.tcx.hir())
}
+ fn visit_mod(&mut self, _m: &'tcx hir::Mod, _s: Span, _n: ast::NodeId) {
+ // Don't visit nested modules, since we run a separate visitor walk
+ // for each module in `privacy_access_levels`
+ }
+
fn visit_nested_body(&mut self, body: hir::BodyId) {
let orig_tables = mem::replace(&mut self.tables, self.tcx.body_tables(body));
let orig_in_body = mem::replace(&mut self.in_body, true);
@@ -1333,11 +1343,11 @@
if self.item_is_public(&impl_item_ref.id.node_id, &impl_item_ref.vis) {
let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
match impl_item_ref.kind {
- hir::AssociatedItemKind::Const => {
+ AssociatedItemKind::Const => {
found_pub_static = true;
intravisit::walk_impl_item(self, impl_item);
}
- hir::AssociatedItemKind::Method { has_self: false } => {
+ AssociatedItemKind::Method { has_self: false } => {
found_pub_static = true;
intravisit::walk_impl_item(self, impl_item);
}
@@ -1558,6 +1568,24 @@
in_assoc_ty: false,
}
}
+
+ fn check_trait_or_impl_item(&self, node_id: ast::NodeId, assoc_item_kind: AssociatedItemKind,
+ defaultness: hir::Defaultness, vis: ty::Visibility) {
+ let mut check = self.check(node_id, vis);
+
+ let (check_ty, is_assoc_ty) = match assoc_item_kind {
+ AssociatedItemKind::Const | AssociatedItemKind::Method { .. } => (true, false),
+ AssociatedItemKind::Type => (defaultness.has_value(), true),
+ // `ty()` for existential types is the underlying type,
+ // it's not a part of interface, so we skip it.
+ AssociatedItemKind::Existential => (false, true),
+ };
+ check.in_assoc_ty = is_assoc_ty;
+ check.generics().predicates();
+ if check_ty {
+ check.ty();
+ }
+ }
}
impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
@@ -1592,16 +1620,8 @@
self.check(item.id, item_visibility).generics().predicates();
for trait_item_ref in trait_item_refs {
- let mut check = self.check(trait_item_ref.id.node_id, item_visibility);
- check.in_assoc_ty = trait_item_ref.kind == hir::AssociatedItemKind::Type;
- check.generics().predicates();
-
- if trait_item_ref.kind == hir::AssociatedItemKind::Type &&
- !trait_item_ref.defaultness.has_value() {
- // No type to visit.
- } else {
- check.ty();
- }
+ self.check_trait_or_impl_item(trait_item_ref.id.node_id, trait_item_ref.kind,
+ trait_item_ref.defaultness, item_visibility);
}
}
hir::ItemKind::TraitAlias(..) => {
@@ -1647,9 +1667,8 @@
} else {
impl_vis
};
- let mut check = self.check(impl_item.id, impl_item_vis);
- check.in_assoc_ty = impl_item_ref.kind == hir::AssociatedItemKind::Type;
- check.generics().predicates().ty();
+ self.check_trait_or_impl_item(impl_item_ref.id.node_id, impl_item_ref.kind,
+ impl_item_ref.defaultness, impl_item_vis);
}
}
}
@@ -1659,6 +1678,7 @@
pub fn provide(providers: &mut Providers) {
*providers = Providers {
privacy_access_levels,
+ check_mod_privacy,
..*providers
};
}
@@ -1667,34 +1687,43 @@
tcx.privacy_access_levels(LOCAL_CRATE)
}
-fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- krate: CrateNum)
- -> Lrc<AccessLevels> {
- assert_eq!(krate, LOCAL_CRATE);
-
- let krate = tcx.hir().krate();
+fn check_mod_privacy<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
let empty_tables = ty::TypeckTables::empty(None);
// Check privacy of names not checked in previous compilation stages.
let mut visitor = NamePrivacyVisitor {
tcx,
tables: &empty_tables,
- current_item: CRATE_NODE_ID,
+ current_item: DUMMY_NODE_ID,
empty_tables: &empty_tables,
};
- intravisit::walk_crate(&mut visitor, krate);
+ let (module, span, node_id) = tcx.hir().get_module(module_def_id);
+ intravisit::walk_mod(&mut visitor, module, node_id);
// Check privacy of explicitly written types and traits as well as
// inferred types of expressions and patterns.
let mut visitor = TypePrivacyVisitor {
tcx,
tables: &empty_tables,
- current_item: DefId::local(CRATE_DEF_INDEX),
+ current_item: module_def_id,
in_body: false,
- span: krate.span,
+ span,
empty_tables: &empty_tables,
};
- intravisit::walk_crate(&mut visitor, krate);
+ intravisit::walk_mod(&mut visitor, module, node_id);
+}
+
+fn privacy_access_levels<'tcx>(
+ tcx: TyCtxt<'_, 'tcx, 'tcx>,
+ krate: CrateNum,
+) -> Lrc<AccessLevels> {
+ assert_eq!(krate, LOCAL_CRATE);
+
+ let krate = tcx.hir().krate();
+
+ for &module in krate.modules.keys() {
+ queries::check_mod_privacy::ensure(tcx, tcx.hir().local_def_id(module));
+ }
// Build up a set of all exported items in the AST. This is a set of all
// items which are reachable from external crates based on visibility.
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index a452bbf..35616cc 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -21,6 +21,8 @@
use std::ptr;
use rustc_data_structures::sync::Lrc;
+use errors::Applicability;
+
use syntax::ast::{Name, Ident};
use syntax::attr;
@@ -345,7 +347,12 @@
let module = if orig_name.is_none() && ident.name == keywords::SelfLower.name() {
self.session
.struct_span_err(item.span, "`extern crate self;` requires renaming")
- .span_suggestion(item.span, "try", "extern crate self as name;".into())
+ .span_suggestion_with_applicability(
+ item.span,
+ "try",
+ "extern crate self as name;".into(),
+ Applicability::HasPlaceholders,
+ )
.emit();
return;
} else if orig_name == Some(keywords::SelfLower.name()) {
@@ -673,6 +680,9 @@
}
module.populated.set(true);
}
+ Def::TraitAlias(..) => {
+ self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion));
+ }
Def::Struct(..) | Def::Union(..) => {
self.define(parent, ident, TypeNS, (def, vis, DUMMY_SP, expansion));
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index b411937..1cd4404 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -3318,7 +3318,12 @@
if let Some(def) = def {
match (def, source) {
(Def::Macro(..), _) => {
- err.span_label(span, format!("did you mean `{}!(...)`?", path_str));
+ err.span_suggestion_with_applicability(
+ span,
+ "use `!` to invoke the macro",
+ format!("{}!", path_str),
+ Applicability::MaybeIncorrect,
+ );
return (err, candidates);
}
(Def::TyAlias(..), PathSource::Trait(_)) => {
@@ -3330,13 +3335,22 @@
}
(Def::Mod(..), PathSource::Expr(Some(parent))) => match parent.node {
ExprKind::Field(_, ident) => {
- err.span_label(parent.span, format!("did you mean `{}::{}`?",
- path_str, ident));
+ err.span_suggestion_with_applicability(
+ parent.span,
+ "use the path separator to refer to an item",
+ format!("{}::{}", path_str, ident),
+ Applicability::MaybeIncorrect,
+ );
return (err, candidates);
}
ExprKind::MethodCall(ref segment, ..) => {
- err.span_label(parent.span, format!("did you mean `{}::{}(...)`?",
- path_str, segment.ident));
+ let span = parent.span.with_hi(segment.ident.span.hi());
+ err.span_suggestion_with_applicability(
+ span,
+ "use the path separator to refer to an item",
+ format!("{}::{}", path_str, segment.ident),
+ Applicability::MaybeIncorrect,
+ );
return (err, candidates);
}
_ => {}
@@ -3387,6 +3401,29 @@
Ok(ref snippet) if snippet == "{" => true,
_ => false,
};
+ // In case this could be a struct literal that needs to be surrounded
+ // by parenthesis, find the appropriate span.
+ let mut i = 0;
+ let mut closing_brace = None;
+ loop {
+ sp = sm.next_point(sp);
+ match sm.span_to_snippet(sp) {
+ Ok(ref snippet) => {
+ if snippet == "}" {
+ let sp = span.to(sp);
+ if let Ok(snippet) = sm.span_to_snippet(sp) {
+ closing_brace = Some((sp, snippet));
+ }
+ break;
+ }
+ }
+ _ => break,
+ }
+ i += 1;
+ if i > 100 { // The bigger the span the more likely we're
+ break; // incorrect. Bound it to 100 chars long.
+ }
+ }
match source {
PathSource::Expr(Some(parent)) => {
match parent.node {
@@ -3413,11 +3450,20 @@
}
},
PathSource::Expr(None) if followed_by_brace == true => {
- err.span_label(
- span,
- format!("did you mean `({} {{ /* fields */ }})`?",
- path_str),
- );
+ if let Some((sp, snippet)) = closing_brace {
+ err.span_suggestion_with_applicability(
+ sp,
+ "surround the struct literal with parenthesis",
+ format!("({})", snippet),
+ Applicability::MaybeIncorrect,
+ );
+ } else {
+ err.span_label(
+ span,
+ format!("did you mean `({} {{ /* fields */ }})`?",
+ path_str),
+ );
+ }
return (err, candidates);
},
_ => {
@@ -4820,8 +4866,13 @@
} else if ident.span.rust_2018() {
let msg = "relative paths are not supported in visibilities on 2018 edition";
self.session.struct_span_err(ident.span, msg)
- .span_suggestion(path.span, "try", format!("crate::{}", path))
- .emit();
+ .span_suggestion_with_applicability(
+ path.span,
+ "try",
+ format!("crate::{}", path),
+ Applicability::MaybeIncorrect,
+ )
+ .emit();
return ty::Visibility::Public;
} else {
let ctxt = ident.span.ctxt();
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index 05156fb..995df38 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -1238,12 +1238,9 @@
};
// Make a comma-separated list of names of imported modules.
- let glob_map = &self.save_ctxt.analysis.glob_map;
- let names = if glob_map.contains_key(&id) {
- glob_map.get(&id).unwrap().iter().map(|n| n.to_string()).collect()
- } else {
- Vec::new()
- };
+ let def_id = self.tcx.hir().local_def_id(id);
+ let names = self.tcx.names_imported_by_glob_use(def_id);
+ let names: Vec<_> = names.iter().map(|n| n.to_string()).collect();
// Otherwise it's a span with wrong macro expansion info, which
// we don't want to track anyway, since it's probably macro-internal `use`
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index 4d55004..73eb5de 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -71,7 +71,6 @@
tcx: TyCtxt<'l, 'tcx, 'tcx>,
tables: &'l ty::TypeckTables<'tcx>,
access_levels: &'l AccessLevels,
- analysis: &'l ty::CrateAnalysis,
span_utils: SpanUtils<'tcx>,
config: Config,
impl_counter: Cell<u32>,
@@ -1120,7 +1119,6 @@
pub fn process_crate<'l, 'tcx, H: SaveHandler>(
tcx: TyCtxt<'l, 'tcx, 'tcx>,
krate: &ast::Crate,
- analysis: &'l ty::CrateAnalysis,
cratename: &str,
input: &'l Input,
config: Option<Config>,
@@ -1139,7 +1137,6 @@
let save_ctxt = SaveContext {
tcx,
tables: &ty::TypeckTables::empty(None),
- analysis,
access_levels: &access_levels,
span_utils: SpanUtils::new(&tcx.sess),
config: find_config(config),
diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs
index f42b0a1..3a21ca1 100644
--- a/src/librustc_target/spec/mod.rs
+++ b/src/librustc_target/spec/mod.rs
@@ -217,6 +217,46 @@
}
}
+#[derive(Clone, Copy, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
+pub enum MergeFunctions {
+ Disabled,
+ Trampolines,
+ Aliases
+}
+
+impl MergeFunctions {
+ pub fn desc(&self) -> &str {
+ match *self {
+ MergeFunctions::Disabled => "disabled",
+ MergeFunctions::Trampolines => "trampolines",
+ MergeFunctions::Aliases => "aliases",
+ }
+ }
+}
+
+impl FromStr for MergeFunctions {
+ type Err = ();
+
+ fn from_str(s: &str) -> Result<MergeFunctions, ()> {
+ match s {
+ "disabled" => Ok(MergeFunctions::Disabled),
+ "trampolines" => Ok(MergeFunctions::Trampolines),
+ "aliases" => Ok(MergeFunctions::Aliases),
+ _ => Err(()),
+ }
+ }
+}
+
+impl ToJson for MergeFunctions {
+ fn to_json(&self) -> Json {
+ match *self {
+ MergeFunctions::Disabled => "disabled".to_json(),
+ MergeFunctions::Trampolines => "trampolines".to_json(),
+ MergeFunctions::Aliases => "aliases".to_json(),
+ }
+ }
+}
+
pub type LinkArgs = BTreeMap<LinkerFlavor, Vec<String>>;
pub type TargetResult = Result<Target, String>;
@@ -690,7 +730,15 @@
/// If set, have the linker export exactly these symbols, instead of using
/// the usual logic to figure this out from the crate itself.
- pub override_export_symbols: Option<Vec<String>>
+ pub override_export_symbols: Option<Vec<String>>,
+
+ /// Determines how or whether the MergeFunctions LLVM pass should run for
+ /// this target. Either "disabled", "trampolines", or "aliases".
+ /// The MergeFunctions pass is generally useful, but some targets may need
+ /// to opt out. The default is "aliases".
+ ///
+ /// Workaround for: https://github.com/rust-lang/rust/issues/57356
+ pub merge_functions: MergeFunctions
}
impl Default for TargetOptions {
@@ -773,6 +821,7 @@
requires_uwtable: false,
simd_types_indirect: true,
override_export_symbols: None,
+ merge_functions: MergeFunctions::Aliases,
}
}
}
@@ -875,6 +924,19 @@
.map(|o| o.as_u64()
.map(|s| base.options.$key_name = Some(s)));
} );
+ ($key_name:ident, MergeFunctions) => ( {
+ let name = (stringify!($key_name)).replace("_", "-");
+ obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
+ match s.parse::<MergeFunctions>() {
+ Ok(mergefunc) => base.options.$key_name = mergefunc,
+ _ => return Some(Err(format!("'{}' is not a valid value for \
+ merge-functions. Use 'disabled', \
+ 'trampolines', or 'aliases'.",
+ s))),
+ }
+ Some(Ok(()))
+ })).unwrap_or(Ok(()))
+ } );
($key_name:ident, PanicStrategy) => ( {
let name = (stringify!($key_name)).replace("_", "-");
obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
@@ -1064,6 +1126,7 @@
key!(requires_uwtable, bool);
key!(simd_types_indirect, bool);
key!(override_export_symbols, opt_list);
+ key!(merge_functions, MergeFunctions)?;
if let Some(array) = obj.find("abi-blacklist").and_then(Json::as_array) {
for name in array.iter().filter_map(|abi| abi.as_string()) {
@@ -1275,6 +1338,7 @@
target_option_val!(requires_uwtable);
target_option_val!(simd_types_indirect);
target_option_val!(override_export_symbols);
+ target_option_val!(merge_functions);
if default.abi_blacklist != self.options.abi_blacklist {
d.insert("abi-blacklist".to_string(), self.options.abi_blacklist.iter()
diff --git a/src/librustc_traits/lowering/mod.rs b/src/librustc_traits/lowering/mod.rs
index 5502a1d..9bdef30 100644
--- a/src/librustc_traits/lowering/mod.rs
+++ b/src/librustc_traits/lowering/mod.rs
@@ -158,7 +158,8 @@
def_id: DefId,
) -> Clauses<'tcx> {
match tcx.def_key(def_id).disambiguated_data.data {
- DefPathData::Trait(_) => program_clauses_for_trait(tcx, def_id),
+ DefPathData::Trait(_) |
+ DefPathData::TraitAlias(_) => program_clauses_for_trait(tcx, def_id),
DefPathData::Impl => program_clauses_for_impl(tcx, def_id),
DefPathData::AssocTypeInImpl(..) => program_clauses_for_associated_type_value(tcx, def_id),
DefPathData::AssocTypeInTrait(..) => program_clauses_for_associated_type_def(tcx, def_id),
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 8e5eaa1..e89506a 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -2,7 +2,7 @@
//! The main routine here is `ast_ty_to_ty()`; each use is parameterized by an
//! instance of `AstConv`.
-use errors::{Applicability, FatalError, DiagnosticId};
+use errors::{Applicability, DiagnosticId};
use hir::{self, GenericArg, GenericArgs};
use hir::def::Def;
use hir::def_id::DefId;
@@ -10,6 +10,7 @@
use lint;
use middle::resolve_lifetime as rl;
use namespace::Namespace;
+use rustc::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS;
use rustc::traits;
use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable};
use rustc::ty::{GenericParamDef, GenericParamDefKind};
@@ -689,27 +690,13 @@
{
self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1);
- let trait_def_id = self.trait_def_id(trait_ref);
self.ast_path_to_mono_trait_ref(trait_ref.path.span,
- trait_def_id,
+ trait_ref.trait_def_id(),
self_ty,
trait_ref.path.segments.last().unwrap())
}
- /// Get the `DefId` of the given trait ref. It _must_ actually be a trait.
- fn trait_def_id(&self, trait_ref: &hir::TraitRef) -> DefId {
- let path = &trait_ref.path;
- match path.def {
- Def::Trait(trait_def_id) => trait_def_id,
- Def::TraitAlias(alias_def_id) => alias_def_id,
- Def::Err => {
- FatalError.raise();
- }
- _ => unreachable!(),
- }
- }
-
- /// The given trait ref must actually be a trait.
+ /// The given trait-ref must actually be a trait.
pub(super) fn instantiate_poly_trait_ref_inner(&self,
trait_ref: &hir::TraitRef,
self_ty: Ty<'tcx>,
@@ -717,7 +704,7 @@
speculative: bool)
-> (ty::PolyTraitRef<'tcx>, Option<Vec<Span>>)
{
- let trait_def_id = self.trait_def_id(trait_ref);
+ let trait_def_id = trait_ref.trait_def_id();
debug!("instantiate_poly_trait_ref({:?}, def_id={:?})", trait_ref, trait_def_id);
@@ -1278,29 +1265,50 @@
}
// Create a type from a path to an associated type.
- // For a path `A::B::C::D`, `ty` and `ty_path_def` are the type and def for `A::B::C`
+ // For a path `A::B::C::D`, `qself_ty` and `qself_def` are the type and def for `A::B::C`
// and item_segment is the path segment for `D`. We return a type and a def for
// the whole path.
- // Will fail except for `T::A` and `Self::A`; i.e., if `ty`/`ty_path_def` are not a type
+ // Will fail except for `T::A` and `Self::A`; i.e., if `qself_ty`/`qself_def` are not a type
// parameter or `Self`.
- pub fn associated_path_def_to_ty(&self,
- ref_id: ast::NodeId,
- span: Span,
- ty: Ty<'tcx>,
- ty_path_def: Def,
- item_segment: &hir::PathSegment)
- -> (Ty<'tcx>, Def)
- {
+ pub fn associated_path_to_ty(
+ &self,
+ ref_id: ast::NodeId,
+ span: Span,
+ qself_ty: Ty<'tcx>,
+ qself_def: Def,
+ assoc_segment: &hir::PathSegment,
+ permit_variants: bool,
+ ) -> (Ty<'tcx>, Def) {
let tcx = self.tcx();
- let assoc_name = item_segment.ident;
+ let assoc_ident = assoc_segment.ident;
- debug!("associated_path_def_to_ty: {:?}::{}", ty, assoc_name);
+ debug!("associated_path_to_ty: {:?}::{}", qself_ty, assoc_ident);
- self.prohibit_generics(slice::from_ref(item_segment));
+ self.prohibit_generics(slice::from_ref(assoc_segment));
+
+ // Check if we have an enum variant.
+ let mut variant_resolution = None;
+ if let ty::Adt(adt_def, _) = qself_ty.sty {
+ if adt_def.is_enum() {
+ let variant_def = adt_def.variants.iter().find(|vd| {
+ tcx.hygienic_eq(assoc_ident, vd.ident, adt_def.did)
+ });
+ if let Some(variant_def) = variant_def {
+ let def = Def::Variant(variant_def.did);
+ if permit_variants {
+ check_type_alias_enum_variants_enabled(tcx, span);
+ tcx.check_stability(variant_def.did, Some(ref_id), span);
+ return (qself_ty, def);
+ } else {
+ variant_resolution = Some(def);
+ }
+ }
+ }
+ }
// Find the type of the associated item, and the trait where the associated
// item is declared.
- let bound = match (&ty.sty, ty_path_def) {
+ let bound = match (&qself_ty.sty, qself_def) {
(_, Def::SelfTy(Some(_), Some(impl_def_id))) => {
// `Self` in an impl of a trait -- we have a concrete self type and a
// trait reference.
@@ -1313,77 +1321,61 @@
};
let candidates = traits::supertraits(tcx, ty::Binder::bind(trait_ref))
- .filter(|r| self.trait_defines_associated_type_named(r.def_id(), assoc_name));
+ .filter(|r| self.trait_defines_associated_type_named(r.def_id(), assoc_ident));
- match self.one_bound_for_assoc_type(candidates, "Self", assoc_name, span) {
+ match self.one_bound_for_assoc_type(candidates, "Self", assoc_ident, span) {
Ok(bound) => bound,
Err(ErrorReported) => return (tcx.types.err, Def::Err),
}
}
(&ty::Param(_), Def::SelfTy(Some(param_did), None)) |
(&ty::Param(_), Def::TyParam(param_did)) => {
- match self.find_bound_for_assoc_item(param_did, assoc_name, span) {
+ match self.find_bound_for_assoc_item(param_did, assoc_ident, span) {
Ok(bound) => bound,
Err(ErrorReported) => return (tcx.types.err, Def::Err),
}
}
- (&ty::Adt(adt_def, _substs), Def::Enum(_did)) => {
- let ty_str = ty.to_string();
- // Incorrect enum variant.
- let mut err = tcx.sess.struct_span_err(
- span,
- &format!("no variant `{}` on enum `{}`", &assoc_name.as_str(), ty_str),
- );
- // Check if it was a typo.
- let input = adt_def.variants.iter().map(|variant| &variant.ident.name);
- if let Some(suggested_name) = find_best_match_for_name(
- input,
- &assoc_name.as_str(),
- None,
- ) {
- err.span_suggestion_with_applicability(
- span,
- "did you mean",
- format!("{}::{}", ty_str, suggested_name.to_string()),
- Applicability::MaybeIncorrect,
- );
- } else {
- err.span_label(span, "unknown variant");
- }
- err.emit();
- return (tcx.types.err, Def::Err);
- }
_ => {
- // Check if we have an enum variant.
- match ty.sty {
- ty::Adt(adt_def, _) if adt_def.is_enum() => {
- let variant_def = adt_def.variants.iter().find(|vd| {
- tcx.hygienic_eq(assoc_name, vd.ident, adt_def.did)
- });
- if let Some(variant_def) = variant_def {
- check_type_alias_enum_variants_enabled(tcx, span);
-
- let def = Def::Variant(variant_def.did);
- tcx.check_stability(def.def_id(), Some(ref_id), span);
- return (ty, def);
- }
- },
- _ => (),
- }
-
- // Don't print `TyErr` to the user.
- if !ty.references_error() {
+ if variant_resolution.is_some() {
+ // Variant in type position
+ let msg = format!("expected type, found variant `{}`", assoc_ident);
+ tcx.sess.span_err(span, &msg);
+ } else if qself_ty.is_enum() {
+ // Report as incorrect enum variant rather than ambiguous type.
+ let mut err = tcx.sess.struct_span_err(
+ span,
+ &format!("no variant `{}` on enum `{}`", &assoc_ident.as_str(), qself_ty),
+ );
+ // Check if it was a typo.
+ let adt_def = qself_ty.ty_adt_def().expect("enum is not an ADT");
+ if let Some(suggested_name) = find_best_match_for_name(
+ adt_def.variants.iter().map(|variant| &variant.ident.name),
+ &assoc_ident.as_str(),
+ None,
+ ) {
+ err.span_suggestion_with_applicability(
+ span,
+ "did you mean",
+ format!("{}::{}", qself_ty, suggested_name),
+ Applicability::MaybeIncorrect,
+ );
+ } else {
+ err.span_label(span, "unknown variant");
+ }
+ err.emit();
+ } else if !qself_ty.references_error() {
+ // Don't print `TyErr` to the user.
self.report_ambiguous_associated_type(span,
- &ty.to_string(),
+ &qself_ty.to_string(),
"Trait",
- &assoc_name.as_str());
+ &assoc_ident.as_str());
}
return (tcx.types.err, Def::Err);
}
};
let trait_did = bound.def_id();
- let (assoc_ident, def_scope) = tcx.adjust_ident(assoc_name, trait_did, ref_id);
+ let (assoc_ident, def_scope) = tcx.adjust_ident(assoc_ident, trait_did, ref_id);
let item = tcx.associated_items(trait_did).find(|i| {
Namespace::from(i.kind) == Namespace::Type &&
i.ident.modern() == assoc_ident
@@ -1394,11 +1386,35 @@
let def = Def::AssociatedTy(item.def_id);
if !item.vis.is_accessible_from(def_scope, tcx) {
- let msg = format!("{} `{}` is private", def.kind_name(), assoc_name);
+ let msg = format!("{} `{}` is private", def.kind_name(), assoc_ident);
tcx.sess.span_err(span, &msg);
}
tcx.check_stability(item.def_id, Some(ref_id), span);
+ if let Some(variant_def) = variant_resolution {
+ let mut err = tcx.struct_span_lint_node(
+ AMBIGUOUS_ASSOCIATED_ITEMS,
+ ref_id,
+ span,
+ "ambiguous associated item",
+ );
+
+ let mut could_refer_to = |def: Def, also| {
+ let note_msg = format!("`{}` could{} refer to {} defined here",
+ assoc_ident, also, def.kind_name());
+ err.span_note(tcx.def_span(def.def_id()), ¬e_msg);
+ };
+ could_refer_to(variant_def, "");
+ could_refer_to(def, " also");
+
+ err.span_suggestion_with_applicability(
+ span,
+ "use fully-qualified syntax",
+ format!("<{} as {}>::{}", qself_ty, "Trait", assoc_ident),
+ Applicability::HasPlaceholders,
+ ).emit();
+ }
+
(ty, def)
}
@@ -1773,7 +1789,7 @@
} else {
Def::Err
};
- self.associated_path_def_to_ty(ast_ty.id, ast_ty.span, ty, def, segment).0
+ self.associated_path_to_ty(ast_ty.id, ast_ty.span, ty, def, segment, false).0
}
hir::TyKind::Array(ref ty, ref length) => {
let length_def_id = tcx.hir().local_def_id(length.id);
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 1767af4..47f258e 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -1,5 +1,6 @@
use check::{FnCtxt, Expectation, Diverges, Needs};
use check::coercion::CoerceMany;
+use errors::Applicability;
use rustc::hir::{self, PatKind};
use rustc::hir::def::{Def, CtorKind};
use rustc::hir::pat_util::EnumerateAndAdjustIterator;
@@ -989,7 +990,13 @@
let suggested_name =
find_best_match_for_name(input, &ident.as_str(), None);
if let Some(suggested_name) = suggested_name {
- err.span_suggestion(*span, "did you mean", suggested_name.to_string());
+ err.span_suggestion_with_applicability(
+ *span,
+ "did you mean",
+ suggested_name.to_string(),
+ Applicability::MaybeIncorrect,
+ );
+
// we don't want to throw `E0027` in case we have thrown `E0026` for them
unmentioned_fields.retain(|&x| x.as_str() != suggested_name.as_str());
}
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index 02687df..e71dc01 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -408,45 +408,36 @@
let tcx = self.tcx;
- let mode = probe::Mode::Path;
- match self.probe_for_name(span, mode, method_name, IsSuggestion(false),
- self_ty, expr_id, ProbeScope::TraitsInScope) {
- Ok(pick) => {
- debug!("resolve_ufcs: pick={:?}", pick);
- if let Some(import_id) = pick.import_id {
- let import_def_id = tcx.hir().local_def_id(import_id);
- debug!("resolve_ufcs: used_trait_import: {:?}", import_def_id);
- Lrc::get_mut(&mut self.tables.borrow_mut().used_trait_imports)
- .unwrap().insert(import_def_id);
+ // Check if we have an enum variant.
+ if let ty::Adt(adt_def, _) = self_ty.sty {
+ if adt_def.is_enum() {
+ let variant_def = adt_def.variants.iter().find(|vd| {
+ tcx.hygienic_eq(method_name, vd.ident, adt_def.did)
+ });
+ if let Some(variant_def) = variant_def {
+ check_type_alias_enum_variants_enabled(tcx, span);
+
+ let def = Def::VariantCtor(variant_def.did, variant_def.ctor_kind);
+ tcx.check_stability(def.def_id(), Some(expr_id), span);
+ return Ok(def);
}
-
- let def = pick.item.def();
- debug!("resolve_ufcs: def={:?}", def);
- tcx.check_stability(def.def_id(), Some(expr_id), span);
-
- Ok(def)
- }
- Err(err) => {
- // Check if we have an enum variant.
- match self_ty.sty {
- ty::Adt(adt_def, _) if adt_def.is_enum() => {
- let variant_def = adt_def.variants.iter().find(|vd| {
- tcx.hygienic_eq(method_name, vd.ident, adt_def.did)
- });
- if let Some(variant_def) = variant_def {
- check_type_alias_enum_variants_enabled(tcx, span);
-
- let def = Def::VariantCtor(variant_def.did, variant_def.ctor_kind);
- tcx.check_stability(def.def_id(), Some(expr_id), span);
- return Ok(def);
- }
- },
- _ => (),
- }
-
- Err(err)
}
}
+
+ let pick = self.probe_for_name(span, probe::Mode::Path, method_name, IsSuggestion(false),
+ self_ty, expr_id, ProbeScope::TraitsInScope)?;
+ debug!("resolve_ufcs: pick={:?}", pick);
+ if let Some(import_id) = pick.import_id {
+ let import_def_id = tcx.hir().local_def_id(import_id);
+ debug!("resolve_ufcs: used_trait_import: {:?}", import_def_id);
+ Lrc::get_mut(&mut self.tables.borrow_mut().used_trait_imports)
+ .unwrap().insert(import_def_id);
+ }
+
+ let def = pick.item.def();
+ debug!("resolve_ufcs: def={:?}", def);
+ tcx.check_stability(def.def_id(), Some(expr_id), span);
+ Ok(def)
}
/// Find item with name `item_name` defined in impl/trait `def_id`
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 1b07385..452fd24 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -132,7 +132,8 @@
use std::slice;
use require_c_abi_if_variadic;
-use session::{CompileIncomplete, config, Session};
+use session::{CompileIncomplete, Session};
+use session::config::EntryFnType;
use TypeAndSubsts;
use lint;
use util::captures::Captures;
@@ -1163,19 +1164,18 @@
// Check that the main return type implements the termination trait.
if let Some(term_id) = fcx.tcx.lang_items().termination() {
- if let Some((id, _, entry_type)) = *fcx.tcx.sess.entry_fn.borrow() {
- if id == fn_id {
- if let config::EntryFnType::Main = entry_type {
- let substs = fcx.tcx.mk_substs_trait(declared_ret_ty, &[]);
- let trait_ref = ty::TraitRef::new(term_id, substs);
- let return_ty_span = decl.output.span();
- let cause = traits::ObligationCause::new(
- return_ty_span, fn_id, ObligationCauseCode::MainFunctionType);
+ if let Some((def_id, EntryFnType::Main)) = fcx.tcx.entry_fn(LOCAL_CRATE) {
+ let main_id = fcx.tcx.hir().as_local_node_id(def_id).unwrap();
+ if main_id == fn_id {
+ let substs = fcx.tcx.mk_substs_trait(declared_ret_ty, &[]);
+ let trait_ref = ty::TraitRef::new(term_id, substs);
+ let return_ty_span = decl.output.span();
+ let cause = traits::ObligationCause::new(
+ return_ty_span, fn_id, ObligationCauseCode::MainFunctionType);
- inherited.register_predicate(
- traits::Obligation::new(
- cause, param_env, trait_ref.to_predicate()));
- }
+ inherited.register_predicate(
+ traits::Obligation::new(
+ cause, param_env, trait_ref.to_predicate()));
}
}
}
@@ -4724,8 +4724,8 @@
} else {
Def::Err
};
- let (ty, def) = AstConv::associated_path_def_to_ty(self, node_id, path_span,
- ty, def, segment);
+ let (ty, def) = AstConv::associated_path_to_ty(self, node_id, path_span,
+ ty, def, segment, true);
// Write back the new resolution.
let hir_id = self.tcx.hir().node_to_hir_id(node_id);
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 3a546f8..93f14a2 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -715,7 +715,7 @@
// In the case of trait aliases, however, we include all bounds in the where clause,
// so e.g., `trait Foo = where u32: PartialEq<Self>` would include `u32: PartialEq<Self>`
// as one of its "superpredicates".
- let is_trait_alias = ty::is_trait_alias(tcx, trait_def_id);
+ let is_trait_alias = tcx.is_trait_alias(trait_def_id);
let superbounds2 = icx.type_parameter_bounds_in_generics(
generics, item.id, self_param_ty, OnlySelfBounds(!is_trait_alias));
diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs
index 4e3ea5c..c0a8dd8 100644
--- a/src/librustc_typeck/diagnostics.rs
+++ b/src/librustc_typeck/diagnostics.rs
@@ -516,7 +516,7 @@
For a somewhat artificial example:
```compile_fail,E0055
-#![recursion_limit="2"]
+#![recursion_limit="5"]
struct Foo;
@@ -526,9 +526,9 @@
fn main() {
let foo = Foo;
- let ref_foo = &&Foo;
+ let ref_foo = &&&&&Foo;
- // error, reached the recursion limit while auto-dereferencing `&&Foo`
+ // error, reached the recursion limit while auto-dereferencing `&&&&&Foo`
ref_foo.foo();
}
```
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index 8bd484a..6c1c49b 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -103,23 +103,22 @@
mod outlives;
mod variance;
-use hir::Node;
use rustc_target::spec::abi::Abi;
-use rustc::hir;
+use rustc::hir::{self, Node};
+use rustc::hir::def_id::{DefId, LOCAL_CRATE};
use rustc::infer::InferOk;
use rustc::lint;
use rustc::middle;
use rustc::session;
-use rustc::session::config::nightly_options;
+use rustc::session::CompileIncomplete;
+use rustc::session::config::{EntryFnType, nightly_options};
use rustc::traits::{ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt};
use rustc::ty::subst::Substs;
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::query::Providers;
use rustc::util;
use rustc::util::profiling::ProfileCategory;
-use session::{CompileIncomplete, config};
use syntax_pos::Span;
-use syntax::ast;
use util::common::time;
use std::iter;
@@ -184,10 +183,9 @@
})
}
-fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- main_id: ast::NodeId,
- main_span: Span) {
- let main_def_id = tcx.hir().local_def_id(main_id);
+fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, main_def_id: DefId) {
+ let main_id = tcx.hir().as_local_node_id(main_def_id).unwrap();
+ let main_span = tcx.def_span(main_def_id);
let main_t = tcx.type_of(main_def_id);
match main_t.sty {
ty::FnDef(..) => {
@@ -250,10 +248,9 @@
}
}
-fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- start_id: ast::NodeId,
- start_span: Span) {
- let start_def_id = tcx.hir().local_def_id(start_id);
+fn check_start_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, start_def_id: DefId) {
+ let start_id = tcx.hir().as_local_node_id(start_def_id).unwrap();
+ let start_span = tcx.def_span(start_def_id);
let start_t = tcx.type_of(start_def_id);
match start_t.sty {
ty::FnDef(..) => {
@@ -309,11 +306,10 @@
}
fn check_for_entry_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
- if let Some((id, sp, entry_type)) = *tcx.sess.entry_fn.borrow() {
- match entry_type {
- config::EntryFnType::Main => check_main_fn_ty(tcx, id, sp),
- config::EntryFnType::Start => check_start_fn_ty(tcx, id, sp),
- }
+ match tcx.entry_fn(LOCAL_CRATE) {
+ Some((def_id, EntryFnType::Main)) => check_main_fn_ty(tcx, def_id),
+ Some((def_id, EntryFnType::Start)) => check_start_fn_ty(tcx, def_id),
+ _ => {}
}
}
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index d991368..635d071 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -68,6 +68,9 @@
pub should_test: bool,
/// List of arguments to pass to the test harness, if running tests.
pub test_args: Vec<String>,
+ /// Optional path to persist the doctest executables to, defaults to a
+ /// temporary directory if not set.
+ pub persist_doctests: Option<PathBuf>,
// Options that affect the documentation process
@@ -121,6 +124,7 @@
.field("lint_cap", &self.lint_cap)
.field("should_test", &self.should_test)
.field("test_args", &self.test_args)
+ .field("persist_doctests", &self.persist_doctests)
.field("default_passes", &self.default_passes)
.field("manual_passes", &self.manual_passes)
.field("display_warnings", &self.display_warnings)
@@ -431,6 +435,7 @@
let enable_index_page = matches.opt_present("enable-index-page") || index_page.is_some();
let static_root_path = matches.opt_str("static-root-path");
let generate_search_filter = !matches.opt_present("disable-per-crate-search");
+ let persist_doctests = matches.opt_str("persist-doctests").map(PathBuf::from);
let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format);
@@ -456,6 +461,7 @@
manual_passes,
display_warnings,
crate_version,
+ persist_doctests,
render_options: RenderOptions {
output,
external_html,
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 78dbf41..7069f04 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -51,9 +51,6 @@
/// The stack of module NodeIds up till this point
pub crate_name: Option<String>,
pub cstore: Rc<CStore>,
- // Note that external items for which `doc(hidden)` applies to are shown as
- // non-reachable while local items aren't. This is because we're reusing
- // the access levels from crateanalysis.
/// Later on moved into `html::render::CACHE_KEY`
pub renderinfo: RefCell<RenderInfo>,
/// Later on moved through `clean::Crate` into `html::render::CACHE_KEY`
@@ -468,15 +465,13 @@
freevars: resolver.freevars.clone(),
export_map: resolver.export_map.clone(),
trait_map: resolver.trait_map.clone(),
+ glob_map: resolver.glob_map.clone(),
maybe_unused_trait_imports: resolver.maybe_unused_trait_imports.clone(),
maybe_unused_extern_crates: resolver.maybe_unused_extern_crates.clone(),
extern_prelude: resolver.extern_prelude.iter().map(|(ident, entry)| {
(ident.name, entry.introduced_by_item)
}).collect(),
};
- let analysis = ty::CrateAnalysis {
- glob_map: resolver.glob_map.clone(),
- };
let mut arenas = AllArenas::new();
let hir_map = hir_map::map_crate(&sess, &*cstore, &mut hir_forest, &defs);
@@ -492,12 +487,11 @@
&sess,
&*cstore,
hir_map,
- analysis,
resolutions,
&mut arenas,
&name,
&output_filenames,
- |tcx, _, _, result| {
+ |tcx, _, result| {
if result.is_err() {
sess.fatal("Compilation failed, aborting rustdoc");
}
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 3a64c56..ad1659b 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -309,7 +309,7 @@
// Note that external items for which `doc(hidden)` applies to are shown as
// non-reachable while local items aren't. This is because we're reusing
- // the access levels from crateanalysis.
+ // the access levels from the privacy check pass.
pub access_levels: AccessLevels<DefId>,
/// The version of the crate being documented, if given from the `--crate-version` flag.
@@ -1076,7 +1076,7 @@
all_sources.sort();
let mut w = try_err!(File::create(&dst), &dst);
try_err!(writeln!(&mut w,
- "var N = null;var sourcesIndex = {{}};\n{}",
+ "var N = null;var sourcesIndex = {{}};\n{}\ncreateSourceSidebar();",
all_sources.join("\n")),
&dst);
}
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index 8a8b7ad..3676549 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -391,10 +391,6 @@
display: block;
}
-.in-band, code {
- z-index: -5;
-}
-
.invisible {
width: 100%;
display: inline-block;
diff --git a/src/librustdoc/html/static/source-script.js b/src/librustdoc/html/static/source-script.js
index 0affe1c..c5d6fa1 100644
--- a/src/librustdoc/html/static/source-script.js
+++ b/src/librustdoc/html/static/source-script.js
@@ -137,5 +137,3 @@
main.insertBefore(sidebar, main.firstChild);
}
-
-createSourceSidebar();
diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css
index 1390be7..52a3096 100644
--- a/src/librustdoc/html/static/themes/dark.css
+++ b/src/librustdoc/html/static/themes/dark.css
@@ -82,12 +82,6 @@
border-bottom-color: #ddd;
}
-:target { background: #494a3d; }
-
-:target > .in-band {
- background: #494a3d;
-}
-
.content .method .where,
.content .fn .where,
.content .where.fmt-newline {
@@ -252,7 +246,7 @@
color: #999;
}
-:target > code {
+:target > code, :target > .in-band {
background-color: #494a3d;
}
diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css
index 2b04dd2..d20fea6 100644
--- a/src/librustdoc/html/static/themes/light.css
+++ b/src/librustdoc/html/static/themes/light.css
@@ -84,12 +84,6 @@
border-bottom-color: #ddd;
}
-:target { background: #FDFFD3; }
-
-:target > .in-band {
- background: #FDFFD3;
-}
-
.content .method .where,
.content .fn .where,
.content .where.fmt-newline {
@@ -247,7 +241,7 @@
color: #999;
}
-:target > code {
+:target > code, :target > .in-band {
background: #FDFFD3;
}
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 1b6d7e8..4bbc01d 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -341,6 +341,12 @@
"disable-per-crate-search",
"disables generating the crate selector on the search box")
}),
+ unstable("persist-doctests", |o| {
+ o.optopt("",
+ "persist-doctests",
+ "Directory to persist doctest executables into",
+ "PATH")
+ }),
]
}
diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs
index da56194..65a96e9 100644
--- a/src/librustdoc/markdown.rs
+++ b/src/librustdoc/markdown.rs
@@ -142,7 +142,7 @@
options.libs, options.codegen_options, options.externs,
true, opts, options.maybe_sysroot, None,
Some(options.input),
- options.linker, options.edition);
+ options.linker, options.edition, options.persist_doctests);
collector.set_position(DUMMY_SP);
let codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build());
let res = find_testable_code(&input_str, &mut collector, codes);
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index af47c7d..0b9fbc8 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -120,7 +120,8 @@
Some(source_map),
None,
options.linker,
- options.edition
+ options.edition,
+ options.persist_doctests,
);
{
@@ -184,7 +185,8 @@
cg: CodegenOptions, externs: Externs,
should_panic: bool, no_run: bool, as_test_harness: bool,
compile_fail: bool, mut error_codes: Vec<String>, opts: &TestOptions,
- maybe_sysroot: Option<PathBuf>, linker: Option<PathBuf>, edition: Edition) {
+ maybe_sysroot: Option<PathBuf>, linker: Option<PathBuf>, edition: Edition,
+ persist_doctests: Option<PathBuf>) {
// The test harness wants its own `main` and top-level functions, so
// never wrap the test in `fn main() { ... }`.
let (test, line_offset) = make_test(test, Some(cratename), as_test_harness, opts);
@@ -249,6 +251,20 @@
let old = io::set_panic(Some(box Sink(data.clone())));
let _bomb = Bomb(data.clone(), old.unwrap_or(box io::stdout()));
+ enum DirState {
+ Temp(tempfile::TempDir),
+ Perm(PathBuf),
+ }
+
+ impl DirState {
+ fn path(&self) -> &std::path::Path {
+ match self {
+ DirState::Temp(t) => t.path(),
+ DirState::Perm(p) => p.as_path(),
+ }
+ }
+ }
+
let (libdir, outdir, compile_result) = driver::spawn_thread_pool(sessopts, |sessopts| {
let source_map = Lrc::new(SourceMap::new(sessopts.file_path_mapping()));
let emitter = errors::emitter::EmitterWriter::new(box Sink(data.clone()),
@@ -267,7 +283,26 @@
rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
let outdir = Mutex::new(
- TempFileBuilder::new().prefix("rustdoctest").tempdir().expect("rustdoc needs a tempdir")
+ if let Some(mut path) = persist_doctests {
+ path.push(format!("{}_{}",
+ filename
+ .to_string()
+ .rsplit('/')
+ .next()
+ .unwrap()
+ .replace(".", "_"),
+ line)
+ );
+ std::fs::create_dir_all(&path)
+ .expect("Couldn't create directory for doctest executables");
+
+ DirState::Perm(path)
+ } else {
+ DirState::Temp(TempFileBuilder::new()
+ .prefix("rustdoctest")
+ .tempdir()
+ .expect("rustdoc needs a tempdir"))
+ }
);
let libdir = sess.target_filesearch(PathKind::All).get_lib_path();
let mut control = driver::CompileController::basic();
@@ -629,13 +664,15 @@
filename: Option<PathBuf>,
linker: Option<PathBuf>,
edition: Edition,
+ persist_doctests: Option<PathBuf>,
}
impl Collector {
pub fn new(cratename: String, cfgs: Vec<String>, libs: Vec<SearchPath>, cg: CodegenOptions,
externs: Externs, use_headers: bool, opts: TestOptions,
maybe_sysroot: Option<PathBuf>, source_map: Option<Lrc<SourceMap>>,
- filename: Option<PathBuf>, linker: Option<PathBuf>, edition: Edition) -> Collector {
+ filename: Option<PathBuf>, linker: Option<PathBuf>, edition: Edition,
+ persist_doctests: Option<PathBuf>) -> Collector {
Collector {
tests: Vec::new(),
names: Vec::new(),
@@ -652,6 +689,7 @@
filename,
linker,
edition,
+ persist_doctests,
}
}
@@ -695,6 +733,8 @@
let maybe_sysroot = self.maybe_sysroot.clone();
let linker = self.linker.clone();
let edition = config.edition.unwrap_or(self.edition);
+ let persist_doctests = self.persist_doctests.clone();
+
debug!("Creating test {}: {}", name, test);
self.tests.push(testing::TestDescAndFn {
desc: testing::TestDesc {
@@ -727,7 +767,8 @@
&opts,
maybe_sysroot,
linker,
- edition)
+ edition,
+ persist_doctests)
}))
} {
Ok(()) => (),
diff --git a/src/libstd/ffi/mod.rs b/src/libstd/ffi/mod.rs
index 62081e7..7a38f0e 100644
--- a/src/libstd/ffi/mod.rs
+++ b/src/libstd/ffi/mod.rs
@@ -169,7 +169,7 @@
#[unstable(feature = "c_variadic",
reason = "the `c_variadic` feature has not been properly tested on \
all supported platforms",
- issue = "27745")]
+ issue = "44930")]
pub use core::ffi::VaList;
mod c_str;
diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs
index 119b3f7..3538816 100644
--- a/src/libstd/fs.rs
+++ b/src/libstd/fs.rs
@@ -1121,7 +1121,9 @@
/// writing.
///
/// This operation does **not** modify the filesystem. To modify the
- /// filesystem use the `fs::set_permissions` function.
+ /// filesystem use the [`fs::set_permissions`] function.
+ ///
+ /// [`fs::set_permissions`]: fn.set_permissions.html
///
/// # Examples
///
@@ -1639,10 +1641,15 @@
///
/// The `dst` path will be a symbolic link pointing to the `src` path.
/// On Windows, this will be a file symlink, not a directory symlink;
-/// for this reason, the platform-specific `std::os::unix::fs::symlink`
-/// and `std::os::windows::fs::{symlink_file, symlink_dir}` should be
+/// for this reason, the platform-specific [`std::os::unix::fs::symlink`]
+/// and [`std::os::windows::fs::symlink_file`] or [`symlink_dir`] should be
/// used instead to make the intent explicit.
///
+/// [`std::os::unix::fs::symlink`]: ../os/unix/fs/fn.symlink.html
+/// [`std::os::windows::fs::symlink_file`]: ../os/windows/fs/fn.symlink_file.html
+/// [`symlink_dir`]: ../os/windows/fs/fn.symlink_dir.html
+///
+///
/// # Examples
///
/// ```no_run
@@ -1795,7 +1802,7 @@
/// * If any directory in the path specified by `path`
/// does not already exist and it could not be created otherwise. The specific
/// error conditions for when a directory is being created (after it is
-/// determined to not exist) are outlined by `fs::create_dir`.
+/// determined to not exist) are outlined by [`fs::create_dir`].
///
/// Notable exception is made for situations where any of the directories
/// specified in the `path` could not be created as it was being created concurrently.
@@ -1803,6 +1810,8 @@
/// concurrently from multiple threads or processes is guaranteed not to fail
/// due to a race condition with itself.
///
+/// [`fs::create_dir`]: fn.create_dir.html
+///
/// # Examples
///
/// ```no_run
@@ -1868,7 +1877,10 @@
///
/// # Errors
///
-/// See `file::remove_file` and `fs::remove_dir`.
+/// See [`fs::remove_file`] and [`fs::remove_dir`].
+///
+/// [`fs::remove_file`]: fn.remove_file.html
+/// [`fs::remove_dir`]: fn.remove_dir.html
///
/// # Examples
///
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 41f1ac8..83db3f3 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -286,6 +286,7 @@
#![feature(staged_api)]
#![feature(stmt_expr_attributes)]
#![feature(str_internals)]
+#![feature(renamed_spin_loop)]
#![feature(rustc_private)]
#![feature(thread_local)]
#![feature(toowned_clone_into)]
diff --git a/src/libstd/prelude/mod.rs b/src/libstd/prelude/mod.rs
index ec8318f..bf689ba 100644
--- a/src/libstd/prelude/mod.rs
+++ b/src/libstd/prelude/mod.rs
@@ -44,8 +44,8 @@
//! The current version of the prelude (version 1) lives in
//! [`std::prelude::v1`], and re-exports the following.
//!
-//! * [`std::marker`]::{[`Copy`], [`Send`], [`Sized`], [`Sync`]}. The marker
-//! traits indicate fundamental properties of types.
+//! * [`std::marker`]::{[`Copy`], [`Send`], [`Sized`], [`Sync`], [`Unpin`]}. The
+//! marker traits indicate fundamental properties of types.
//! * [`std::ops`]::{[`Drop`], [`Fn`], [`FnMut`], [`FnOnce`]}. Various
//! operations for both destructors and overloading `()`.
//! * [`std::mem`]::[`drop`][`mem::drop`], a convenience function for explicitly
@@ -108,6 +108,7 @@
//! [`Sync`]: ../marker/trait.Sync.html
//! [`ToOwned`]: ../borrow/trait.ToOwned.html
//! [`ToString`]: ../string/trait.ToString.html
+//! [`Unpin`]: ../marker/trait.Unpin.html
//! [`Vec`]: ../vec/struct.Vec.html
//! [`Clone::clone`]: ../clone/trait.Clone.html#tymethod.clone
//! [`mem::drop`]: ../mem/fn.drop.html
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 99ab9fb..bbcaaac 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -15,7 +15,7 @@
use source_map::{dummy_spanned, respan, Spanned};
use symbol::{keywords, Symbol};
use syntax_pos::{Span, DUMMY_SP};
-use tokenstream::{ThinTokenStream, TokenStream};
+use tokenstream::TokenStream;
use ThinVec;
use rustc_data_structures::fx::FxHashSet;
@@ -1216,7 +1216,7 @@
pub struct Mac_ {
pub path: Path,
pub delim: MacDelimiter,
- pub tts: ThinTokenStream,
+ pub tts: TokenStream,
}
#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)]
@@ -1228,13 +1228,13 @@
impl Mac_ {
pub fn stream(&self) -> TokenStream {
- self.tts.stream()
+ self.tts.clone()
}
}
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct MacroDef {
- pub tokens: ThinTokenStream,
+ pub tokens: TokenStream,
pub legacy: bool,
}
diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs
index f83c1ec..f6d7590 100644
--- a/src/libsyntax/attr/mod.rs
+++ b/src/libsyntax/attr/mod.rs
@@ -570,7 +570,7 @@
}
Some(TokenTree::Delimited(_, delim, ref tts)) if delim == token::Paren => {
tokens.next();
- tts.stream()
+ tts.clone()
}
_ => return Some(MetaItemKind::Word),
};
diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs
index c312414..c01e7f5 100644
--- a/src/libsyntax/ext/quote.rs
+++ b/src/libsyntax/ext/quote.rs
@@ -748,7 +748,7 @@
},
TokenTree::Delimited(span, delim, ref tts) => {
let mut stmts = statements_mk_tt(cx, &TokenTree::open_tt(span.open, delim), false);
- stmts.extend(statements_mk_tts(cx, tts.stream()));
+ stmts.extend(statements_mk_tts(cx, tts.clone()));
stmts.extend(statements_mk_tt(cx, &TokenTree::close_tt(span.close, delim), false));
stmts
}
diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs
index 24202ca..9a129e7 100644
--- a/src/libsyntax/ext/tt/macro_rules.rs
+++ b/src/libsyntax/ext/tt/macro_rules.rs
@@ -435,7 +435,8 @@
match *seq_tt {
TokenTree::MetaVarDecl(_, _, id) => id.name == "vis",
TokenTree::Sequence(_, ref sub_seq) =>
- sub_seq.op == quoted::KleeneOp::ZeroOrMore,
+ sub_seq.op == quoted::KleeneOp::ZeroOrMore
+ || sub_seq.op == quoted::KleeneOp::ZeroOrOne,
_ => false,
}
}) {
@@ -543,7 +544,10 @@
}
// Reverse scan: Sequence comes before `first`.
- if subfirst.maybe_empty || seq_rep.op == quoted::KleeneOp::ZeroOrMore {
+ if subfirst.maybe_empty
+ || seq_rep.op == quoted::KleeneOp::ZeroOrMore
+ || seq_rep.op == quoted::KleeneOp::ZeroOrOne
+ {
// If sequence is potentially empty, then
// union them (preserving first emptiness).
first.add_all(&TokenSet { maybe_empty: true, ..subfirst });
@@ -591,8 +595,10 @@
assert!(first.maybe_empty);
first.add_all(subfirst);
- if subfirst.maybe_empty ||
- seq_rep.op == quoted::KleeneOp::ZeroOrMore {
+ if subfirst.maybe_empty
+ || seq_rep.op == quoted::KleeneOp::ZeroOrMore
+ || seq_rep.op == quoted::KleeneOp::ZeroOrOne
+ {
// continue scanning for more first
// tokens, but also make sure we
// restore empty-tracking state
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 8ac1038..a4c3b38 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -598,7 +598,7 @@
TokenTree::Delimited(span, delim, tts) => TokenTree::Delimited(
DelimSpan::from_pair(fld.new_span(span.open), fld.new_span(span.close)),
delim,
- fld.fold_tts(tts.stream()).into(),
+ fld.fold_tts(tts).into(),
),
}
}
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index ea20553..ddb350f 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -817,7 +817,7 @@
)
if name_macro_rules.name == "macro_rules"
&& name_zip.name == "zip" => {
- let tts = ¯o_tts.stream().trees().collect::<Vec<_>>();
+ let tts = ¯o_tts.trees().collect::<Vec<_>>();
match (tts.len(), tts.get(0), tts.get(1), tts.get(2)) {
(
3,
@@ -826,7 +826,7 @@
Some(&TokenTree::Delimited(_, second_delim, ref second_tts)),
)
if macro_delim == token::Paren => {
- let tts = &first_tts.stream().trees().collect::<Vec<_>>();
+ let tts = &first_tts.trees().collect::<Vec<_>>();
match (tts.len(), tts.get(0), tts.get(1)) {
(
2,
@@ -836,7 +836,7 @@
if first_delim == token::Paren && ident.name == "a" => {},
_ => panic!("value 3: {:?} {:?}", first_delim, first_tts),
}
- let tts = &second_tts.stream().trees().collect::<Vec<_>>();
+ let tts = &second_tts.trees().collect::<Vec<_>>();
match (tts.len(), tts.get(0), tts.get(1)) {
(
2,
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 823c786..7e15b231 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -46,7 +46,7 @@
use ptr::P;
use parse::PResult;
use ThinVec;
-use tokenstream::{self, DelimSpan, ThinTokenStream, TokenTree, TokenStream};
+use tokenstream::{self, DelimSpan, TokenTree, TokenStream, TreeAndJoint};
use symbol::{Symbol, keywords};
use std::borrow::Cow;
@@ -280,17 +280,17 @@
/// on the parser.
#[derive(Clone)]
enum LastToken {
- Collecting(Vec<TokenStream>),
- Was(Option<TokenStream>),
+ Collecting(Vec<TreeAndJoint>),
+ Was(Option<TreeAndJoint>),
}
impl TokenCursorFrame {
- fn new(sp: DelimSpan, delim: DelimToken, tts: &ThinTokenStream) -> Self {
+ fn new(sp: DelimSpan, delim: DelimToken, tts: &TokenStream) -> Self {
TokenCursorFrame {
delim: delim,
span: sp,
open_delim: delim == token::NoDelim,
- tree_cursor: tts.stream().into_trees(),
+ tree_cursor: tts.clone().into_trees(),
close_delim: delim == token::NoDelim,
last_token: LastToken::Was(None),
}
@@ -2330,7 +2330,7 @@
})
}
- fn expect_delimited_token_tree(&mut self) -> PResult<'a, (MacDelimiter, ThinTokenStream)> {
+ fn expect_delimited_token_tree(&mut self) -> PResult<'a, (MacDelimiter, TokenStream)> {
let delim = match self.token {
token::OpenDelim(delim) => delim,
_ => {
@@ -2350,7 +2350,7 @@
token::Brace => MacDelimiter::Brace,
token::NoDelim => self.bug("unexpected no delimiter"),
};
- Ok((delim, tts.stream().into()))
+ Ok((delim, tts.into()))
}
/// At the bottom (top?) of the precedence hierarchy,
@@ -4063,12 +4063,13 @@
if let Some(mut err) = delayed_err {
if let Some(etc_span) = etc_span {
- err.multipart_suggestion(
+ err.multipart_suggestion_with_applicability(
"move the `..` to the end of the field list",
vec![
(etc_span, String::new()),
(self.span, format!("{}.. }}", if ate_comma { "" } else { ", " })),
],
+ Applicability::MachineApplicable,
);
}
err.emit();
@@ -4641,7 +4642,7 @@
let ident = self.parse_ident()?;
let tokens = if self.check(&token::OpenDelim(token::Brace)) {
match self.parse_token_tree() {
- TokenTree::Delimited(_, _, tts) => tts.stream(),
+ TokenTree::Delimited(_, _, tts) => tts,
_ => unreachable!(),
}
} else if self.check(&token::OpenDelim(token::Paren)) {
@@ -5234,22 +5235,13 @@
kind: ast::GenericParamKind::Lifetime,
});
if let Some(sp) = seen_ty_param {
- let param_span = self.prev_span;
- let ate_comma = self.eat(&token::Comma);
- let remove_sp = if ate_comma {
- param_span.until(self.span)
- } else {
- last_comma_span.unwrap_or(param_span).to(param_span)
- };
- bad_lifetime_pos.push(param_span);
-
- if let Ok(snippet) = self.sess.source_map().span_to_snippet(param_span) {
+ let remove_sp = last_comma_span.unwrap_or(self.prev_span).to(self.prev_span);
+ bad_lifetime_pos.push(self.prev_span);
+ if let Ok(snippet) = self.sess.source_map().span_to_snippet(self.prev_span) {
suggestions.push((remove_sp, String::new()));
- suggestions.push((sp.shrink_to_lo(), format!("{}, ", snippet)));
- }
- if ate_comma {
- last_comma_span = Some(self.prev_span);
- continue
+ suggestions.push((
+ sp.shrink_to_lo(),
+ format!("{}, ", snippet)));
}
}
} else if self.check_ident() {
@@ -6913,7 +6905,11 @@
let mut err = self.struct_span_err(fixed_name_sp, error_msg);
err.span_label(fixed_name_sp, "dash-separated idents are not valid");
- err.multipart_suggestion(suggestion_msg, replacement);
+ err.multipart_suggestion_with_applicability(
+ suggestion_msg,
+ replacement,
+ Applicability::MachineApplicable,
+ );
err.emit();
}
Ok(ident)
@@ -7766,7 +7762,7 @@
&mut self.token_cursor.stack[prev].last_token
};
- // Pull our the toekns that we've collected from the call to `f` above
+ // Pull out the tokens that we've collected from the call to `f` above.
let mut collected_tokens = match *last_token {
LastToken::Collecting(ref mut v) => mem::replace(v, Vec::new()),
LastToken::Was(_) => panic!("our vector went away?"),
@@ -7785,10 +7781,9 @@
// call. In that case we need to record all the tokens we collected in
// our parent list as well. To do that we push a clone of our stream
// onto the previous list.
- let stream = collected_tokens.into_iter().collect::<TokenStream>();
match prev_collecting {
Some(mut list) => {
- list.push(stream.clone());
+ list.extend(collected_tokens.iter().cloned());
list.extend(extra_token);
*last_token = LastToken::Collecting(list);
}
@@ -7797,7 +7792,7 @@
}
}
- Ok((ret?, stream))
+ Ok((ret?, TokenStream::new(collected_tokens)))
}
pub fn parse_item(&mut self) -> PResult<'a, Option<P<Item>>> {
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 2ad3d3a..c535940 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -807,7 +807,7 @@
TokenTree::Delimited(_, delim, tts) => {
self.writer().word(token_to_string(&token::OpenDelim(delim)))?;
self.writer().space()?;
- self.print_tts(tts.stream())?;
+ self.print_tts(tts)?;
self.writer().space()?;
self.writer().word(token_to_string(&token::CloseDelim(delim)))
},
diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs
index fb72ef9..f5d2d6f 100644
--- a/src/libsyntax/tokenstream.rs
+++ b/src/libsyntax/tokenstream.rs
@@ -41,7 +41,7 @@
/// A single token
Token(Span, token::Token),
/// A delimited sequence of token trees
- Delimited(DelimSpan, DelimToken, ThinTokenStream),
+ Delimited(DelimSpan, DelimToken, TokenStream),
}
impl TokenTree {
@@ -62,8 +62,7 @@
(&TokenTree::Token(_, ref tk), &TokenTree::Token(_, ref tk2)) => tk == tk2,
(&TokenTree::Delimited(_, delim, ref tts),
&TokenTree::Delimited(_, delim2, ref tts2)) => {
- delim == delim2 &&
- tts.stream().eq_unspanned(&tts2.stream())
+ delim == delim2 && tts.eq_unspanned(&tts2)
}
(_, _) => false,
}
@@ -81,8 +80,7 @@
}
(&TokenTree::Delimited(_, delim, ref tts),
&TokenTree::Delimited(_, delim2, ref tts2)) => {
- delim == delim2 &&
- tts.stream().probably_equal_for_proc_macro(&tts2.stream())
+ delim == delim2 && tts.probably_equal_for_proc_macro(&tts2)
}
(_, _) => false,
}
@@ -113,7 +111,7 @@
}
pub fn joint(self) -> TokenStream {
- TokenStream::Tree(self, Joint)
+ TokenStream::new(vec![(self, Joint)])
}
/// Returns the opening delimiter as a token tree.
@@ -143,18 +141,19 @@
/// The goal is for procedural macros to work with `TokenStream`s and `TokenTree`s
/// instead of a representation of the abstract syntax tree.
/// Today's `TokenTree`s can still contain AST via `Token::Interpolated` for back-compat.
+///
+/// The use of `Option` is an optimization that avoids the need for an
+/// allocation when the stream is empty. However, it is not guaranteed that an
+/// empty stream is represented with `None`; it may be represented as a `Some`
+/// around an empty `Vec`.
#[derive(Clone, Debug)]
-pub enum TokenStream {
- Empty,
- Tree(TokenTree, IsJoint),
- Stream(Lrc<Vec<TreeAndJoint>>),
-}
+pub struct TokenStream(Option<Lrc<Vec<TreeAndJoint>>>);
pub type TreeAndJoint = (TokenTree, IsJoint);
// `TokenStream` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(target_arch = "x86_64")]
-static_assert!(MEM_SIZE_OF_TOKEN_STREAM: mem::size_of::<TokenStream>() == 32);
+static_assert!(MEM_SIZE_OF_TOKEN_STREAM: mem::size_of::<TokenStream>() == 8);
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum IsJoint {
@@ -169,7 +168,7 @@
/// separating the two arguments with a comma for diagnostic suggestions.
pub(crate) fn add_comma(&self) -> Option<(TokenStream, Span)> {
// Used to suggest if a user writes `foo!(a b);`
- if let TokenStream::Stream(ref stream) = self {
+ if let Some(ref stream) = self.0 {
let mut suggestion = None;
let mut iter = stream.iter().enumerate().peekable();
while let Some((pos, ts)) = iter.next() {
@@ -201,7 +200,7 @@
impl From<TokenTree> for TokenStream {
fn from(tree: TokenTree) -> TokenStream {
- TokenStream::Tree(tree, NonJoint)
+ TokenStream::new(vec![(tree, NonJoint)])
}
}
@@ -233,7 +232,7 @@
impl TokenStream {
pub fn len(&self) -> usize {
- if let TokenStream::Stream(ref slice) = self {
+ if let Some(ref slice) = self.0 {
slice.len()
} else {
0
@@ -241,13 +240,13 @@
}
pub fn empty() -> TokenStream {
- TokenStream::Empty
+ TokenStream(None)
}
pub fn is_empty(&self) -> bool {
- match self {
- TokenStream::Empty => true,
- _ => false,
+ match self.0 {
+ None => true,
+ Some(ref stream) => stream.is_empty(),
}
}
@@ -258,10 +257,9 @@
_ => {
let mut vec = vec![];
for stream in streams {
- match stream {
- TokenStream::Empty => {},
- TokenStream::Tree(tree, is_joint) => vec.push((tree, is_joint)),
- TokenStream::Stream(stream2) => vec.extend(stream2.iter().cloned()),
+ match stream.0 {
+ None => {},
+ Some(stream2) => vec.extend(stream2.iter().cloned()),
}
}
TokenStream::new(vec)
@@ -269,22 +267,16 @@
}
}
- pub fn new(mut streams: Vec<TreeAndJoint>) -> TokenStream {
+ pub fn new(streams: Vec<TreeAndJoint>) -> TokenStream {
match streams.len() {
- 0 => TokenStream::empty(),
- 1 => {
- let (tree, is_joint) = streams.pop().unwrap();
- TokenStream::Tree(tree, is_joint)
- }
- _ => TokenStream::Stream(Lrc::new(streams)),
+ 0 => TokenStream(None),
+ _ => TokenStream(Some(Lrc::new(streams))),
}
}
pub fn append_to_tree_and_joint_vec(self, vec: &mut Vec<TreeAndJoint>) {
- match self {
- TokenStream::Empty => {}
- TokenStream::Tree(tree, is_joint) => vec.push((tree, is_joint)),
- TokenStream::Stream(stream) => vec.extend(stream.iter().cloned()),
+ if let Some(stream) = self.0 {
+ vec.extend(stream.iter().cloned());
}
}
@@ -349,51 +341,36 @@
}
pub fn map_enumerated<F: FnMut(usize, TokenTree) -> TokenTree>(self, mut f: F) -> TokenStream {
- match self {
- TokenStream::Empty => TokenStream::Empty,
- TokenStream::Tree(tree, is_joint) => TokenStream::Tree(f(0, tree), is_joint),
- TokenStream::Stream(stream) => TokenStream::Stream(Lrc::new(
+ TokenStream(self.0.map(|stream| {
+ Lrc::new(
stream
.iter()
.enumerate()
.map(|(i, (tree, is_joint))| (f(i, tree.clone()), *is_joint))
- .collect()
- )),
- }
+ .collect())
+ }))
}
pub fn map<F: FnMut(TokenTree) -> TokenTree>(self, mut f: F) -> TokenStream {
- match self {
- TokenStream::Empty => TokenStream::Empty,
- TokenStream::Tree(tree, is_joint) => TokenStream::Tree(f(tree), is_joint),
- TokenStream::Stream(stream) => TokenStream::Stream(Lrc::new(
+ TokenStream(self.0.map(|stream| {
+ Lrc::new(
stream
.iter()
.map(|(tree, is_joint)| (f(tree.clone()), *is_joint))
- .collect()
- )),
- }
+ .collect())
+ }))
}
- fn first_tree_and_joint(&self) -> Option<(TokenTree, IsJoint)> {
- match self {
- TokenStream::Empty => None,
- TokenStream::Tree(ref tree, is_joint) => Some((tree.clone(), *is_joint)),
- TokenStream::Stream(ref stream) => Some(stream.first().unwrap().clone())
- }
+ fn first_tree_and_joint(&self) -> Option<TreeAndJoint> {
+ self.0.as_ref().map(|stream| {
+ stream.first().unwrap().clone()
+ })
}
fn last_tree_if_joint(&self) -> Option<TokenTree> {
- match self {
- TokenStream::Empty => None,
- TokenStream::Tree(ref tree, is_joint) => {
- if *is_joint == Joint {
- Some(tree.clone())
- } else {
- None
- }
- }
- TokenStream::Stream(ref stream) => {
+ match self.0 {
+ None => None,
+ Some(ref stream) => {
if let (tree, Joint) = stream.last().unwrap() {
Some(tree.clone())
} else {
@@ -422,7 +399,7 @@
self.push_all_but_last_tree(&last_stream);
let glued_span = last_span.to(span);
let glued_tt = TokenTree::Token(glued_span, glued_tok);
- let glued_tokenstream = TokenStream::Tree(glued_tt, is_joint);
+ let glued_tokenstream = TokenStream::new(vec![(glued_tt, is_joint)]);
self.0.push(glued_tokenstream);
self.push_all_but_first_tree(&stream);
return
@@ -437,23 +414,21 @@
}
fn push_all_but_last_tree(&mut self, stream: &TokenStream) {
- if let TokenStream::Stream(ref streams) = stream {
+ if let Some(ref streams) = stream.0 {
let len = streams.len();
match len {
1 => {}
- 2 => self.0.push(TokenStream::Tree(streams[0].0.clone(), streams[0].1)),
- _ => self.0.push(TokenStream::Stream(Lrc::new(streams[0 .. len - 1].to_vec()))),
+ _ => self.0.push(TokenStream(Some(Lrc::new(streams[0 .. len - 1].to_vec())))),
}
}
}
fn push_all_but_first_tree(&mut self, stream: &TokenStream) {
- if let TokenStream::Stream(ref streams) = stream {
+ if let Some(ref streams) = stream.0 {
let len = streams.len();
match len {
1 => {}
- 2 => self.0.push(TokenStream::Tree(streams[1].0.clone(), streams[1].1)),
- _ => self.0.push(TokenStream::Stream(Lrc::new(streams[1 .. len].to_vec()))),
+ _ => self.0.push(TokenStream(Some(Lrc::new(streams[1 .. len].to_vec())))),
}
}
}
@@ -479,17 +454,9 @@
}
pub fn next_with_joint(&mut self) -> Option<TreeAndJoint> {
- match self.stream {
- TokenStream::Empty => None,
- TokenStream::Tree(ref tree, ref is_joint) => {
- if self.index == 0 {
- self.index = 1;
- Some((tree.clone(), *is_joint))
- } else {
- None
- }
- }
- TokenStream::Stream(ref stream) => {
+ match self.stream.0 {
+ None => None,
+ Some(ref stream) => {
if self.index < stream.len() {
self.index += 1;
Some(stream[self.index - 1].clone())
@@ -505,63 +472,19 @@
return;
}
let index = self.index;
- let stream = mem::replace(&mut self.stream, TokenStream::Empty);
+ let stream = mem::replace(&mut self.stream, TokenStream(None));
*self = TokenStream::from_streams(vec![stream, new_stream]).into_trees();
self.index = index;
}
pub fn look_ahead(&self, n: usize) -> Option<TokenTree> {
- match self.stream {
- TokenStream::Empty => None,
- TokenStream::Tree(ref tree, _) => {
- if n == 0 && self.index == 0 {
- Some(tree.clone())
- } else {
- None
- }
- }
- TokenStream::Stream(ref stream) =>
- stream[self.index ..].get(n).map(|(tree, _)| tree.clone()),
+ match self.stream.0 {
+ None => None,
+ Some(ref stream) => stream[self.index ..].get(n).map(|(tree, _)| tree.clone()),
}
}
}
-/// The `TokenStream` type is large enough to represent a single `TokenTree` without allocation.
-/// `ThinTokenStream` is smaller, but needs to allocate to represent a single `TokenTree`.
-/// We must use `ThinTokenStream` in `TokenTree::Delimited` to avoid infinite size due to recursion.
-#[derive(Debug, Clone)]
-pub struct ThinTokenStream(Option<Lrc<Vec<TreeAndJoint>>>);
-
-impl ThinTokenStream {
- pub fn stream(&self) -> TokenStream {
- self.clone().into()
- }
-}
-
-impl From<TokenStream> for ThinTokenStream {
- fn from(stream: TokenStream) -> ThinTokenStream {
- ThinTokenStream(match stream {
- TokenStream::Empty => None,
- TokenStream::Tree(tree, is_joint) => Some(Lrc::new(vec![(tree, is_joint)])),
- TokenStream::Stream(stream) => Some(stream),
- })
- }
-}
-
-impl From<ThinTokenStream> for TokenStream {
- fn from(stream: ThinTokenStream) -> TokenStream {
- stream.0.map(TokenStream::Stream).unwrap_or_else(TokenStream::empty)
- }
-}
-
-impl Eq for ThinTokenStream {}
-
-impl PartialEq<ThinTokenStream> for ThinTokenStream {
- fn eq(&self, other: &ThinTokenStream) -> bool {
- TokenStream::from(self.clone()) == TokenStream::from(other.clone())
- }
-}
-
impl fmt::Display for TokenStream {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(&pprust::tokens_to_string(self.clone()))
@@ -580,18 +503,6 @@
}
}
-impl Encodable for ThinTokenStream {
- fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), E::Error> {
- TokenStream::from(self.clone()).encode(encoder)
- }
-}
-
-impl Decodable for ThinTokenStream {
- fn decode<D: Decoder>(decoder: &mut D) -> Result<ThinTokenStream, D::Error> {
- TokenStream::decode(decoder).map(Into::into)
- }
-}
-
#[derive(Debug, Copy, Clone, PartialEq, RustcEncodable, RustcDecodable)]
pub struct DelimSpan {
pub open: Span,
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 156546b..8cbd47c 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -832,7 +832,7 @@
pub fn walk_tt<'a, V: Visitor<'a>>(visitor: &mut V, tt: TokenTree) {
match tt {
TokenTree::Token(_, tok) => visitor.visit_token(tok),
- TokenTree::Delimited(_, _, tts) => visitor.visit_tts(tts.stream()),
+ TokenTree::Delimited(_, _, tts) => visitor.visit_tts(tts),
}
}
diff --git a/src/libsyntax_ext/proc_macro_server.rs b/src/libsyntax_ext/proc_macro_server.rs
index 158cbc7..7de9b93 100644
--- a/src/libsyntax_ext/proc_macro_server.rs
+++ b/src/libsyntax_ext/proc_macro_server.rs
@@ -269,7 +269,7 @@
};
let tree = tokenstream::TokenTree::Token(span, token);
- TokenStream::Tree(tree, if joint { Joint } else { NonJoint })
+ TokenStream::new(vec![(tree, if joint { Joint } else { NonJoint })])
}
}
diff --git a/src/test/incremental/change_name_of_static_in_fn.rs b/src/test/incremental/change_name_of_static_in_fn.rs
new file mode 100644
index 0000000..5b27b68
--- /dev/null
+++ b/src/test/incremental/change_name_of_static_in_fn.rs
@@ -0,0 +1,17 @@
+
+// revisions:rpass1 rpass2 rpass3
+
+// See issue #57692.
+
+#![allow(warnings)]
+
+fn main() {
+ #[cfg(rpass1)]
+ {
+ static map: u64 = 0;
+ }
+ #[cfg(not(rpass1))]
+ {
+ static MAP: u64 = 0;
+ }
+}
diff --git a/src/test/run-pass/weird-exprs.rs b/src/test/run-pass/weird-exprs.rs
index 6d0c5c1..7ce7e29 100644
--- a/src/test/run-pass/weird-exprs.rs
+++ b/src/test/run-pass/weird-exprs.rs
@@ -4,7 +4,7 @@
#![allow(unused_parens)]
// compile-flags: -Z borrowck=compare
-#![recursion_limit = "128"]
+#![recursion_limit = "256"]
use std::cell::Cell;
use std::mem::swap;
diff --git a/src/test/rustdoc-ui/failed-doctest-output.stdout b/src/test/rustdoc-ui/failed-doctest-output.stdout
index d584845..8af05e9 100644
--- a/src/test/rustdoc-ui/failed-doctest-output.stdout
+++ b/src/test/rustdoc-ui/failed-doctest-output.stdout
@@ -12,7 +12,7 @@
3 | no
| ^^ not found in this scope
-thread '$DIR/failed-doctest-output.rs - OtherStruct (line 17)' panicked at 'couldn't compile the test', src/librustdoc/test.rs:319:13
+thread '$DIR/failed-doctest-output.rs - OtherStruct (line 17)' panicked at 'couldn't compile the test', src/librustdoc/test.rs:354:13
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
---- $DIR/failed-doctest-output.rs - SomeStruct (line 11) stdout ----
@@ -21,7 +21,7 @@
thread 'main' panicked at 'oh no', $DIR/failed-doctest-output.rs:3:1
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
-', src/librustdoc/test.rs:354:17
+', src/librustdoc/test.rs:389:17
failures:
diff --git a/src/test/rustdoc/issue-56701.rs b/src/test/rustdoc/issue-56701.rs
new file mode 100644
index 0000000..6fb30a4
--- /dev/null
+++ b/src/test/rustdoc/issue-56701.rs
@@ -0,0 +1,34 @@
+// This shouldn't cause a stack overflow when rustdoc is run
+
+use std::ops::Deref;
+use std::ops::DerefMut;
+
+pub trait SimpleTrait {
+ type SimpleT;
+}
+
+impl<Inner: SimpleTrait, Outer: Deref<Target = Inner>> SimpleTrait for Outer {
+ type SimpleT = Inner::SimpleT;
+}
+
+pub trait AnotherTrait {
+ type AnotherT;
+}
+
+impl<T, Simple: SimpleTrait<SimpleT = Vec<T>>> AnotherTrait for Simple {
+ type AnotherT = T;
+}
+
+pub struct Unrelated<Inner, UnrelatedT: DerefMut<Target = Vec<Inner>>>(UnrelatedT);
+
+impl<Inner, UnrelatedT: DerefMut<Target = Vec<Inner>>> Deref for Unrelated<Inner, UnrelatedT> {
+ type Target = Vec<Inner>;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+
+pub fn main() { }
+
diff --git a/src/test/ui/did_you_mean/recursion_limit.stderr b/src/test/ui/did_you_mean/recursion_limit.stderr
index 08947fd..0738c3f 100644
--- a/src/test/ui/did_you_mean/recursion_limit.stderr
+++ b/src/test/ui/did_you_mean/recursion_limit.stderr
@@ -1,11 +1,10 @@
-error[E0275]: overflow evaluating the requirement `K: std::marker::Send`
+error[E0275]: overflow evaluating the requirement `J: std::marker::Send`
--> $DIR/recursion_limit.rs:34:5
|
LL | is_send::<A>(); //~ ERROR overflow evaluating the requirement
| ^^^^^^^^^^^^
|
= help: consider adding a `#![recursion_limit="20"]` attribute to your crate
- = note: required because it appears within the type `J`
= note: required because it appears within the type `I`
= note: required because it appears within the type `H`
= note: required because it appears within the type `G`
diff --git a/src/test/ui/error-codes/E0055.rs b/src/test/ui/error-codes/E0055.rs
index a3ade92..b525575 100644
--- a/src/test/ui/error-codes/E0055.rs
+++ b/src/test/ui/error-codes/E0055.rs
@@ -1,4 +1,4 @@
-#![recursion_limit="2"]
+#![recursion_limit="5"]
struct Foo;
impl Foo {
@@ -7,7 +7,7 @@
fn main() {
let foo = Foo;
- let ref_foo = &&Foo;
+ let ref_foo = &&&&&Foo;
ref_foo.foo();
//~^ ERROR E0055
}
diff --git a/src/test/ui/error-codes/E0055.stderr b/src/test/ui/error-codes/E0055.stderr
index cd2bd92..d06566f 100644
--- a/src/test/ui/error-codes/E0055.stderr
+++ b/src/test/ui/error-codes/E0055.stderr
@@ -4,7 +4,7 @@
LL | ref_foo.foo();
| ^^^ deref recursion limit reached
|
- = help: consider adding a `#![recursion_limit="4"]` attribute to your crate
+ = help: consider adding a `#![recursion_limit="10"]` attribute to your crate
error: aborting due to previous error
diff --git a/src/test/ui/error-codes/E0275.stderr b/src/test/ui/error-codes/E0275.stderr
index 817b482..f2b0f39 100644
--- a/src/test/ui/error-codes/E0275.stderr
+++ b/src/test/ui/error-codes/E0275.stderr
@@ -1,11 +1,10 @@
-error[E0275]: overflow evaluating the requirement `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: std::marker::Sized`
+error[E0275]: overflow evaluating the requirement `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Foo`
--> $DIR/E0275.rs:5:1
|
LL | impl<T> Foo for T where Bar<T>: Foo {} //~ ERROR E0275
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider adding a `#![recursion_limit="128"]` attribute to your crate
- = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
diff --git a/src/test/ui/error-codes/E0423.stderr b/src/test/ui/error-codes/E0423.stderr
index c422a1e..d0deb8c 100644
--- a/src/test/ui/error-codes/E0423.stderr
+++ b/src/test/ui/error-codes/E0423.stderr
@@ -29,19 +29,25 @@
--> $DIR/E0423.rs:12:32
|
LL | if let S { x: _x, y: 2 } = S { x: 1, y: 2 } { println!("Ok"); }
- | ^ did you mean `(S { /* fields */ })`?
+ | ^---------------
+ | |
+ | help: surround the struct literal with parenthesis: `(S { x: 1, y: 2 })`
error[E0423]: expected value, found struct `T`
--> $DIR/E0423.rs:15:8
|
LL | if T {} == T {} { println!("Ok"); }
- | ^ did you mean `(T { /* fields */ })`?
+ | ^---
+ | |
+ | help: surround the struct literal with parenthesis: `(T {})`
error[E0423]: expected value, found struct `std::ops::Range`
--> $DIR/E0423.rs:21:14
|
LL | for _ in std::ops::Range { start: 0, end: 10 } {}
- | ^^^^^^^^^^^^^^^ did you mean `(std::ops::Range { /* fields */ })`?
+ | ^^^^^^^^^^^^^^^----------------------
+ | |
+ | help: surround the struct literal with parenthesis: `(std::ops::Range { start: 0, end: 10 })`
error: aborting due to 7 previous errors
diff --git a/src/test/ui/feature-gate/feature-gate-static-nobundle-2.rs b/src/test/ui/feature-gate/feature-gate-static-nobundle-2.rs
new file mode 100644
index 0000000..92844f9
--- /dev/null
+++ b/src/test/ui/feature-gate/feature-gate-static-nobundle-2.rs
@@ -0,0 +1,6 @@
+//~ ERROR kind="static-nobundle" is feature gated
+// Test the behavior of rustc when non-existent library is statically linked
+
+// compile-flags: -l static-nobundle=nonexistent
+
+fn main() {}
diff --git a/src/test/ui/feature-gate/feature-gate-static-nobundle-2.stderr b/src/test/ui/feature-gate/feature-gate-static-nobundle-2.stderr
new file mode 100644
index 0000000..419c219
--- /dev/null
+++ b/src/test/ui/feature-gate/feature-gate-static-nobundle-2.stderr
@@ -0,0 +1,7 @@
+error[E0658]: kind="static-nobundle" is feature gated (see issue #37403)
+ |
+ = help: add #![feature(static_nobundle)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/huge-enum.rs b/src/test/ui/huge-enum.rs
index 18ef457..71c8fd5 100644
--- a/src/test/ui/huge-enum.rs
+++ b/src/test/ui/huge-enum.rs
@@ -1,7 +1,5 @@
-// error-pattern: Option
-// normalize-stderr-test "<\[u32; \d+\]>" -> "<[u32; N]>"
-
-// FIXME: work properly with higher limits
+// normalize-stderr-test "std::option::Option<\[u32; \d+\]>" -> "TYPE"
+// normalize-stderr-test "\[u32; \d+\]" -> "TYPE"
#[cfg(target_pointer_width = "32")]
fn main() {
diff --git a/src/test/ui/huge-enum.stderr b/src/test/ui/huge-enum.stderr
index b7cf255..67cae3d 100644
--- a/src/test/ui/huge-enum.stderr
+++ b/src/test/ui/huge-enum.stderr
@@ -1,4 +1,4 @@
-error: the type `std::option::Option<[u32; N]>` is too big for the current architecture
+error: the type `TYPE` is too big for the current architecture
error: aborting due to previous error
diff --git a/src/test/ui/imports/issue-57539.rs b/src/test/ui/imports/issue-57539.rs
new file mode 100644
index 0000000..90b74eb
--- /dev/null
+++ b/src/test/ui/imports/issue-57539.rs
@@ -0,0 +1,8 @@
+// edition:2018
+
+mod core {
+ use core; //~ ERROR `core` is ambiguous
+ use crate::*;
+}
+
+fn main() {}
diff --git a/src/test/ui/imports/issue-57539.stderr b/src/test/ui/imports/issue-57539.stderr
new file mode 100644
index 0000000..3f745fd
--- /dev/null
+++ b/src/test/ui/imports/issue-57539.stderr
@@ -0,0 +1,18 @@
+error[E0659]: `core` is ambiguous (name vs any other name during import resolution)
+ --> $DIR/issue-57539.rs:4:9
+ |
+LL | use core; //~ ERROR `core` is ambiguous
+ | ^^^^ ambiguous name
+ |
+ = note: `core` could refer to a built-in extern crate
+ = help: use `::core` to refer to this extern crate unambiguously
+note: `core` could also refer to the module imported here
+ --> $DIR/issue-57539.rs:5:9
+ |
+LL | use crate::*;
+ | ^^^^^^^^
+ = help: use `self::core` to refer to this module unambiguously
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0659`.
diff --git a/src/test/ui/issue-53787-inline-assembler-macro.rs b/src/test/ui/issue-53787-inline-assembler-macro.rs
new file mode 100644
index 0000000..937bce1
--- /dev/null
+++ b/src/test/ui/issue-53787-inline-assembler-macro.rs
@@ -0,0 +1,23 @@
+// Regression test for Issue #53787: Fix ICE when creating a label in inline assembler with macros.
+
+#![feature(asm)]
+
+macro_rules! fake_jump {
+ ($id:expr) => {
+ unsafe {
+ asm!(
+ "
+ jmp $0
+ lea eax, [ebx]
+ xor eax, 0xDEADBEEF
+ retn
+ $0:
+ "::"0"($id)::"volatile", "intel");
+ }
+ };
+}
+
+fn main() {
+ fake_jump!("FirstFunc"); //~ ERROR invalid value for constraint in inline assembly
+ println!("Hello, world!");
+}
diff --git a/src/test/ui/issue-53787-inline-assembler-macro.stderr b/src/test/ui/issue-53787-inline-assembler-macro.stderr
new file mode 100644
index 0000000..69f380b
--- /dev/null
+++ b/src/test/ui/issue-53787-inline-assembler-macro.stderr
@@ -0,0 +1,9 @@
+error[E0669]: invalid value for constraint in inline assembly
+ --> $DIR/issue-53787-inline-assembler-macro.rs:21:16
+ |
+LL | fake_jump!("FirstFunc"); //~ ERROR invalid value for constraint in inline assembly
+ | ^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0669`.
diff --git a/src/test/ui/issues/issue-20413.stderr b/src/test/ui/issues/issue-20413.stderr
index 20e5758..1c353fe 100644
--- a/src/test/ui/issues/issue-20413.stderr
+++ b/src/test/ui/issues/issue-20413.stderr
@@ -6,7 +6,7 @@
|
= help: consider removing `T` or using a marker such as `std::marker::PhantomData`
-error[E0275]: overflow evaluating the requirement `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: std::marker::Sized`
+error[E0275]: overflow evaluating the requirement `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Foo`
--> $DIR/issue-20413.rs:8:1
|
LL | / impl<T> Foo for T where NoData<T>: Foo {
@@ -18,7 +18,6 @@
| |_^
|
= help: consider adding a `#![recursion_limit="128"]` attribute to your crate
- = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
= note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
diff --git a/src/test/ui/issues/issue-5067.rs b/src/test/ui/issues/issue-5067.rs
index 526a683..616fd09 100644
--- a/src/test/ui/issues/issue-5067.rs
+++ b/src/test/ui/issues/issue-5067.rs
@@ -1,37 +1,59 @@
#![allow(unused_macros)]
+// Tests that repetition matchers cannot match the empty token tree (since that would be
+// ambiguous).
+
+// edition:2018
+
macro_rules! foo {
( $()* ) => {};
//~^ ERROR repetition matches empty token tree
( $()+ ) => {};
//~^ ERROR repetition matches empty token tree
-
+ ( $()? ) => {};
+ //~^ ERROR repetition matches empty token tree
( $(),* ) => {}; // PASS
( $(),+ ) => {}; // PASS
-
+ // `?` cannot have a separator...
( [$()*] ) => {};
//~^ ERROR repetition matches empty token tree
( [$()+] ) => {};
//~^ ERROR repetition matches empty token tree
-
+ ( [$()?] ) => {};
+ //~^ ERROR repetition matches empty token tree
( [$(),*] ) => {}; // PASS
( [$(),+] ) => {}; // PASS
-
+ // `?` cannot have a separator...
( $($()* $(),* $(a)* $(a),* )* ) => {};
//~^ ERROR repetition matches empty token tree
( $($()* $(),* $(a)* $(a),* )+ ) => {};
//~^ ERROR repetition matches empty token tree
-
+ ( $($()* $(),* $(a)* $(a),* )? ) => {};
+ //~^ ERROR repetition matches empty token tree
+ ( $($()? $(),* $(a)? $(a),* )* ) => {};
+ //~^ ERROR repetition matches empty token tree
+ ( $($()? $(),* $(a)? $(a),* )+ ) => {};
+ //~^ ERROR repetition matches empty token tree
+ ( $($()? $(),* $(a)? $(a),* )? ) => {};
+ //~^ ERROR repetition matches empty token tree
( $(a $(),* $(a)* $(a),* )* ) => {}; // PASS
( $($(a)+ $(),* $(a)* $(a),* )+ ) => {}; // PASS
+ ( $($(a)+ $(),* $(a)* $(a),* )? ) => {}; // PASS
+
+ ( $(a $(),* $(a)? $(a),* )* ) => {}; // PASS
+ ( $($(a)+ $(),* $(a)? $(a),* )+ ) => {}; // PASS
+ ( $($(a)+ $(),* $(a)? $(a),* )? ) => {}; // PASS
( $(a $()+)* ) => {};
//~^ ERROR repetition matches empty token tree
( $(a $()*)+ ) => {};
//~^ ERROR repetition matches empty token tree
+ ( $(a $()+)? ) => {};
+ //~^ ERROR repetition matches empty token tree
+ ( $(a $()?)+ ) => {};
+ //~^ ERROR repetition matches empty token tree
}
-
// --- Original Issue --- //
macro_rules! make_vec {
@@ -43,11 +65,10 @@
let _ = make_vec![a 1, a 2, a 3];
}
-
// --- Minified Issue --- //
macro_rules! m {
- ( $()* ) => {}
+ ( $()* ) => {};
//~^ ERROR repetition matches empty token tree
}
diff --git a/src/test/ui/issues/issue-5067.stderr b/src/test/ui/issues/issue-5067.stderr
index 433b7c8..7ffc607 100644
--- a/src/test/ui/issues/issue-5067.stderr
+++ b/src/test/ui/issues/issue-5067.stderr
@@ -1,62 +1,110 @@
error: repetition matches empty token tree
- --> $DIR/issue-5067.rs:4:8
+ --> $DIR/issue-5067.rs:9:8
|
LL | ( $()* ) => {};
| ^^
error: repetition matches empty token tree
- --> $DIR/issue-5067.rs:6:8
+ --> $DIR/issue-5067.rs:11:8
|
LL | ( $()+ ) => {};
| ^^
error: repetition matches empty token tree
- --> $DIR/issue-5067.rs:12:9
+ --> $DIR/issue-5067.rs:13:8
+ |
+LL | ( $()? ) => {};
+ | ^^
+
+error: repetition matches empty token tree
+ --> $DIR/issue-5067.rs:18:9
|
LL | ( [$()*] ) => {};
| ^^
error: repetition matches empty token tree
- --> $DIR/issue-5067.rs:14:9
+ --> $DIR/issue-5067.rs:20:9
|
LL | ( [$()+] ) => {};
| ^^
error: repetition matches empty token tree
- --> $DIR/issue-5067.rs:20:8
+ --> $DIR/issue-5067.rs:22:9
+ |
+LL | ( [$()?] ) => {};
+ | ^^
+
+error: repetition matches empty token tree
+ --> $DIR/issue-5067.rs:27:8
|
LL | ( $($()* $(),* $(a)* $(a),* )* ) => {};
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
error: repetition matches empty token tree
- --> $DIR/issue-5067.rs:22:8
+ --> $DIR/issue-5067.rs:29:8
|
LL | ( $($()* $(),* $(a)* $(a),* )+ ) => {};
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
error: repetition matches empty token tree
- --> $DIR/issue-5067.rs:28:12
+ --> $DIR/issue-5067.rs:31:8
+ |
+LL | ( $($()* $(),* $(a)* $(a),* )? ) => {};
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+ --> $DIR/issue-5067.rs:33:8
+ |
+LL | ( $($()? $(),* $(a)? $(a),* )* ) => {};
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+ --> $DIR/issue-5067.rs:35:8
+ |
+LL | ( $($()? $(),* $(a)? $(a),* )+ ) => {};
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+ --> $DIR/issue-5067.rs:37:8
+ |
+LL | ( $($()? $(),* $(a)? $(a),* )? ) => {};
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+ --> $DIR/issue-5067.rs:47:12
|
LL | ( $(a $()+)* ) => {};
| ^^
error: repetition matches empty token tree
- --> $DIR/issue-5067.rs:30:12
+ --> $DIR/issue-5067.rs:49:12
|
LL | ( $(a $()*)+ ) => {};
| ^^
error: repetition matches empty token tree
- --> $DIR/issue-5067.rs:38:18
+ --> $DIR/issue-5067.rs:51:12
+ |
+LL | ( $(a $()+)? ) => {};
+ | ^^
+
+error: repetition matches empty token tree
+ --> $DIR/issue-5067.rs:53:12
+ |
+LL | ( $(a $()?)+ ) => {};
+ | ^^
+
+error: repetition matches empty token tree
+ --> $DIR/issue-5067.rs:60:18
|
LL | (a $e1:expr $($(, a $e2:expr)*)*) => ([$e1 $($(, $e2)*)*]);
| ^^^^^^^^^^^^^^^^^^
error: repetition matches empty token tree
- --> $DIR/issue-5067.rs:50:8
+ --> $DIR/issue-5067.rs:71:8
|
-LL | ( $()* ) => {}
+LL | ( $()* ) => {};
| ^^
-error: aborting due to 10 previous errors
+error: aborting due to 18 previous errors
diff --git a/src/test/ui/issues/issue-56488.rs b/src/test/ui/issues/issue-56488.rs
new file mode 100644
index 0000000..e2f3996
--- /dev/null
+++ b/src/test/ui/issues/issue-56488.rs
@@ -0,0 +1,13 @@
+// run-pass
+
+#![feature(trait_alias)]
+
+mod alpha {
+ pub trait A {}
+ pub trait C = A;
+}
+
+#[allow(unused_imports)]
+use alpha::C;
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-57597.rs b/src/test/ui/issues/issue-57597.rs
new file mode 100644
index 0000000..ebeb3fe
--- /dev/null
+++ b/src/test/ui/issues/issue-57597.rs
@@ -0,0 +1,80 @@
+// Regression test for #57597.
+//
+// Make sure that nested matchers work correctly rather than causing an infinite loop or crash.
+
+// edition:2018
+
+macro_rules! foo1 {
+ ($($($i:ident)?)+) => {};
+ //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo2 {
+ ($($($i:ident)?)*) => {};
+ //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo3 {
+ ($($($i:ident)?)?) => {};
+ //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo4 {
+ ($($($($i:ident)?)?)?) => {};
+ //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo5 {
+ ($($($($i:ident)*)?)?) => {};
+ //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo6 {
+ ($($($($i:ident)?)*)?) => {};
+ //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo7 {
+ ($($($($i:ident)?)?)*) => {};
+ //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo8 {
+ ($($($($i:ident)*)*)?) => {};
+ //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo9 {
+ ($($($($i:ident)?)*)*) => {};
+ //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo10 {
+ ($($($($i:ident)?)*)+) => {};
+ //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo11 {
+ ($($($($i:ident)+)?)*) => {};
+ //~^ ERROR repetition matches empty token tree
+}
+
+macro_rules! foo12 {
+ ($($($($i:ident)+)*)?) => {};
+ //~^ ERROR repetition matches empty token tree
+}
+
+fn main() {
+ foo1!();
+ foo2!();
+ foo3!();
+ foo4!();
+ foo5!();
+ foo6!();
+ foo7!();
+ foo8!();
+ foo9!();
+ foo10!();
+ foo11!();
+ foo12!();
+}
diff --git a/src/test/ui/issues/issue-57597.stderr b/src/test/ui/issues/issue-57597.stderr
new file mode 100644
index 0000000..0a02ac8
--- /dev/null
+++ b/src/test/ui/issues/issue-57597.stderr
@@ -0,0 +1,74 @@
+error: repetition matches empty token tree
+ --> $DIR/issue-57597.rs:8:7
+ |
+LL | ($($($i:ident)?)+) => {};
+ | ^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+ --> $DIR/issue-57597.rs:13:7
+ |
+LL | ($($($i:ident)?)*) => {};
+ | ^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+ --> $DIR/issue-57597.rs:18:7
+ |
+LL | ($($($i:ident)?)?) => {};
+ | ^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+ --> $DIR/issue-57597.rs:23:7
+ |
+LL | ($($($($i:ident)?)?)?) => {};
+ | ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+ --> $DIR/issue-57597.rs:28:7
+ |
+LL | ($($($($i:ident)*)?)?) => {};
+ | ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+ --> $DIR/issue-57597.rs:33:7
+ |
+LL | ($($($($i:ident)?)*)?) => {};
+ | ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+ --> $DIR/issue-57597.rs:38:7
+ |
+LL | ($($($($i:ident)?)?)*) => {};
+ | ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+ --> $DIR/issue-57597.rs:43:7
+ |
+LL | ($($($($i:ident)*)*)?) => {};
+ | ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+ --> $DIR/issue-57597.rs:48:7
+ |
+LL | ($($($($i:ident)?)*)*) => {};
+ | ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+ --> $DIR/issue-57597.rs:53:7
+ |
+LL | ($($($($i:ident)?)*)+) => {};
+ | ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+ --> $DIR/issue-57597.rs:58:7
+ |
+LL | ($($($($i:ident)+)?)*) => {};
+ | ^^^^^^^^^^^^^^^^^^
+
+error: repetition matches empty token tree
+ --> $DIR/issue-57597.rs:63:7
+ |
+LL | ($($($($i:ident)+)*)?) => {};
+ | ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 12 previous errors
+
diff --git a/src/test/ui/lifetime-before-type-params.rs b/src/test/ui/lifetime-before-type-params.rs
new file mode 100644
index 0000000..9b905d4
--- /dev/null
+++ b/src/test/ui/lifetime-before-type-params.rs
@@ -0,0 +1,9 @@
+#![allow(unused)]
+fn first<T, 'a, 'b>() {}
+//~^ ERROR lifetime parameters must be declared prior to type parameters
+fn second<'a, T, 'b>() {}
+//~^ ERROR lifetime parameters must be declared prior to type parameters
+fn third<T, U, 'a>() {}
+//~^ ERROR lifetime parameters must be declared prior to type parameters
+fn fourth<'a, T, 'b, U, 'c, V>() {}
+//~^ ERROR lifetime parameters must be declared prior to type parameters
diff --git a/src/test/ui/lifetime-before-type-params.stderr b/src/test/ui/lifetime-before-type-params.stderr
new file mode 100644
index 0000000..7ac8dff
--- /dev/null
+++ b/src/test/ui/lifetime-before-type-params.stderr
@@ -0,0 +1,47 @@
+error: lifetime parameters must be declared prior to type parameters
+ --> $DIR/lifetime-before-type-params.rs:2:13
+ |
+LL | fn first<T, 'a, 'b>() {}
+ | ^^ ^^
+help: move the lifetime parameter prior to the first type parameter
+ |
+LL | fn first<'a, 'b, T>() {}
+ | ^^^ ^^^ --
+
+error: lifetime parameters must be declared prior to type parameters
+ --> $DIR/lifetime-before-type-params.rs:4:18
+ |
+LL | fn second<'a, T, 'b>() {}
+ | ^^
+help: move the lifetime parameter prior to the first type parameter
+ |
+LL | fn second<'a, 'b, T>() {}
+ | ^^^ --
+
+error: lifetime parameters must be declared prior to type parameters
+ --> $DIR/lifetime-before-type-params.rs:6:16
+ |
+LL | fn third<T, U, 'a>() {}
+ | ^^
+help: move the lifetime parameter prior to the first type parameter
+ |
+LL | fn third<'a, T, U>() {}
+ | ^^^ --
+
+error: lifetime parameters must be declared prior to type parameters
+ --> $DIR/lifetime-before-type-params.rs:8:18
+ |
+LL | fn fourth<'a, T, 'b, U, 'c, V>() {}
+ | ^^ ^^
+help: move the lifetime parameter prior to the first type parameter
+ |
+LL | fn fourth<'a, 'b, 'c, T, U, V>() {}
+ | ^^^ ^^^ -- --
+
+error[E0601]: `main` function not found in crate `lifetime_before_type_params`
+ |
+ = note: consider adding a `main` function to `$DIR/lifetime-before-type-params.rs`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/lint/lint-incoherent-auto-trait-objects.rs b/src/test/ui/lint/lint-incoherent-auto-trait-objects.rs
new file mode 100644
index 0000000..0d18965
--- /dev/null
+++ b/src/test/ui/lint/lint-incoherent-auto-trait-objects.rs
@@ -0,0 +1,21 @@
+// ignore-tidy-linelength
+
+trait Foo {}
+
+impl Foo for dyn Send {}
+
+impl Foo for dyn Send + Send {}
+//~^ ERROR conflicting implementations
+//~| hard error
+
+impl Foo for dyn Send + Sync {}
+
+impl Foo for dyn Sync + Send {}
+//~^ ERROR conflicting implementations
+//~| hard error
+
+impl Foo for dyn Send + Sync + Send {}
+//~^ ERROR conflicting implementations
+//~| hard error
+
+fn main() {}
diff --git a/src/test/ui/lint/lint-incoherent-auto-trait-objects.stderr b/src/test/ui/lint/lint-incoherent-auto-trait-objects.stderr
new file mode 100644
index 0000000..928c92e
--- /dev/null
+++ b/src/test/ui/lint/lint-incoherent-auto-trait-objects.stderr
@@ -0,0 +1,39 @@
+error: conflicting implementations of trait `Foo` for type `(dyn std::marker::Send + 'static)`: (E0119)
+ --> $DIR/lint-incoherent-auto-trait-objects.rs:7:1
+ |
+LL | impl Foo for dyn Send {}
+ | --------------------- first implementation here
+LL |
+LL | impl Foo for dyn Send + Send {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + 'static)`
+ |
+ = note: #[deny(order_dependent_trait_objects)] 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 #56484 <https://github.com/rust-lang/rust/issues/56484>
+
+error: conflicting implementations of trait `Foo` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119)
+ --> $DIR/lint-incoherent-auto-trait-objects.rs:13:1
+ |
+LL | impl Foo for dyn Send + Sync {}
+ | ---------------------------- first implementation here
+LL |
+LL | impl Foo for dyn Sync + Send {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)`
+ |
+ = 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 #56484 <https://github.com/rust-lang/rust/issues/56484>
+
+error: conflicting implementations of trait `Foo` for type `(dyn std::marker::Send + std::marker::Sync + 'static)`: (E0119)
+ --> $DIR/lint-incoherent-auto-trait-objects.rs:17:1
+ |
+LL | impl Foo for dyn Sync + Send {}
+ | ---------------------------- first implementation here
+...
+LL | impl Foo for dyn Send + Sync + Send {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(dyn std::marker::Send + std::marker::Sync + 'static)`
+ |
+ = 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 #56484 <https://github.com/rust-lang/rust/issues/56484>
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/liveness/liveness-dead.rs b/src/test/ui/liveness/liveness-dead.rs
index 7d420af..004663c 100644
--- a/src/test/ui/liveness/liveness-dead.rs
+++ b/src/test/ui/liveness/liveness-dead.rs
@@ -27,4 +27,13 @@
x = 4; //~ ERROR: value assigned to `x` is never read
}
+// #22630
+fn f6() {
+ let mut done = false;
+ while !done {
+ done = true; // no error
+ continue;
+ }
+}
+
fn main() {}
diff --git a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
index 66f8791..8e40707 100644
--- a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
+++ b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr
@@ -9,7 +9,7 @@
for<'r, 's, 't0> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) mut &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) i32, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 't0)) i32))
]
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/escape-argument-callee.rs:26:45
|
LL | let mut closure = expect_sig(|p, y| *p = y);
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
index 5594271..55e4573 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
@@ -16,7 +16,7 @@
= note: late-bound region is '_#5r
= note: late-bound region is '_#6r
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/propagate-approximated-fail-no-postdom.rs:46:13
|
LL | |_outlives1, _outlives2, _outlives3, x, y| {
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.rs
index 7296bba..1c409a1 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.rs
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.rs
@@ -41,10 +41,9 @@
#[rustc_regions]
fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
-
// Only works if 'x: 'y:
demand_y(x, y, x.get())
- //~^ ERROR unsatisfied lifetime constraints
+ //~^ ERROR lifetime may not live long enough
});
}
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
index a827b85..5863b9b 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr
@@ -3,10 +3,9 @@
|
LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
| _______________________________________________^
-LL | |
LL | | // Only works if 'x: 'y:
LL | | demand_y(x, y, x.get())
-LL | | //~^ ERROR unsatisfied lifetime constraints
+LL | | //~^ ERROR lifetime may not live long enough
LL | | });
| |_____^
|
@@ -24,17 +23,17 @@
|
LL | / fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
LL | | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
-LL | |
LL | | // Only works if 'x: 'y:
-... |
+LL | | demand_y(x, y, x.get())
+LL | | //~^ ERROR lifetime may not live long enough
LL | | });
LL | | }
| |_^
|
= note: defining type: DefId(0/0:6 ~ propagate_approximated_ref[317d]::supply[0]) with substs []
-error: unsatisfied lifetime constraints
- --> $DIR/propagate-approximated-ref.rs:46:9
+error: lifetime may not live long enough
+ --> $DIR/propagate-approximated-ref.rs:45:9
|
LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
| -- -- lifetime `'b` defined here
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-val.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-val.rs
index eb6159c..233a5dc 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-val.rs
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-val.rs
@@ -34,10 +34,9 @@
#[rustc_regions]
fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| {
-
// Only works if 'x: 'y:
demand_y(outlives1, outlives2, x.get())
- //~^ ERROR unsatisfied lifetime constraints
+ //~^ ERROR lifetime may not live long enough
});
}
diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
index 1f9d1d7..b6d9d85 100644
--- a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr
@@ -3,10 +3,9 @@
|
LL | establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| {
| _____________________________________________^
-LL | |
LL | | // Only works if 'x: 'y:
LL | | demand_y(outlives1, outlives2, x.get())
-LL | | //~^ ERROR unsatisfied lifetime constraints
+LL | | //~^ ERROR lifetime may not live long enough
LL | | });
| |_____^
|
@@ -24,17 +23,17 @@
|
LL | / fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
LL | | establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| {
-LL | |
LL | | // Only works if 'x: 'y:
-... |
+LL | | demand_y(outlives1, outlives2, x.get())
+LL | | //~^ ERROR lifetime may not live long enough
LL | | });
LL | | }
| |_^
|
= note: defining type: DefId(0/0:6 ~ propagate_approximated_val[317d]::test[0]) with substs []
-error: unsatisfied lifetime constraints
- --> $DIR/propagate-approximated-val.rs:39:9
+error: lifetime may not live long enough
+ --> $DIR/propagate-approximated-val.rs:38:9
|
LL | fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
| -- -- lifetime `'b` defined here
diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
index 1a8988f..93eb93b 100644
--- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
@@ -16,7 +16,7 @@
= note: late-bound region is '_#2r
= note: late-bound region is '_#3r
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:37:9
|
LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
index d0492bd..c7809de 100644
--- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
+++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
@@ -16,7 +16,7 @@
= note: late-bound region is '_#3r
= note: late-bound region is '_#4r
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:41:9
|
LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
diff --git a/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr b/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr
index 0bc0592..d0a24a2 100644
--- a/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr
+++ b/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr
@@ -1,4 +1,4 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/region-lbr-named-does-not-outlive-static.rs:9:5
|
LL | fn foo<'a>(x: &'a u32) -> &'static u32 {
diff --git a/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.rs b/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.rs
index 1be27ae..4d864c6 100644
--- a/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.rs
+++ b/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.rs
@@ -7,7 +7,7 @@
fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> &'b u32 {
&*x
- //~^ ERROR unsatisfied lifetime constraints
+ //~^ ERROR lifetime may not live long enough
}
-fn main() { }
+fn main() {}
diff --git a/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr b/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr
index 2332332..6dc98a9 100644
--- a/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr
+++ b/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr
@@ -1,4 +1,4 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/region-lbr1-does-not-outlive-ebr2.rs:9:5
|
LL | fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> &'b u32 {
diff --git a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr
index 26243f9..4a035d0 100644
--- a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr
+++ b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr
@@ -9,7 +9,7 @@
for<'r, 's> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) i32, &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 's)) i32)) -> &ReLateBound(DebruijnIndex(0), BrNamed(crate0:DefIndex(0:0), 'r)) i32
]
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/return-wrong-bound-region.rs:11:23
|
LL | expect_sig(|a, b| b); // ought to return `a`
diff --git a/src/test/ui/nll/issue-48238.stderr b/src/test/ui/nll/issue-48238.stderr
index 913effa..7cb5eb7 100644
--- a/src/test/ui/nll/issue-48238.stderr
+++ b/src/test/ui/nll/issue-48238.stderr
@@ -1,4 +1,4 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/issue-48238.rs:11:13
|
LL | move || use_val(&orig); //~ ERROR
diff --git a/src/test/ui/nll/issue-50716.stderr b/src/test/ui/nll/issue-50716.stderr
index fa893df..229bb17 100644
--- a/src/test/ui/nll/issue-50716.stderr
+++ b/src/test/ui/nll/issue-50716.stderr
@@ -1,4 +1,4 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/issue-50716.rs:16:14
|
LL | fn foo<'a, T: 'static>(s: Box<<&'a T as A>::X>)
diff --git a/src/test/ui/nll/issue-52113.rs b/src/test/ui/nll/issue-52113.rs
index 8428e55..795f4f4 100644
--- a/src/test/ui/nll/issue-52113.rs
+++ b/src/test/ui/nll/issue-52113.rs
@@ -3,8 +3,8 @@
#![allow(warnings)]
#![feature(nll)]
-trait Bazinga { }
-impl<F> Bazinga for F { }
+trait Bazinga {}
+impl<F> Bazinga for F {}
fn produce1<'a>(data: &'a u32) -> impl Bazinga + 'a {
let x = move || {
@@ -21,7 +21,6 @@
x
}
-
fn produce3<'a, 'b: 'a>(data: &'a mut Vec<&'a u32>, value: &'b u32) -> impl Bazinga + 'a {
let x = move || {
let value: &'a u32 = value;
@@ -35,7 +34,7 @@
let value: &'a u32 = value;
data.push(value);
};
- x //~ ERROR unsatisfied lifetime constraints
+ x //~ ERROR lifetime may not live long enough
}
-fn main() { }
+fn main() {}
diff --git a/src/test/ui/nll/issue-52113.stderr b/src/test/ui/nll/issue-52113.stderr
index 873612d..ceae161 100644
--- a/src/test/ui/nll/issue-52113.stderr
+++ b/src/test/ui/nll/issue-52113.stderr
@@ -1,12 +1,12 @@
-error: unsatisfied lifetime constraints
- --> $DIR/issue-52113.rs:38:5
+error: lifetime may not live long enough
+ --> $DIR/issue-52113.rs:37:5
|
LL | fn produce_err<'a, 'b: 'a>(data: &'b mut Vec<&'b u32>, value: &'a u32) -> impl Bazinga + 'b {
| -- -- lifetime `'b` defined here
| |
| lifetime `'a` defined here
...
-LL | x //~ ERROR unsatisfied lifetime constraints
+LL | x //~ ERROR lifetime may not live long enough
| ^ returning this value requires that `'a` must outlive `'b`
error: aborting due to previous error
diff --git a/src/test/ui/nll/issue-52742.rs b/src/test/ui/nll/issue-52742.rs
index d8251cb..150e67f 100644
--- a/src/test/ui/nll/issue-52742.rs
+++ b/src/test/ui/nll/issue-52742.rs
@@ -7,14 +7,14 @@
}
struct Bar<'b> {
- z: &'b u32
+ z: &'b u32,
}
impl Foo<'_, '_> {
fn take_bar(&mut self, b: Bar<'_>) {
self.y = b.z
- //~^ ERROR unsatisfied lifetime constraints
+ //~^ ERROR lifetime may not live long enough
}
}
-fn main() { }
+fn main() {}
diff --git a/src/test/ui/nll/issue-52742.stderr b/src/test/ui/nll/issue-52742.stderr
index f733702..6b25296 100644
--- a/src/test/ui/nll/issue-52742.stderr
+++ b/src/test/ui/nll/issue-52742.stderr
@@ -1,4 +1,4 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/issue-52742.rs:15:9
|
LL | fn take_bar(&mut self, b: Bar<'_>) {
diff --git a/src/test/ui/nll/issue-55394.rs b/src/test/ui/nll/issue-55394.rs
index 4a83c33..deb1034 100644
--- a/src/test/ui/nll/issue-55394.rs
+++ b/src/test/ui/nll/issue-55394.rs
@@ -8,7 +8,7 @@
impl Foo<'_> {
fn new(bar: &mut Bar) -> Self {
- Foo { bar } //~ ERROR unsatisfied lifetime constraints
+ Foo { bar } //~ERROR lifetime may not live long enough
}
}
diff --git a/src/test/ui/nll/issue-55394.stderr b/src/test/ui/nll/issue-55394.stderr
index a4c5160..bcdd782 100644
--- a/src/test/ui/nll/issue-55394.stderr
+++ b/src/test/ui/nll/issue-55394.stderr
@@ -1,11 +1,11 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/issue-55394.rs:11:9
|
LL | fn new(bar: &mut Bar) -> Self {
| - ---- return type is Foo<'2>
| |
| let's call the lifetime of this reference `'1`
-LL | Foo { bar } //~ ERROR unsatisfied lifetime constraints
+LL | Foo { bar } //~ERROR lifetime may not live long enough
| ^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2`
error: aborting due to previous error
diff --git a/src/test/ui/nll/issue-55401.stderr b/src/test/ui/nll/issue-55401.stderr
index 9e50db7..952b544 100644
--- a/src/test/ui/nll/issue-55401.stderr
+++ b/src/test/ui/nll/issue-55401.stderr
@@ -1,4 +1,4 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/issue-55401.rs:5:5
|
LL | fn static_to_a_to_static_through_ref_in_tuple<'a>(x: &'a u32) -> &'static u32 {
diff --git a/src/test/ui/nll/mir_check_cast_closure.rs b/src/test/ui/nll/mir_check_cast_closure.rs
index 5298e84..0619ff3 100644
--- a/src/test/ui/nll/mir_check_cast_closure.rs
+++ b/src/test/ui/nll/mir_check_cast_closure.rs
@@ -5,7 +5,7 @@
fn bar<'a, 'b>() -> fn(&'a u32, &'b u32) -> &'a u32 {
let g: fn(_, _) -> _ = |_x, y| y;
g
- //~^ ERROR unsatisfied lifetime constraints
+ //~^ ERROR lifetime may not live long enough
}
fn main() {}
diff --git a/src/test/ui/nll/mir_check_cast_closure.stderr b/src/test/ui/nll/mir_check_cast_closure.stderr
index b883533..e14cb07 100644
--- a/src/test/ui/nll/mir_check_cast_closure.stderr
+++ b/src/test/ui/nll/mir_check_cast_closure.stderr
@@ -1,4 +1,4 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/mir_check_cast_closure.rs:7:5
|
LL | fn bar<'a, 'b>() -> fn(&'a u32, &'b u32) -> &'a u32 {
diff --git a/src/test/ui/nll/mir_check_cast_reify.rs b/src/test/ui/nll/mir_check_cast_reify.rs
index b0ad8e3..be12e31 100644
--- a/src/test/ui/nll/mir_check_cast_reify.rs
+++ b/src/test/ui/nll/mir_check_cast_reify.rs
@@ -35,7 +35,7 @@
// as part of checking the `ReifyFnPointer`.
let f: fn(_) -> _ = foo;
f(x)
- //~^ ERROR unsatisfied lifetime constraints
+ //~^ ERROR lifetime may not live long enough
}
fn main() {}
diff --git a/src/test/ui/nll/mir_check_cast_reify.stderr b/src/test/ui/nll/mir_check_cast_reify.stderr
index 2585486..4e8eec3 100644
--- a/src/test/ui/nll/mir_check_cast_reify.stderr
+++ b/src/test/ui/nll/mir_check_cast_reify.stderr
@@ -1,4 +1,4 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/mir_check_cast_reify.rs:37:5
|
LL | fn bar<'a>(x: &'a u32) -> &'static u32 {
diff --git a/src/test/ui/nll/mir_check_cast_unsafe_fn.rs b/src/test/ui/nll/mir_check_cast_unsafe_fn.rs
index 29fbf46..9df9c05 100644
--- a/src/test/ui/nll/mir_check_cast_unsafe_fn.rs
+++ b/src/test/ui/nll/mir_check_cast_unsafe_fn.rs
@@ -7,7 +7,7 @@
// in `g`. These are related via the `UnsafeFnPointer` cast.
let g: unsafe fn(_) -> _ = f;
unsafe { g(input) }
- //~^ ERROR unsatisfied lifetime constraints
+ //~^ ERROR lifetime may not live long enough
}
fn main() {}
diff --git a/src/test/ui/nll/mir_check_cast_unsafe_fn.stderr b/src/test/ui/nll/mir_check_cast_unsafe_fn.stderr
index e7b945a..5295985 100644
--- a/src/test/ui/nll/mir_check_cast_unsafe_fn.stderr
+++ b/src/test/ui/nll/mir_check_cast_unsafe_fn.stderr
@@ -1,4 +1,4 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/mir_check_cast_unsafe_fn.rs:9:14
|
LL | fn bar<'a>(input: &'a u32, f: fn(&'a u32) -> &'a u32) -> &'static u32 {
diff --git a/src/test/ui/nll/mir_check_cast_unsize.rs b/src/test/ui/nll/mir_check_cast_unsize.rs
index e98d5e1..d15c4e4 100644
--- a/src/test/ui/nll/mir_check_cast_unsize.rs
+++ b/src/test/ui/nll/mir_check_cast_unsize.rs
@@ -6,7 +6,7 @@
fn bar<'a>(x: &'a u32) -> &'static dyn Debug {
x
- //~^ ERROR unsatisfied lifetime constraints
+ //~^ ERROR lifetime may not live long enough
}
fn main() {}
diff --git a/src/test/ui/nll/mir_check_cast_unsize.stderr b/src/test/ui/nll/mir_check_cast_unsize.stderr
index 189bb2d..364d6c1 100644
--- a/src/test/ui/nll/mir_check_cast_unsize.stderr
+++ b/src/test/ui/nll/mir_check_cast_unsize.stderr
@@ -1,4 +1,4 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/mir_check_cast_unsize.rs:8:5
|
LL | fn bar<'a>(x: &'a u32) -> &'static dyn Debug {
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
index f2bfdae..e8283d1 100644
--- a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr
@@ -40,7 +40,7 @@
|
= 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: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/projection-one-region-closure.rs:45:39
|
LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
@@ -94,7 +94,7 @@
|
= help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`...
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/projection-one-region-closure.rs:56:39
|
LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
index fc59100..78a8c80 100644
--- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr
@@ -31,7 +31,7 @@
T
]
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/projection-one-region-trait-bound-closure.rs:37:39
|
LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
@@ -76,7 +76,7 @@
T
]
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/projection-one-region-trait-bound-closure.rs:47:39
|
LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
diff --git a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.rs b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.rs
index 25877e6..20edfb3 100644
--- a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.rs
+++ b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.rs
@@ -85,7 +85,7 @@
T: Anything<'b, 'b>,
{
with_signature(cell, t, |cell, t| require(cell, t));
- //~^ ERROR unsatisfied lifetime constraints
+ //~^ ERROR lifetime may not live long enough
}
#[rustc_regions]
diff --git a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
index c2b54b6..d8725dc 100644
--- a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr
@@ -217,7 +217,7 @@
LL | | T: Anything<'b, 'b>,
LL | | {
LL | | with_signature(cell, t, |cell, t| require(cell, t));
-LL | | //~^ ERROR unsatisfied lifetime constraints
+LL | | //~^ ERROR lifetime may not live long enough
LL | | }
| |_^
|
@@ -226,7 +226,7 @@
T
]
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/projection-two-region-trait-bound-closure.rs:87:29
|
LL | fn two_regions<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
diff --git a/src/test/ui/nll/type-alias-free-regions.stderr b/src/test/ui/nll/type-alias-free-regions.stderr
index 6b3bb60..bcd141b 100644
--- a/src/test/ui/nll/type-alias-free-regions.stderr
+++ b/src/test/ui/nll/type-alias-free-regions.stderr
@@ -1,4 +1,4 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/type-alias-free-regions.rs:19:9
|
LL | impl<'a> FromBox<'a> for C<'a> {
@@ -8,7 +8,7 @@
LL | C { f: b } //~ ERROR
| ^^^^^^^^^^ returning this value requires that `'1` must outlive `'a`
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/type-alias-free-regions.rs:29:9
|
LL | impl<'a> FromTuple<'a> for C<'a> {
diff --git a/src/test/ui/nll/user-annotations/closure-substs.rs b/src/test/ui/nll/user-annotations/closure-substs.rs
index 9dc84aa..cafdd92 100644
--- a/src/test/ui/nll/user-annotations/closure-substs.rs
+++ b/src/test/ui/nll/user-annotations/closure-substs.rs
@@ -5,21 +5,21 @@
fn foo<'a>() {
// Here `x` is free in the closure sig:
|x: &'a i32| -> &'static i32 {
- return x; //~ ERROR unsatisfied lifetime constraints
+ return x; //~ ERROR lifetime may not live long enough
};
}
fn foo1() {
// Here `x` is bound in the closure sig:
|x: &i32| -> &'static i32 {
- return x; //~ ERROR unsatisfied lifetime constraints
+ return x; //~ ERROR lifetime may not live long enough
};
}
fn bar<'a>() {
// Here `x` is free in the closure sig:
|x: &'a i32, b: fn(&'static i32)| {
- b(x); //~ ERROR unsatisfied lifetime constraints
+ b(x); //~ ERROR lifetime may not live long enough
};
}
@@ -30,4 +30,4 @@
};
}
-fn main() { }
+fn main() {}
diff --git a/src/test/ui/nll/user-annotations/closure-substs.stderr b/src/test/ui/nll/user-annotations/closure-substs.stderr
index ffc6e5a..a46ab61 100644
--- a/src/test/ui/nll/user-annotations/closure-substs.stderr
+++ b/src/test/ui/nll/user-annotations/closure-substs.stderr
@@ -1,27 +1,27 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/closure-substs.rs:8:16
|
LL | fn foo<'a>() {
| -- lifetime `'a` defined here
...
-LL | return x; //~ ERROR unsatisfied lifetime constraints
+LL | return x; //~ ERROR lifetime may not live long enough
| ^ returning this value requires that `'a` must outlive `'static`
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/closure-substs.rs:15:16
|
LL | |x: &i32| -> &'static i32 {
| - let's call the lifetime of this reference `'1`
-LL | return x; //~ ERROR unsatisfied lifetime constraints
+LL | return x; //~ ERROR lifetime may not live long enough
| ^ returning this value requires that `'1` must outlive `'static`
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/closure-substs.rs:22:9
|
LL | fn bar<'a>() {
| -- lifetime `'a` defined here
...
-LL | b(x); //~ ERROR unsatisfied lifetime constraints
+LL | b(x); //~ ERROR lifetime may not live long enough
| ^^^^ argument requires that `'a` must outlive `'static`
error[E0521]: borrowed data escapes outside of closure
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr
index 94fbe01..541a711 100644
--- a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr
+++ b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr
@@ -1,4 +1,4 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/constant-in-expr-inherent-1.rs:10:5
|
LL | fn foo<'a>(_: &'a u32) -> &'static u32 {
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-normalize.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-normalize.stderr
index 7aeb276..5b97c12 100644
--- a/src/test/ui/nll/user-annotations/constant-in-expr-normalize.stderr
+++ b/src/test/ui/nll/user-annotations/constant-in-expr-normalize.stderr
@@ -1,4 +1,4 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/constant-in-expr-normalize.rs:20:5
|
LL | fn foo<'a>(_: &'a u32) -> &'static u32 {
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.stderr
index fee9abc..10e48b5 100644
--- a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.stderr
+++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.stderr
@@ -1,4 +1,4 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/constant-in-expr-trait-item-1.rs:12:5
|
LL | fn foo<'a>(_: &'a u32) -> &'static u32 {
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.stderr
index 047aad9..5bfa32e 100644
--- a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.stderr
+++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.stderr
@@ -1,4 +1,4 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/constant-in-expr-trait-item-2.rs:12:5
|
LL | fn foo<'a, T: Foo<'a>>() -> &'static u32 {
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr
index b373ceb..a1e60db 100644
--- a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr
+++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr
@@ -1,4 +1,4 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/constant-in-expr-trait-item-3.rs:12:5
|
LL | fn foo<'a, T: Foo<'a>>() -> &'static u32 {
diff --git a/src/test/ui/nll/user-annotations/issue-54124.rs b/src/test/ui/nll/user-annotations/issue-54124.rs
index 042ad02..e1de67a 100644
--- a/src/test/ui/nll/user-annotations/issue-54124.rs
+++ b/src/test/ui/nll/user-annotations/issue-54124.rs
@@ -1,8 +1,8 @@
#![feature(nll)]
fn test<'a>() {
- let _:fn(&()) = |_:&'a ()| {}; //~ ERROR unsatisfied lifetime constraints
- //~^ ERROR unsatisfied lifetime constraints
+ let _:fn(&()) = |_:&'a ()| {}; //~ ERROR lifetime may not live long enough
+ //~^ ERROR lifetime may not live long enough
}
fn main() {
diff --git a/src/test/ui/nll/user-annotations/issue-54124.stderr b/src/test/ui/nll/user-annotations/issue-54124.stderr
index 5b5afaee..b1c2411 100644
--- a/src/test/ui/nll/user-annotations/issue-54124.stderr
+++ b/src/test/ui/nll/user-annotations/issue-54124.stderr
@@ -1,19 +1,19 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/issue-54124.rs:4:22
|
LL | fn test<'a>() {
| -- lifetime `'a` defined here
-LL | let _:fn(&()) = |_:&'a ()| {}; //~ ERROR unsatisfied lifetime constraints
+LL | let _:fn(&()) = |_:&'a ()| {}; //~ ERROR lifetime may not live long enough
| ^ - let's call the lifetime of this reference `'1`
| |
| requires that `'1` must outlive `'a`
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/issue-54124.rs:4:22
|
LL | fn test<'a>() {
| -- lifetime `'a` defined here
-LL | let _:fn(&()) = |_:&'a ()| {}; //~ ERROR unsatisfied lifetime constraints
+LL | let _:fn(&()) = |_:&'a ()| {}; //~ ERROR lifetime may not live long enough
| ^ requires that `'a` must outlive `'static`
error: aborting due to 2 previous errors
diff --git a/src/test/ui/nll/user-annotations/patterns.stderr b/src/test/ui/nll/user-annotations/patterns.stderr
index b0c554e..476578e 100644
--- a/src/test/ui/nll/user-annotations/patterns.stderr
+++ b/src/test/ui/nll/user-annotations/patterns.stderr
@@ -148,7 +148,7 @@
LL | }
| - `x` dropped here while still borrowed
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/patterns.rs:113:5
|
LL | fn static_to_a_to_static_through_variable<'a>(x: &'a u32) -> &'static u32 {
@@ -157,7 +157,7 @@
LL | y //~ ERROR
| ^ returning this value requires that `'a` must outlive `'static`
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/patterns.rs:125:5
|
LL | fn static_to_a_to_static_through_tuple<'a>(x: &'a u32) -> &'static u32 {
@@ -166,7 +166,7 @@
LL | y //~ ERROR
| ^ returning this value requires that `'a` must outlive `'static`
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/patterns.rs:130:5
|
LL | fn static_to_a_to_static_through_struct<'a>(_x: &'a u32) -> &'static u32 {
@@ -175,7 +175,7 @@
LL | y //~ ERROR
| ^ returning this value requires that `'a` must outlive `'static`
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/patterns.rs:134:18
|
LL | fn a_to_static_then_static<'a>(x: &'a u32) -> &'static u32 {
diff --git a/src/test/ui/nll/user-annotations/wf-self-type.rs b/src/test/ui/nll/user-annotations/wf-self-type.rs
index da9ef8c..d8caf46 100644
--- a/src/test/ui/nll/user-annotations/wf-self-type.rs
+++ b/src/test/ui/nll/user-annotations/wf-self-type.rs
@@ -9,7 +9,7 @@
}
pub fn foo<'a, 'b>(u: &'b ()) -> &'a () {
- Foo::xmute(u) //~ ERROR unsatisfied lifetime constraints
+ Foo::xmute(u) //~ ERROR lifetime may not live long enough
}
fn main() {}
diff --git a/src/test/ui/nll/user-annotations/wf-self-type.stderr b/src/test/ui/nll/user-annotations/wf-self-type.stderr
index 401fe2a..00500c8 100644
--- a/src/test/ui/nll/user-annotations/wf-self-type.stderr
+++ b/src/test/ui/nll/user-annotations/wf-self-type.stderr
@@ -1,11 +1,11 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/wf-self-type.rs:12:5
|
LL | pub fn foo<'a, 'b>(u: &'b ()) -> &'a () {
| -- -- lifetime `'b` defined here
| |
| lifetime `'a` defined here
-LL | Foo::xmute(u) //~ ERROR unsatisfied lifetime constraints
+LL | Foo::xmute(u) //~ ERROR lifetime may not live long enough
| ^^^^^^^^^^^^^ returning this value requires that `'b` must outlive `'a`
error: aborting due to previous error
diff --git a/src/test/ui/nll/where_clauses_in_functions.rs b/src/test/ui/nll/where_clauses_in_functions.rs
index 256ec60..0d35c09 100644
--- a/src/test/ui/nll/where_clauses_in_functions.rs
+++ b/src/test/ui/nll/where_clauses_in_functions.rs
@@ -11,7 +11,7 @@
fn bar<'a, 'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) {
foo(x, y)
- //~^ ERROR unsatisfied lifetime constraints
+ //~^ ERROR lifetime may not live long enough
}
fn main() {}
diff --git a/src/test/ui/nll/where_clauses_in_functions.stderr b/src/test/ui/nll/where_clauses_in_functions.stderr
index 4419a19..f3b65ec 100644
--- a/src/test/ui/nll/where_clauses_in_functions.stderr
+++ b/src/test/ui/nll/where_clauses_in_functions.stderr
@@ -1,4 +1,4 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/where_clauses_in_functions.rs:13:5
|
LL | fn bar<'a, 'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) {
diff --git a/src/test/ui/nll/where_clauses_in_structs.rs b/src/test/ui/nll/where_clauses_in_structs.rs
index 1b02f26..8bc6b2e 100644
--- a/src/test/ui/nll/where_clauses_in_structs.rs
+++ b/src/test/ui/nll/where_clauses_in_structs.rs
@@ -11,7 +11,7 @@
fn bar<'a, 'b>(x: Cell<&'a u32>, y: Cell<&'b u32>) {
Foo { x, y };
- //~^ ERROR unsatisfied lifetime constraints
+ //~^ ERROR lifetime may not live long enough
}
fn main() {}
diff --git a/src/test/ui/nll/where_clauses_in_structs.stderr b/src/test/ui/nll/where_clauses_in_structs.stderr
index 8704b0dc..e0feb40 100644
--- a/src/test/ui/nll/where_clauses_in_structs.stderr
+++ b/src/test/ui/nll/where_clauses_in_structs.stderr
@@ -1,4 +1,4 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/where_clauses_in_structs.rs:13:11
|
LL | fn bar<'a, 'b>(x: Cell<&'a u32>, y: Cell<&'b u32>) {
diff --git a/src/test/ui/privacy/private-in-public-assoc-ty.rs b/src/test/ui/privacy/private-in-public-assoc-ty.rs
index c6e86ed..81d2395 100644
--- a/src/test/ui/privacy/private-in-public-assoc-ty.rs
+++ b/src/test/ui/privacy/private-in-public-assoc-ty.rs
@@ -1,7 +1,7 @@
// Private types and traits are not allowed in interfaces of associated types.
// This test also ensures that the checks are performed even inside private modules.
-#![feature(associated_type_defaults)]
+#![feature(associated_type_defaults, existential_type)]
mod m {
struct Priv;
@@ -23,10 +23,17 @@
type Alias4 = Priv;
//~^ ERROR private type `m::Priv` in public interface
+
+ type Exist;
+ fn infer_exist() -> Self::Exist;
}
impl PubTr for u8 {
type Alias1 = Priv;
//~^ ERROR private type `m::Priv` in public interface
+
+ existential type Exist: PrivTr;
+ //~^ ERROR private trait `m::PrivTr` in public interface
+ fn infer_exist() -> Self::Exist { Priv }
}
}
diff --git a/src/test/ui/privacy/private-in-public-assoc-ty.stderr b/src/test/ui/privacy/private-in-public-assoc-ty.stderr
index 6740277..0e5dab1 100644
--- a/src/test/ui/privacy/private-in-public-assoc-ty.stderr
+++ b/src/test/ui/privacy/private-in-public-assoc-ty.stderr
@@ -6,7 +6,7 @@
LL | | //~| WARN this was previously accepted
LL | | //~| WARN private type `m::Priv` in public interface
... |
-LL | | //~^ ERROR private type `m::Priv` in public interface
+LL | | fn infer_exist() -> Self::Exist;
LL | | }
| |_____^
|
@@ -22,7 +22,7 @@
LL | | //~| WARN this was previously accepted
LL | | //~| WARN private type `m::Priv` in public interface
... |
-LL | | //~^ ERROR private type `m::Priv` in public interface
+LL | | fn infer_exist() -> Self::Exist;
LL | | }
| |_____^
|
@@ -39,7 +39,7 @@
| ^^^^^^^^^^^^^^^^^^^ can't leak private type
error[E0446]: private type `m::Priv` in public interface
- --> $DIR/private-in-public-assoc-ty.rs:28:9
+ --> $DIR/private-in-public-assoc-ty.rs:31:9
|
LL | struct Priv;
| - `m::Priv` declared as private
@@ -47,6 +47,16 @@
LL | type Alias1 = Priv;
| ^^^^^^^^^^^^^^^^^^^ can't leak private type
-error: aborting due to 2 previous errors
+error[E0445]: private trait `m::PrivTr` in public interface
+ --> $DIR/private-in-public-assoc-ty.rs:34:9
+ |
+LL | trait PrivTr {}
+ | - `m::PrivTr` declared as private
+...
+LL | existential type Exist: PrivTr;
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
-For more information about this error, try `rustc --explain E0446`.
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0445, E0446.
+For more information about an error, try `rustc --explain E0445`.
diff --git a/src/test/ui/privacy/private-in-public-existential.rs b/src/test/ui/privacy/private-in-public-existential.rs
index 95658f4..61c6130 100644
--- a/src/test/ui/privacy/private-in-public-existential.rs
+++ b/src/test/ui/privacy/private-in-public-existential.rs
@@ -12,4 +12,14 @@
Priv
}
+pub trait Trait {
+ type Pub: Default;
+ fn method() -> Self::Pub;
+}
+
+impl Trait for u8 {
+ existential type Pub: Default;
+ fn method() -> Self::Pub { Priv }
+}
+
fn main() {}
diff --git a/src/test/ui/regions/regions-static-bound.nll.stderr b/src/test/ui/regions/regions-static-bound.nll.stderr
index f667afd..d6cec03 100644
--- a/src/test/ui/regions/regions-static-bound.nll.stderr
+++ b/src/test/ui/regions/regions-static-bound.nll.stderr
@@ -1,4 +1,4 @@
-error: unsatisfied lifetime constraints
+error: lifetime may not live long enough
--> $DIR/regions-static-bound.rs:9:5
|
LL | fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a {
diff --git a/src/test/ui/regions/regions-static-bound.rs b/src/test/ui/regions/regions-static-bound.rs
index 3ee5187..c1a15e5 100644
--- a/src/test/ui/regions/regions-static-bound.rs
+++ b/src/test/ui/regions/regions-static-bound.rs
@@ -7,7 +7,7 @@
where 'a: 'b, 'b: 'static { t }
fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a {
t //[ll]~ ERROR E0312
- //[nll]~^ ERROR unsatisfied lifetime constraints
+ //[nll]~^ ERROR lifetime may not live long enough
}
fn error(u: &(), v: &()) {
diff --git a/src/test/ui/resolve/resolve-hint-macro.stderr b/src/test/ui/resolve/resolve-hint-macro.stderr
index 4f6d0f6..ebe3c36 100644
--- a/src/test/ui/resolve/resolve-hint-macro.stderr
+++ b/src/test/ui/resolve/resolve-hint-macro.stderr
@@ -2,7 +2,7 @@
--> $DIR/resolve-hint-macro.rs:2:5
|
LL | assert(true);
- | ^^^^^^ did you mean `assert!(...)`?
+ | ^^^^^^ help: use `!` to invoke the macro: `assert!`
error: aborting due to previous error
diff --git a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr
index 8a9426b..b7b158c 100644
--- a/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr
+++ b/src/test/ui/resolve/suggest-path-instead-of-mod-dot-item.stderr
@@ -4,15 +4,15 @@
LL | a.I
| ^--
| |
- | did you mean `a::I`?
+ | help: use the path separator to refer to an item: `a::I`
error[E0423]: expected value, found module `a`
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:22:5
|
LL | a.g()
- | ^----
+ | ^--
| |
- | did you mean `a::g(...)`?
+ | help: use the path separator to refer to an item: `a::g`
error[E0423]: expected value, found module `a`
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:27:5
@@ -20,16 +20,21 @@
LL | a.b.J
| ^--
| |
- | did you mean `a::b`?
+ | help: use the path separator to refer to an item: `a::b`
error[E0423]: expected value, found module `a::b`
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:32:5
|
LL | a::b.J
- | ^^^---
- | | |
- | | help: a constant with a similar name exists: `I`
- | did you mean `a::b::J`?
+ | ^^^^
+help: a constant with a similar name exists
+ |
+LL | a::I.J
+ | ^
+help: use the path separator to refer to an item
+ |
+LL | a::b::J
+ |
error[E0423]: expected value, found module `a`
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:37:5
@@ -37,7 +42,7 @@
LL | a.b.f();
| ^--
| |
- | did you mean `a::b`?
+ | help: use the path separator to refer to an item: `a::b`
error[E0423]: expected value, found module `a::b`
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:40:12
@@ -51,10 +56,15 @@
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:45:5
|
LL | a::b.f()
- | ^^^-----
- | | |
- | | help: a constant with a similar name exists: `I`
- | did you mean `a::b::f(...)`?
+ | ^^^^
+help: a constant with a similar name exists
+ |
+LL | a::I.f()
+ | ^
+help: use the path separator to refer to an item
+ |
+LL | a::b::f()
+ | ^^^^^^^
error[E0423]: expected value, found module `a::b`
--> $DIR/suggest-path-instead-of-mod-dot-item.rs:50:5
diff --git a/src/test/ui/str/str-idx.stderr b/src/test/ui/str/str-idx.stderr
index 108096d..71b1747 100644
--- a/src/test/ui/str/str-idx.stderr
+++ b/src/test/ui/str/str-idx.stderr
@@ -5,6 +5,8 @@
| ^^^^ `str` cannot be indexed by `{integer}`
|
= help: the trait `std::ops::Index<{integer}>` is not implemented for `str`
+ = note: you can use `.chars().nth()` or `.bytes().nth()`
+ see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
error: aborting due to previous error
diff --git a/src/test/ui/str/str-mut-idx.stderr b/src/test/ui/str/str-mut-idx.stderr
index a0c7c2c..a1212c5 100644
--- a/src/test/ui/str/str-mut-idx.stderr
+++ b/src/test/ui/str/str-mut-idx.stderr
@@ -29,6 +29,8 @@
| ^^^^^^^^^ `str` cannot be mutably indexed by `usize`
|
= help: the trait `std::ops::IndexMut<usize>` is not implemented for `str`
+ = note: you can use `.chars().nth()` or `.bytes().nth()`
+ see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
error: aborting due to 3 previous errors
diff --git a/src/test/ui/suggestions/suggest-move-lifetimes.stderr b/src/test/ui/suggestions/suggest-move-lifetimes.stderr
index 72a2cbe..b36e927 100644
--- a/src/test/ui/suggestions/suggest-move-lifetimes.stderr
+++ b/src/test/ui/suggestions/suggest-move-lifetimes.stderr
@@ -16,7 +16,7 @@
help: move the lifetime parameter prior to the first type parameter
|
LL | struct B<'a, T, U> { //~ ERROR lifetime parameters must be declared
- | ^^^ --
+ | ^^^ --
error: lifetime parameters must be declared prior to type parameters
--> $DIR/suggest-move-lifetimes.rs:10:16
@@ -36,7 +36,7 @@
help: move the lifetime parameter prior to the first type parameter
|
LL | struct D<'a, 'b, 'c, T, U, V> { //~ ERROR lifetime parameters must be declared
- | ^^^ ^^^ ^^^ ---
+ | ^^^ ^^^ ^^^ -- --
error: aborting due to 4 previous errors
diff --git a/src/test/ui/thread-local-mutation.nll.stderr b/src/test/ui/thread-local-mutation.nll.stderr
new file mode 100644
index 0000000..0a3664b
--- /dev/null
+++ b/src/test/ui/thread-local-mutation.nll.stderr
@@ -0,0 +1,9 @@
+error[E0594]: cannot assign to immutable static item `S`
+ --> $DIR/thread-local-mutation.rs:11:5
+ |
+LL | S = "after"; //~ ERROR cannot assign to immutable
+ | ^^^^^^^^^^^ cannot assign
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/thread-local-mutation.rs b/src/test/ui/thread-local-mutation.rs
new file mode 100644
index 0000000..e738225
--- /dev/null
+++ b/src/test/ui/thread-local-mutation.rs
@@ -0,0 +1,18 @@
+// Regression test for #54901: immutable thread locals could be mutated. See:
+// https://github.com/rust-lang/rust/issues/29594#issuecomment-328177697
+// https://github.com/rust-lang/rust/issues/54901
+
+#![feature(thread_local)]
+
+#[thread_local]
+static S: &str = "before";
+
+fn set_s() {
+ S = "after"; //~ ERROR cannot assign to immutable
+}
+
+fn main() {
+ println!("{}", S);
+ set_s();
+ println!("{}", S);
+}
diff --git a/src/test/ui/thread-local-mutation.stderr b/src/test/ui/thread-local-mutation.stderr
new file mode 100644
index 0000000..bf29852
--- /dev/null
+++ b/src/test/ui/thread-local-mutation.stderr
@@ -0,0 +1,9 @@
+error[E0594]: cannot assign to immutable thread-local static item
+ --> $DIR/thread-local-mutation.rs:11:5
+ |
+LL | S = "after"; //~ ERROR cannot assign to immutable
+ | ^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0594`.
diff --git a/src/test/ui/traits/auxiliary/trait_alias.rs b/src/test/ui/traits/auxiliary/trait_alias.rs
new file mode 100644
index 0000000..9e56b87
--- /dev/null
+++ b/src/test/ui/traits/auxiliary/trait_alias.rs
@@ -0,0 +1,3 @@
+#![feature(trait_alias)]
+
+pub trait SendSync = Send + Sync;
diff --git a/src/test/ui/traits/trait-alias-cross-crate.rs b/src/test/ui/traits/trait-alias-cross-crate.rs
new file mode 100644
index 0000000..259fc4f
--- /dev/null
+++ b/src/test/ui/traits/trait-alias-cross-crate.rs
@@ -0,0 +1,17 @@
+// aux-build:trait_alias.rs
+
+#![feature(trait_alias)]
+
+extern crate trait_alias;
+
+use std::rc::Rc;
+use trait_alias::SendSync;
+
+fn use_alias<T: SendSync>() {}
+
+fn main() {
+ use_alias::<u32>();
+ use_alias::<Rc<u32>>();
+ //~^ ERROR `std::rc::Rc<u32>` cannot be sent between threads safely [E0277]
+ //~^^ ERROR `std::rc::Rc<u32>` cannot be shared between threads safely [E0277]
+}
diff --git a/src/test/ui/traits/trait-alias-cross-crate.stderr b/src/test/ui/traits/trait-alias-cross-crate.stderr
new file mode 100644
index 0000000..972d213
--- /dev/null
+++ b/src/test/ui/traits/trait-alias-cross-crate.stderr
@@ -0,0 +1,29 @@
+error[E0277]: `std::rc::Rc<u32>` cannot be sent between threads safely
+ --> $DIR/trait-alias-cross-crate.rs:14:5
+ |
+LL | use_alias::<Rc<u32>>();
+ | ^^^^^^^^^^^^^^^^^^^^ `std::rc::Rc<u32>` cannot be sent between threads safely
+ |
+ = help: the trait `std::marker::Send` is not implemented for `std::rc::Rc<u32>`
+note: required by `use_alias`
+ --> $DIR/trait-alias-cross-crate.rs:10:1
+ |
+LL | fn use_alias<T: SendSync>() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0277]: `std::rc::Rc<u32>` cannot be shared between threads safely
+ --> $DIR/trait-alias-cross-crate.rs:14:5
+ |
+LL | use_alias::<Rc<u32>>();
+ | ^^^^^^^^^^^^^^^^^^^^ `std::rc::Rc<u32>` cannot be shared between threads safely
+ |
+ = help: the trait `std::marker::Sync` is not implemented for `std::rc::Rc<u32>`
+note: required by `use_alias`
+ --> $DIR/trait-alias-cross-crate.rs:10:1
+ |
+LL | fn use_alias<T: SendSync>() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/try-block/try-block-in-edition2015.stderr b/src/test/ui/try-block/try-block-in-edition2015.stderr
index 6365008..a7b8106 100644
--- a/src/test/ui/try-block/try-block-in-edition2015.stderr
+++ b/src/test/ui/try-block/try-block-in-edition2015.stderr
@@ -15,7 +15,7 @@
--> $DIR/try-block-in-edition2015.rs:4:33
|
LL | let try_result: Option<_> = try {
- | ^^^ did you mean `try!(...)`?
+ | ^^^ help: use `!` to invoke the macro: `try!`
error: aborting due to 2 previous errors
diff --git a/src/test/ui/type-alias-enum-variants-priority-2.rs b/src/test/ui/type-alias-enum-variants-priority-2.rs
new file mode 100644
index 0000000..295f8ac
--- /dev/null
+++ b/src/test/ui/type-alias-enum-variants-priority-2.rs
@@ -0,0 +1,13 @@
+#![feature(type_alias_enum_variants)]
+
+enum E {
+ V(u8)
+}
+
+impl E {
+ fn V() {}
+}
+
+fn main() {
+ <E>::V(); //~ ERROR this function takes 1 parameter but 0 parameters were supplied
+}
diff --git a/src/test/ui/type-alias-enum-variants-priority-2.stderr b/src/test/ui/type-alias-enum-variants-priority-2.stderr
new file mode 100644
index 0000000..c6ec96e
--- /dev/null
+++ b/src/test/ui/type-alias-enum-variants-priority-2.stderr
@@ -0,0 +1,12 @@
+error[E0061]: this function takes 1 parameter but 0 parameters were supplied
+ --> $DIR/type-alias-enum-variants-priority-2.rs:12:5
+ |
+LL | V(u8)
+ | ----- defined here
+...
+LL | <E>::V(); //~ ERROR this function takes 1 parameter but 0 parameters were supplied
+ | ^^^^^^^^ expected 1 parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0061`.
diff --git a/src/test/ui/type-alias-enum-variants-priority-3.rs b/src/test/ui/type-alias-enum-variants-priority-3.rs
new file mode 100644
index 0000000..33f9655
--- /dev/null
+++ b/src/test/ui/type-alias-enum-variants-priority-3.rs
@@ -0,0 +1,10 @@
+#![feature(type_alias_enum_variants)]
+
+enum E {
+ V
+}
+
+fn check() -> <E>::V {}
+//~^ ERROR expected type, found variant `V`
+
+fn main() {}
diff --git a/src/test/ui/type-alias-enum-variants-priority-3.stderr b/src/test/ui/type-alias-enum-variants-priority-3.stderr
new file mode 100644
index 0000000..b345154
--- /dev/null
+++ b/src/test/ui/type-alias-enum-variants-priority-3.stderr
@@ -0,0 +1,8 @@
+error: expected type, found variant `V`
+ --> $DIR/type-alias-enum-variants-priority-3.rs:7:15
+ |
+LL | fn check() -> <E>::V {}
+ | ^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/type-alias-enum-variants-priority.rs b/src/test/ui/type-alias-enum-variants-priority.rs
new file mode 100644
index 0000000..db1da2b
--- /dev/null
+++ b/src/test/ui/type-alias-enum-variants-priority.rs
@@ -0,0 +1,20 @@
+#![feature(type_alias_enum_variants)]
+#![deny(ambiguous_associated_items)]
+
+enum E {
+ V
+}
+
+trait Tr {
+ type V;
+ fn f() -> Self::V;
+}
+
+impl Tr for E {
+ type V = u8;
+ fn f() -> Self::V { 0 }
+ //~^ ERROR ambiguous associated item
+ //~| WARN this was previously accepted
+}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-enum-variants-priority.stderr b/src/test/ui/type-alias-enum-variants-priority.stderr
new file mode 100644
index 0000000..dcf7dc7
--- /dev/null
+++ b/src/test/ui/type-alias-enum-variants-priority.stderr
@@ -0,0 +1,26 @@
+error: ambiguous associated item
+ --> $DIR/type-alias-enum-variants-priority.rs:15:15
+ |
+LL | fn f() -> Self::V { 0 }
+ | ^^^^^^^ help: use fully-qualified syntax: `<E as Trait>::V`
+ |
+note: lint level defined here
+ --> $DIR/type-alias-enum-variants-priority.rs:2:9
+ |
+LL | #![deny(ambiguous_associated_items)]
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = 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 #57644 <https://github.com/rust-lang/rust/issues/57644>
+note: `V` could refer to variant defined here
+ --> $DIR/type-alias-enum-variants-priority.rs:5:5
+ |
+LL | V
+ | ^
+note: `V` could also refer to associated type defined here
+ --> $DIR/type-alias-enum-variants-priority.rs:9:5
+ |
+LL | type V;
+ | ^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index 8c1baa5..4ca285b 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -95,6 +95,7 @@
"wasm32-unknown-unknown",
"x86_64-apple-darwin",
"x86_64-apple-ios",
+ "x86_64-fortanix-unknown-sgx",
"x86_64-fuchsia",
"x86_64-linux-android",
"x86_64-pc-windows-gnu",