Rollup merge of #57604 - alercah:str-index, r=sfackler
Make `str` indexing generic on `SliceIndex`.
Fixes #55603
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/appveyor.yml b/appveyor.yml
index f043b8b..d70ad54 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -5,12 +5,6 @@
# server goes down presumably. See #43333 for more info
CARGO_HTTP_CHECK_REVOKE: false
- # Recommended by AppVeyor this moves our builds to GCE which incurs a 3-4
- # minute startup overhead, but that's paltry compared to our overall build
- # times so we're will to eat the cost. This is intended to give us better
- # performance I believe!
- appveyor_build_worker_cloud: gce
-
matrix:
# 32/64 bit MSVC tests
- MSYS_BITS: 64
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/bootstrap.py b/src/bootstrap/bootstrap.py
index f3dbae6..e8c1594 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -230,6 +230,9 @@
err = "unknown OS type: {}".format(ostype)
sys.exit(err)
+ if cputype == 'powerpc' and ostype == 'unknown-freebsd':
+ cputype = subprocess.check_output(
+ ['uname', '-p']).strip().decode(default_encoding)
cputype_mapper = {
'BePC': 'i686',
'aarch64': 'aarch64',
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 9c58f5b..31adab6 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -660,6 +660,15 @@
}
}
+ /// Get the paths to all of the compiler's codegen backends.
+ fn codegen_backends(&self, compiler: Compiler) -> impl Iterator<Item = PathBuf> {
+ fs::read_dir(self.sysroot_codegen_backends(compiler))
+ .into_iter()
+ .flatten()
+ .filter_map(Result::ok)
+ .map(|entry| entry.path())
+ }
+
pub fn rustdoc(&self, host: Interned<String>) -> PathBuf {
self.ensure(tool::Rustdoc { host })
}
@@ -750,6 +759,9 @@
match mode {
Mode::Std => {
self.clear_if_dirty(&my_out, &self.rustc(compiler));
+ for backend in self.codegen_backends(compiler) {
+ self.clear_if_dirty(&my_out, &backend);
+ }
},
Mode::Test => {
self.clear_if_dirty(&my_out, &libstd_stamp);
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/dist.rs b/src/bootstrap/dist.rs
index df34dfe..71662e8 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -602,6 +602,8 @@
// gdb debugger scripts
builder.install(&builder.src.join("src/etc/rust-gdb"), &sysroot.join("bin"),
0o755);
+ builder.install(&builder.src.join("src/etc/rust-gdbgui"), &sysroot.join("bin"),
+ 0o755);
cp_debugger_script("gdb_load_rust_pretty_printers.py");
cp_debugger_script("gdb_rust_pretty_printing.py");
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/unstable-book/src/library-features/is-sorted.md b/src/doc/unstable-book/src/library-features/is-sorted.md
new file mode 100644
index 0000000..e3b7dc3
--- /dev/null
+++ b/src/doc/unstable-book/src/library-features/is-sorted.md
@@ -0,0 +1,11 @@
+# `is_sorted`
+
+The tracking issue for this feature is: [#53485]
+
+[#53485]: https://github.com/rust-lang/rust/issues/53485
+
+------------------------
+
+Add the methods `is_sorted`, `is_sorted_by` and `is_sorted_by_key` to `[T]`;
+add the methods `is_sorted`, `is_sorted_by` and `is_sorted_by_key` to
+`Iterator`.
diff --git a/src/libcore/benches/fmt.rs b/src/libcore/benches/fmt.rs
new file mode 100644
index 0000000..92f10c7
--- /dev/null
+++ b/src/libcore/benches/fmt.rs
@@ -0,0 +1,110 @@
+use std::io::{self, Write as IoWrite};
+use std::fmt::{self, Write as FmtWrite};
+use test::Bencher;
+
+#[bench]
+fn write_vec_value(bh: &mut Bencher) {
+ bh.iter(|| {
+ let mut mem = Vec::new();
+ for _ in 0..1000 {
+ mem.write_all("abc".as_bytes()).unwrap();
+ }
+ });
+}
+
+#[bench]
+fn write_vec_ref(bh: &mut Bencher) {
+ bh.iter(|| {
+ let mut mem = Vec::new();
+ let wr = &mut mem as &mut dyn io::Write;
+ for _ in 0..1000 {
+ wr.write_all("abc".as_bytes()).unwrap();
+ }
+ });
+}
+
+#[bench]
+fn write_vec_macro1(bh: &mut Bencher) {
+ bh.iter(|| {
+ let mut mem = Vec::new();
+ let wr = &mut mem as &mut dyn io::Write;
+ for _ in 0..1000 {
+ write!(wr, "abc").unwrap();
+ }
+ });
+}
+
+#[bench]
+fn write_vec_macro2(bh: &mut Bencher) {
+ bh.iter(|| {
+ let mut mem = Vec::new();
+ let wr = &mut mem as &mut dyn io::Write;
+ for _ in 0..1000 {
+ write!(wr, "{}", "abc").unwrap();
+ }
+ });
+}
+
+#[bench]
+fn write_vec_macro_debug(bh: &mut Bencher) {
+ bh.iter(|| {
+ let mut mem = Vec::new();
+ let wr = &mut mem as &mut dyn io::Write;
+ for _ in 0..1000 {
+ write!(wr, "{:?}", "☃").unwrap();
+ }
+ });
+}
+
+#[bench]
+fn write_str_value(bh: &mut Bencher) {
+ bh.iter(|| {
+ let mut mem = String::new();
+ for _ in 0..1000 {
+ mem.write_str("abc").unwrap();
+ }
+ });
+}
+
+#[bench]
+fn write_str_ref(bh: &mut Bencher) {
+ bh.iter(|| {
+ let mut mem = String::new();
+ let wr = &mut mem as &mut dyn fmt::Write;
+ for _ in 0..1000 {
+ wr.write_str("abc").unwrap();
+ }
+ });
+}
+
+#[bench]
+fn write_str_macro1(bh: &mut Bencher) {
+ bh.iter(|| {
+ let mut mem = String::new();
+ for _ in 0..1000 {
+ write!(mem, "abc").unwrap();
+ }
+ });
+}
+
+#[bench]
+fn write_str_macro2(bh: &mut Bencher) {
+ bh.iter(|| {
+ let mut mem = String::new();
+ let wr = &mut mem as &mut dyn fmt::Write;
+ for _ in 0..1000 {
+ write!(wr, "{}", "abc").unwrap();
+ }
+ });
+}
+
+#[bench]
+fn write_str_macro_debug(bh: &mut Bencher) {
+ bh.iter(|| {
+ let mut mem = String::new();
+ let wr = &mut mem as &mut dyn fmt::Write;
+ for _ in 0..1000 {
+ write!(wr, "{:?}", "☃").unwrap();
+ }
+ });
+}
diff --git a/src/libcore/benches/lib.rs b/src/libcore/benches/lib.rs
index 5b4971c..48572af 100644
--- a/src/libcore/benches/lib.rs
+++ b/src/libcore/benches/lib.rs
@@ -11,3 +11,4 @@
mod num;
mod ops;
mod slice;
+mod fmt;
diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs
index 08b5ac0..203be54 100644
--- a/src/libcore/convert.rs
+++ b/src/libcore/convert.rs
@@ -463,11 +463,11 @@
// Infallible conversions are semantically equivalent to fallible conversions
// with an uninhabited error type.
#[unstable(feature = "try_from", issue = "33417")]
-impl<T, U> TryFrom<U> for T where T: From<U> {
+impl<T, U> TryFrom<U> for T where U: Into<T> {
type Error = !;
fn try_from(value: U) -> Result<Self, Self::Error> {
- Ok(T::from(value))
+ Ok(U::into(value))
}
}
diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs
index 214b5d3..935579f 100644
--- a/src/libcore/fmt/mod.rs
+++ b/src/libcore/fmt/mod.rs
@@ -211,9 +211,18 @@
}
}
-/// A struct to represent both where to emit formatting strings to and how they
-/// should be formatted. A mutable version of this is passed to all formatting
-/// traits.
+/// Configuration for formatting.
+///
+/// A `Formatter` represents various options related to formatting. Users do not
+/// construct `Formatter`s directly; a mutable reference to one is passed to
+/// the `fmt` method of all formatting traits, like [`Debug`] and [`Display`].
+///
+/// To interact with a `Formatter`, you'll call various methods to change the
+/// various options related to formatting. For examples, please see the
+/// documentation of the methods defined on `Formatter` below.
+///
+/// [`Debug`]: trait.Debug.html
+/// [`Display`]: trait.Display.html
#[allow(missing_debug_implementations)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Formatter<'a> {
@@ -997,28 +1006,30 @@
curarg: args.args.iter(),
};
- let mut pieces = args.pieces.iter();
+ let mut idx = 0;
match args.fmt {
None => {
// We can use default formatting parameters for all arguments.
- for (arg, piece) in args.args.iter().zip(pieces.by_ref()) {
+ for (arg, piece) in args.args.iter().zip(args.pieces.iter()) {
formatter.buf.write_str(*piece)?;
(arg.formatter)(arg.value, &mut formatter)?;
+ idx += 1;
}
}
Some(fmt) => {
// Every spec has a corresponding argument that is preceded by
// a string piece.
- for (arg, piece) in fmt.iter().zip(pieces.by_ref()) {
+ for (arg, piece) in fmt.iter().zip(args.pieces.iter()) {
formatter.buf.write_str(*piece)?;
formatter.run(arg)?;
+ idx += 1;
}
}
}
// There can be only one trailing string piece left.
- if let Some(piece) = pieces.next() {
+ if let Some(piece) = args.pieces.get(idx) {
formatter.buf.write_str(*piece)?;
}
diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs
index 0ad29af..ac21586 100644
--- a/src/libcore/iter/iterator.rs
+++ b/src/libcore/iter/iterator.rs
@@ -2605,6 +2605,95 @@
}
}
}
+
+ /// Checks if the elements of this iterator are sorted.
+ ///
+ /// That is, for each element `a` and its following element `b`, `a <= b` must hold. If the
+ /// iterator yields exactly zero or one element, `true` is returned.
+ ///
+ /// Note that if `Self::Item` is only `PartialOrd`, but not `Ord`, the above definition
+ /// implies that this function returns `false` if any two consecutive items are not
+ /// comparable.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(is_sorted)]
+ ///
+ /// assert!([1, 2, 2, 9].iter().is_sorted());
+ /// assert!(![1, 3, 2, 4].iter().is_sorted());
+ /// assert!([0].iter().is_sorted());
+ /// assert!(std::iter::empty::<i32>().is_sorted());
+ /// assert!(![0.0, 1.0, std::f32::NAN].iter().is_sorted());
+ /// ```
+ #[inline]
+ #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
+ fn is_sorted(self) -> bool
+ where
+ Self: Sized,
+ Self::Item: PartialOrd,
+ {
+ self.is_sorted_by(|a, b| a.partial_cmp(b))
+ }
+
+ /// Checks if the elements of this iterator are sorted using the given comparator function.
+ ///
+ /// Instead of using `PartialOrd::partial_cmp`, this function uses the given `compare`
+ /// function to determine the ordering of two elements. Apart from that, it's equivalent to
+ /// [`is_sorted`]; see its documentation for more information.
+ ///
+ /// [`is_sorted`]: trait.Iterator.html#method.is_sorted
+ #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
+ fn is_sorted_by<F>(mut self, mut compare: F) -> bool
+ where
+ Self: Sized,
+ F: FnMut(&Self::Item, &Self::Item) -> Option<Ordering>
+ {
+ let mut last = match self.next() {
+ Some(e) => e,
+ None => return true,
+ };
+
+ while let Some(curr) = self.next() {
+ if compare(&last, &curr)
+ .map(|o| o == Ordering::Greater)
+ .unwrap_or(true)
+ {
+ return false;
+ }
+ last = curr;
+ }
+
+ true
+ }
+
+ /// Checks if the elements of this iterator are sorted using the given key extraction
+ /// function.
+ ///
+ /// Instead of comparing the iterator's elements directly, this function compares the keys of
+ /// the elements, as determined by `f`. Apart from that, it's equivalent to [`is_sorted`]; see
+ /// its documentation for more information.
+ ///
+ /// [`is_sorted`]: trait.Iterator.html#method.is_sorted
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(is_sorted)]
+ ///
+ /// assert!(["c", "bb", "aaa"].iter().is_sorted_by_key(|s| s.len()));
+ /// assert!(![-2i32, -1, 0, 3].iter().is_sorted_by_key(|n| n.abs()));
+ /// ```
+ #[inline]
+ #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
+ fn is_sorted_by_key<F, K>(self, mut f: F) -> bool
+ where
+ Self: Sized,
+ F: FnMut(&Self::Item) -> K,
+ K: PartialOrd
+ {
+ self.is_sorted_by(|a, b| f(a).partial_cmp(&f(b)))
+ }
}
/// Select an element from an iterator based on the given "projection"
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 33c0da8..df32cfa 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -79,6 +79,7 @@
#![feature(extern_types)]
#![feature(fundamental)]
#![feature(intrinsics)]
+#![feature(is_sorted)]
#![feature(iter_once_with)]
#![feature(lang_items)]
#![feature(link_llvm_intrinsics)]
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index 6827364..41caa17 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -10,9 +10,9 @@
use str::FromStr;
macro_rules! impl_nonzero_fmt {
- ( ( $( $Trait: ident ),+ ) for $Ty: ident ) => {
+ ( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => {
$(
- #[stable(feature = "nonzero", since = "1.28.0")]
+ #[$stability]
impl fmt::$Trait for $Ty {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -31,7 +31,7 @@
}
macro_rules! nonzero_integers {
- ( $( $Ty: ident($Int: ty); )+ ) => {
+ ( $( #[$stability: meta] $Ty: ident($Int: ty); )+ ) => {
$(
doc_comment! {
concat!("An integer that is known not to equal zero.
@@ -41,10 +41,10 @@
```rust
use std::mem::size_of;
-assert_eq!(size_of::<Option<std::num::", stringify!($Ty), ">>(), size_of::<", stringify!($Int),
+assert_eq!(size_of::<Option<core::num::", stringify!($Ty), ">>(), size_of::<", stringify!($Int),
">());
```"),
- #[stable(feature = "nonzero", since = "1.28.0")]
+ #[$stability]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start(1)]
@@ -57,14 +57,14 @@
/// # Safety
///
/// The value must not be zero.
- #[stable(feature = "nonzero", since = "1.28.0")]
+ #[$stability]
#[inline]
pub const unsafe fn new_unchecked(n: $Int) -> Self {
$Ty(n)
}
/// Create a non-zero if the given value is not zero.
- #[stable(feature = "nonzero", since = "1.28.0")]
+ #[$stability]
#[inline]
pub fn new(n: $Int) -> Option<Self> {
if n != 0 {
@@ -75,7 +75,7 @@
}
/// Returns the value as a primitive type.
- #[stable(feature = "nonzero", since = "1.28.0")]
+ #[$stability]
#[inline]
pub const fn get(self) -> $Int {
self.0
@@ -91,19 +91,25 @@
}
impl_nonzero_fmt! {
- (Debug, Display, Binary, Octal, LowerHex, UpperHex) for $Ty
+ #[$stability] (Debug, Display, Binary, Octal, LowerHex, UpperHex) for $Ty
}
)+
}
}
nonzero_integers! {
- NonZeroU8(u8);
- NonZeroU16(u16);
- NonZeroU32(u32);
- NonZeroU64(u64);
- NonZeroU128(u128);
- NonZeroUsize(usize);
+ #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU8(u8);
+ #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU16(u16);
+ #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU32(u32);
+ #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU64(u64);
+ #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU128(u128);
+ #[stable(feature = "nonzero", since = "1.28.0")] NonZeroUsize(usize);
+ #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI8(i8);
+ #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI16(i16);
+ #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI32(i32);
+ #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI64(i64);
+ #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI128(i128);
+ #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroIsize(isize);
}
/// Provides intentionally-wrapped arithmetic on `T`.
diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs
index 2245d48..9f9515e 100644
--- a/src/libcore/slice/mod.rs
+++ b/src/libcore/slice/mod.rs
@@ -1783,7 +1783,7 @@
/// let mut a = ['a', 'b', 'c', 'd', 'e', 'f'];
/// a[1..5].rotate_left(1);
/// assert_eq!(a, ['a', 'c', 'd', 'e', 'b', 'f']);
- /// ```
+ /// ```
#[stable(feature = "slice_rotate", since = "1.26.0")]
pub fn rotate_left(&mut self, mid: usize) {
assert!(mid <= self.len());
@@ -2250,6 +2250,77 @@
from_raw_parts_mut(mut_ptr.add(rest.len() - ts_len), ts_len))
}
}
+
+ /// Checks if the elements of this slice are sorted.
+ ///
+ /// That is, for each element `a` and its following element `b`, `a <= b` must hold. If the
+ /// slice yields exactly zero or one element, `true` is returned.
+ ///
+ /// Note that if `Self::Item` is only `PartialOrd`, but not `Ord`, the above definition
+ /// implies that this function returns `false` if any two consecutive items are not
+ /// comparable.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(is_sorted)]
+ /// let empty: [i32; 0] = [];
+ ///
+ /// assert!([1, 2, 2, 9].is_sorted());
+ /// assert!(![1, 3, 2, 4].is_sorted());
+ /// assert!([0].is_sorted());
+ /// assert!(empty.is_sorted());
+ /// assert!(![0.0, 1.0, std::f32::NAN].is_sorted());
+ /// ```
+ #[inline]
+ #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
+ pub fn is_sorted(&self) -> bool
+ where
+ T: PartialOrd,
+ {
+ self.is_sorted_by(|a, b| a.partial_cmp(b))
+ }
+
+ /// Checks if the elements of this slice are sorted using the given comparator function.
+ ///
+ /// Instead of using `PartialOrd::partial_cmp`, this function uses the given `compare`
+ /// function to determine the ordering of two elements. Apart from that, it's equivalent to
+ /// [`is_sorted`]; see its documentation for more information.
+ ///
+ /// [`is_sorted`]: #method.is_sorted
+ #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
+ pub fn is_sorted_by<F>(&self, mut compare: F) -> bool
+ where
+ F: FnMut(&T, &T) -> Option<Ordering>
+ {
+ self.iter().is_sorted_by(|a, b| compare(*a, *b))
+ }
+
+ /// Checks if the elements of this slice are sorted using the given key extraction function.
+ ///
+ /// Instead of comparing the slice's elements directly, this function compares the keys of the
+ /// elements, as determined by `f`. Apart from that, it's equivalent to [`is_sorted`]; see its
+ /// documentation for more information.
+ ///
+ /// [`is_sorted`]: #method.is_sorted
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(is_sorted)]
+ ///
+ /// assert!(["c", "bb", "aaa"].is_sorted_by_key(|s| s.len()));
+ /// assert!(![-2i32, -1, 0, 3].is_sorted_by_key(|n| n.abs()));
+ /// ```
+ #[inline]
+ #[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
+ pub fn is_sorted_by_key<F, K>(&self, mut f: F) -> bool
+ where
+ F: FnMut(&T) -> K,
+ K: PartialOrd
+ {
+ self.is_sorted_by(|a, b| f(a).partial_cmp(&f(b)))
+ }
}
#[lang = "slice_u8"]
@@ -2783,7 +2854,13 @@
// The shared definition of the `Iter` and `IterMut` iterators
macro_rules! iterator {
- (struct $name:ident -> $ptr:ty, $elem:ty, $raw_mut:tt, $( $mut_:tt )*) => {
+ (
+ struct $name:ident -> $ptr:ty,
+ $elem:ty,
+ $raw_mut:tt,
+ {$( $mut_:tt )*},
+ {$($extra:tt)*}
+ ) => {
impl<'a, T> $name<'a, T> {
// Helper function for creating a slice from the iterator.
#[inline(always)]
@@ -2960,6 +3037,8 @@
i
})
}
+
+ $($extra)*
}
#[stable(feature = "rust1", since = "1.0.0")]
@@ -3097,7 +3176,17 @@
}
}
-iterator!{struct Iter -> *const T, &'a T, const, /* no mut */}
+iterator!{struct Iter -> *const T, &'a T, const, {/* no mut */}, {
+ fn is_sorted_by<F>(self, mut compare: F) -> bool
+ where
+ Self: Sized,
+ F: FnMut(&Self::Item, &Self::Item) -> Option<Ordering>,
+ {
+ self.as_slice().windows(2).all(|w| {
+ compare(&&w[0], &&w[1]).map(|o| o != Ordering::Greater).unwrap_or(false)
+ })
+ }
+}}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Clone for Iter<'_, T> {
@@ -3198,7 +3287,7 @@
}
}
-iterator!{struct IterMut -> *mut T, &'a mut T, mut, mut}
+iterator!{struct IterMut -> *mut T, &'a mut T, mut, {mut}, {}}
/// An internal abstraction over the splitting iterators, so that
/// splitn, splitn_mut etc can be implemented once.
diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs
index 3944bc7..0fa9974 100644
--- a/src/libcore/tests/iter.rs
+++ b/src/libcore/tests/iter.rs
@@ -2235,3 +2235,16 @@
assert_eq!((0..10).flat_map(f).flat_map(g).sum::<usize>(),
(0..10).flat_map(|x| f(x).flat_map(g)).sum::<usize>());
}
+
+#[test]
+fn test_is_sorted() {
+ assert!([1, 2, 2, 9].iter().is_sorted());
+ assert!(![1, 3, 2].iter().is_sorted());
+ assert!([0].iter().is_sorted());
+ assert!(std::iter::empty::<i32>().is_sorted());
+ assert!(![0.0, 1.0, std::f32::NAN].iter().is_sorted());
+ assert!([-2, -1, 0, 3].iter().is_sorted());
+ assert!(![-2i32, -1, 0, 3].iter().is_sorted_by_key(|n| n.abs()));
+ assert!(!["c", "bb", "aaa"].iter().is_sorted());
+ assert!(["c", "bb", "aaa"].iter().is_sorted_by_key(|s| s.len()));
+}
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index a9b8dec..3e8549f 100644
--- a/src/libcore/tests/lib.rs
+++ b/src/libcore/tests/lib.rs
@@ -10,6 +10,7 @@
#![feature(flt2dec)]
#![feature(fmt_internals)]
#![feature(hashmap_internals)]
+#![feature(is_sorted)]
#![feature(iter_copied)]
#![feature(iter_nth_back)]
#![feature(iter_once_with)]
diff --git a/src/libcore/tests/nonzero.rs b/src/libcore/tests/nonzero.rs
index c813bf2..4532568 100644
--- a/src/libcore/tests/nonzero.rs
+++ b/src/libcore/tests/nonzero.rs
@@ -1,4 +1,4 @@
-use core::num::NonZeroU32;
+use core::num::{NonZeroU32, NonZeroI32};
use core::option::Option;
use core::option::Option::{Some, None};
use std::mem::size_of;
@@ -13,6 +13,7 @@
#[test]
fn test_size_nonzero_in_option() {
assert_eq!(size_of::<NonZeroU32>(), size_of::<Option<NonZeroU32>>());
+ assert_eq!(size_of::<NonZeroI32>(), size_of::<Option<NonZeroI32>>());
}
#[test]
@@ -118,3 +119,10 @@
let num: u32 = nz.into();
assert_eq!(num, 1u32);
}
+
+#[test]
+fn test_from_signed_nonzero() {
+ let nz = NonZeroI32::new(1).unwrap();
+ let num: i32 = nz.into();
+ assert_eq!(num, 1i32);
+}
diff --git a/src/libcore/tests/slice.rs b/src/libcore/tests/slice.rs
index 2c96efb..e210e83 100644
--- a/src/libcore/tests/slice.rs
+++ b/src/libcore/tests/slice.rs
@@ -1317,3 +1317,18 @@
// 2 is greater than 1, so this range is invalid.
bytes.copy_within(2..1, 0);
}
+
+#[test]
+fn test_is_sorted() {
+ let empty: [i32; 0] = [];
+
+ assert!([1, 2, 2, 9].is_sorted());
+ assert!(![1, 3, 2].is_sorted());
+ assert!([0].is_sorted());
+ assert!(empty.is_sorted());
+ assert!(![0.0, 1.0, std::f32::NAN].is_sorted());
+ assert!([-2, -1, 0, 3].is_sorted());
+ assert!(![-2i32, -1, 0, 3].is_sorted_by_key(|n| n.abs()));
+ assert!(!["c", "bb", "aaa"].is_sorted());
+ assert!(["c", "bb", "aaa"].is_sorted_by_key(|s| s.len()));
+}
diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs
index 32ae878..da440cd 100644
--- a/src/libfmt_macros/lib.rs
+++ b/src/libfmt_macros/lib.rs
@@ -72,6 +72,15 @@
ArgumentNamed(&'a str),
}
+impl Position<'_> {
+ pub fn index(&self) -> Option<usize> {
+ match self {
+ ArgumentIs(i) | ArgumentImplicitlyIs(i) => Some(*i),
+ _ => None,
+ }
+ }
+}
+
/// Enum of alignments which are supported.
#[derive(Copy, Clone, PartialEq)]
pub enum Alignment {
diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs
index 978d20e..6122fe6 100644
--- a/src/librustc/cfg/construct.rs
+++ b/src/librustc/cfg/construct.rs
@@ -99,30 +99,21 @@
}
fn stmt(&mut self, stmt: &hir::Stmt, pred: CFGIndex) -> CFGIndex {
- let hir_id = self.tcx.hir().node_to_hir_id(stmt.node.id());
- match stmt.node {
- hir::StmtKind::Decl(ref decl, _) => {
- let exit = self.decl(&decl, pred);
- self.add_ast_node(hir_id.local_id, &[exit])
- }
-
- hir::StmtKind::Expr(ref expr, _) |
- hir::StmtKind::Semi(ref expr, _) => {
- let exit = self.expr(&expr, pred);
- self.add_ast_node(hir_id.local_id, &[exit])
- }
- }
- }
-
- fn decl(&mut self, decl: &hir::Decl, pred: CFGIndex) -> CFGIndex {
- match decl.node {
- hir::DeclKind::Local(ref local) => {
+ let hir_id = self.tcx.hir().node_to_hir_id(stmt.id);
+ let exit = match stmt.node {
+ hir::StmtKind::Local(ref local) => {
let init_exit = self.opt_expr(&local.init, pred);
self.pat(&local.pat, init_exit)
}
-
- hir::DeclKind::Item(_) => pred,
- }
+ hir::StmtKind::Item(_) => {
+ pred
+ }
+ hir::StmtKind::Expr(ref expr) |
+ hir::StmtKind::Semi(ref expr) => {
+ self.expr(&expr, pred)
+ }
+ };
+ self.add_ast_node(hir_id.local_id, &[exit])
}
fn pat(&mut self, pat: &hir::Pat, pred: CFGIndex) -> CFGIndex {
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 0a0dff0..a9e80dd 100644
--- a/src/librustc/dep_graph/graph.rs
+++ b/src/librustc/dep_graph/graph.rs
@@ -638,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
diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs
index b4a0071..df111b2 100644
--- a/src/librustc/hir/check_attr.rs
+++ b/src/librustc/hir/check_attr.rs
@@ -283,8 +283,8 @@
fn check_stmt_attributes(&self, stmt: &hir::Stmt) {
// When checking statements ignore expressions, they will be checked later
- if let hir::StmtKind::Decl(_, _) = stmt.node {
- for attr in stmt.node.attrs() {
+ if let hir::StmtKind::Local(ref l) = stmt.node {
+ for attr in l.attrs.iter() {
if attr.check_name("inline") {
self.check_inline(attr, &stmt.span, Target::Statement);
}
diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs
index f633703..592fb78 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()`
@@ -260,9 +258,6 @@
fn visit_pat(&mut self, p: &'v Pat) {
walk_pat(self, p)
}
- fn visit_decl(&mut self, d: &'v Decl) {
- walk_decl(self, d)
- }
fn visit_anon_const(&mut self, c: &'v AnonConst) {
walk_anon_const(self, c)
}
@@ -953,26 +948,17 @@
}
pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt) {
+ visitor.visit_id(statement.id);
match statement.node {
- StmtKind::Decl(ref declaration, id) => {
- visitor.visit_id(id);
- visitor.visit_decl(declaration)
- }
- StmtKind::Expr(ref expression, id) |
- StmtKind::Semi(ref expression, id) => {
- visitor.visit_id(id);
+ StmtKind::Local(ref local) => visitor.visit_local(local),
+ StmtKind::Item(ref item) => visitor.visit_nested_item(**item),
+ StmtKind::Expr(ref expression) |
+ StmtKind::Semi(ref expression) => {
visitor.visit_expr(expression)
}
}
}
-pub fn walk_decl<'v, V: Visitor<'v>>(visitor: &mut V, declaration: &'v Decl) {
- match declaration.node {
- DeclKind::Local(ref local) => visitor.visit_local(local),
- DeclKind::Item(item) => visitor.visit_nested_item(item),
- }
-}
-
pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonConst) {
visitor.visit_id(constant.id);
visitor.visit_nested_body(constant.body);
@@ -1133,57 +1119,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 8cdc493..f7af135 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -31,6 +31,7 @@
//! in the HIR, especially for multiple identifiers.
use dep_graph::DepGraph;
+use errors::Applicability;
use hir::{self, ParamName};
use hir::HirVec;
use hir::map::{DefKey, DefPathData, Definitions};
@@ -1806,7 +1807,7 @@
explicit_owner: Option<NodeId>,
) -> hir::PathSegment {
let (mut generic_args, infer_types) = if let Some(ref generic_args) = segment.args {
- let msg = "parenthesized parameters may only be used with a trait";
+ let msg = "parenthesized type parameters may only be used with a `Fn` trait";
match **generic_args {
GenericArgs::AngleBracketed(ref data) => {
self.lower_angle_bracketed_parameter_data(data, param_mode, itctx)
@@ -1823,10 +1824,25 @@
(hir::GenericArgs::none(), true)
}
ParenthesizedGenericArgs::Err => {
- struct_span_err!(self.sess, data.span, E0214, "{}", msg)
- .span_label(data.span, "only traits may use parentheses")
- .emit();
- (hir::GenericArgs::none(), true)
+ let mut err = struct_span_err!(self.sess, data.span, E0214, "{}", msg);
+ err.span_label(data.span, "only `Fn` traits may use parentheses");
+ if let Ok(snippet) = self.sess.source_map().span_to_snippet(data.span) {
+ // Do not suggest going from `Trait()` to `Trait<>`
+ if data.inputs.len() > 0 {
+ err.span_suggestion_with_applicability(
+ data.span,
+ "use angle brackets instead",
+ format!("<{}>", &snippet[1..snippet.len() - 1]),
+ Applicability::MaybeIncorrect,
+ );
+ }
+ };
+ err.emit();
+ (self.lower_angle_bracketed_parameter_data(
+ &data.as_angle_bracketed_args(),
+ param_mode,
+ itctx).0,
+ false)
}
},
}
@@ -1957,7 +1973,7 @@
)
}
- fn lower_local(&mut self, l: &Local) -> (P<hir::Local>, SmallVec<[hir::ItemId; 1]>) {
+ fn lower_local(&mut self, l: &Local) -> (hir::Local, SmallVec<[hir::ItemId; 1]>) {
let LoweredNodeId { node_id, hir_id } = self.lower_node_id(l.id);
let mut ids = SmallVec::<[hir::ItemId; 1]>::new();
if self.sess.features_untracked().impl_trait_in_bindings {
@@ -1967,7 +1983,7 @@
}
}
let parent_def_id = DefId::local(self.current_hir_id_owner.last().unwrap().0);
- (P(hir::Local {
+ (hir::Local {
id: node_id,
hir_id,
ty: l.ty
@@ -1984,7 +2000,7 @@
span: l.span,
attrs: l.attrs.clone(),
source: hir::LocalSource::Normal,
- }), ids)
+ }, ids)
}
fn lower_mutability(&mut self, m: Mutability) -> hir::Mutability {
@@ -4331,10 +4347,11 @@
ThinVec::new(),
))
};
- let match_stmt = respan(
- head_sp,
- hir::StmtKind::Expr(match_expr, self.next_id().node_id)
- );
+ let match_stmt = hir::Stmt {
+ id: self.next_id().node_id,
+ node: hir::StmtKind::Expr(match_expr),
+ span: head_sp,
+ };
let next_expr = P(self.expr_ident(head_sp, next_ident, next_pat.id));
@@ -4357,10 +4374,11 @@
let body_block = self.with_loop_scope(e.id, |this| this.lower_block(body, false));
let body_expr = P(self.expr_block(body_block, ThinVec::new()));
- let body_stmt = respan(
- body.span,
- hir::StmtKind::Expr(body_expr, self.next_id().node_id)
- );
+ let body_stmt = hir::Stmt {
+ id: self.next_id().node_id,
+ node: hir::StmtKind::Expr(body_expr),
+ span: body.span,
+ };
let loop_block = P(self.block_all(
e.span,
@@ -4533,25 +4551,15 @@
let (l, item_ids) = self.lower_local(l);
let mut ids: SmallVec<[hir::Stmt; 1]> = item_ids
.into_iter()
- .map(|item_id| Spanned {
- node: hir::StmtKind::Decl(
- P(Spanned {
- node: hir::DeclKind::Item(item_id),
- span: s.span,
- }),
- self.next_id().node_id,
- ),
+ .map(|item_id| hir::Stmt {
+ id: self.next_id().node_id,
+ node: hir::StmtKind::Item(P(item_id)),
span: s.span,
})
.collect();
- ids.push(Spanned {
- node: hir::StmtKind::Decl(
- P(Spanned {
- node: hir::DeclKind::Local(l),
- span: s.span,
- }),
- self.lower_node_id(s.id).node_id,
- ),
+ ids.push(hir::Stmt {
+ id: self.lower_node_id(s.id).node_id,
+ node: hir::StmtKind::Local(P(l)),
span: s.span,
});
return ids;
@@ -4561,26 +4569,23 @@
let mut id = Some(s.id);
return self.lower_item_id(it)
.into_iter()
- .map(|item_id| Spanned {
- node: hir::StmtKind::Decl(
- P(Spanned {
- node: hir::DeclKind::Item(item_id),
- span: s.span,
- }),
- id.take()
+ .map(|item_id| hir::Stmt {
+ id: id.take()
.map(|id| self.lower_node_id(id).node_id)
.unwrap_or_else(|| self.next_id().node_id),
- ),
+ node: hir::StmtKind::Item(P(item_id)),
span: s.span,
})
.collect();
}
- StmtKind::Expr(ref e) => Spanned {
- node: hir::StmtKind::Expr(P(self.lower_expr(e)), self.lower_node_id(s.id).node_id),
+ StmtKind::Expr(ref e) => hir::Stmt {
+ id: self.lower_node_id(s.id).node_id,
+ node: hir::StmtKind::Expr(P(self.lower_expr(e))),
span: s.span,
},
- StmtKind::Semi(ref e) => Spanned {
- node: hir::StmtKind::Semi(P(self.lower_expr(e)), self.lower_node_id(s.id).node_id),
+ StmtKind::Semi(ref e) => hir::Stmt {
+ id: self.lower_node_id(s.id).node_id,
+ node: hir::StmtKind::Semi(P(self.lower_expr(e))),
span: s.span,
},
StmtKind::Mac(..) => panic!("Shouldn't exist here"),
@@ -4795,7 +4800,7 @@
) -> hir::Stmt {
let LoweredNodeId { node_id, hir_id } = self.next_id();
- let local = P(hir::Local {
+ let local = hir::Local {
pat,
ty: None,
init: ex,
@@ -4804,9 +4809,12 @@
span: sp,
attrs: ThinVec::new(),
source,
- });
- let decl = respan(sp, hir::DeclKind::Local(local));
- respan(sp, hir::StmtKind::Decl(P(decl), self.next_id().node_id))
+ };
+ hir::Stmt {
+ id: self.next_id().node_id,
+ node: hir::StmtKind::Local(P(local)),
+ span: sp
+ }
}
fn stmt_let(
diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs
index ae9bb37..7cc5d75 100644
--- a/src/librustc/hir/map/collector.rs
+++ b/src/librustc/hir/map/collector.rs
@@ -426,7 +426,7 @@
}
fn visit_stmt(&mut self, stmt: &'hir Stmt) {
- let id = stmt.node.id();
+ let id = stmt.id;
self.insert(stmt.span, id, Node::Stmt(stmt));
self.with_parent(id, |this| {
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..c3e4f0c 100644
--- a/src/librustc/hir/map/mod.rs
+++ b/src/librustc/hir/map/mod.rs
@@ -455,11 +455,20 @@
Node::AnonConst(_) => {
BodyOwnerKind::Const
}
+ Node::Variant(&Spanned { node: VariantKind { data: VariantData::Tuple(..), .. }, .. }) |
+ Node::StructCtor(..) |
+ Node::Item(&Item { node: ItemKind::Fn(..), .. }) |
+ Node::TraitItem(&TraitItem { node: TraitItemKind::Method(..), .. }) |
+ Node::ImplItem(&ImplItem { node: ImplItemKind::Method(..), .. }) => {
+ BodyOwnerKind::Fn
+ }
Node::Item(&Item { node: ItemKind::Static(_, m, _), .. }) => {
BodyOwnerKind::Static(m)
}
- // Default to function if it's not a constant or static.
- _ => BodyOwnerKind::Fn
+ Node::Expr(&Expr { node: ExprKind::Closure(..), .. }) => {
+ BodyOwnerKind::Closure
+ }
+ node => bug!("{:#?} is not a body node", node),
}
}
@@ -509,6 +518,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 aaef1c7..b58b1d3 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -10,13 +10,14 @@
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};
use mir::mono::Linkage;
use syntax_pos::{Span, DUMMY_SP, symbol::InternedString};
-use syntax::source_map::{self, Spanned};
+use syntax::source_map::Spanned;
use rustc_target::spec::abi::Abi;
use syntax::ast::{self, CrateSugar, Ident, Name, NodeId, DUMMY_NODE_ID, AsmDialect};
use syntax::ast::{Attribute, Label, Lit, StrStyle, FloatTy, IntTy, UintTy};
@@ -1133,45 +1134,41 @@
}
/// A statement
-pub type Stmt = Spanned<StmtKind>;
+#[derive(Clone, RustcEncodable, RustcDecodable)]
+pub struct Stmt {
+ pub id: NodeId,
+ pub node: StmtKind,
+ pub span: Span,
+}
-impl fmt::Debug for StmtKind {
+impl fmt::Debug for Stmt {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- // Sadness.
- let spanned = source_map::dummy_spanned(self.clone());
- write!(f,
- "stmt({}: {})",
- spanned.node.id(),
- print::to_string(print::NO_ANN, |s| s.print_stmt(&spanned)))
+ write!(f, "stmt({}: {})", self.id,
+ print::to_string(print::NO_ANN, |s| s.print_stmt(self)))
}
}
#[derive(Clone, RustcEncodable, RustcDecodable)]
pub enum StmtKind {
- /// Could be an item or a local (let) binding:
- Decl(P<Decl>, NodeId),
+ /// A local (let) binding:
+ Local(P<Local>),
+ /// An item binding:
+ Item(P<ItemId>),
/// Expr without trailing semi-colon (must have unit type):
- Expr(P<Expr>, NodeId),
+ Expr(P<Expr>),
/// Expr with trailing semi-colon (may have any type):
- Semi(P<Expr>, NodeId),
+ Semi(P<Expr>),
}
impl StmtKind {
pub fn attrs(&self) -> &[Attribute] {
match *self {
- StmtKind::Decl(ref d, _) => d.node.attrs(),
- StmtKind::Expr(ref e, _) |
- StmtKind::Semi(ref e, _) => &e.attrs,
- }
- }
-
- pub fn id(&self) -> NodeId {
- match *self {
- StmtKind::Decl(_, id) |
- StmtKind::Expr(_, id) |
- StmtKind::Semi(_, id) => id,
+ StmtKind::Local(ref l) => &l.attrs,
+ StmtKind::Item(_) => &[],
+ StmtKind::Expr(ref e) |
+ StmtKind::Semi(ref e) => &e.attrs,
}
}
}
@@ -1190,32 +1187,6 @@
pub source: LocalSource,
}
-pub type Decl = Spanned<DeclKind>;
-
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
-pub enum DeclKind {
- /// A local (let) binding:
- Local(P<Local>),
- /// An item binding:
- Item(ItemId),
-}
-
-impl DeclKind {
- pub fn attrs(&self) -> &[Attribute] {
- match *self {
- DeclKind::Local(ref l) => &l.attrs,
- DeclKind::Item(_) => &[]
- }
- }
-
- pub fn is_local(&self) -> bool {
- match *self {
- DeclKind::Local(_) => true,
- _ => false,
- }
- }
-}
-
/// represents one arm of a 'match'
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct Arm {
@@ -1299,6 +1270,9 @@
/// Functions and methods.
Fn,
+ /// Closures
+ Closure,
+
/// Constants and associated constants.
Const,
@@ -1306,6 +1280,15 @@
Static(Mutability),
}
+impl BodyOwnerKind {
+ pub fn is_fn_or_closure(self) -> bool {
+ match self {
+ BodyOwnerKind::Fn | BodyOwnerKind::Closure => true,
+ BodyOwnerKind::Const | BodyOwnerKind::Static(_) => false,
+ }
+ }
+}
+
/// A constant (expression) that's not an item or associated item,
/// but needs its own `DefId` for type-checking, const-eval, etc.
/// These are usually found nested inside types (e.g., array lengths)
@@ -2055,6 +2038,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/hir/print.rs b/src/librustc/hir/print.rs
index d7acdef..e950f25 100644
--- a/src/librustc/hir/print.rs
+++ b/src/librustc/hir/print.rs
@@ -992,14 +992,29 @@
pub fn print_stmt(&mut self, st: &hir::Stmt) -> io::Result<()> {
self.maybe_print_comment(st.span.lo())?;
match st.node {
- hir::StmtKind::Decl(ref decl, _) => {
- self.print_decl(&decl)?;
+ hir::StmtKind::Local(ref loc) => {
+ self.space_if_not_bol()?;
+ self.ibox(indent_unit)?;
+ self.word_nbsp("let")?;
+
+ self.ibox(indent_unit)?;
+ self.print_local_decl(&loc)?;
+ self.end()?;
+ if let Some(ref init) = loc.init {
+ self.nbsp()?;
+ self.word_space("=")?;
+ self.print_expr(&init)?;
+ }
+ self.end()?
}
- hir::StmtKind::Expr(ref expr, _) => {
+ hir::StmtKind::Item(ref item) => {
+ self.ann.nested(self, Nested::Item(**item))?
+ }
+ hir::StmtKind::Expr(ref expr) => {
self.space_if_not_bol()?;
self.print_expr(&expr)?;
}
- hir::StmtKind::Semi(ref expr, _) => {
+ hir::StmtKind::Semi(ref expr) => {
self.space_if_not_bol()?;
self.print_expr(&expr)?;
self.s.word(";")?;
@@ -1562,30 +1577,6 @@
Ok(())
}
- pub fn print_decl(&mut self, decl: &hir::Decl) -> io::Result<()> {
- self.maybe_print_comment(decl.span.lo())?;
- match decl.node {
- hir::DeclKind::Local(ref loc) => {
- self.space_if_not_bol()?;
- self.ibox(indent_unit)?;
- self.word_nbsp("let")?;
-
- self.ibox(indent_unit)?;
- self.print_local_decl(&loc)?;
- self.end()?;
- if let Some(ref init) = loc.init {
- self.nbsp()?;
- self.word_space("=")?;
- self.print_expr(&init)?;
- }
- self.end()
- }
- hir::DeclKind::Item(item) => {
- self.ann.nested(self, Nested::Item(item))
- }
- }
- }
-
pub fn print_usize(&mut self, i: usize) -> io::Result<()> {
self.s.word(i.to_string())
}
@@ -2401,18 +2392,10 @@
/// seen the semicolon, and thus don't need another.
fn stmt_ends_with_semi(stmt: &hir::StmtKind) -> bool {
match *stmt {
- hir::StmtKind::Decl(ref d, _) => {
- match d.node {
- hir::DeclKind::Local(_) => true,
- hir::DeclKind::Item(_) => false,
- }
- }
- hir::StmtKind::Expr(ref e, _) => {
- expr_requires_semi_to_be_stmt(&e)
- }
- hir::StmtKind::Semi(..) => {
- false
- }
+ hir::StmtKind::Local(_) => true,
+ hir::StmtKind::Item(_) => false,
+ hir::StmtKind::Expr(ref e) => expr_requires_semi_to_be_stmt(&e),
+ hir::StmtKind::Semi(..) => false,
}
}
diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs
index f48059b..1590676 100644
--- a/src/librustc/ich/impls_hir.rs
+++ b/src/librustc/ich/impls_hir.rs
@@ -483,7 +483,12 @@
UnNeg
});
-impl_stable_hash_for_spanned!(hir::StmtKind);
+impl_stable_hash_for!(struct hir::Stmt {
+ id,
+ node,
+ span,
+});
+
impl_stable_hash_for!(struct hir::Local {
pat,
@@ -496,12 +501,6 @@
source
});
-impl_stable_hash_for_spanned!(hir::DeclKind);
-impl_stable_hash_for!(enum hir::DeclKind {
- Local(local),
- Item(item_id)
-});
-
impl_stable_hash_for!(struct hir::Arm {
attrs,
pats,
@@ -941,9 +940,10 @@
});
impl_stable_hash_for!(enum hir::StmtKind {
- Decl(decl, id),
- Expr(expr, id),
- Semi(expr, id)
+ Local(local),
+ Item(item_id),
+ Expr(expr),
+ Semi(expr)
});
impl_stable_hash_for!(struct hir::Arg {
diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs
index 70ec72d..7e48554 100644
--- a/src/librustc/ich/impls_syntax.rs
+++ b/src/librustc/ich/impls_syntax.rs
@@ -164,6 +164,7 @@
impl_stable_hash_for_spanned!(::syntax::ast::LitKind);
impl_stable_hash_for!(enum ::syntax::ast::LitKind {
Str(value, style),
+ Err(value),
ByteStr(value),
Byte(value),
Char(value),
@@ -258,7 +259,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);
}
}
@@ -329,6 +330,7 @@
match *lit {
token::Lit::Byte(val) |
token::Lit::Char(val) |
+ token::Lit::Err(val) |
token::Lit::Integer(val) |
token::Lit::Float(val) |
token::Lit::Str_(val) |
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index 2995b25..35f6e6a 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -485,12 +485,29 @@
}
}
- fn note_error_origin(&self, err: &mut DiagnosticBuilder<'tcx>, cause: &ObligationCause<'tcx>) {
+ fn note_error_origin(
+ &self,
+ err: &mut DiagnosticBuilder<'tcx>,
+ cause: &ObligationCause<'tcx>,
+ exp_found: Option<ty::error::ExpectedFound<Ty<'tcx>>>,
+ ) {
match cause.code {
ObligationCauseCode::MatchExpressionArmPattern { span, ty } => {
if ty.is_suggestable() { // don't show type `_`
err.span_label(span, format!("this match expression has type `{}`", ty));
}
+ if let Some(ty::error::ExpectedFound { found, .. }) = exp_found {
+ if ty.is_box() && ty.boxed_ty() == found {
+ if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
+ err.span_suggestion_with_applicability(
+ span,
+ "consider dereferencing the boxed value",
+ format!("*{}", snippet),
+ Applicability::MachineApplicable,
+ );
+ }
+ }
+ }
}
ObligationCauseCode::MatchExpressionArm { arm_span, source } => match source {
hir::MatchSource::IfLetDesugar { .. } => {
@@ -1013,7 +1030,7 @@
// It reads better to have the error origin as the final
// thing.
- self.note_error_origin(diag, &cause);
+ self.note_error_origin(diag, &cause, exp_found);
}
/// When encountering a case where `.as_ref()` on a `Result` or `Option` would be appropriate,
diff --git a/src/librustc/infer/lexical_region_resolve/mod.rs b/src/librustc/infer/lexical_region_resolve/mod.rs
index 39ce8cc..c0952fe 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>,
@@ -236,6 +241,14 @@
match *b_data {
VarValue::Value(cur_region) => {
+ // Identical scopes can show up quite often, if the fixed point
+ // iteration converges slowly, skip them
+ if let (ReScope(a_scope), ReScope(cur_scope)) = (a_region, cur_region) {
+ if a_scope == cur_scope {
+ return false;
+ }
+ }
+
let mut lub = self.lub_concrete_regions(a_region, cur_region);
if lub == cur_region {
return false;
@@ -275,12 +288,6 @@
fn lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'tcx> {
let tcx = self.tcx();
- // Equal scopes can show up quite often, if the fixed point
- // iteration converges slowly, skip them
- if a == b {
- return a;
- }
-
match (a, b) {
(&ty::ReClosureBound(..), _)
| (_, &ty::ReClosureBound(..))
@@ -722,18 +729,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/lint/context.rs b/src/librustc/lint/context.rs
index f5a7919..837a364 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -941,11 +941,6 @@
hir_visit::walk_arm(self, a);
}
- fn visit_decl(&mut self, d: &'tcx hir::Decl) {
- run_lints!(self, check_decl, d);
- hir_visit::walk_decl(self, d);
- }
-
fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam) {
run_lints!(self, check_generic_param, p);
hir_visit::walk_generic_param(self, p);
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index 730ce91..e83ba74 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -192,7 +192,6 @@
fn check_stmt(a: &$hir hir::Stmt);
fn check_arm(a: &$hir hir::Arm);
fn check_pat(a: &$hir hir::Pat);
- fn check_decl(a: &$hir hir::Decl);
fn check_expr(a: &$hir hir::Expr);
fn check_expr_post(a: &$hir hir::Expr);
fn check_ty(a: &$hir hir::Ty);
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/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index c1aa25b..08210c3 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -589,21 +589,17 @@
fn walk_stmt(&mut self, stmt: &hir::Stmt) {
match stmt.node {
- hir::StmtKind::Decl(ref decl, _) => {
- match decl.node {
- hir::DeclKind::Local(ref local) => {
- self.walk_local(&local);
- }
-
- hir::DeclKind::Item(_) => {
- // we don't visit nested items in this visitor,
- // only the fn body we were given.
- }
- }
+ hir::StmtKind::Local(ref local) => {
+ self.walk_local(&local);
}
- hir::StmtKind::Expr(ref expr, _) |
- hir::StmtKind::Semi(ref expr, _) => {
+ hir::StmtKind::Item(_) => {
+ // we don't visit nested items in this visitor,
+ // only the fn body we were given.
+ }
+
+ hir::StmtKind::Expr(ref expr) |
+ hir::StmtKind::Semi(ref expr) => {
self.consume_expr(&expr);
}
}
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 2ca8239..220bec7 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())
@@ -947,46 +962,31 @@
fn propagate_through_stmt(&mut self, stmt: &hir::Stmt, succ: LiveNode)
-> LiveNode {
match stmt.node {
- hir::StmtKind::Decl(ref decl, _) => {
- self.propagate_through_decl(&decl, succ)
- }
+ hir::StmtKind::Local(ref local) => {
+ // Note: we mark the variable as defined regardless of whether
+ // there is an initializer. Initially I had thought to only mark
+ // the live variable as defined if it was initialized, and then we
+ // could check for uninit variables just by scanning what is live
+ // at the start of the function. But that doesn't work so well for
+ // immutable variables defined in a loop:
+ // loop { let x; x = 5; }
+ // because the "assignment" loops back around and generates an error.
+ //
+ // So now we just check that variables defined w/o an
+ // initializer are not live at the point of their
+ // initialization, which is mildly more complex than checking
+ // once at the func header but otherwise equivalent.
- hir::StmtKind::Expr(ref expr, _) | hir::StmtKind::Semi(ref expr, _) => {
+ let succ = self.propagate_through_opt_expr(local.init.as_ref().map(|e| &**e), succ);
+ self.define_bindings_in_pat(&local.pat, succ)
+ }
+ hir::StmtKind::Item(..) => succ,
+ hir::StmtKind::Expr(ref expr) | hir::StmtKind::Semi(ref expr) => {
self.propagate_through_expr(&expr, succ)
}
}
}
- fn propagate_through_decl(&mut self, decl: &hir::Decl, succ: LiveNode)
- -> LiveNode {
- match decl.node {
- hir::DeclKind::Local(ref local) => {
- self.propagate_through_local(&local, succ)
- }
- hir::DeclKind::Item(_) => succ,
- }
- }
-
- fn propagate_through_local(&mut self, local: &hir::Local, succ: LiveNode)
- -> LiveNode {
- // Note: we mark the variable as defined regardless of whether
- // there is an initializer. Initially I had thought to only mark
- // the live variable as defined if it was initialized, and then we
- // could check for uninit variables just by scanning what is live
- // at the start of the function. But that doesn't work so well for
- // immutable variables defined in a loop:
- // loop { let x; x = 5; }
- // because the "assignment" loops back around and generates an error.
- //
- // So now we just check that variables defined w/o an
- // initializer are not live at the point of their
- // initialization, which is mildly more complex than checking
- // once at the func header but otherwise equivalent.
-
- let succ = self.propagate_through_opt_expr(local.init.as_ref().map(|e| &**e), succ);
- self.define_bindings_in_pat(&local.pat, succ)
- }
-
fn propagate_through_exprs(&mut self, exprs: &[Expr], succ: LiveNode)
-> LiveNode {
exprs.iter().rev().fold(succ, |succ, expr| {
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index ce2a348..31f91a1 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -784,20 +784,25 @@
// index information.)
for (i, statement) in blk.stmts.iter().enumerate() {
- if let hir::StmtKind::Decl(..) = statement.node {
- // Each StmtKind::Decl introduces a subscope for bindings
- // introduced by the declaration; this subscope covers
- // a suffix of the block . Each subscope in a block
- // has the previous subscope in the block as a parent,
- // except for the first such subscope, which has the
- // block itself as a parent.
- visitor.enter_scope(
- Scope {
- id: blk.hir_id.local_id,
- data: ScopeData::Remainder(FirstStatementIndex::new(i))
- }
- );
- visitor.cx.var_parent = visitor.cx.parent;
+ match statement.node {
+ hir::StmtKind::Local(..) |
+ hir::StmtKind::Item(..) => {
+ // Each declaration introduces a subscope for bindings
+ // introduced by the declaration; this subscope covers a
+ // suffix of the block. Each subscope in a block has the
+ // previous subscope in the block as a parent, except for
+ // the first such subscope, which has the block itself as a
+ // parent.
+ visitor.enter_scope(
+ Scope {
+ id: blk.hir_id.local_id,
+ data: ScopeData::Remainder(FirstStatementIndex::new(i))
+ }
+ );
+ visitor.cx.var_parent = visitor.cx.parent;
+ }
+ hir::StmtKind::Expr(..) |
+ hir::StmtKind::Semi(..) => {}
}
visitor.visit_stmt(statement)
}
@@ -835,7 +840,7 @@
}
fn resolve_stmt<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, stmt: &'tcx hir::Stmt) {
- let stmt_id = visitor.tcx.hir().node_to_hir_id(stmt.node.id()).local_id;
+ let stmt_id = visitor.tcx.hir().node_to_hir_id(stmt.id).local_id;
debug!("resolve_stmt(stmt.id={:?})", stmt_id);
// Every statement will clean up the temporaries created during
@@ -1263,8 +1268,8 @@
// The body of the every fn is a root scope.
self.cx.parent = self.cx.var_parent;
- if let hir::BodyOwnerKind::Fn = self.tcx.hir().body_owner_kind(owner_id) {
- self.visit_expr(&body.value);
+ if self.tcx.hir().body_owner_kind(owner_id).is_fn_or_closure() {
+ self.visit_expr(&body.value)
} else {
// Only functions have an outer terminating (drop) scope, while
// temporaries in constant initializers may be 'static, but only
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/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index 367a7ea..1c92e2d 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -471,7 +471,7 @@
}
fn report_similar_impl_candidates(&self,
- mut impl_candidates: Vec<ty::TraitRef<'tcx>>,
+ impl_candidates: Vec<ty::TraitRef<'tcx>>,
err: &mut DiagnosticBuilder<'_>)
{
if impl_candidates.is_empty() {
@@ -497,14 +497,18 @@
});
// Sort impl candidates so that ordering is consistent for UI tests.
- let normalized_impl_candidates = &mut impl_candidates[0..end]
+ let mut normalized_impl_candidates = impl_candidates
.iter()
.map(normalize)
.collect::<Vec<String>>();
+
+ // Sort before taking the `..end` range,
+ // because the ordering of `impl_candidates` may not be deterministic:
+ // https://github.com/rust-lang/rust/pull/57475#issuecomment-455519507
normalized_impl_candidates.sort();
err.help(&format!("the following implementations were found:{}{}",
- normalized_impl_candidates.join(""),
+ normalized_impl_candidates[..end].join(""),
if len > 5 {
format!("\nand {} others", len - 4)
} else {
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 05a6cce..9a0610f 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -2198,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()));
}
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 5d827e0..1cc9bbd 100644
--- a/src/librustc/ty/query/plumbing.rs
+++ b/src/librustc/ty/query/plumbing.rs
@@ -1248,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); }
@@ -1329,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!()); }
@@ -1380,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_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_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_lint/unused.rs b/src/librustc_lint/unused.rs
index bc29020..8a68f1b 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -41,7 +41,7 @@
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) {
let expr = match s.node {
- hir::StmtKind::Semi(ref expr, _) => &**expr,
+ hir::StmtKind::Semi(ref expr) => &**expr,
_ => return,
};
@@ -205,7 +205,7 @@
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PathStatements {
fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) {
- if let hir::StmtKind::Semi(ref expr, _) = s.node {
+ if let hir::StmtKind::Semi(ref expr) = s.node {
if let hir::ExprKind::Path(_) = expr.node {
cx.span_lint(PATH_STATEMENTS, s.span, "path statement with no effect");
}
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/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/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 4563224..9d49814 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -163,10 +163,7 @@
|bd, i| DebugFormatted::new(&bd.move_data().move_paths[i]),
));
- let locals_are_invalidated_at_exit = match tcx.hir().body_owner_kind(id) {
- hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => false,
- hir::BodyOwnerKind::Fn => true,
- };
+ let locals_are_invalidated_at_exit = tcx.hir().body_owner_kind(id).is_fn_or_closure();
let borrow_set = Rc::new(BorrowSet::build(
tcx, mir, locals_are_invalidated_at_exit, &mdpe.move_data));
diff --git a/src/librustc_mir/borrow_check/nll/universal_regions.rs b/src/librustc_mir/borrow_check/nll/universal_regions.rs
index c63d45c..0a214e6 100644
--- a/src/librustc_mir/borrow_check/nll/universal_regions.rs
+++ b/src/librustc_mir/borrow_check/nll/universal_regions.rs
@@ -476,6 +476,7 @@
let closure_base_def_id = tcx.closure_base_def_id(self.mir_def_id);
match tcx.hir().body_owner_kind(self.mir_node_id) {
+ BodyOwnerKind::Closure |
BodyOwnerKind::Fn => {
let defining_ty = if self.mir_def_id == closure_base_def_id {
tcx.type_of(closure_base_def_id)
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index 2bf2824..420ae11 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -75,7 +75,7 @@
let cx = Cx::new(&infcx, id);
let mut mir = if cx.tables().tainted_by_errors {
build::construct_error(cx, body_id)
- } else if let hir::BodyOwnerKind::Fn = cx.body_owner_kind {
+ } else if cx.body_owner_kind.is_fn_or_closure() {
// fetch the fully liberated fn signature (that is, all bound
// types/lifetimes replaced)
let fn_hir_id = tcx.hir().node_to_hir_id(id);
diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs
index b44c2cc..78abba5 100644
--- a/src/librustc_mir/build/scope.rs
+++ b/src/librustc_mir/build/scope.rs
@@ -613,6 +613,7 @@
hir::BodyOwnerKind::Static(_) =>
// No need to free storage in this context.
None,
+ hir::BodyOwnerKind::Closure |
hir::BodyOwnerKind::Fn =>
Some(self.topmost_scope()),
}
diff --git a/src/librustc_mir/hair/constant.rs b/src/librustc_mir/hair/constant.rs
index 37d741d..f63c3e2 100644
--- a/src/librustc_mir/hair/constant.rs
+++ b/src/librustc_mir/hair/constant.rs
@@ -37,6 +37,14 @@
let id = tcx.allocate_bytes(s.as_bytes());
ConstValue::new_slice(Scalar::Ptr(id.into()), s.len() as u64, &tcx)
},
+ LitKind::Err(ref s) => {
+ let s = s.as_str();
+ let id = tcx.allocate_bytes(s.as_bytes());
+ return Ok(ty::Const {
+ val: ConstValue::new_slice(Scalar::Ptr(id.into()), s.len() as u64, &tcx),
+ ty: tcx.types.err,
+ });
+ },
LitKind::ByteStr(ref data) => {
let id = tcx.allocate_bytes(data);
ConstValue::Scalar(Scalar::Ptr(id.into()))
diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir/hair/cx/block.rs
index ea8b282..c50d9dd 100644
--- a/src/librustc_mir/hair/cx/block.rs
+++ b/src/librustc_mir/hair/cx/block.rs
@@ -46,12 +46,12 @@
-> Vec<StmtRef<'tcx>> {
let mut result = vec![];
for (index, stmt) in stmts.iter().enumerate() {
- let hir_id = cx.tcx.hir().node_to_hir_id(stmt.node.id());
+ let hir_id = cx.tcx.hir().node_to_hir_id(stmt.id);
let opt_dxn_ext = cx.region_scope_tree.opt_destruction_scope(hir_id.local_id);
- let stmt_span = StatementSpan(cx.tcx.hir().span(stmt.node.id()));
+ let stmt_span = StatementSpan(cx.tcx.hir().span(stmt.id));
match stmt.node {
- hir::StmtKind::Expr(ref expr, _) |
- hir::StmtKind::Semi(ref expr, _) => {
+ hir::StmtKind::Expr(ref expr) |
+ hir::StmtKind::Semi(ref expr) => {
result.push(StmtRef::Mirror(Box::new(Stmt {
kind: StmtKind::Expr {
scope: region::Scope {
@@ -64,52 +64,48 @@
span: stmt_span,
})))
}
- hir::StmtKind::Decl(ref decl, _) => {
- match decl.node {
- hir::DeclKind::Item(..) => {
- // ignore for purposes of the MIR
- }
- hir::DeclKind::Local(ref local) => {
- let remainder_scope = region::Scope {
- id: block_id,
- data: region::ScopeData::Remainder(
- region::FirstStatementIndex::new(index)),
+ hir::StmtKind::Item(..) => {
+ // ignore for purposes of the MIR
+ }
+ hir::StmtKind::Local(ref local) => {
+ let remainder_scope = region::Scope {
+ id: block_id,
+ data: region::ScopeData::Remainder(
+ region::FirstStatementIndex::new(index)),
+ };
+
+ let mut pattern = cx.pattern_from_hir(&local.pat);
+
+ if let Some(ty) = &local.ty {
+ if let Some(&user_ty) = cx.tables.user_provided_types().get(ty.hir_id) {
+ debug!("mirror_stmts: user_ty={:?}", user_ty);
+ pattern = Pattern {
+ ty: pattern.ty,
+ span: pattern.span,
+ kind: Box::new(PatternKind::AscribeUserType {
+ user_ty: PatternTypeProjection::from_user_type(user_ty),
+ user_ty_span: ty.span,
+ subpattern: pattern,
+ variance: ty::Variance::Covariant,
+ })
};
-
- let mut pattern = cx.pattern_from_hir(&local.pat);
-
- if let Some(ty) = &local.ty {
- if let Some(&user_ty) = cx.tables.user_provided_types().get(ty.hir_id) {
- debug!("mirror_stmts: user_ty={:?}", user_ty);
- pattern = Pattern {
- ty: pattern.ty,
- span: pattern.span,
- kind: Box::new(PatternKind::AscribeUserType {
- user_ty: PatternTypeProjection::from_user_type(user_ty),
- user_ty_span: ty.span,
- subpattern: pattern,
- variance: ty::Variance::Covariant,
- })
- };
- }
- }
-
- result.push(StmtRef::Mirror(Box::new(Stmt {
- kind: StmtKind::Let {
- remainder_scope: remainder_scope,
- init_scope: region::Scope {
- id: hir_id.local_id,
- data: region::ScopeData::Node
- },
- pattern,
- initializer: local.init.to_ref(),
- lint_level: cx.lint_level_of(local.id),
- },
- opt_destruction_scope: opt_dxn_ext,
- span: stmt_span,
- })));
}
}
+
+ result.push(StmtRef::Mirror(Box::new(Stmt {
+ kind: StmtKind::Let {
+ remainder_scope: remainder_scope,
+ init_scope: region::Scope {
+ id: hir_id.local_id,
+ data: region::ScopeData::Node
+ },
+ pattern,
+ initializer: local.init.to_ref(),
+ lint_level: cx.lint_level_of(local.id),
+ },
+ opt_destruction_scope: opt_dxn_ext,
+ span: stmt_span,
+ })));
}
}
}
diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs
index 6113d88..f514cac 100644
--- a/src/librustc_mir/hair/cx/mod.rs
+++ b/src/librustc_mir/hair/cx/mod.rs
@@ -61,6 +61,7 @@
let constness = match body_owner_kind {
hir::BodyOwnerKind::Const |
hir::BodyOwnerKind::Static(_) => hir::Constness::Const,
+ hir::BodyOwnerKind::Closure |
hir::BodyOwnerKind::Fn => hir::Constness::NotConst,
};
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_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index eb151b5..ab8da2f 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -4,6 +4,7 @@
use rustc::ty::query::Providers;
use rustc::ty::{self, TyCtxt};
+use rustc::ty::cast::CastTy;
use rustc::hir;
use rustc::hir::Node;
use rustc::hir::def_id::DefId;
@@ -20,6 +21,7 @@
pub struct UnsafetyChecker<'a, 'tcx: 'a> {
mir: &'a Mir<'tcx>,
+ const_context: bool,
min_const_fn: bool,
source_scope_local_data: &'a IndexVec<SourceScope, SourceScopeLocalData>,
violations: Vec<UnsafetyViolation>,
@@ -33,14 +35,20 @@
impl<'a, 'gcx, 'tcx> UnsafetyChecker<'a, 'tcx> {
fn new(
+ const_context: bool,
min_const_fn: bool,
mir: &'a Mir<'tcx>,
source_scope_local_data: &'a IndexVec<SourceScope, SourceScopeLocalData>,
tcx: TyCtxt<'a, 'tcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> Self {
+ // sanity check
+ if min_const_fn {
+ assert!(const_context);
+ }
Self {
mir,
+ const_context,
min_const_fn,
source_scope_local_data,
violations: vec![],
@@ -124,29 +132,70 @@
rvalue: &Rvalue<'tcx>,
location: Location)
{
- if let &Rvalue::Aggregate(box ref aggregate, _) = rvalue {
- match aggregate {
- &AggregateKind::Array(..) |
- &AggregateKind::Tuple => {}
- &AggregateKind::Adt(ref def, ..) => {
- match self.tcx.layout_scalar_valid_range(def.did) {
- (Bound::Unbounded, Bound::Unbounded) => {},
- _ => self.require_unsafe(
- "initializing type with `rustc_layout_scalar_valid_range` attr",
- "initializing a layout restricted type's field with a value outside \
- the valid range is undefined behavior",
- UnsafetyViolationKind::GeneralAndConstFn,
- ),
+ match rvalue {
+ Rvalue::Aggregate(box ref aggregate, _) => {
+ match aggregate {
+ &AggregateKind::Array(..) |
+ &AggregateKind::Tuple => {}
+ &AggregateKind::Adt(ref def, ..) => {
+ match self.tcx.layout_scalar_valid_range(def.did) {
+ (Bound::Unbounded, Bound::Unbounded) => {},
+ _ => self.require_unsafe(
+ "initializing type with `rustc_layout_scalar_valid_range` attr",
+ "initializing a layout restricted type's field with a value \
+ outside the valid range is undefined behavior",
+ UnsafetyViolationKind::GeneralAndConstFn,
+ ),
+ }
+ }
+ &AggregateKind::Closure(def_id, _) |
+ &AggregateKind::Generator(def_id, _, _) => {
+ let UnsafetyCheckResult {
+ violations, unsafe_blocks
+ } = self.tcx.unsafety_check_result(def_id);
+ self.register_violations(&violations, &unsafe_blocks);
}
}
- &AggregateKind::Closure(def_id, _) |
- &AggregateKind::Generator(def_id, _, _) => {
- let UnsafetyCheckResult {
- violations, unsafe_blocks
- } = self.tcx.unsafety_check_result(def_id);
- self.register_violations(&violations, &unsafe_blocks);
+ },
+ // casting pointers to ints is unsafe in const fn because the const evaluator cannot
+ // possibly know what the result of various operations like `address / 2` would be
+ // pointers during const evaluation have no integral address, only an abstract one
+ Rvalue::Cast(CastKind::Misc, ref operand, cast_ty)
+ if self.const_context && self.tcx.features().const_raw_ptr_to_usize_cast => {
+ let operand_ty = operand.ty(self.mir, self.tcx);
+ let cast_in = CastTy::from_ty(operand_ty).expect("bad input type for cast");
+ let cast_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
+ match (cast_in, cast_out) {
+ (CastTy::Ptr(_), CastTy::Int(_)) |
+ (CastTy::FnPtr, CastTy::Int(_)) => {
+ self.register_violations(&[UnsafetyViolation {
+ source_info: self.source_info,
+ description: Symbol::intern("cast of pointer to int").as_interned_str(),
+ details: Symbol::intern("casting pointers to integers in constants")
+ .as_interned_str(),
+ kind: UnsafetyViolationKind::General,
+ }], &[]);
+ },
+ _ => {},
}
}
+ // raw pointer and fn pointer operations are unsafe as it is not clear whether one
+ // pointer would be "less" or "equal" to another, because we cannot know where llvm
+ // or the linker will place various statics in memory. Without this information the
+ // result of a comparison of addresses would differ between runtime and compile-time.
+ Rvalue::BinaryOp(_, ref lhs, _)
+ if self.const_context && self.tcx.features().const_compare_raw_pointers => {
+ if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(self.mir, self.tcx).sty {
+ self.register_violations(&[UnsafetyViolation {
+ source_info: self.source_info,
+ description: Symbol::intern("pointer operation").as_interned_str(),
+ details: Symbol::intern("operations on pointers in constants")
+ .as_interned_str(),
+ kind: UnsafetyViolationKind::General,
+ }], &[]);
+ }
+ }
+ _ => {},
}
self.super_rvalue(rvalue, location);
}
@@ -484,8 +533,16 @@
};
let param_env = tcx.param_env(def_id);
+
+ let id = tcx.hir().as_local_node_id(def_id).unwrap();
+ let (const_context, min_const_fn) = match tcx.hir().body_owner_kind(id) {
+ hir::BodyOwnerKind::Closure => (false, false),
+ hir::BodyOwnerKind::Fn => (tcx.is_const_fn(def_id), tcx.is_min_const_fn(def_id)),
+ hir::BodyOwnerKind::Const |
+ hir::BodyOwnerKind::Static(_) => (true, false),
+ };
let mut checker = UnsafetyChecker::new(
- tcx.is_min_const_fn(def_id),
+ const_context, min_const_fn,
mir, source_scope_local_data, tcx, param_env);
checker.visit_mir(mir);
diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs
index 8b970c1..9f0907a 100644
--- a/src/librustc_mir/transform/inline.rs
+++ b/src/librustc_mir/transform/inline.rs
@@ -1,6 +1,5 @@
//! Inlining pass for MIR functions
-use rustc::hir;
use rustc::hir::CodegenFnAttrFlags;
use rustc::hir::def_id::DefId;
@@ -74,15 +73,12 @@
// Only do inlining into fn bodies.
let id = self.tcx.hir().as_local_node_id(self.source.def_id).unwrap();
- let body_owner_kind = self.tcx.hir().body_owner_kind(id);
-
- if let (hir::BodyOwnerKind::Fn, None) = (body_owner_kind, self.source.promoted) {
-
+ if self.tcx.hir().body_owner_kind(id).is_fn_or_closure() && self.source.promoted.is_none() {
for (bb, bb_data) in caller_mir.basic_blocks().iter_enumerated() {
if let Some(callsite) = self.get_valid_function_call(bb,
- bb_data,
- caller_mir,
- param_env) {
+ bb_data,
+ caller_mir,
+ param_env) {
callsites.push_back(callsite);
}
}
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 78cf715..2d94190 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -1152,6 +1152,7 @@
let id = tcx.hir().as_local_node_id(def_id).unwrap();
let mut const_promoted_temps = None;
let mode = match tcx.hir().body_owner_kind(id) {
+ hir::BodyOwnerKind::Closure => Mode::Fn,
hir::BodyOwnerKind::Fn => {
if tcx.is_const_fn(def_id) {
Mode::ConstFn
diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs
index 059b88a..85bf1e7 100644
--- a/src/librustc_mir/transform/qualify_min_const_fn.rs
+++ b/src/librustc_mir/transform/qualify_min_const_fn.rs
@@ -21,6 +21,7 @@
| Predicate::RegionOutlives(_)
| Predicate::TypeOutlives(_)
| Predicate::WellFormed(_)
+ | Predicate::Projection(_)
| Predicate::ConstEvaluatable(..) => continue,
| Predicate::ObjectSafe(_) => {
bug!("object safe predicate on function: {:#?}", predicate)
@@ -29,13 +30,6 @@
bug!("closure kind predicate on function: {:#?}", predicate)
}
Predicate::Subtype(_) => bug!("subtype predicate on function: {:#?}", predicate),
- Predicate::Projection(_) => {
- let span = tcx.def_span(current);
- // we'll hit a `Predicate::Trait` later which will report an error
- tcx.sess
- .delay_span_bug(span, "projection without trait bound");
- continue;
- }
Predicate::Trait(pred) => {
if Some(pred.def_id()) == tcx.lang_items().sized_trait() {
continue;
diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs
index fca208b..f4685e0 100644
--- a/src/librustc_mir/util/pretty.rs
+++ b/src/librustc_mir/util/pretty.rs
@@ -573,6 +573,7 @@
let body_owner_kind = tcx.hir().body_owner_kind(id);
match (body_owner_kind, src.promoted) {
(_, Some(i)) => write!(w, "{:?} in", i)?,
+ (hir::BodyOwnerKind::Closure, _) |
(hir::BodyOwnerKind::Fn, _) => write!(w, "fn")?,
(hir::BodyOwnerKind::Const, _) => write!(w, "const")?,
(hir::BodyOwnerKind::Static(hir::MutImmutable), _) => write!(w, "static")?,
@@ -585,6 +586,7 @@
})?;
match (body_owner_kind, src.promoted) {
+ (hir::BodyOwnerKind::Closure, None) |
(hir::BodyOwnerKind::Fn, None) => {
write!(w, "(")?;
diff --git a/src/librustc_passes/hir_stats.rs b/src/librustc_passes/hir_stats.rs
index 604b31e..74d6d75 100644
--- a/src/librustc_passes/hir_stats.rs
+++ b/src/librustc_passes/hir_stats.rs
@@ -144,7 +144,7 @@
}
fn visit_stmt(&mut self, s: &'v hir::Stmt) {
- self.record("Stmt", Id::Node(s.node.id()), s);
+ self.record("Stmt", Id::Node(s.id), s);
hir_visit::walk_stmt(self, s)
}
@@ -158,11 +158,6 @@
hir_visit::walk_pat(self, p)
}
- fn visit_decl(&mut self, d: &'v hir::Decl) {
- self.record("Decl", Id::None, d);
- hir_visit::walk_decl(self, d)
- }
-
fn visit_expr(&mut self, ex: &'v hir::Expr) {
self.record("Expr", Id::Node(ex.id), ex);
hir_visit::walk_expr(self, ex)
diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs
index f0b559f..c11b1af 100644
--- a/src/librustc_passes/rvalue_promotion.rs
+++ b/src/librustc_passes/rvalue_promotion.rs
@@ -191,6 +191,7 @@
self.in_static = false;
match self.tcx.hir().body_owner_kind(item_id) {
+ hir::BodyOwnerKind::Closure |
hir::BodyOwnerKind::Fn => self.in_fn = true,
hir::BodyOwnerKind::Static(_) => self.in_static = true,
_ => {}
@@ -220,26 +221,22 @@
fn check_stmt(&mut self, stmt: &'tcx hir::Stmt) -> Promotability {
match stmt.node {
- hir::StmtKind::Decl(ref decl, _node_id) => {
- match &decl.node {
- hir::DeclKind::Local(local) => {
- if self.remove_mut_rvalue_borrow(&local.pat) {
- if let Some(init) = &local.init {
- self.mut_rvalue_borrows.insert(init.id);
- }
- }
-
- if let Some(ref expr) = local.init {
- let _ = self.check_expr(&expr);
- }
- NotPromotable
+ hir::StmtKind::Local(ref local) => {
+ if self.remove_mut_rvalue_borrow(&local.pat) {
+ if let Some(init) = &local.init {
+ self.mut_rvalue_borrows.insert(init.id);
}
- // Item statements are allowed
- hir::DeclKind::Item(_) => Promotable
}
+
+ if let Some(ref expr) = local.init {
+ let _ = self.check_expr(&expr);
+ }
+ NotPromotable
}
- hir::StmtKind::Expr(ref box_expr, _node_id) |
- hir::StmtKind::Semi(ref box_expr, _node_id) => {
+ // Item statements are allowed
+ hir::StmtKind::Item(..) => Promotable,
+ hir::StmtKind::Expr(ref box_expr) |
+ hir::StmtKind::Semi(ref box_expr) => {
let _ = self.check_expr(box_expr);
NotPromotable
}
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 a58d63e..1cd4404 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -4866,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/coercion.rs b/src/librustc_typeck/check/coercion.rs
index a82a0d3..dd63b4f 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -1216,7 +1216,7 @@
"supposed to be part of a block tail expression, but the \
expression is empty");
});
- fcx.suggest_mismatched_types_on_tail(
+ let pointing_at_return_type = fcx.suggest_mismatched_types_on_tail(
&mut db,
expr,
expected,
@@ -1224,7 +1224,44 @@
cause.span,
blk_id,
);
- if let Some(sp) = fcx.ret_coercion_span.borrow().as_ref() {
+ // FIXME: replace with navigating up the chain until hitting an fn or
+ // bailing if no "pass-through" Node is found, in order to provide a
+ // suggestion when encountering something like:
+ // ```
+ // fn foo(a: bool) -> impl Debug {
+ // if a {
+ // bar()?;
+ // }
+ // {
+ // let x = unsafe { bar() };
+ // x
+ // }
+ // }
+ // ```
+ //
+ // Verify that this is a tail expression of a function, otherwise the
+ // label pointing out the cause for the type coercion will be wrong
+ // as prior return coercions would not be relevant (#57664).
+ let parent_id = fcx.tcx.hir().get_parent_node(blk_id);
+ let parent = fcx.tcx.hir().get(fcx.tcx.hir().get_parent_node(parent_id));
+ if fcx.get_node_fn_decl(parent).is_some() && !pointing_at_return_type {
+ if let Some(sp) = fcx.ret_coercion_span.borrow().as_ref() {
+ db.span_label(*sp, reason_label);
+ }
+ }
+ }
+ ObligationCauseCode::ReturnType(_id) => {
+ db = fcx.report_mismatched_types(cause, expected, found, err);
+ let _id = fcx.tcx.hir().get_parent_node(_id);
+ let mut pointing_at_return_type = false;
+ if let Some((fn_decl, can_suggest)) = fcx.get_fn_decl(_id) {
+ pointing_at_return_type = fcx.suggest_missing_return_type(
+ &mut db, &fn_decl, expected, found, can_suggest);
+ }
+ if let (Some(sp), false) = (
+ fcx.ret_coercion_span.borrow().as_ref(),
+ pointing_at_return_type,
+ ) {
if !sp.overlaps(cause.span) {
db.span_label(*sp, reason_label);
}
@@ -1232,11 +1269,6 @@
}
_ => {
db = fcx.report_mismatched_types(cause, expected, found, err);
- if let Some(sp) = fcx.ret_coercion_span.borrow().as_ref() {
- if !sp.overlaps(cause.span) {
- db.span_label(*sp, reason_label);
- }
- }
}
}
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index c0cedd7..d985bda 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -454,12 +454,13 @@
false
}
- pub fn check_for_cast(&self,
- err: &mut DiagnosticBuilder<'tcx>,
- expr: &hir::Expr,
- checked_ty: Ty<'tcx>,
- expected_ty: Ty<'tcx>)
- -> bool {
+ pub fn check_for_cast(
+ &self,
+ err: &mut DiagnosticBuilder<'tcx>,
+ expr: &hir::Expr,
+ checked_ty: Ty<'tcx>,
+ expected_ty: Ty<'tcx>,
+ ) -> bool {
let parent_id = self.tcx.hir().get_parent_node(expr.id);
if let Some(parent) = self.tcx.hir().find(parent_id) {
// Shouldn't suggest `.into()` on `const`s.
@@ -487,17 +488,40 @@
// For now, don't suggest casting with `as`.
let can_cast = false;
+ let mut prefix = String::new();
+ if let Some(hir::Node::Expr(hir::Expr {
+ node: hir::ExprKind::Struct(_, fields, _),
+ ..
+ })) = self.tcx.hir().find(self.tcx.hir().get_parent_node(expr.id)) {
+ // `expr` is a literal field for a struct, only suggest if appropriate
+ for field in fields {
+ if field.expr.id == expr.id && field.is_shorthand {
+ // This is a field literal
+ prefix = format!("{}: ", field.ident);
+ break;
+ }
+ }
+ if &prefix == "" {
+ // Likely a field was meant, but this field wasn't found. Do not suggest anything.
+ return false;
+ }
+ }
+
let needs_paren = expr.precedence().order() < (PREC_POSTFIX as i8);
if let Ok(src) = self.tcx.sess.source_map().span_to_snippet(expr.span) {
let msg = format!("you can cast an `{}` to `{}`", checked_ty, expected_ty);
- let cast_suggestion = format!("{}{}{} as {}",
- if needs_paren { "(" } else { "" },
- src,
- if needs_paren { ")" } else { "" },
- expected_ty);
+ let cast_suggestion = format!(
+ "{}{}{}{} as {}",
+ prefix,
+ if needs_paren { "(" } else { "" },
+ src,
+ if needs_paren { ")" } else { "" },
+ expected_ty,
+ );
let into_suggestion = format!(
- "{}{}{}.into()",
+ "{}{}{}{}.into()",
+ prefix,
if needs_paren { "(" } else { "" },
src,
if needs_paren { ")" } else { "" },
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..ad4bc3c 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()));
}
}
}
@@ -3121,7 +3121,8 @@
opt_ty.unwrap_or_else(
|| tcx.mk_float_var(self.next_float_var_id()))
}
- ast::LitKind::Bool(_) => tcx.types.bool
+ ast::LitKind::Bool(_) => tcx.types.bool,
+ ast::LitKind::Err(_) => tcx.types.err,
}
}
@@ -4347,11 +4348,15 @@
struct_span_err!(self.tcx.sess, expr.span, E0572,
"return statement outside of function body").emit();
} else if let Some(ref e) = *expr_opt {
- *self.ret_coercion_span.borrow_mut() = Some(e.span);
+ if self.ret_coercion_span.borrow().is_none() {
+ *self.ret_coercion_span.borrow_mut() = Some(e.span);
+ }
self.check_return_expr(e);
} else {
let mut coercion = self.ret_coercion.as_ref().unwrap().borrow_mut();
- *self.ret_coercion_span.borrow_mut() = Some(expr.span);
+ if self.ret_coercion_span.borrow().is_none() {
+ *self.ret_coercion_span.borrow_mut() = Some(expr.span);
+ }
let cause = self.cause(expr.span, ObligationCauseCode::ReturnNoExpression);
if let Some((fn_decl, _)) = self.get_fn_decl(expr.id) {
coercion.coerce_forced_unit(
@@ -4724,8 +4729,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);
@@ -4840,15 +4845,11 @@
pub fn check_stmt(&self, stmt: &'gcx hir::Stmt) {
// Don't do all the complex logic below for `DeclItem`.
match stmt.node {
- hir::StmtKind::Decl(ref decl, _) => {
- if let hir::DeclKind::Item(_) = decl.node {
- return
- }
- }
- hir::StmtKind::Expr(..) | hir::StmtKind::Semi(..) => {}
+ hir::StmtKind::Item(..) => return,
+ hir::StmtKind::Local(..) | hir::StmtKind::Expr(..) | hir::StmtKind::Semi(..) => {}
}
- self.warn_if_unreachable(stmt.node.id(), stmt.span, "statement");
+ self.warn_if_unreachable(stmt.id, stmt.span, "statement");
// Hide the outer diverging and `has_errors` flags.
let old_diverges = self.diverges.get();
@@ -4857,20 +4858,16 @@
self.has_errors.set(false);
match stmt.node {
- hir::StmtKind::Decl(ref decl, _) => {
- match decl.node {
- hir::DeclKind::Local(ref l) => {
- self.check_decl_local(&l);
- }
- // Ignore for now.
- hir::DeclKind::Item(_) => ()
- }
+ hir::StmtKind::Local(ref l) => {
+ self.check_decl_local(&l);
}
- hir::StmtKind::Expr(ref expr, _) => {
+ // Ignore for now.
+ hir::StmtKind::Item(_) => {}
+ hir::StmtKind::Expr(ref expr) => {
// Check with expected type of `()`.
self.check_expr_has_type_or_error(&expr, self.tcx.mk_unit());
}
- hir::StmtKind::Semi(ref expr, _) => {
+ hir::StmtKind::Semi(ref expr) => {
self.check_expr(&expr);
}
}
@@ -5089,12 +5086,15 @@
found: Ty<'tcx>,
cause_span: Span,
blk_id: ast::NodeId,
- ) {
+ ) -> bool {
self.suggest_missing_semicolon(err, expression, expected, cause_span);
+ let mut pointing_at_return_type = false;
if let Some((fn_decl, can_suggest)) = self.get_fn_decl(blk_id) {
- self.suggest_missing_return_type(err, &fn_decl, expected, found, can_suggest);
+ pointing_at_return_type = self.suggest_missing_return_type(
+ err, &fn_decl, expected, found, can_suggest);
}
self.suggest_ref_or_into(err, expression, expected, found);
+ pointing_at_return_type
}
pub fn suggest_ref_or_into(
@@ -5193,12 +5193,14 @@
/// This routine checks if the return type is left as default, the method is not part of an
/// `impl` block and that it isn't the `main` method. If so, it suggests setting the return
/// type.
- fn suggest_missing_return_type(&self,
- err: &mut DiagnosticBuilder<'tcx>,
- fn_decl: &hir::FnDecl,
- expected: Ty<'tcx>,
- found: Ty<'tcx>,
- can_suggest: bool) {
+ fn suggest_missing_return_type(
+ &self,
+ err: &mut DiagnosticBuilder<'tcx>,
+ fn_decl: &hir::FnDecl,
+ expected: Ty<'tcx>,
+ found: Ty<'tcx>,
+ can_suggest: bool,
+ ) -> bool {
// Only suggest changing the return type for methods that
// haven't set a return type at all (and aren't `fn main()` or an impl).
match (&fn_decl.output, found.is_suggestable(), can_suggest, expected.is_unit()) {
@@ -5208,16 +5210,19 @@
"try adding a return type",
format!("-> {} ", self.resolve_type_vars_with_obligations(found)),
Applicability::MachineApplicable);
+ true
}
(&hir::FunctionRetTy::DefaultReturn(span), false, true, true) => {
err.span_label(span, "possibly return type missing here?");
+ true
}
(&hir::FunctionRetTy::DefaultReturn(span), _, false, true) => {
// `fn main()` must return `()`, do not suggest changing return type
err.span_label(span, "expected `()` because of default return type");
+ true
}
// expectation was caused by something else, not the default return
- (&hir::FunctionRetTy::DefaultReturn(_), _, _, false) => {}
+ (&hir::FunctionRetTy::DefaultReturn(_), _, _, false) => false,
(&hir::FunctionRetTy::Return(ref ty), _, _, _) => {
// Only point to return type if the expected type is the return type, as if they
// are not, the expectation must have been caused by something else.
@@ -5229,7 +5234,9 @@
if ty.sty == expected.sty {
err.span_label(sp, format!("expected `{}` because of return type",
expected));
+ return true;
}
+ false
}
}
}
@@ -5273,7 +5280,7 @@
None => return None,
};
let last_expr = match last_stmt.node {
- hir::StmtKind::Semi(ref e, _) => e,
+ hir::StmtKind::Semi(ref e) => e,
_ => return None,
};
let last_expr_ty = self.node_ty(last_expr.hir_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/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/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/highlight.rs b/src/librustdoc/html/highlight.rs
index 87e979b..e43251b 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -25,40 +25,51 @@
tooltip: Option<(&str, &str)>,
) -> String {
debug!("highlighting: ================\n{}\n==============", src);
- let sess = parse::ParseSess::new(FilePathMapping::empty());
- let fm = sess.source_map().new_source_file(FileName::Custom("stdin".to_string()),
- src.to_string());
-
let mut out = Vec::new();
if let Some((tooltip, class)) = tooltip {
write!(out, "<div class='information'><div class='tooltip {}'>ⓘ<span \
class='tooltiptext'>{}</span></div></div>",
class, tooltip).unwrap();
}
- write_header(class, &mut out).unwrap();
- let lexer = match lexer::StringReader::new_without_err(&sess, fm, None, "Output from rustc:") {
- Ok(l) => l,
- Err(_) => {
- let first_line = src.lines().next().unwrap_or_else(|| "");
- let mut err = sess.span_diagnostic
- .struct_warn(&format!("Invalid doc comment starting with: `{}`\n\
- (Ignoring this codeblock)",
- first_line));
- err.emit();
- return String::new();
+ let sess = parse::ParseSess::new(FilePathMapping::empty());
+ let fm = sess.source_map().new_source_file(
+ FileName::Custom(String::from("rustdoc-highlighting")),
+ src.to_owned(),
+ );
+ let highlight_result =
+ lexer::StringReader::new_or_buffered_errs(&sess, fm, None).and_then(|lexer| {
+ let mut classifier = Classifier::new(lexer, sess.source_map());
+
+ let mut highlighted_source = vec![];
+ if classifier.write_source(&mut highlighted_source).is_err() {
+ Err(classifier.lexer.buffer_fatal_errors())
+ } else {
+ Ok(String::from_utf8_lossy(&highlighted_source).into_owned())
+ }
+ });
+
+ match highlight_result {
+ Ok(highlighted_source) => {
+ write_header(class, &mut out).unwrap();
+ write!(out, "{}", highlighted_source).unwrap();
+ if let Some(extension) = extension {
+ write!(out, "{}", extension).unwrap();
+ }
+ write_footer(&mut out).unwrap();
}
- };
- let mut classifier = Classifier::new(lexer, sess.source_map());
- if classifier.write_source(&mut out).is_err() {
- classifier.lexer.emit_fatal_errors();
- return format!("<pre>{}</pre>", src);
+ Err(errors) => {
+ // If errors are encountered while trying to highlight, cancel the errors and just emit
+ // the unhighlighted source. The errors will have already been reported in the
+ // `check-code-block-syntax` pass.
+ for mut error in errors {
+ error.cancel();
+ }
+
+ write!(out, "<pre><code>{}</code></pre>", src).unwrap();
+ }
}
- if let Some(extension) = extension {
- write!(out, "{}", extension).unwrap();
- }
- write_footer(&mut out).unwrap();
String::from_utf8_lossy(&out[..]).into_owned()
}
@@ -151,6 +162,17 @@
}
}
+enum HighlightError {
+ LexError,
+ IoError(io::Error),
+}
+
+impl From<io::Error> for HighlightError {
+ fn from(err: io::Error) -> Self {
+ HighlightError::IoError(err)
+ }
+}
+
impl<'a> Classifier<'a> {
fn new(lexer: lexer::StringReader<'a>, source_map: &'a SourceMap) -> Classifier<'a> {
Classifier {
@@ -162,17 +184,11 @@
}
}
- /// Gets the next token out of the lexer, emitting fatal errors if lexing fails.
- fn try_next_token(&mut self) -> io::Result<TokenAndSpan> {
+ /// Gets the next token out of the lexer.
+ fn try_next_token(&mut self) -> Result<TokenAndSpan, HighlightError> {
match self.lexer.try_next_token() {
Ok(tas) => Ok(tas),
- Err(_) => {
- let mut err = self.lexer.sess.span_diagnostic
- .struct_warn("Backing out of syntax highlighting");
- err.note("You probably did not intend to render this as a rust code-block");
- err.emit();
- Err(io::Error::new(io::ErrorKind::Other, ""))
- }
+ Err(_) => Err(HighlightError::LexError),
}
}
@@ -185,7 +201,7 @@
/// source.
fn write_source<W: Writer>(&mut self,
out: &mut W)
- -> io::Result<()> {
+ -> Result<(), HighlightError> {
loop {
let next = self.try_next_token()?;
if next.tok == token::Eof {
@@ -202,7 +218,7 @@
fn write_token<W: Writer>(&mut self,
out: &mut W,
tas: TokenAndSpan)
- -> io::Result<()> {
+ -> Result<(), HighlightError> {
let klass = match tas.tok {
token::Shebang(s) => {
out.string(Escape(&s.as_str()), Class::None)?;
@@ -296,7 +312,7 @@
token::Literal(lit, _suf) => {
match lit {
// Text literals.
- token::Byte(..) | token::Char(..) |
+ token::Byte(..) | token::Char(..) | token::Err(..) |
token::ByteStr(..) | token::ByteStrRaw(..) |
token::Str_(..) | token::StrRaw(..) => Class::String,
@@ -341,7 +357,9 @@
// Anything that didn't return above is the simple case where we the
// class just spans a single token, so we can use the `string` method.
- out.string(Escape(&self.snip(tas.sp)), klass)
+ out.string(Escape(&self.snip(tas.sp)), klass)?;
+
+ Ok(())
}
// Helper function to get a snippet from the source_map.
diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs
index 987cec6..c34dcbb 100644
--- a/src/librustdoc/html/layout.rs
+++ b/src/librustdoc/html/layout.rs
@@ -177,7 +177,10 @@
root_path = page.root_path,
css_class = page.css_class,
logo = if layout.logo.is_empty() {
- String::new()
+ format!("<a href='{}{}/index.html'>\
+ <img src='{static_root_path}rust-logo{suffix}.png' alt='logo' width='100'></a>",
+ static_root_path=static_root_path,
+ suffix=page.resource_suffix)
} else {
format!("<a href='{}{}/index.html'>\
<img src='{}' alt='logo' width='100'></a>",
@@ -188,7 +191,9 @@
description = page.description,
keywords = page.keywords,
favicon = if layout.favicon.is_empty() {
- String::new()
+ format!(r#"<link rel="shortcut icon" href="{static_root_path}favicon{suffix}.ico">"#,
+ static_root_path=static_root_path,
+ suffix=page.resource_suffix)
} else {
format!(r#"<link rel="shortcut icon" href="{}">"#, layout.favicon)
},
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 05a9a2d..6b7f540 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -919,6 +919,115 @@
links
}
+#[derive(Debug)]
+crate struct RustCodeBlock {
+ /// The range in the markdown that the code block occupies. Note that this includes the fences
+ /// for fenced code blocks.
+ pub range: Range<usize>,
+ /// The range in the markdown that the code within the code block occupies.
+ pub code: Range<usize>,
+ pub is_fenced: bool,
+ pub syntax: Option<String>,
+}
+
+/// Returns a range of bytes for each code block in the markdown that is tagged as `rust` or
+/// untagged (and assumed to be rust).
+crate fn rust_code_blocks(md: &str) -> Vec<RustCodeBlock> {
+ let mut code_blocks = vec![];
+
+ if md.is_empty() {
+ return code_blocks;
+ }
+
+ let mut opts = Options::empty();
+ opts.insert(OPTION_ENABLE_TABLES);
+ opts.insert(OPTION_ENABLE_FOOTNOTES);
+ let mut p = Parser::new_ext(md, opts);
+
+ let mut code_block_start = 0;
+ let mut code_start = 0;
+ let mut is_fenced = false;
+ let mut previous_offset = 0;
+ let mut in_rust_code_block = false;
+ while let Some(event) = p.next() {
+ let offset = p.get_offset();
+
+ match event {
+ Event::Start(Tag::CodeBlock(syntax)) => {
+ let lang_string = if syntax.is_empty() {
+ LangString::all_false()
+ } else {
+ LangString::parse(&*syntax, ErrorCodes::Yes)
+ };
+
+ if lang_string.rust {
+ in_rust_code_block = true;
+
+ code_start = offset;
+ code_block_start = match md[previous_offset..offset].find("```") {
+ Some(fence_idx) => {
+ is_fenced = true;
+ previous_offset + fence_idx
+ }
+ None => offset,
+ };
+ }
+ }
+ Event::End(Tag::CodeBlock(syntax)) if in_rust_code_block => {
+ in_rust_code_block = false;
+
+ let code_block_end = if is_fenced {
+ let fence_str = &md[previous_offset..offset]
+ .chars()
+ .rev()
+ .collect::<String>();
+ fence_str
+ .find("```")
+ .map(|fence_idx| offset - fence_idx)
+ .unwrap_or_else(|| offset)
+ } else if md
+ .as_bytes()
+ .get(offset)
+ .map(|b| *b == b'\n')
+ .unwrap_or_default()
+ {
+ offset - 1
+ } else {
+ offset
+ };
+
+ let code_end = if is_fenced {
+ previous_offset
+ } else {
+ code_block_end
+ };
+
+ code_blocks.push(RustCodeBlock {
+ is_fenced,
+ range: Range {
+ start: code_block_start,
+ end: code_block_end,
+ },
+ code: Range {
+ start: code_start,
+ end: code_end,
+ },
+ syntax: if !syntax.is_empty() {
+ Some(syntax.into_owned())
+ } else {
+ None
+ },
+ });
+ }
+ _ => (),
+ }
+
+ previous_offset = offset;
+ }
+
+ code_blocks
+}
+
#[derive(Clone, Default, Debug)]
pub struct IdMap {
map: FxHashMap<String, usize>,
diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index 06846d4..86fb514 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.
@@ -789,6 +789,14 @@
themes.insert(theme.to_owned());
}
+ if (*cx.shared).layout.logo.is_empty() {
+ write(cx.dst.join(&format!("rust-logo{}.png", cx.shared.resource_suffix)),
+ static_files::RUST_LOGO)?;
+ }
+ if (*cx.shared).layout.favicon.is_empty() {
+ write(cx.dst.join(&format!("favicon{}.ico", cx.shared.resource_suffix)),
+ static_files::RUST_FAVICON)?;
+ }
write(cx.dst.join(&format!("brush{}.svg", cx.shared.resource_suffix)),
static_files::BRUSH_SVG)?;
write(cx.dst.join(&format!("wheel{}.svg", cx.shared.resource_suffix)),
@@ -2068,8 +2076,6 @@
themes.push(PathBuf::from("settings.css"));
let mut layout = self.shared.layout.clone();
layout.krate = String::new();
- layout.logo = String::new();
- layout.favicon = String::new();
try_err!(layout::render(&mut w, &layout,
&page, &sidebar, &settings,
self.shared.css_file_extension.is_some(),
diff --git a/src/librustdoc/html/static/favicon.ico b/src/librustdoc/html/static/favicon.ico
new file mode 100644
index 0000000..b8ad237
--- /dev/null
+++ b/src/librustdoc/html/static/favicon.ico
Binary files differ
diff --git a/src/librustdoc/html/static/rust-logo.png b/src/librustdoc/html/static/rust-logo.png
new file mode 100644
index 0000000..74b4bd6
--- /dev/null
+++ b/src/librustdoc/html/static/rust-logo.png
Binary files differ
diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs
index f340590..a1d8cfa 100644
--- a/src/librustdoc/html/static_files.rs
+++ b/src/librustdoc/html/static_files.rs
@@ -51,6 +51,11 @@
/// The contents of `LICENSE-MIT.txt`, the text of the MIT License.
pub static LICENSE_MIT: &'static [u8] = include_bytes!("static/LICENSE-MIT.txt");
+/// The contents of `rust-logo.png`, the default icon of the documentation.
+pub static RUST_LOGO: &'static [u8] = include_bytes!("static/rust-logo.png");
+/// The contents of `favicon.ico`, the default favicon of the documentation.
+pub static RUST_FAVICON: &'static [u8] = include_bytes!("static/favicon.ico");
+
/// The built-in themes given to every documentation site.
pub mod themes {
/// The "light" theme, selected by default when no setting is available. Used as the basis for
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 4bbc01d..f4149b5 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -3,6 +3,7 @@
html_root_url = "https://doc.rust-lang.org/nightly/",
html_playground_url = "https://play.rust-lang.org/")]
+#![feature(bind_by_move_pattern_guards)]
#![feature(rustc_private)]
#![feature(box_patterns)]
#![feature(box_syntax)]
diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs
new file mode 100644
index 0000000..a013cc3
--- /dev/null
+++ b/src/librustdoc/passes/check_code_block_syntax.rs
@@ -0,0 +1,109 @@
+use errors::Applicability;
+use syntax::parse::lexer::{TokenAndSpan, StringReader as Lexer};
+use syntax::parse::{ParseSess, token};
+use syntax::source_map::FilePathMapping;
+use syntax_pos::FileName;
+
+use clean;
+use core::DocContext;
+use fold::DocFolder;
+use html::markdown::{self, RustCodeBlock};
+use passes::Pass;
+
+pub const CHECK_CODE_BLOCK_SYNTAX: Pass =
+ Pass::early("check-code-block-syntax", check_code_block_syntax,
+ "validates syntax inside Rust code blocks");
+
+pub fn check_code_block_syntax(krate: clean::Crate, cx: &DocContext) -> clean::Crate {
+ SyntaxChecker { cx }.fold_crate(krate)
+}
+
+struct SyntaxChecker<'a, 'tcx: 'a, 'rcx: 'a> {
+ cx: &'a DocContext<'a, 'tcx, 'rcx>,
+}
+
+impl<'a, 'tcx, 'rcx> SyntaxChecker<'a, 'tcx, 'rcx> {
+ fn check_rust_syntax(&self, item: &clean::Item, dox: &str, code_block: RustCodeBlock) {
+ let sess = ParseSess::new(FilePathMapping::empty());
+ let source_file = sess.source_map().new_source_file(
+ FileName::Custom(String::from("doctest")),
+ dox[code_block.code].to_owned(),
+ );
+
+ let errors = Lexer::new_or_buffered_errs(&sess, source_file, None).and_then(|mut lexer| {
+ while let Ok(TokenAndSpan { tok, .. }) = lexer.try_next_token() {
+ if tok == token::Eof {
+ break;
+ }
+ }
+
+ let errors = lexer.buffer_fatal_errors();
+
+ if !errors.is_empty() {
+ Err(errors)
+ } else {
+ Ok(())
+ }
+ });
+
+ if let Err(errors) = errors {
+ let mut diag = if let Some(sp) =
+ super::source_span_for_markdown_range(self.cx, &dox, &code_block.range, &item.attrs)
+ {
+ let mut diag = self
+ .cx
+ .sess()
+ .struct_span_warn(sp, "could not parse code block as Rust code");
+
+ for mut err in errors {
+ diag.note(&format!("error from rustc: {}", err.message()));
+ err.cancel();
+ }
+
+ if code_block.syntax.is_none() && code_block.is_fenced {
+ let sp = sp.from_inner_byte_pos(0, 3);
+ diag.span_suggestion_with_applicability(
+ sp,
+ "mark blocks that do not contain Rust code as text",
+ String::from("```text"),
+ Applicability::MachineApplicable,
+ );
+ }
+
+ diag
+ } else {
+ // We couldn't calculate the span of the markdown block that had the error, so our
+ // diagnostics are going to be a bit lacking.
+ let mut diag = self.cx.sess().struct_span_warn(
+ super::span_of_attrs(&item.attrs),
+ "doc comment contains an invalid Rust code block",
+ );
+
+ for mut err in errors {
+ // Don't bother reporting the error, because we can't show where it happened.
+ err.cancel();
+ }
+
+ if code_block.syntax.is_none() && code_block.is_fenced {
+ diag.help("mark blocks that do not contain Rust code as text: ```text");
+ }
+
+ diag
+ };
+
+ diag.emit();
+ }
+ }
+}
+
+impl<'a, 'tcx, 'rcx> DocFolder for SyntaxChecker<'a, 'tcx, 'rcx> {
+ fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
+ if let Some(dox) = &item.attrs.collapsed_doc_value() {
+ for code_block in markdown::rust_code_blocks(&dox) {
+ self.check_rust_syntax(&item, &dox, code_block);
+ }
+ }
+
+ self.fold_item_recur(item)
+ }
+}
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index fdc1c06..3d6096b 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -6,7 +6,7 @@
use syntax::ast::{self, Ident, NodeId};
use syntax::feature_gate::UnstableFeatures;
use syntax::symbol::Symbol;
-use syntax_pos::{self, DUMMY_SP};
+use syntax_pos::DUMMY_SP;
use std::ops::Range;
@@ -16,6 +16,7 @@
use clean::*;
use passes::{look_for_tests, Pass};
+use super::span_of_attrs;
pub const COLLECT_INTRA_DOC_LINKS: Pass =
Pass::early("collect-intra-doc-links", collect_intra_doc_links,
@@ -440,28 +441,11 @@
None
}
-pub fn span_of_attrs(attrs: &Attributes) -> syntax_pos::Span {
- if attrs.doc_strings.is_empty() {
- return DUMMY_SP;
- }
- let start = attrs.doc_strings[0].span();
- let end = attrs.doc_strings.last().expect("No doc strings provided").span();
- start.to(end)
-}
-
/// Reports a resolution failure diagnostic.
///
-/// Ideally we can report the diagnostic with the actual span in the source where the link failure
-/// occurred. However, there's a mismatch between the span in the source code and the span in the
-/// markdown, so we have to do a bit of work to figure out the correspondence.
-///
-/// It's not too hard to find the span for sugared doc comments (`///` and `/**`), because the
-/// source will match the markdown exactly, excluding the comment markers. However, it's much more
-/// difficult to calculate the spans for unsugared docs, because we have to deal with escaping and
-/// other source features. So, we attempt to find the exact source span of the resolution failure
-/// in sugared docs, but use the span of the documentation attributes themselves for unsugared
-/// docs. Because this span might be overly large, we display the markdown line containing the
-/// failure as a note.
+/// If we cannot find the exact source span of the resolution failure, we use the span of the
+/// documentation attributes themselves. This is a little heavy-handed, so we display the markdown
+/// line containing the failure as a note as well.
fn resolution_failure(
cx: &DocContext,
attrs: &Attributes,
@@ -473,54 +457,7 @@
let msg = format!("`[{}]` cannot be resolved, ignoring it...", path_str);
let mut diag = if let Some(link_range) = link_range {
- let src = cx.sess().source_map().span_to_snippet(sp);
- let is_all_sugared_doc = attrs.doc_strings.iter().all(|frag| match frag {
- DocFragment::SugaredDoc(..) => true,
- _ => false,
- });
-
- if let (Ok(src), true) = (src, is_all_sugared_doc) {
- // The number of markdown lines up to and including the resolution failure.
- let num_lines = dox[..link_range.start].lines().count();
-
- // We use `split_terminator('\n')` instead of `lines()` when counting bytes to ensure
- // that DOS-style line endings do not cause the spans to be calculated incorrectly.
- let mut src_lines = src.split_terminator('\n');
- let mut md_lines = dox.split_terminator('\n').take(num_lines).peekable();
-
- // The number of bytes from the start of the source span to the resolution failure that
- // are *not* part of the markdown, like comment markers.
- let mut extra_src_bytes = 0;
-
- while let Some(md_line) = md_lines.next() {
- loop {
- let source_line = src_lines
- .next()
- .expect("could not find markdown line in source");
-
- match source_line.find(md_line) {
- Some(offset) => {
- extra_src_bytes += if md_lines.peek().is_some() {
- source_line.len() - md_line.len()
- } else {
- offset
- };
- break;
- }
- None => {
- // Since this is a source line that doesn't include a markdown line,
- // we have to count the newline that we split from earlier.
- extra_src_bytes += source_line.len() + 1;
- }
- }
- }
- }
-
- let sp = sp.from_inner_byte_pos(
- link_range.start + extra_src_bytes,
- link_range.end + extra_src_bytes,
- );
-
+ if let Some(sp) = super::source_span_for_markdown_range(cx, dox, &link_range, attrs) {
let mut diag = cx.tcx.struct_span_lint_node(
lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE,
NodeId::from_u32(0),
diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs
index e897b9a..c9a3a2c 100644
--- a/src/librustdoc/passes/mod.rs
+++ b/src/librustdoc/passes/mod.rs
@@ -8,6 +8,8 @@
use std::mem;
use std::fmt;
use syntax::ast::NodeId;
+use syntax_pos::{DUMMY_SP, Span};
+use std::ops::Range;
use clean::{self, GetDefId, Item};
use core::{DocContext, DocAccessLevels};
@@ -16,8 +18,6 @@
use html::markdown::{find_testable_code, ErrorCodes, LangString};
-use self::collect_intra_doc_links::span_of_attrs;
-
mod collapse_docs;
pub use self::collapse_docs::COLLAPSE_DOCS;
@@ -45,6 +45,9 @@
mod collect_trait_impls;
pub use self::collect_trait_impls::COLLECT_TRAIT_IMPLS;
+mod check_code_block_syntax;
+pub use self::check_code_block_syntax::CHECK_CODE_BLOCK_SYNTAX;
+
/// Represents a single pass.
#[derive(Copy, Clone)]
pub enum Pass {
@@ -135,6 +138,7 @@
STRIP_PRIV_IMPORTS,
PROPAGATE_DOC_CFG,
COLLECT_INTRA_DOC_LINKS,
+ CHECK_CODE_BLOCK_SYNTAX,
COLLECT_TRAIT_IMPLS,
];
@@ -145,6 +149,7 @@
"strip-hidden",
"strip-private",
"collect-intra-doc-links",
+ "check-code-block-syntax",
"collapse-docs",
"unindent-comments",
"propagate-doc-cfg",
@@ -156,6 +161,7 @@
"check-private-items-doc-tests",
"strip-priv-imports",
"collect-intra-doc-links",
+ "check-code-block-syntax",
"collapse-docs",
"unindent-comments",
"propagate-doc-cfg",
@@ -396,3 +402,94 @@
}
}
}
+
+/// Return a span encompassing all the given attributes.
+crate fn span_of_attrs(attrs: &clean::Attributes) -> Span {
+ if attrs.doc_strings.is_empty() {
+ return DUMMY_SP;
+ }
+ let start = attrs.doc_strings[0].span();
+ let end = attrs.doc_strings.last().expect("No doc strings provided").span();
+ start.to(end)
+}
+
+/// Attempts to match a range of bytes from parsed markdown to a `Span` in the source code.
+///
+/// This method will return `None` if we cannot construct a span from the source map or if the
+/// attributes are not all sugared doc comments. It's difficult to calculate the correct span in
+/// that case due to escaping and other source features.
+crate fn source_span_for_markdown_range(
+ cx: &DocContext,
+ markdown: &str,
+ md_range: &Range<usize>,
+ attrs: &clean::Attributes,
+) -> Option<Span> {
+ let is_all_sugared_doc = attrs.doc_strings.iter().all(|frag| match frag {
+ clean::DocFragment::SugaredDoc(..) => true,
+ _ => false,
+ });
+
+ if !is_all_sugared_doc {
+ return None;
+ }
+
+ let snippet = cx
+ .sess()
+ .source_map()
+ .span_to_snippet(span_of_attrs(attrs))
+ .ok()?;
+
+ let starting_line = markdown[..md_range.start].lines().count() - 1;
+ let ending_line = markdown[..md_range.end].lines().count() - 1;
+
+ // We use `split_terminator('\n')` instead of `lines()` when counting bytes so that we only
+ // we can treat CRLF and LF line endings the same way.
+ let mut src_lines = snippet.split_terminator('\n');
+ let md_lines = markdown.split_terminator('\n');
+
+ // The number of bytes from the source span to the markdown span that are not part
+ // of the markdown, like comment markers.
+ let mut start_bytes = 0;
+ let mut end_bytes = 0;
+
+ 'outer: for (line_no, md_line) in md_lines.enumerate() {
+ loop {
+ let source_line = src_lines.next().expect("could not find markdown in source");
+ match source_line.find(md_line) {
+ Some(offset) => {
+ if line_no == starting_line {
+ start_bytes += offset;
+
+ if starting_line == ending_line {
+ break 'outer;
+ }
+ } else if line_no == ending_line {
+ end_bytes += offset;
+ break 'outer;
+ } else if line_no < starting_line {
+ start_bytes += source_line.len() - md_line.len();
+ } else {
+ end_bytes += source_line.len() - md_line.len();
+ }
+ break;
+ }
+ None => {
+ // Since this is a source line that doesn't include a markdown line,
+ // we have to count the newline that we split from earlier.
+ if line_no <= starting_line {
+ start_bytes += source_line.len() + 1;
+ } else {
+ end_bytes += source_line.len() + 1;
+ }
+ }
+ }
+ }
+ }
+
+ let sp = span_of_attrs(attrs).from_inner_byte_pos(
+ md_range.start + start_bytes,
+ md_range.end + start_bytes + end_bytes,
+ );
+
+ Some(sp)
+}
diff --git a/src/libstd/sys/unix/fast_thread_local.rs b/src/libstd/sys/unix/fast_thread_local.rs
index d48d701d..742ffd1 100644
--- a/src/libstd/sys/unix/fast_thread_local.rs
+++ b/src/libstd/sys/unix/fast_thread_local.rs
@@ -33,30 +33,57 @@
register_dtor_fallback(t, dtor);
}
-// macOS's analog of the above linux function is this _tlv_atexit function.
-// The disassembly of thread_local globals in C++ (at least produced by
-// clang) will have this show up in the output.
+// This implementation is very similar to register_dtor_fallback in
+// sys_common/thread_local.rs. The main difference is that we want to hook into
+// macOS's analog of the above linux function, _tlv_atexit. OSX will run the
+// registered dtors before any TLS slots get freed, and when the main thread
+// exits.
+//
+// Unfortunately, calling _tlv_atexit while tls dtors are running is UB. The
+// workaround below is to register, via _tlv_atexit, a custom DTOR list once per
+// thread. thread_local dtors are pushed to the DTOR list without calling
+// _tlv_atexit.
#[cfg(target_os = "macos")]
pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
+ use cell::Cell;
+ use ptr;
+
+ #[thread_local]
+ static REGISTERED: Cell<bool> = Cell::new(false);
+ if !REGISTERED.get() {
+ _tlv_atexit(run_dtors, ptr::null_mut());
+ REGISTERED.set(true);
+ }
+
+ type List = Vec<(*mut u8, unsafe extern fn(*mut u8))>;
+
+ #[thread_local]
+ static DTORS: Cell<*mut List> = Cell::new(ptr::null_mut());
+ if DTORS.get().is_null() {
+ let v: Box<List> = box Vec::new();
+ DTORS.set(Box::into_raw(v));
+ }
+
extern {
fn _tlv_atexit(dtor: unsafe extern fn(*mut u8),
arg: *mut u8);
}
- _tlv_atexit(dtor, t);
+
+ let list: &mut List = &mut *DTORS.get();
+ list.push((t, dtor));
+
+ unsafe extern fn run_dtors(_: *mut u8) {
+ let mut ptr = DTORS.replace(ptr::null_mut());
+ while !ptr.is_null() {
+ let list = Box::from_raw(ptr);
+ for (ptr, dtor) in list.into_iter() {
+ dtor(ptr);
+ }
+ ptr = DTORS.replace(ptr::null_mut());
+ }
+ }
}
pub fn requires_move_before_drop() -> bool {
- // The macOS implementation of TLS apparently had an odd aspect to it
- // where the pointer we have may be overwritten while this destructor
- // is running. Specifically if a TLS destructor re-accesses TLS it may
- // trigger a re-initialization of all TLS variables, paving over at
- // least some destroyed ones with initial values.
- //
- // This means that if we drop a TLS value in place on macOS that we could
- // revert the value to its original state halfway through the
- // destructor, which would be bad!
- //
- // Hence, we use `ptr::read` on macOS (to move to a "safe" location)
- // instead of drop_in_place.
- cfg!(target_os = "macos")
+ false
}
diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs
index efd231e..5d2eb5f 100644
--- a/src/libstd/thread/local.rs
+++ b/src/libstd/thread/local.rs
@@ -69,9 +69,6 @@
/// destroyed, but not all platforms have this guard. Those platforms that do
/// not guard typically have a synthetic limit after which point no more
/// destructors are run.
-/// 3. On macOS, initializing TLS during destruction of other TLS slots can
-/// sometimes cancel *all* destructors for the current thread, whether or not
-/// the slots have already had their destructors run or not.
///
/// [`with`]: ../../std/thread/struct.LocalKey.html#method.with
/// [`thread_local!`]: ../../std/macro.thread_local.html
@@ -604,11 +601,8 @@
}
// Note that this test will deadlock if TLS destructors aren't run (this
- // requires the destructor to be run to pass the test). macOS has a known bug
- // where dtors-in-dtors may cancel other destructors, so we just ignore this
- // test on macOS.
+ // requires the destructor to be run to pass the test).
#[test]
- #[cfg_attr(target_os = "macos", ignore)]
fn dtors_in_dtors_in_dtors() {
struct S1(Sender<()>);
thread_local!(static K1: UnsafeCell<Option<S1>> = UnsafeCell::new(None));
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 99ab9fb..405cf61 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;
@@ -192,6 +192,16 @@
pub output: Option<P<Ty>>,
}
+impl ParenthesisedArgs {
+ pub fn as_angle_bracketed_args(&self) -> AngleBracketedArgs {
+ AngleBracketedArgs {
+ span: self.span,
+ args: self.inputs.iter().cloned().map(|input| GenericArg::Type(input)).collect(),
+ bindings: vec![],
+ }
+ }
+}
+
// hack to ensure that we don't try to access the private parts of `NodeId` in this module
mod node_id_inner {
use rustc_data_structures::indexed_vec::Idx;
@@ -1216,7 +1226,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 +1238,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,
}
@@ -1285,6 +1295,8 @@
FloatUnsuffixed(Symbol),
/// A boolean literal.
Bool(bool),
+ /// A recovered character literal that contains mutliple `char`s, most likely a typo.
+ Err(Symbol),
}
impl LitKind {
@@ -1321,6 +1333,7 @@
| LitKind::ByteStr(..)
| LitKind::Byte(..)
| LitKind::Char(..)
+ | LitKind::Err(..)
| LitKind::Int(_, LitIntType::Unsuffixed)
| LitKind::FloatUnsuffixed(..)
| LitKind::Bool(..) => true,
diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs
index f83c1ec..e5ce6a3 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),
};
@@ -666,6 +666,7 @@
} else {
"false"
})), false),
+ LitKind::Err(val) => Token::Literal(token::Lit::Err(val), None),
}
}
diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs
index c312414..df3b49c 100644
--- a/src/libsyntax/ext/quote.rs
+++ b/src/libsyntax/ext/quote.rs
@@ -646,6 +646,7 @@
token::Literal(token::Byte(i), suf) => return mk_lit!("Byte", suf, i),
token::Literal(token::Char(i), suf) => return mk_lit!("Char", suf, i),
+ token::Literal(token::Err(_i), _suf) => return cx.expr(sp, ast::ExprKind::Err),
token::Literal(token::Integer(i), suf) => return mk_lit!("Integer", suf, i),
token::Literal(token::Float(i), suf) => return mk_lit!("Float", suf, i),
token::Literal(token::Str_(i), suf) => return mk_lit!("Str_", suf, i),
@@ -748,7 +749,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/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs
index 0e1c3b4..8827e04 100644
--- a/src/libsyntax/parse/lexer/mod.rs
+++ b/src/libsyntax/parse/lexer/mod.rs
@@ -238,19 +238,6 @@
sr
}
- pub fn new_without_err(sess: &'a ParseSess,
- source_file: Lrc<syntax_pos::SourceFile>,
- override_span: Option<Span>,
- prepend_error_text: &str) -> Result<Self, ()> {
- let mut sr = StringReader::new_raw(sess, source_file, override_span);
- if sr.advance_token().is_err() {
- eprintln!("{}", prepend_error_text);
- sr.emit_fatal_errors();
- return Err(());
- }
- Ok(sr)
- }
-
pub fn new_or_buffered_errs(sess: &'a ParseSess,
source_file: Lrc<syntax_pos::SourceFile>,
override_span: Option<Span>) -> Result<Self, Vec<Diagnostic>> {
@@ -1408,9 +1395,10 @@
// lifetimes shouldn't end with a single quote
// if we find one, then this is an invalid character literal
if self.ch_is('\'') {
- self.fatal_span_verbose(start_with_quote, self.next_pos,
- String::from("character literal may only contain one codepoint"))
- .raise();
+ self.err_span_(start_with_quote, self.next_pos,
+ "character literal may only contain one codepoint");
+ self.bump();
+ return Ok(token::Literal(token::Err(Symbol::intern("??")), None))
}
@@ -1445,7 +1433,7 @@
format!("\"{}\"", &self.src[start..end]),
Applicability::MachineApplicable
).emit();
- return Ok(token::Literal(token::Str_(Symbol::intern("??")), None))
+ return Ok(token::Literal(token::Err(Symbol::intern("??")), None))
}
if self.ch_is('\n') || self.is_eof() || self.ch_is('/') {
// Only attempt to infer single line string literals. If we encounter
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index ea20553..8d03969 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -466,6 +466,7 @@
match lit {
token::Byte(i) => (true, Some(LitKind::Byte(byte_lit(&i.as_str()).0))),
token::Char(i) => (true, Some(LitKind::Char(char_lit(&i.as_str(), diag).0))),
+ token::Err(i) => (true, Some(LitKind::Err(i))),
// There are some valid suffixes for integer and float literals,
// so all the handling is done internally.
@@ -817,7 +818,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 +827,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 +837,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 5b430d1..439eec5 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),
}
@@ -2176,11 +2176,11 @@
style != PathStyle::Mod && self.check(&token::ModSep)
&& self.look_ahead(1, |t| is_args_start(t)) {
// Generic arguments are found - `<`, `(`, `::<` or `::(`.
- let lo = self.span;
if self.eat(&token::ModSep) && style == PathStyle::Type && enable_warning {
self.diagnostic().struct_span_warn(self.prev_span, "unnecessary path disambiguator")
.span_label(self.prev_span, "try removing `::`").emit();
}
+ let lo = self.span;
let args = if self.eat_lt() {
// `<'a, T, A = U>`
@@ -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();
@@ -4482,13 +4483,17 @@
}
/// Emit an expected item after attributes error.
- fn expected_item_err(&self, attrs: &[Attribute]) {
+ fn expected_item_err(&mut self, attrs: &[Attribute]) -> PResult<'a, ()> {
let message = match attrs.last() {
Some(&Attribute { is_sugared_doc: true, .. }) => "expected item after doc comment",
_ => "expected item after attributes",
};
- self.span_err(self.prev_span, message);
+ let mut err = self.diagnostic().struct_span_err(self.prev_span, message);
+ if attrs.last().unwrap().is_sugared_doc {
+ err.span_label(self.prev_span, "this doc comment doesn't document anything");
+ }
+ Err(err)
}
/// Parse a statement. This stops just before trailing semicolons on everything but items.
@@ -4641,7 +4646,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)) {
@@ -6904,7 +6909,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)
@@ -7631,7 +7640,7 @@
}
None => {
if !attrs.is_empty() {
- self.expected_item_err(&attrs);
+ self.expected_item_err(&attrs)?;
}
self.unexpected()
@@ -7694,7 +7703,7 @@
}
if !attributes_allowed && !attrs.is_empty() {
- self.expected_item_err(&attrs);
+ self.expected_item_err(&attrs)?;
}
Ok(None)
}
@@ -7757,7 +7766,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?"),
@@ -7776,10 +7785,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);
}
@@ -7788,7 +7796,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/parse/token.rs b/src/libsyntax/parse/token.rs
index 25a4da3..f06e975 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -60,6 +60,7 @@
pub enum Lit {
Byte(ast::Name),
Char(ast::Name),
+ Err(ast::Name),
Integer(ast::Name),
Float(ast::Name),
Str_(ast::Name),
@@ -73,6 +74,7 @@
match *self {
Byte(_) => "byte literal",
Char(_) => "char literal",
+ Err(_) => "invalid literal",
Integer(_) => "integer literal",
Float(_) => "float literal",
Str_(_) | StrRaw(..) => "string literal",
@@ -471,8 +473,7 @@
Le | EqEq | Ne | Ge | AndAnd | OrOr | Tilde | BinOpEq(..) | At | DotDotDot |
DotDotEq | Comma | Semi | ModSep | RArrow | LArrow | FatArrow | Pound | Dollar |
- Question | OpenDelim(..) | CloseDelim(..) => return None,
-
+ Question | OpenDelim(..) | CloseDelim(..) |
Literal(..) | Ident(..) | Lifetime(..) | Interpolated(..) | DocComment(..) |
Whitespace | Comment | Shebang(..) | Eof => return None,
})
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 2ad3d3a..7cecf4b 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -224,6 +224,7 @@
let mut out = match lit {
token::Byte(b) => format!("b'{}'", b),
token::Char(c) => format!("'{}'", c),
+ token::Err(c) => format!("'{}'", c),
token::Float(c) |
token::Integer(c) => c.to_string(),
token::Str_(s) => format!("\"{}\"", s),
@@ -603,6 +604,14 @@
}
match lit.node {
ast::LitKind::Str(st, style) => self.print_string(&st.as_str(), style),
+ ast::LitKind::Err(st) => {
+ let st = st.as_str().escape_debug();
+ let mut res = String::with_capacity(st.len() + 2);
+ res.push('\'');
+ res.push_str(&st);
+ res.push('\'');
+ self.writer().word(res)
+ }
ast::LitKind::Byte(byte) => {
let mut res = String::from("b'");
res.extend(ascii::escape_default(byte).map(|c| c as char));
@@ -807,7 +816,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/concat.rs b/src/libsyntax_ext/concat.rs
index 807f190..f148f8e 100644
--- a/src/libsyntax_ext/concat.rs
+++ b/src/libsyntax_ext/concat.rs
@@ -23,6 +23,7 @@
match e.node {
ast::ExprKind::Lit(ref lit) => match lit.node {
ast::LitKind::Str(ref s, _)
+ | ast::LitKind::Err(ref s)
| ast::LitKind::Float(ref s, _)
| ast::LitKind::FloatUnsuffixed(ref s) => {
accumulator.push_str(&s.as_str());
diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs
index 3e3bca7..215df42 100644
--- a/src/libsyntax_ext/format.rs
+++ b/src/libsyntax_ext/format.rs
@@ -493,7 +493,10 @@
let fill = arg.format.fill.unwrap_or(' ');
- if *arg != simple_arg || fill != ' ' {
+ let pos_simple =
+ arg.position.index() == simple_arg.position.index();
+
+ if !pos_simple || arg.format != simple_arg.format || fill != ' ' {
self.all_pieces_simple = false;
}
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/try_from.rs b/src/test/run-pass/try_from.rs
new file mode 100644
index 0000000..4522ce3
--- /dev/null
+++ b/src/test/run-pass/try_from.rs
@@ -0,0 +1,37 @@
+// This test relies on `TryFrom` being blanket impl for all `T: Into`
+// and `TryInto` being blanket impl for all `U: TryFrom`
+
+// This test was added to show the motivation for doing this
+// over `TryFrom` being blanket impl for all `T: From`
+
+#![feature(try_from, never_type)]
+
+use std::convert::TryInto;
+
+struct Foo<T> {
+ t: T,
+}
+
+// This fails to compile due to coherence restrictions
+// as of Rust version 1.32.x, therefore it could not be used
+// instead of the `Into` version of the impl, and serves as
+// motivation for a blanket impl for all `T: Into`, instead
+// of a blanket impl for all `T: From`
+/*
+impl<T> From<Foo<T>> for Box<T> {
+ fn from(foo: Foo<T>) -> Box<T> {
+ Box::new(foo.t)
+ }
+}
+*/
+
+impl<T> Into<Vec<T>> for Foo<T> {
+ fn into(self) -> Vec<T> {
+ vec![self.t]
+ }
+}
+
+pub fn main() {
+ let _: Result<Vec<i32>, !> = Foo { t: 10 }.try_into();
+}
+
diff --git a/src/test/rustdoc-ui/invalid-syntax.rs b/src/test/rustdoc-ui/invalid-syntax.rs
index 537816b..924e038 100644
--- a/src/test/rustdoc-ui/invalid-syntax.rs
+++ b/src/test/rustdoc-ui/invalid-syntax.rs
@@ -1,7 +1,66 @@
// compile-pass
-// compile-flags: --error-format=human
/// ```
/// \__________pkt->size___________/ \_result->size_/ \__pkt->size__/
/// ```
pub fn foo() {}
+
+/// ```
+/// |
+/// LL | use foobar::Baz;
+/// | ^^^^^^ did you mean `baz::foobar`?
+/// ```
+pub fn bar() {}
+
+/// ```
+/// valid
+/// ```
+///
+/// ```
+/// \_
+/// ```
+///
+/// ```text
+/// "invalid
+/// ```
+pub fn valid_and_invalid() {}
+
+/// This is a normal doc comment, but...
+///
+/// There's a code block with bad syntax in it:
+///
+/// ```rust
+/// \_
+/// ```
+///
+/// Good thing we tested it!
+pub fn baz() {}
+
+/// Indented block start
+///
+/// code with bad syntax
+/// \_
+///
+/// Indented block end
+pub fn quux() {}
+
+/// Unclosed fence
+///
+/// ```
+/// slkdjf
+pub fn xyzzy() {}
+
+/// Indented code that contains a fence
+///
+/// ```
+pub fn blah() {}
+
+/// ```edition2018
+/// \_
+/// ```
+pub fn blargh() {}
+
+#[doc = "```"]
+/// \_
+#[doc = "```"]
+pub fn crazy_attrs() {}
diff --git a/src/test/rustdoc-ui/invalid-syntax.stderr b/src/test/rustdoc-ui/invalid-syntax.stderr
index b566133..1080038 100644
--- a/src/test/rustdoc-ui/invalid-syntax.stderr
+++ b/src/test/rustdoc-ui/invalid-syntax.stderr
@@ -1,10 +1,97 @@
-Output from rustc:
-error: unknown start of token: /
- --> <stdin>:1:1
- |
-1 | /__________pkt->size___________/ /_result->size_/ /__pkt->size__/
- | ^
+warning: could not parse code block as Rust code
+ --> $DIR/invalid-syntax.rs:3:5
+ |
+LL | /// ```
+ | _____^
+LL | | /// /__________pkt->size___________/ /_result->size_/ /__pkt->size__/
+LL | | /// ```
+ | |_______^
+ |
+ = note: error from rustc: unknown start of token: /
+help: mark blocks that do not contain Rust code as text
+ |
+LL | /// ```text
+ | ^^^^^^^
-warning: Invalid doc comment starting with: `/__________pkt->size___________/ /_result->size_/ /__pkt->size__/`
-(Ignoring this codeblock)
+warning: could not parse code block as Rust code
+ --> $DIR/invalid-syntax.rs:8:5
+ |
+LL | /// ```
+ | _____^
+LL | | /// |
+LL | | /// LL | use foobar::Baz;
+LL | | /// | ^^^^^^ did you mean `baz::foobar`?
+LL | | /// ```
+ | |_______^
+ |
+ = note: error from rustc: unknown start of token: `
+help: mark blocks that do not contain Rust code as text
+ |
+LL | /// ```text
+ | ^^^^^^^
+
+warning: could not parse code block as Rust code
+ --> $DIR/invalid-syntax.rs:19:5
+ |
+LL | /// ```
+ | _____^
+LL | | /// /_
+LL | | /// ```
+ | |_______^
+ |
+ = note: error from rustc: unknown start of token: /
+help: mark blocks that do not contain Rust code as text
+ |
+LL | /// ```text
+ | ^^^^^^^
+
+warning: could not parse code block as Rust code
+ --> $DIR/invalid-syntax.rs:32:5
+ |
+LL | /// ```rust
+ | _____^
+LL | | /// /_
+LL | | /// ```
+ | |_______^
+ |
+ = note: error from rustc: unknown start of token: /
+
+warning: could not parse code block as Rust code
+ --> $DIR/invalid-syntax.rs:41:9
+ |
+LL | /// code with bad syntax
+ | _________^
+LL | | /// /_
+ | |__________^
+ |
+ = note: error from rustc: unknown start of token: /
+
+warning: could not parse code block as Rust code
+ --> $DIR/invalid-syntax.rs:55:9
+ |
+LL | /// ```
+ | ^^^
+ |
+ = note: error from rustc: unknown start of token: `
+
+warning: could not parse code block as Rust code
+ --> $DIR/invalid-syntax.rs:58:5
+ |
+LL | /// ```edition2018
+ | _____^
+LL | | /// /_
+LL | | /// ```
+ | |_______^
+ |
+ = note: error from rustc: unknown start of token: /
+
+warning: doc comment contains an invalid Rust code block
+ --> $DIR/invalid-syntax.rs:63:1
+ |
+LL | / #[doc = "```"]
+LL | | /// /_
+LL | | #[doc = "```"]
+ | |______________^
+ |
+ = help: mark blocks that do not contain Rust code as text: ```text
diff --git a/src/test/rustdoc/bad-codeblock-syntax.rs b/src/test/rustdoc/bad-codeblock-syntax.rs
new file mode 100644
index 0000000..0ab2f68
--- /dev/null
+++ b/src/test/rustdoc/bad-codeblock-syntax.rs
@@ -0,0 +1,27 @@
+// @has bad_codeblock_syntax/fn.foo.html
+// @has - '//*[@class="docblock"]/pre/code' '\_'
+/// ```
+/// \_
+/// ```
+pub fn foo() {}
+
+// @has bad_codeblock_syntax/fn.bar.html
+// @has - '//*[@class="docblock"]/pre/code' '`baz::foobar`'
+/// ```
+/// `baz::foobar`
+/// ```
+pub fn bar() {}
+
+// @has bad_codeblock_syntax/fn.quux.html
+// @has - '//*[@class="docblock"]/pre/code' '\_'
+/// ```rust
+/// \_
+/// ```
+pub fn quux() {}
+
+// @has bad_codeblock_syntax/fn.ok.html
+// @has - '//*[@class="docblock"]/pre/code[@class="language-text"]' '\_'
+/// ```text
+/// \_
+/// ```
+pub fn ok() {}
diff --git a/src/test/ui/cast/cast-ptr-to-int-const.rs b/src/test/ui/cast/cast-ptr-to-int-const.rs
index 70b4869..ac153cb 100644
--- a/src/test/ui/cast/cast-ptr-to-int-const.rs
+++ b/src/test/ui/cast/cast-ptr-to-int-const.rs
@@ -1,7 +1,11 @@
// gate-test-const_raw_ptr_to_usize_cast
fn main() {
- const X: u32 = main as u32; //~ ERROR casting pointers to integers in constants is unstable
+ const X: u32 = unsafe {
+ main as u32 //~ ERROR casting pointers to integers in constants is unstable
+ };
const Y: u32 = 0;
- const Z: u32 = &Y as *const u32 as u32; //~ ERROR is unstable
+ const Z: u32 = unsafe {
+ &Y as *const u32 as u32 //~ ERROR is unstable
+ };
}
diff --git a/src/test/ui/cast/cast-ptr-to-int-const.stderr b/src/test/ui/cast/cast-ptr-to-int-const.stderr
index 3cce07d..d04595e 100644
--- a/src/test/ui/cast/cast-ptr-to-int-const.stderr
+++ b/src/test/ui/cast/cast-ptr-to-int-const.stderr
@@ -1,16 +1,16 @@
error[E0658]: casting pointers to integers in constants is unstable (see issue #51910)
- --> $DIR/cast-ptr-to-int-const.rs:4:20
+ --> $DIR/cast-ptr-to-int-const.rs:5:9
|
-LL | const X: u32 = main as u32; //~ ERROR casting pointers to integers in constants is unstable
- | ^^^^^^^^^^^
+LL | main as u32 //~ ERROR casting pointers to integers in constants is unstable
+ | ^^^^^^^^^^^
|
= help: add #![feature(const_raw_ptr_to_usize_cast)] to the crate attributes to enable
error[E0658]: casting pointers to integers in constants is unstable (see issue #51910)
- --> $DIR/cast-ptr-to-int-const.rs:6:20
+ --> $DIR/cast-ptr-to-int-const.rs:9:9
|
-LL | const Z: u32 = &Y as *const u32 as u32; //~ ERROR is unstable
- | ^^^^^^^^^^^^^^^^^^^^^^^
+LL | &Y as *const u32 as u32 //~ ERROR is unstable
+ | ^^^^^^^^^^^^^^^^^^^^^^^
|
= help: add #![feature(const_raw_ptr_to_usize_cast)] to the crate attributes to enable
diff --git a/src/test/ui/consts/const-eval/const_raw_ptr_ops.rs b/src/test/ui/consts/const-eval/const_raw_ptr_ops.rs
index 63bac17..4426668 100644
--- a/src/test/ui/consts/const-eval/const_raw_ptr_ops.rs
+++ b/src/test/ui/consts/const-eval/const_raw_ptr_ops.rs
@@ -3,13 +3,13 @@
fn main() {}
// unconst and bad, will thus error in miri
-const X: bool = &1 as *const i32 == &2 as *const i32; //~ ERROR any use of this value will cause
+const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; //~ ERROR any use of this
// unconst and fine
-const X2: bool = 42 as *const i32 == 43 as *const i32;
+const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 };
// unconst and fine
-const Y: usize = 42usize as *const i32 as usize + 1;
+const Y: usize = unsafe { 42usize as *const i32 as usize + 1 };
// unconst and bad, will thus error in miri
-const Y2: usize = &1 as *const i32 as usize + 1; //~ ERROR any use of this value will cause
+const Y2: usize = unsafe { &1 as *const i32 as usize + 1 }; //~ ERROR any use of this
// unconst and fine
const Z: i32 = unsafe { *(&1 as *const i32) };
// unconst and bad, will thus error in miri
diff --git a/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr b/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr
index ea11359..6be54c0 100644
--- a/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr
+++ b/src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr
@@ -1,20 +1,20 @@
error: any use of this value will cause an error
--> $DIR/const_raw_ptr_ops.rs:6:1
|
-LL | const X: bool = &1 as *const i32 == &2 as *const i32; //~ ERROR any use of this value will cause
- | ^^^^^^^^^^^^^^^^------------------------------------^
- | |
- | "pointer arithmetic or comparison" needs an rfc before being allowed inside constants
+LL | const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; //~ ERROR any use of this
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^------------------------------------^^^
+ | |
+ | "pointer arithmetic or comparison" needs an rfc before being allowed inside constants
|
= note: #[deny(const_err)] on by default
error: any use of this value will cause an error
--> $DIR/const_raw_ptr_ops.rs:12:1
|
-LL | const Y2: usize = &1 as *const i32 as usize + 1; //~ ERROR any use of this value will cause
- | ^^^^^^^^^^^^^^^^^^-----------------------------^
- | |
- | "pointer arithmetic or comparison" needs an rfc before being allowed inside constants
+LL | const Y2: usize = unsafe { &1 as *const i32 as usize + 1 }; //~ ERROR any use of this
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------------------^^^
+ | |
+ | "pointer arithmetic or comparison" needs an rfc before being allowed inside constants
error: any use of this value will cause an error
--> $DIR/const_raw_ptr_ops.rs:16:1
diff --git a/src/test/ui/consts/min_const_fn/cmp_fn_pointers.rs b/src/test/ui/consts/min_const_fn/cmp_fn_pointers.rs
index d8abd97..c2600f8 100644
--- a/src/test/ui/consts/min_const_fn/cmp_fn_pointers.rs
+++ b/src/test/ui/consts/min_const_fn/cmp_fn_pointers.rs
@@ -1,5 +1,5 @@
const fn cmp(x: fn(), y: fn()) -> bool { //~ ERROR function pointers in const fn are unstable
- x == y
+ unsafe { x == y }
}
fn main() {}
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr
index 91b0760..763c69e 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr
+++ b/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr
@@ -95,97 +95,109 @@
| ^^^^^^^^^^
error: casting pointers to ints is unstable in const fn
- --> $DIR/min_const_fn.rs:94:42
+ --> $DIR/min_const_fn.rs:94:63
+ |
+LL | const fn foo30_with_unsafe(x: *const u32) -> usize { unsafe { x as usize } }
+ | ^^^^^^^^^^
+
+error: casting pointers to ints is unstable in const fn
+ --> $DIR/min_const_fn.rs:96:42
|
LL | const fn foo30_2(x: *mut u32) -> usize { x as usize }
| ^^^^^^^^^^
+error: casting pointers to ints is unstable in const fn
+ --> $DIR/min_const_fn.rs:98:63
+ |
+LL | const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize } }
+ | ^^^^^^^^^^
+
error: `if`, `match`, `&&` and `||` are not stable in const fn
- --> $DIR/min_const_fn.rs:96:38
+ --> $DIR/min_const_fn.rs:100:38
|
LL | const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } }
| ^^^^^^^^^^^^^^^^^^^^^^
error: `if`, `match`, `&&` and `||` are not stable in const fn
- --> $DIR/min_const_fn.rs:98:29
+ --> $DIR/min_const_fn.rs:102:29
|
LL | const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
| ^^^^^^^^^^^
error: `if`, `match`, `&&` and `||` are not stable in const fn
- --> $DIR/min_const_fn.rs:100:44
+ --> $DIR/min_const_fn.rs:104:44
|
LL | const fn foo36(a: bool, b: bool) -> bool { a && b }
| ^^^^^^
error: `if`, `match`, `&&` and `||` are not stable in const fn
- --> $DIR/min_const_fn.rs:102:44
+ --> $DIR/min_const_fn.rs:106:44
|
LL | const fn foo37(a: bool, b: bool) -> bool { a || b }
| ^^^^^^
error: mutable references in const fn are unstable
- --> $DIR/min_const_fn.rs:104:14
+ --> $DIR/min_const_fn.rs:108:14
|
LL | const fn inc(x: &mut i32) { *x += 1 }
| ^
error: trait bounds other than `Sized` on const fn parameters are unstable
- --> $DIR/min_const_fn.rs:109:6
+ --> $DIR/min_const_fn.rs:113:6
|
LL | impl<T: std::fmt::Debug> Foo<T> {
| ^
error: trait bounds other than `Sized` on const fn parameters are unstable
- --> $DIR/min_const_fn.rs:114:6
+ --> $DIR/min_const_fn.rs:118:6
|
LL | impl<T: std::fmt::Debug + Sized> Foo<T> {
| ^
error: trait bounds other than `Sized` on const fn parameters are unstable
- --> $DIR/min_const_fn.rs:119:6
+ --> $DIR/min_const_fn.rs:123:6
|
LL | impl<T: Sync + Sized> Foo<T> {
| ^
error: `impl Trait` in const fn is unstable
- --> $DIR/min_const_fn.rs:125:24
+ --> $DIR/min_const_fn.rs:129:24
|
LL | const fn no_rpit2() -> AlanTuring<impl std::fmt::Debug> { AlanTuring(0) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: trait bounds other than `Sized` on const fn parameters are unstable
- --> $DIR/min_const_fn.rs:127:34
+ --> $DIR/min_const_fn.rs:131:34
|
LL | const fn no_apit2(_x: AlanTuring<impl std::fmt::Debug>) {}
| ^^^^^^^^^^^^^^^^^^^^
error: trait bounds other than `Sized` on const fn parameters are unstable
- --> $DIR/min_const_fn.rs:129:22
+ --> $DIR/min_const_fn.rs:133:22
|
LL | const fn no_apit(_x: impl std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized`
| ^^^^^^^^^^^^^^^^^^^^
error: `impl Trait` in const fn is unstable
- --> $DIR/min_const_fn.rs:130:23
+ --> $DIR/min_const_fn.rs:134:23
|
LL | const fn no_rpit() -> impl std::fmt::Debug {} //~ ERROR `impl Trait` in const fn is unstable
| ^^^^^^^^^^^^^^^^^^^^
error: trait bounds other than `Sized` on const fn parameters are unstable
- --> $DIR/min_const_fn.rs:131:23
+ --> $DIR/min_const_fn.rs:135:23
|
LL | const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized`
| ^^
error: trait bounds other than `Sized` on const fn parameters are unstable
- --> $DIR/min_const_fn.rs:132:32
+ --> $DIR/min_const_fn.rs:136:32
|
LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning[E0515]: cannot return reference to temporary value
- --> $DIR/min_const_fn.rs:132:63
+ --> $DIR/min_const_fn.rs:136:63
|
LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
| ^--
@@ -197,24 +209,24 @@
= warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
error: trait bounds other than `Sized` on const fn parameters are unstable
- --> $DIR/min_const_fn.rs:137:41
+ --> $DIR/min_const_fn.rs:141:41
|
LL | const fn really_no_traits_i_mean_it() { (&() as &std::fmt::Debug, ()).1 }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: function pointers in const fn are unstable
- --> $DIR/min_const_fn.rs:140:21
+ --> $DIR/min_const_fn.rs:144:21
|
LL | const fn no_fn_ptrs(_x: fn()) {}
| ^^
error: function pointers in const fn are unstable
- --> $DIR/min_const_fn.rs:142:27
+ --> $DIR/min_const_fn.rs:146:27
|
LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo }
| ^^^^
-error: aborting due to 34 previous errors
+error: aborting due to 36 previous errors
Some errors occurred: E0493, E0515.
For more information about an error, try `rustc --explain E0493`.
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.rs b/src/test/ui/consts/min_const_fn/min_const_fn.rs
index 05cf3d5..ee3ffcd 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn.rs
+++ b/src/test/ui/consts/min_const_fn/min_const_fn.rs
@@ -90,9 +90,13 @@
const fn foo25() -> u32 { BAR } //~ ERROR cannot access `static` items in const fn
const fn foo26() -> &'static u32 { &BAR } //~ ERROR cannot access `static` items
const fn foo30(x: *const u32) -> usize { x as usize }
-//~^ ERROR casting pointers to int
+//~^ ERROR casting pointers to ints is unstable
+const fn foo30_with_unsafe(x: *const u32) -> usize { unsafe { x as usize } }
+//~^ ERROR casting pointers to ints is unstable
const fn foo30_2(x: *mut u32) -> usize { x as usize }
-//~^ ERROR casting pointers to int
+//~^ ERROR casting pointers to ints is unstable
+const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize } }
+//~^ ERROR casting pointers to ints is unstable
const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } }
//~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.stderr
index 2cae714..52c60c5 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn.stderr
+++ b/src/test/ui/consts/min_const_fn/min_const_fn.stderr
@@ -95,113 +95,125 @@
| ^^^^^^^^^^
error: casting pointers to ints is unstable in const fn
- --> $DIR/min_const_fn.rs:94:42
+ --> $DIR/min_const_fn.rs:94:63
+ |
+LL | const fn foo30_with_unsafe(x: *const u32) -> usize { unsafe { x as usize } }
+ | ^^^^^^^^^^
+
+error: casting pointers to ints is unstable in const fn
+ --> $DIR/min_const_fn.rs:96:42
|
LL | const fn foo30_2(x: *mut u32) -> usize { x as usize }
| ^^^^^^^^^^
+error: casting pointers to ints is unstable in const fn
+ --> $DIR/min_const_fn.rs:98:63
+ |
+LL | const fn foo30_2_with_unsafe(x: *mut u32) -> usize { unsafe { x as usize } }
+ | ^^^^^^^^^^
+
error: `if`, `match`, `&&` and `||` are not stable in const fn
- --> $DIR/min_const_fn.rs:96:38
+ --> $DIR/min_const_fn.rs:100:38
|
LL | const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } }
| ^^^^^^^^^^^^^^^^^^^^^^
error: `if`, `match`, `&&` and `||` are not stable in const fn
- --> $DIR/min_const_fn.rs:98:29
+ --> $DIR/min_const_fn.rs:102:29
|
LL | const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
| ^^^^^^^^^^^
error: `if`, `match`, `&&` and `||` are not stable in const fn
- --> $DIR/min_const_fn.rs:100:44
+ --> $DIR/min_const_fn.rs:104:44
|
LL | const fn foo36(a: bool, b: bool) -> bool { a && b }
| ^^^^^^
error: `if`, `match`, `&&` and `||` are not stable in const fn
- --> $DIR/min_const_fn.rs:102:44
+ --> $DIR/min_const_fn.rs:106:44
|
LL | const fn foo37(a: bool, b: bool) -> bool { a || b }
| ^^^^^^
error: mutable references in const fn are unstable
- --> $DIR/min_const_fn.rs:104:14
+ --> $DIR/min_const_fn.rs:108:14
|
LL | const fn inc(x: &mut i32) { *x += 1 }
| ^
error: trait bounds other than `Sized` on const fn parameters are unstable
- --> $DIR/min_const_fn.rs:109:6
+ --> $DIR/min_const_fn.rs:113:6
|
LL | impl<T: std::fmt::Debug> Foo<T> {
| ^
error: trait bounds other than `Sized` on const fn parameters are unstable
- --> $DIR/min_const_fn.rs:114:6
+ --> $DIR/min_const_fn.rs:118:6
|
LL | impl<T: std::fmt::Debug + Sized> Foo<T> {
| ^
error: trait bounds other than `Sized` on const fn parameters are unstable
- --> $DIR/min_const_fn.rs:119:6
+ --> $DIR/min_const_fn.rs:123:6
|
LL | impl<T: Sync + Sized> Foo<T> {
| ^
error: `impl Trait` in const fn is unstable
- --> $DIR/min_const_fn.rs:125:24
+ --> $DIR/min_const_fn.rs:129:24
|
LL | const fn no_rpit2() -> AlanTuring<impl std::fmt::Debug> { AlanTuring(0) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: trait bounds other than `Sized` on const fn parameters are unstable
- --> $DIR/min_const_fn.rs:127:34
+ --> $DIR/min_const_fn.rs:131:34
|
LL | const fn no_apit2(_x: AlanTuring<impl std::fmt::Debug>) {}
| ^^^^^^^^^^^^^^^^^^^^
error: trait bounds other than `Sized` on const fn parameters are unstable
- --> $DIR/min_const_fn.rs:129:22
+ --> $DIR/min_const_fn.rs:133:22
|
LL | const fn no_apit(_x: impl std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized`
| ^^^^^^^^^^^^^^^^^^^^
error: `impl Trait` in const fn is unstable
- --> $DIR/min_const_fn.rs:130:23
+ --> $DIR/min_const_fn.rs:134:23
|
LL | const fn no_rpit() -> impl std::fmt::Debug {} //~ ERROR `impl Trait` in const fn is unstable
| ^^^^^^^^^^^^^^^^^^^^
error: trait bounds other than `Sized` on const fn parameters are unstable
- --> $DIR/min_const_fn.rs:131:23
+ --> $DIR/min_const_fn.rs:135:23
|
LL | const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized`
| ^^
error: trait bounds other than `Sized` on const fn parameters are unstable
- --> $DIR/min_const_fn.rs:132:32
+ --> $DIR/min_const_fn.rs:136:32
|
LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: trait bounds other than `Sized` on const fn parameters are unstable
- --> $DIR/min_const_fn.rs:137:41
+ --> $DIR/min_const_fn.rs:141:41
|
LL | const fn really_no_traits_i_mean_it() { (&() as &std::fmt::Debug, ()).1 }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: function pointers in const fn are unstable
- --> $DIR/min_const_fn.rs:140:21
+ --> $DIR/min_const_fn.rs:144:21
|
LL | const fn no_fn_ptrs(_x: fn()) {}
| ^^
error: function pointers in const fn are unstable
- --> $DIR/min_const_fn.rs:142:27
+ --> $DIR/min_const_fn.rs:146:27
|
LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo }
| ^^^^
-error: aborting due to 34 previous errors
+error: aborting due to 36 previous errors
For more information about this error, try `rustc --explain E0493`.
diff --git a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr
index 140f98b..d6d5ce4 100644
--- a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr
+++ b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr
@@ -8,7 +8,7 @@
<Bar as Foo<i16>>
<Bar as Foo<i32>>
<Bar as Foo<i8>>
- <Bar as Foo<u8>>
+ <Bar as Foo<u16>>
and 2 others
error: aborting due to previous error
diff --git a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr
index 2346698..3411958 100644
--- a/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr
+++ b/src/test/ui/did_you_mean/issue-39802-show-5-trait-impls.stderr
@@ -40,10 +40,10 @@
| ^^^^^^^^^^^^^^^ the trait `Foo<i32>` is not implemented for `bool`
|
= help: the following implementations were found:
+ <bool as Foo<bool>>
+ <bool as Foo<i8>>
<bool as Foo<u16>>
<bool as Foo<u32>>
- <bool as Foo<u64>>
- <bool as Foo<u8>>
and 2 others
note: required by `Foo::bar`
--> $DIR/issue-39802-show-5-trait-impls.rs:2:5
diff --git a/src/test/ui/e0119/conflict-with-std.stderr b/src/test/ui/e0119/conflict-with-std.stderr
index d94e4dc..c2ae321 100644
--- a/src/test/ui/e0119/conflict-with-std.stderr
+++ b/src/test/ui/e0119/conflict-with-std.stderr
@@ -25,7 +25,7 @@
|
= note: conflicting implementation in crate `core`:
- impl<T, U> std::convert::TryFrom<U> for T
- where T: std::convert::From<U>;
+ where U: std::convert::Into<T>;
error: aborting due to 3 previous errors
diff --git a/src/test/ui/error-codes/E0214.stderr b/src/test/ui/error-codes/E0214.stderr
index 08a98b1..a10f2c0 100644
--- a/src/test/ui/error-codes/E0214.stderr
+++ b/src/test/ui/error-codes/E0214.stderr
@@ -1,8 +1,11 @@
-error[E0214]: parenthesized parameters may only be used with a trait
+error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
--> $DIR/E0214.rs:2:15
|
LL | let v: Vec(&str) = vec!["foo"];
- | ^^^^^^ only traits may use parentheses
+ | ^^^^^^
+ | |
+ | only `Fn` traits may use parentheses
+ | help: use angle brackets instead: `<&str>`
error: aborting due to previous error
diff --git a/src/test/ui/error-codes/E0395.rs b/src/test/ui/error-codes/E0395.rs
index c2de56c..9657bbd 100644
--- a/src/test/ui/error-codes/E0395.rs
+++ b/src/test/ui/error-codes/E0395.rs
@@ -3,6 +3,6 @@
static FOO: i32 = 42;
static BAR: i32 = 42;
-static BAZ: bool = { (&FOO as *const i32) == (&BAR as *const i32) }; //~ ERROR issue #53020
+static BAZ: bool = unsafe { (&FOO as *const i32) == (&BAR as *const i32) }; //~ ERROR issue #53020
fn main() {
}
diff --git a/src/test/ui/error-codes/E0395.stderr b/src/test/ui/error-codes/E0395.stderr
index 45e1ba0..cc7d94e 100644
--- a/src/test/ui/error-codes/E0395.stderr
+++ b/src/test/ui/error-codes/E0395.stderr
@@ -1,8 +1,8 @@
error[E0658]: comparing raw pointers inside static (see issue #53020)
- --> $DIR/E0395.rs:6:22
+ --> $DIR/E0395.rs:6:29
|
-LL | static BAZ: bool = { (&FOO as *const i32) == (&BAR as *const i32) }; //~ ERROR issue #53020
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | static BAZ: bool = unsafe { (&FOO as *const i32) == (&BAR as *const i32) }; //~ ERROR issue #53020
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: add #![feature(const_compare_raw_pointers)] to the crate attributes to enable
diff --git a/src/test/ui/feature-gates/feature-gate-is_sorted.rs b/src/test/ui/feature-gates/feature-gate-is_sorted.rs
new file mode 100644
index 0000000..078ecc5
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-is_sorted.rs
@@ -0,0 +1,13 @@
+fn main() {
+ // Assert `Iterator` methods are feature gated
+ assert!([1, 2, 2, 9].iter().is_sorted());
+ //~^ ERROR: use of unstable library feature 'is_sorted': new API
+ assert!(![-2i32, -1, 0, 3].iter().is_sorted_by_key(|n| n.abs()));
+ //~^ ERROR: use of unstable library feature 'is_sorted': new API
+
+ // Assert `[T]` methods are feature gated
+ assert!([1, 2, 2, 9].is_sorted());
+ //~^ ERROR: use of unstable library feature 'is_sorted': new API
+ assert!(![-2i32, -1, 0, 3].is_sorted_by_key(|n| n.abs()));
+ //~^ ERROR: use of unstable library feature 'is_sorted': new API
+}
diff --git a/src/test/ui/feature-gates/feature-gate-is_sorted.stderr b/src/test/ui/feature-gates/feature-gate-is_sorted.stderr
new file mode 100644
index 0000000..8230c1e
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-is_sorted.stderr
@@ -0,0 +1,35 @@
+error[E0658]: use of unstable library feature 'is_sorted': new API (see issue #53485)
+ --> $DIR/feature-gate-is_sorted.rs:3:33
+ |
+LL | assert!([1, 2, 2, 9].iter().is_sorted());
+ | ^^^^^^^^^
+ |
+ = help: add #![feature(is_sorted)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'is_sorted': new API (see issue #53485)
+ --> $DIR/feature-gate-is_sorted.rs:5:39
+ |
+LL | assert!(![-2i32, -1, 0, 3].iter().is_sorted_by_key(|n| n.abs()));
+ | ^^^^^^^^^^^^^^^^
+ |
+ = help: add #![feature(is_sorted)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'is_sorted': new API (see issue #53485)
+ --> $DIR/feature-gate-is_sorted.rs:9:26
+ |
+LL | assert!([1, 2, 2, 9].is_sorted());
+ | ^^^^^^^^^
+ |
+ = help: add #![feature(is_sorted)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'is_sorted': new API (see issue #53485)
+ --> $DIR/feature-gate-is_sorted.rs:11:32
+ |
+LL | assert!(![-2i32, -1, 0, 3].is_sorted_by_key(|n| n.abs()));
+ | ^^^^^^^^^^^^^^^^
+ |
+ = help: add #![feature(is_sorted)] to the crate attributes to enable
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/fully-qualified-type/fully-qualified-type-name2.stderr b/src/test/ui/fully-qualified-type/fully-qualified-type-name2.stderr
index 9a33d29..47bb5e4 100644
--- a/src/test/ui/fully-qualified-type/fully-qualified-type-name2.stderr
+++ b/src/test/ui/fully-qualified-type/fully-qualified-type-name2.stderr
@@ -1,6 +1,8 @@
error[E0308]: mismatched types
--> $DIR/fully-qualified-type-name2.rs:12:12
|
+LL | fn bar(x: x::Foo) -> y::Foo {
+ | ------ expected `y::Foo` because of return type
LL | return x;
| ^ expected enum `y::Foo`, found enum `x::Foo`
|
diff --git a/src/test/ui/fully-qualified-type/fully-qualified-type-name4.stderr b/src/test/ui/fully-qualified-type/fully-qualified-type-name4.stderr
index f03aaa6..b341879 100644
--- a/src/test/ui/fully-qualified-type/fully-qualified-type-name4.stderr
+++ b/src/test/ui/fully-qualified-type/fully-qualified-type-name4.stderr
@@ -1,6 +1,8 @@
error[E0308]: mismatched types
--> $DIR/fully-qualified-type-name4.rs:6:12
|
+LL | fn bar(x: usize) -> Option<usize> {
+ | ------------- expected `std::option::Option<usize>` because of return type
LL | return x;
| ^ expected enum `std::option::Option`, found usize
|
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/issues/issue-17458.rs b/src/test/ui/issues/issue-17458.rs
index d7a1752..444e94d 100644
--- a/src/test/ui/issues/issue-17458.rs
+++ b/src/test/ui/issues/issue-17458.rs
@@ -1,4 +1,4 @@
-static X: usize = 0 as *const usize as usize;
+static X: usize = unsafe { 0 as *const usize as usize };
//~^ ERROR: casting pointers to integers in statics is unstable
fn main() {
diff --git a/src/test/ui/issues/issue-17458.stderr b/src/test/ui/issues/issue-17458.stderr
index 0492141..a1a8ed9 100644
--- a/src/test/ui/issues/issue-17458.stderr
+++ b/src/test/ui/issues/issue-17458.stderr
@@ -1,8 +1,8 @@
error[E0658]: casting pointers to integers in statics is unstable (see issue #51910)
- --> $DIR/issue-17458.rs:1:19
+ --> $DIR/issue-17458.rs:1:28
|
-LL | static X: usize = 0 as *const usize as usize;
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | static X: usize = unsafe { 0 as *const usize as usize };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: add #![feature(const_raw_ptr_to_usize_cast)] to the crate attributes to enable
diff --git a/src/test/ui/issues/issue-18294.rs b/src/test/ui/issues/issue-18294.rs
index df4fd16..1c2229f 100644
--- a/src/test/ui/issues/issue-18294.rs
+++ b/src/test/ui/issues/issue-18294.rs
@@ -1,5 +1,5 @@
fn main() {
const X: u32 = 1;
- const Y: usize = &X as *const u32 as usize; //~ ERROR is unstable
+ const Y: usize = unsafe { &X as *const u32 as usize }; //~ ERROR is unstable
println!("{}", Y);
}
diff --git a/src/test/ui/issues/issue-18294.stderr b/src/test/ui/issues/issue-18294.stderr
index 2af7f45..f3e8ab1 100644
--- a/src/test/ui/issues/issue-18294.stderr
+++ b/src/test/ui/issues/issue-18294.stderr
@@ -1,8 +1,8 @@
error[E0658]: casting pointers to integers in constants is unstable (see issue #51910)
- --> $DIR/issue-18294.rs:3:22
+ --> $DIR/issue-18294.rs:3:31
|
-LL | const Y: usize = &X as *const u32 as usize; //~ ERROR is unstable
- | ^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | const Y: usize = unsafe { &X as *const u32 as usize }; //~ ERROR is unstable
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: add #![feature(const_raw_ptr_to_usize_cast)] to the crate attributes to enable
diff --git a/src/test/ui/issues/issue-23589.rs b/src/test/ui/issues/issue-23589.rs
index a59710a..1c640af 100644
--- a/src/test/ui/issues/issue-23589.rs
+++ b/src/test/ui/issues/issue-23589.rs
@@ -1,4 +1,5 @@
fn main() {
let v: Vec(&str) = vec!['1', '2'];
- //~^ ERROR parenthesized parameters may only be used with a trait
+ //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
+ //~| ERROR mismatched types
}
diff --git a/src/test/ui/issues/issue-23589.stderr b/src/test/ui/issues/issue-23589.stderr
index e6e07c1..bc2007b 100644
--- a/src/test/ui/issues/issue-23589.stderr
+++ b/src/test/ui/issues/issue-23589.stderr
@@ -1,9 +1,22 @@
-error[E0214]: parenthesized parameters may only be used with a trait
+error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
--> $DIR/issue-23589.rs:2:15
|
LL | let v: Vec(&str) = vec!['1', '2'];
- | ^^^^^^ only traits may use parentheses
+ | ^^^^^^
+ | |
+ | only `Fn` traits may use parentheses
+ | help: use angle brackets instead: `<&str>`
-error: aborting due to previous error
+error[E0308]: mismatched types
+ --> $DIR/issue-23589.rs:2:29
+ |
+LL | let v: Vec(&str) = vec!['1', '2'];
+ | ^^^ expected &str, found char
+ |
+ = note: expected type `&str`
+ found type `char`
-For more information about this error, try `rustc --explain E0214`.
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0214, E0308.
+For more information about an error, try `rustc --explain E0214`.
diff --git a/src/test/ui/issues/issue-25826.rs b/src/test/ui/issues/issue-25826.rs
index e602265..36a69cf 100644
--- a/src/test/ui/issues/issue-25826.rs
+++ b/src/test/ui/issues/issue-25826.rs
@@ -1,6 +1,6 @@
fn id<T>(t: T) -> T { t }
fn main() {
- const A: bool = id::<u8> as *const () < id::<u16> as *const ();
+ const A: bool = unsafe { id::<u8> as *const () < id::<u16> as *const () };
//~^ ERROR comparing raw pointers inside constant
println!("{}", A);
}
diff --git a/src/test/ui/issues/issue-25826.stderr b/src/test/ui/issues/issue-25826.stderr
index 73ebf29..dc547f7c 100644
--- a/src/test/ui/issues/issue-25826.stderr
+++ b/src/test/ui/issues/issue-25826.stderr
@@ -1,8 +1,8 @@
error[E0658]: comparing raw pointers inside constant (see issue #53020)
- --> $DIR/issue-25826.rs:3:21
+ --> $DIR/issue-25826.rs:3:30
|
-LL | const A: bool = id::<u8> as *const () < id::<u16> as *const ();
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | const A: bool = unsafe { id::<u8> as *const () < id::<u16> as *const () };
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: add #![feature(const_compare_raw_pointers)] to the crate attributes to enable
diff --git a/src/test/ui/issues/issue-32995-2.rs b/src/test/ui/issues/issue-32995-2.rs
index a4e333e..2234f68 100644
--- a/src/test/ui/issues/issue-32995-2.rs
+++ b/src/test/ui/issues/issue-32995-2.rs
@@ -2,11 +2,11 @@
fn main() {
{ fn f<X: ::std::marker()::Send>() {} }
- //~^ ERROR parenthesized parameters may only be used with a trait
+ //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
//~| WARN previously accepted
{ fn f() -> impl ::std::marker()::Send { } }
- //~^ ERROR parenthesized parameters may only be used with a trait
+ //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
//~| WARN previously accepted
}
@@ -14,5 +14,5 @@
struct X;
impl ::std::marker()::Copy for X {}
-//~^ ERROR parenthesized parameters may only be used with a trait
+//~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
//~| WARN previously accepted
diff --git a/src/test/ui/issues/issue-32995-2.stderr b/src/test/ui/issues/issue-32995-2.stderr
index 0ac12b7..104b76c 100644
--- a/src/test/ui/issues/issue-32995-2.stderr
+++ b/src/test/ui/issues/issue-32995-2.stderr
@@ -1,4 +1,4 @@
-error: parenthesized parameters may only be used with a trait
+error: parenthesized type parameters may only be used with a `Fn` trait
--> $DIR/issue-32995-2.rs:4:28
|
LL | { fn f<X: ::std::marker()::Send>() {} }
@@ -8,7 +8,7 @@
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #42238 <https://github.com/rust-lang/rust/issues/42238>
-error: parenthesized parameters may only be used with a trait
+error: parenthesized type parameters may only be used with a `Fn` trait
--> $DIR/issue-32995-2.rs:8:35
|
LL | { fn f() -> impl ::std::marker()::Send { } }
@@ -17,7 +17,7 @@
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #42238 <https://github.com/rust-lang/rust/issues/42238>
-error: parenthesized parameters may only be used with a trait
+error: parenthesized type parameters may only be used with a `Fn` trait
--> $DIR/issue-32995-2.rs:16:19
|
LL | impl ::std::marker()::Copy for X {}
diff --git a/src/test/ui/issues/issue-32995.rs b/src/test/ui/issues/issue-32995.rs
index 726cc85..c32fb63 100644
--- a/src/test/ui/issues/issue-32995.rs
+++ b/src/test/ui/issues/issue-32995.rs
@@ -2,32 +2,32 @@
fn main() {
let x: usize() = 1;
- //~^ ERROR parenthesized parameters may only be used with a trait
+ //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
//~| WARN previously accepted
let b: ::std::boxed()::Box<_> = Box::new(1);
- //~^ ERROR parenthesized parameters may only be used with a trait
+ //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
//~| WARN previously accepted
let p = ::std::str::()::from_utf8(b"foo").unwrap();
- //~^ ERROR parenthesized parameters may only be used with a trait
+ //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
//~| WARN previously accepted
let p = ::std::str::from_utf8::()(b"foo").unwrap();
- //~^ ERROR parenthesized parameters may only be used with a trait
+ //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
//~| WARN previously accepted
let o : Box<::std::marker()::Send> = Box::new(1);
- //~^ ERROR parenthesized parameters may only be used with a trait
+ //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
//~| WARN previously accepted
let o : Box<Send + ::std::marker()::Sync> = Box::new(1);
- //~^ ERROR parenthesized parameters may only be used with a trait
+ //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
//~| WARN previously accepted
}
fn foo<X:Default>() {
let d : X() = Default::default();
- //~^ ERROR parenthesized parameters may only be used with a trait
+ //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
//~| WARN previously accepted
}
diff --git a/src/test/ui/issues/issue-32995.stderr b/src/test/ui/issues/issue-32995.stderr
index 12551bb..97b4b7fa 100644
--- a/src/test/ui/issues/issue-32995.stderr
+++ b/src/test/ui/issues/issue-32995.stderr
@@ -1,4 +1,4 @@
-error: parenthesized parameters may only be used with a trait
+error: parenthesized type parameters may only be used with a `Fn` trait
--> $DIR/issue-32995.rs:4:17
|
LL | let x: usize() = 1;
@@ -8,7 +8,7 @@
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #42238 <https://github.com/rust-lang/rust/issues/42238>
-error: parenthesized parameters may only be used with a trait
+error: parenthesized type parameters may only be used with a `Fn` trait
--> $DIR/issue-32995.rs:8:24
|
LL | let b: ::std::boxed()::Box<_> = Box::new(1);
@@ -17,25 +17,25 @@
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #42238 <https://github.com/rust-lang/rust/issues/42238>
-error: parenthesized parameters may only be used with a trait
- --> $DIR/issue-32995.rs:12:23
+error: parenthesized type parameters may only be used with a `Fn` trait
+ --> $DIR/issue-32995.rs:12:25
|
LL | let p = ::std::str::()::from_utf8(b"foo").unwrap();
- | ^^^^
+ | ^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #42238 <https://github.com/rust-lang/rust/issues/42238>
-error: parenthesized parameters may only be used with a trait
- --> $DIR/issue-32995.rs:16:34
+error: parenthesized type parameters may only be used with a `Fn` trait
+ --> $DIR/issue-32995.rs:16:36
|
LL | let p = ::std::str::from_utf8::()(b"foo").unwrap();
- | ^^^^
+ | ^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #42238 <https://github.com/rust-lang/rust/issues/42238>
-error: parenthesized parameters may only be used with a trait
+error: parenthesized type parameters may only be used with a `Fn` trait
--> $DIR/issue-32995.rs:20:30
|
LL | let o : Box<::std::marker()::Send> = Box::new(1);
@@ -44,7 +44,7 @@
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #42238 <https://github.com/rust-lang/rust/issues/42238>
-error: parenthesized parameters may only be used with a trait
+error: parenthesized type parameters may only be used with a `Fn` trait
--> $DIR/issue-32995.rs:24:37
|
LL | let o : Box<Send + ::std::marker()::Sync> = Box::new(1);
@@ -53,7 +53,7 @@
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #42238 <https://github.com/rust-lang/rust/issues/42238>
-error: parenthesized parameters may only be used with a trait
+error: parenthesized type parameters may only be used with a `Fn` trait
--> $DIR/issue-32995.rs:30:14
|
LL | let d : X() = Default::default();
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/issues/issue-57741-1.rs b/src/test/ui/issues/issue-57741-1.rs
new file mode 100644
index 0000000..d0aae23
--- /dev/null
+++ b/src/test/ui/issues/issue-57741-1.rs
@@ -0,0 +1,18 @@
+#![allow(warnings)]
+
+// This tests that the `help: consider dereferencing the boxed value` suggestion isn't made
+// because the box doesn't deref to the type of the arm.
+
+enum S {
+ A { a: usize },
+ B { b: usize },
+}
+
+fn main() {
+ let x = Box::new(3u32);
+ let y = match x {
+ S::A { a } | S::B { b: a } => a,
+ //~^ ERROR mismatched types [E0308]
+ //~^^ ERROR mismatched types [E0308]
+ };
+}
diff --git a/src/test/ui/issues/issue-57741-1.stderr b/src/test/ui/issues/issue-57741-1.stderr
new file mode 100644
index 0000000..d36424b
--- /dev/null
+++ b/src/test/ui/issues/issue-57741-1.stderr
@@ -0,0 +1,25 @@
+error[E0308]: mismatched types
+ --> $DIR/issue-57741-1.rs:14:9
+ |
+LL | let y = match x {
+ | - this match expression has type `std::boxed::Box<u32>`
+LL | S::A { a } | S::B { b: a } => a,
+ | ^^^^^^^^^^ expected struct `std::boxed::Box`, found enum `S`
+ |
+ = note: expected type `std::boxed::Box<u32>`
+ found type `S`
+
+error[E0308]: mismatched types
+ --> $DIR/issue-57741-1.rs:14:22
+ |
+LL | let y = match x {
+ | - this match expression has type `std::boxed::Box<u32>`
+LL | S::A { a } | S::B { b: a } => a,
+ | ^^^^^^^^^^^^^ expected struct `std::boxed::Box`, found enum `S`
+ |
+ = note: expected type `std::boxed::Box<u32>`
+ found type `S`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-57741.fixed b/src/test/ui/issues/issue-57741.fixed
new file mode 100644
index 0000000..4cae080
--- /dev/null
+++ b/src/test/ui/issues/issue-57741.fixed
@@ -0,0 +1,31 @@
+// run-rustfix
+
+#![allow(warnings)]
+
+// This tests that the `help: consider dereferencing the boxed value` suggestion is made and works.
+
+enum S {
+ A { a: usize },
+ B { b: usize },
+}
+
+enum T {
+ A(usize),
+ B(usize),
+}
+
+fn main() {
+ let x = Box::new(T::A(3));
+ let y = match *x {
+ T::A(a) | T::B(a) => a,
+ //~^ ERROR mismatched types [E0308]
+ //~^^ ERROR mismatched types [E0308]
+ };
+
+ let x = Box::new(S::A { a: 3 });
+ let y = match *x {
+ S::A { a } | S::B { b: a } => a,
+ //~^ ERROR mismatched types [E0308]
+ //~^^ ERROR mismatched types [E0308]
+ };
+}
diff --git a/src/test/ui/issues/issue-57741.rs b/src/test/ui/issues/issue-57741.rs
new file mode 100644
index 0000000..e265829
--- /dev/null
+++ b/src/test/ui/issues/issue-57741.rs
@@ -0,0 +1,31 @@
+// run-rustfix
+
+#![allow(warnings)]
+
+// This tests that the `help: consider dereferencing the boxed value` suggestion is made and works.
+
+enum S {
+ A { a: usize },
+ B { b: usize },
+}
+
+enum T {
+ A(usize),
+ B(usize),
+}
+
+fn main() {
+ let x = Box::new(T::A(3));
+ let y = match x {
+ T::A(a) | T::B(a) => a,
+ //~^ ERROR mismatched types [E0308]
+ //~^^ ERROR mismatched types [E0308]
+ };
+
+ let x = Box::new(S::A { a: 3 });
+ let y = match x {
+ S::A { a } | S::B { b: a } => a,
+ //~^ ERROR mismatched types [E0308]
+ //~^^ ERROR mismatched types [E0308]
+ };
+}
diff --git a/src/test/ui/issues/issue-57741.stderr b/src/test/ui/issues/issue-57741.stderr
new file mode 100644
index 0000000..a26b1d20
--- /dev/null
+++ b/src/test/ui/issues/issue-57741.stderr
@@ -0,0 +1,59 @@
+error[E0308]: mismatched types
+ --> $DIR/issue-57741.rs:20:9
+ |
+LL | let y = match x {
+ | -
+ | |
+ | this match expression has type `std::boxed::Box<T>`
+ | help: consider dereferencing the boxed value: `*x`
+LL | T::A(a) | T::B(a) => a,
+ | ^^^^^^^ expected struct `std::boxed::Box`, found enum `T`
+ |
+ = note: expected type `std::boxed::Box<T>`
+ found type `T`
+
+error[E0308]: mismatched types
+ --> $DIR/issue-57741.rs:20:19
+ |
+LL | let y = match x {
+ | -
+ | |
+ | this match expression has type `std::boxed::Box<T>`
+ | help: consider dereferencing the boxed value: `*x`
+LL | T::A(a) | T::B(a) => a,
+ | ^^^^^^^ expected struct `std::boxed::Box`, found enum `T`
+ |
+ = note: expected type `std::boxed::Box<T>`
+ found type `T`
+
+error[E0308]: mismatched types
+ --> $DIR/issue-57741.rs:27:9
+ |
+LL | let y = match x {
+ | -
+ | |
+ | this match expression has type `std::boxed::Box<S>`
+ | help: consider dereferencing the boxed value: `*x`
+LL | S::A { a } | S::B { b: a } => a,
+ | ^^^^^^^^^^ expected struct `std::boxed::Box`, found enum `S`
+ |
+ = note: expected type `std::boxed::Box<S>`
+ found type `S`
+
+error[E0308]: mismatched types
+ --> $DIR/issue-57741.rs:27:22
+ |
+LL | let y = match x {
+ | -
+ | |
+ | this match expression has type `std::boxed::Box<S>`
+ | help: consider dereferencing the boxed value: `*x`
+LL | S::A { a } | S::B { b: a } => a,
+ | ^^^^^^^^^^^^^ expected struct `std::boxed::Box`, found enum `S`
+ |
+ = note: expected type `std::boxed::Box<S>`
+ found type `S`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
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-forgot-ret.stderr b/src/test/ui/liveness/liveness-forgot-ret.stderr
index bbcbbdb..a970b80 100644
--- a/src/test/ui/liveness/liveness-forgot-ret.stderr
+++ b/src/test/ui/liveness/liveness-forgot-ret.stderr
@@ -2,7 +2,7 @@
--> $DIR/liveness-forgot-ret.rs:3:19
|
LL | fn f(a: isize) -> isize { if god_exists(a) { return 5; }; }
- | - ^^^^^ expected isize, found () - expected because of this statement
+ | - ^^^^^ expected isize, found ()
| |
| this function's body doesn't return
|
diff --git a/src/test/ui/parser/doc-before-eof.stderr b/src/test/ui/parser/doc-before-eof.stderr
index b764e9f..5809d64 100644
--- a/src/test/ui/parser/doc-before-eof.stderr
+++ b/src/test/ui/parser/doc-before-eof.stderr
@@ -2,7 +2,7 @@
--> $DIR/doc-before-eof.rs:3:1
|
LL | /// hi //~ERROR expected item after doc comment
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this doc comment doesn't document anything
error: aborting due to previous error
diff --git a/src/test/ui/parser/doc-before-extern-rbrace.stderr b/src/test/ui/parser/doc-before-extern-rbrace.stderr
index 47fab7b..8cc9c91 100644
--- a/src/test/ui/parser/doc-before-extern-rbrace.stderr
+++ b/src/test/ui/parser/doc-before-extern-rbrace.stderr
@@ -2,7 +2,7 @@
--> $DIR/doc-before-extern-rbrace.rs:2:5
|
LL | /// hi
- | ^^^^^^
+ | ^^^^^^ this doc comment doesn't document anything
error: aborting due to previous error
diff --git a/src/test/ui/parser/doc-before-mod-rbrace.stderr b/src/test/ui/parser/doc-before-mod-rbrace.stderr
index 41c1d70..4eaf351 100644
--- a/src/test/ui/parser/doc-before-mod-rbrace.stderr
+++ b/src/test/ui/parser/doc-before-mod-rbrace.stderr
@@ -2,7 +2,7 @@
--> $DIR/doc-before-mod-rbrace.rs:4:5
|
LL | /// document
- | ^^^^^^^^^^^^
+ | ^^^^^^^^^^^^ this doc comment doesn't document anything
error: aborting due to previous error
diff --git a/src/test/ui/parser/lex-bad-char-literals-2.rs b/src/test/ui/parser/lex-bad-char-literals-2.rs
index 7f85999..1e180f8 100644
--- a/src/test/ui/parser/lex-bad-char-literals-2.rs
+++ b/src/test/ui/parser/lex-bad-char-literals-2.rs
@@ -1,4 +1,4 @@
// This test needs to the last one appearing in this file as it kills the parser
static c: char =
- 'nope' //~ ERROR: character literal may only contain one codepoint: 'nope'
+ 'nope' //~ ERROR: character literal may only contain one codepoint
;
diff --git a/src/test/ui/parser/lex-bad-char-literals-2.stderr b/src/test/ui/parser/lex-bad-char-literals-2.stderr
index a7075b7..7eadb8e 100644
--- a/src/test/ui/parser/lex-bad-char-literals-2.stderr
+++ b/src/test/ui/parser/lex-bad-char-literals-2.stderr
@@ -1,8 +1,13 @@
-error: character literal may only contain one codepoint: 'nope'
+error: character literal may only contain one codepoint
--> $DIR/lex-bad-char-literals-2.rs:3:5
|
-LL | 'nope' //~ ERROR: character literal may only contain one codepoint: 'nope'
+LL | 'nope' //~ ERROR: character literal may only contain one codepoint
| ^^^^^^
-error: aborting due to previous error
+error[E0601]: `main` function not found in crate `lex_bad_char_literals_2`
+ |
+ = note: consider adding a `main` function to `$DIR/lex-bad-char-literals-2.rs`
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/parser/lex-bad-char-literals-3.rs b/src/test/ui/parser/lex-bad-char-literals-3.rs
index f874970..5194ff4 100644
--- a/src/test/ui/parser/lex-bad-char-literals-3.rs
+++ b/src/test/ui/parser/lex-bad-char-literals-3.rs
@@ -1,7 +1,7 @@
-// This test needs to the last one appearing in this file as it kills the parser
-static c: char =
- '●●' //~ ERROR: character literal may only contain one codepoint
- //~| ERROR: mismatched types
-;
+static c: char = '●●';
+//~^ ERROR: character literal may only contain one codepoint
-fn main() {}
+fn main() {
+ let ch: &str = '●●';
+ //~^ ERROR: character literal may only contain one codepoint
+}
diff --git a/src/test/ui/parser/lex-bad-char-literals-3.stderr b/src/test/ui/parser/lex-bad-char-literals-3.stderr
index 89f18e3..6462a3c 100644
--- a/src/test/ui/parser/lex-bad-char-literals-3.stderr
+++ b/src/test/ui/parser/lex-bad-char-literals-3.stderr
@@ -1,22 +1,22 @@
error: character literal may only contain one codepoint
- --> $DIR/lex-bad-char-literals-3.rs:3:5
+ --> $DIR/lex-bad-char-literals-3.rs:1:18
|
-LL | '●●' //~ ERROR: character literal may only contain one codepoint
- | ^^^^
+LL | static c: char = '●●';
+ | ^^^^
help: if you meant to write a `str` literal, use double quotes
|
-LL | "●●" //~ ERROR: character literal may only contain one codepoint
- | ^^^^
+LL | static c: char = "●●";
+ | ^^^^
-error[E0308]: mismatched types
- --> $DIR/lex-bad-char-literals-3.rs:3:5
+error: character literal may only contain one codepoint
+ --> $DIR/lex-bad-char-literals-3.rs:5:20
|
-LL | '●●' //~ ERROR: character literal may only contain one codepoint
- | ^^^^ expected char, found reference
+LL | let ch: &str = '●●';
+ | ^^^^
+help: if you meant to write a `str` literal, use double quotes
|
- = note: expected type `char`
- found type `&'static str`
+LL | let ch: &str = "●●";
+ | ^^^^
error: aborting due to 2 previous errors
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/lex-bad-char-literals-4.rs b/src/test/ui/parser/lex-bad-char-literals-4.rs
index 966e2bb..e13f11f 100644
--- a/src/test/ui/parser/lex-bad-char-literals-4.rs
+++ b/src/test/ui/parser/lex-bad-char-literals-4.rs
@@ -1,5 +1,5 @@
//
// This test needs to the last one appearing in this file as it kills the parser
static c: char =
- '● //~ ERROR: character literal may only contain one codepoint: '●
+ '● //~ ERROR: character literal may only contain one codepoint
;
diff --git a/src/test/ui/parser/lex-bad-char-literals-4.stderr b/src/test/ui/parser/lex-bad-char-literals-4.stderr
index 550cb54..881e3d5 100644
--- a/src/test/ui/parser/lex-bad-char-literals-4.stderr
+++ b/src/test/ui/parser/lex-bad-char-literals-4.stderr
@@ -1,7 +1,7 @@
error: character literal may only contain one codepoint: '●
--> $DIR/lex-bad-char-literals-4.rs:4:5
|
-LL | '● //~ ERROR: character literal may only contain one codepoint: '●
+LL | '● //~ ERROR: character literal may only contain one codepoint
| ^^
error: aborting due to previous error
diff --git a/src/test/ui/parser/lex-bad-char-literals-5.rs b/src/test/ui/parser/lex-bad-char-literals-5.rs
index 247289e..0c4339e 100644
--- a/src/test/ui/parser/lex-bad-char-literals-5.rs
+++ b/src/test/ui/parser/lex-bad-char-literals-5.rs
@@ -1,8 +1,7 @@
-//
-// This test needs to the last one appearing in this file as it kills the parser
-static c: char =
- '\x10\x10' //~ ERROR: character literal may only contain one codepoint
- //~| ERROR: mismatched types
-;
+static c: char = '\x10\x10';
+//~^ ERROR: character literal may only contain one codepoint
-fn main() {}
+fn main() {
+ let ch: &str = '\x10\x10';
+ //~^ ERROR: character literal may only contain one codepoint
+}
diff --git a/src/test/ui/parser/lex-bad-char-literals-5.stderr b/src/test/ui/parser/lex-bad-char-literals-5.stderr
index 523d71f..ef02973 100644
--- a/src/test/ui/parser/lex-bad-char-literals-5.stderr
+++ b/src/test/ui/parser/lex-bad-char-literals-5.stderr
@@ -1,22 +1,22 @@
error: character literal may only contain one codepoint
- --> $DIR/lex-bad-char-literals-5.rs:4:5
+ --> $DIR/lex-bad-char-literals-5.rs:1:18
|
-LL | '/x10/x10' //~ ERROR: character literal may only contain one codepoint
- | ^^^^^^^^^^
+LL | static c: char = '/x10/x10';
+ | ^^^^^^^^^^
help: if you meant to write a `str` literal, use double quotes
|
-LL | "/x10/x10" //~ ERROR: character literal may only contain one codepoint
- | ^^^^^^^^^^
+LL | static c: char = "/x10/x10";
+ | ^^^^^^^^^^
-error[E0308]: mismatched types
- --> $DIR/lex-bad-char-literals-5.rs:4:5
+error: character literal may only contain one codepoint
+ --> $DIR/lex-bad-char-literals-5.rs:5:20
|
-LL | '/x10/x10' //~ ERROR: character literal may only contain one codepoint
- | ^^^^^^^^^^ expected char, found reference
+LL | let ch: &str = '/x10/x10';
+ | ^^^^^^^^^^
+help: if you meant to write a `str` literal, use double quotes
|
- = note: expected type `char`
- found type `&'static str`
+LL | let ch: &str = "/x10/x10";
+ | ^^^^^^^^^^
error: aborting due to 2 previous errors
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/parser/lex-bad-char-literals-6.rs b/src/test/ui/parser/lex-bad-char-literals-6.rs
new file mode 100644
index 0000000..4379b4f
--- /dev/null
+++ b/src/test/ui/parser/lex-bad-char-literals-6.rs
@@ -0,0 +1,17 @@
+fn main() {
+ let x: &str = 'ab';
+ //~^ ERROR: character literal may only contain one codepoint
+ let y: char = 'cd';
+ //~^ ERROR: character literal may only contain one codepoint
+ let z = 'ef';
+ //~^ ERROR: character literal may only contain one codepoint
+
+ if x == y {}
+ //~^ ERROR: can't compare `&str` with `char`
+ if y == z {} // no error here
+ if x == z {}
+ //~^ ERROR: can't compare `&str` with `char`
+
+ let a: usize = "";
+ //~^ ERROR: mismatched types
+}
diff --git a/src/test/ui/parser/lex-bad-char-literals-6.stderr b/src/test/ui/parser/lex-bad-char-literals-6.stderr
new file mode 100644
index 0000000..df99726
--- /dev/null
+++ b/src/test/ui/parser/lex-bad-char-literals-6.stderr
@@ -0,0 +1,47 @@
+error: character literal may only contain one codepoint
+ --> $DIR/lex-bad-char-literals-6.rs:2:19
+ |
+LL | let x: &str = 'ab';
+ | ^^^^
+
+error: character literal may only contain one codepoint
+ --> $DIR/lex-bad-char-literals-6.rs:4:19
+ |
+LL | let y: char = 'cd';
+ | ^^^^
+
+error: character literal may only contain one codepoint
+ --> $DIR/lex-bad-char-literals-6.rs:6:13
+ |
+LL | let z = 'ef';
+ | ^^^^
+
+error[E0277]: can't compare `&str` with `char`
+ --> $DIR/lex-bad-char-literals-6.rs:9:10
+ |
+LL | if x == y {}
+ | ^^ no implementation for `&str == char`
+ |
+ = help: the trait `std::cmp::PartialEq<char>` is not implemented for `&str`
+
+error[E0308]: mismatched types
+ --> $DIR/lex-bad-char-literals-6.rs:15:20
+ |
+LL | let a: usize = "";
+ | ^^ expected usize, found reference
+ |
+ = note: expected type `usize`
+ found type `&'static str`
+
+error[E0277]: can't compare `&str` with `char`
+ --> $DIR/lex-bad-char-literals-6.rs:12:10
+ |
+LL | if x == z {}
+ | ^^ no implementation for `&str == char`
+ |
+ = help: the trait `std::cmp::PartialEq<char>` is not implemented for `&str`
+
+error: aborting due to 6 previous errors
+
+Some errors occurred: E0277, E0308.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/parser/type-parameters-in-field-exprs.stderr b/src/test/ui/parser/type-parameters-in-field-exprs.stderr
index e68e1f3..2183c74 100644
--- a/src/test/ui/parser/type-parameters-in-field-exprs.stderr
+++ b/src/test/ui/parser/type-parameters-in-field-exprs.stderr
@@ -1,20 +1,20 @@
error: field expressions may not have generic arguments
- --> $DIR/type-parameters-in-field-exprs.rs:13:8
+ --> $DIR/type-parameters-in-field-exprs.rs:13:10
|
LL | f.x::<isize>;
- | ^^^^^^^^^
+ | ^^^^^^^
error: field expressions may not have generic arguments
- --> $DIR/type-parameters-in-field-exprs.rs:15:8
+ --> $DIR/type-parameters-in-field-exprs.rs:15:10
|
LL | f.x::<>;
- | ^^^^
+ | ^^
error: field expressions may not have generic arguments
- --> $DIR/type-parameters-in-field-exprs.rs:17:8
+ --> $DIR/type-parameters-in-field-exprs.rs:17:10
|
LL | f.x::();
- | ^^^^
+ | ^^
error: aborting due to 3 previous errors
diff --git a/src/test/ui/point-to-type-err-cause-on-impl-trait-return-2.rs b/src/test/ui/point-to-type-err-cause-on-impl-trait-return-2.rs
new file mode 100644
index 0000000..50f1fe8
--- /dev/null
+++ b/src/test/ui/point-to-type-err-cause-on-impl-trait-return-2.rs
@@ -0,0 +1,17 @@
+fn unrelated() -> Result<(), std::string::ParseError> { // #57664
+ let x = 0;
+
+ match x {
+ 1 => {
+ let property_value_as_string = "a".parse()?;
+ }
+ 2 => {
+ let value: &bool = unsafe { &42 };
+ //~^ ERROR mismatched types
+ }
+ };
+
+ Ok(())
+}
+
+fn main() {}
diff --git a/src/test/ui/point-to-type-err-cause-on-impl-trait-return-2.stderr b/src/test/ui/point-to-type-err-cause-on-impl-trait-return-2.stderr
new file mode 100644
index 0000000..edaa60e
--- /dev/null
+++ b/src/test/ui/point-to-type-err-cause-on-impl-trait-return-2.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+ --> $DIR/point-to-type-err-cause-on-impl-trait-return-2.rs:9:41
+ |
+LL | let value: &bool = unsafe { &42 };
+ | ^^^ expected bool, found integer
+ |
+ = note: expected type `&bool`
+ found type `&{integer}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/point-to-type-err-cause-on-impl-trait-return.rs b/src/test/ui/point-to-type-err-cause-on-impl-trait-return.rs
new file mode 100644
index 0000000..95b4036
--- /dev/null
+++ b/src/test/ui/point-to-type-err-cause-on-impl-trait-return.rs
@@ -0,0 +1,36 @@
+fn foo() -> impl std::fmt::Display {
+ if false {
+ return 0i32;
+ }
+ 1u32
+ //~^ ERROR mismatched types
+}
+
+fn bar() -> impl std::fmt::Display {
+ if false {
+ return 0i32;
+ } else {
+ return 1u32;
+ //~^ ERROR mismatched types
+ }
+}
+
+fn baz() -> impl std::fmt::Display {
+ if false {
+ //~^ ERROR mismatched types
+ return 0i32;
+ } else {
+ 1u32
+ }
+}
+
+fn qux() -> impl std::fmt::Display {
+ if false {
+ 0i32
+ } else {
+ 1u32
+ //~^ ERROR if and else have incompatible types
+ }
+}
+
+fn main() {}
diff --git a/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr b/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr
new file mode 100644
index 0000000..62da078
--- /dev/null
+++ b/src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr
@@ -0,0 +1,58 @@
+error[E0308]: mismatched types
+ --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:5:5
+ |
+LL | return 0i32;
+ | ---- expected because of this statement
+LL | }
+LL | 1u32
+ | ^^^^ expected i32, found u32
+ |
+ = note: expected type `i32`
+ found type `u32`
+
+error[E0308]: mismatched types
+ --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:13:16
+ |
+LL | return 0i32;
+ | ---- expected because of this statement
+LL | } else {
+LL | return 1u32;
+ | ^^^^ expected i32, found u32
+ |
+ = note: expected type `i32`
+ found type `u32`
+
+error[E0308]: mismatched types
+ --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:19:5
+ |
+LL | / if false {
+LL | | //~^ ERROR mismatched types
+LL | | return 0i32;
+ | | ---- expected because of this statement
+LL | | } else {
+LL | | 1u32
+LL | | }
+ | |_____^ expected i32, found u32
+ |
+ = note: expected type `i32`
+ found type `u32`
+
+error[E0308]: if and else have incompatible types
+ --> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:31:9
+ |
+LL | / if false {
+LL | | 0i32
+ | | ---- expected because of this
+LL | | } else {
+LL | | 1u32
+ | | ^^^^ expected i32, found u32
+LL | | //~^ ERROR if and else have incompatible types
+LL | | }
+ | |_____- if and else have incompatible types
+ |
+ = note: expected type `i32`
+ found type `u32`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
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/proc-macro/span-preservation.stderr b/src/test/ui/proc-macro/span-preservation.stderr
index 1f9103a..db52490 100644
--- a/src/test/ui/proc-macro/span-preservation.stderr
+++ b/src/test/ui/proc-macro/span-preservation.stderr
@@ -15,6 +15,9 @@
error[E0308]: mismatched types
--> $DIR/span-preservation.rs:19:29
|
+LL | fn b(x: Option<isize>) -> usize {
+ | ----- expected `usize` because of return type
+LL | match x {
LL | Some(x) => { return x }, //~ ERROR mismatched types
| ^ expected usize, found isize
diff --git a/src/test/ui/return/return-from-diverging.stderr b/src/test/ui/return/return-from-diverging.stderr
index c84dd19..2862ae6 100644
--- a/src/test/ui/return/return-from-diverging.stderr
+++ b/src/test/ui/return/return-from-diverging.stderr
@@ -1,6 +1,8 @@
error[E0308]: mismatched types
--> $DIR/return-from-diverging.rs:4:12
|
+LL | fn fail() -> ! {
+ | - expected `!` because of return type
LL | return "wow"; //~ ERROR mismatched types
| ^^^^^ expected !, found reference
|
diff --git a/src/test/ui/span/macro-ty-params.stderr b/src/test/ui/span/macro-ty-params.stderr
index 23fdde0..965ca70 100644
--- a/src/test/ui/span/macro-ty-params.stderr
+++ b/src/test/ui/span/macro-ty-params.stderr
@@ -1,14 +1,14 @@
error: generic arguments in macro path
- --> $DIR/macro-ty-params.rs:10:8
+ --> $DIR/macro-ty-params.rs:10:10
|
LL | foo::<T>!(); //~ ERROR generic arguments in macro path
- | ^^^^^
+ | ^^^
error: generic arguments in macro path
- --> $DIR/macro-ty-params.rs:11:8
+ --> $DIR/macro-ty-params.rs:11:10
|
LL | foo::<>!(); //~ ERROR generic arguments in macro path
- | ^^^^
+ | ^^
error: unexpected generic arguments in path
--> $DIR/macro-ty-params.rs:12:8
diff --git a/src/test/ui/str/str-as-char.fixed b/src/test/ui/str/str-as-char.fixed
index 9d4297b..accead5 100644
--- a/src/test/ui/str/str-as-char.fixed
+++ b/src/test/ui/str/str-as-char.fixed
@@ -1,6 +1,6 @@
// run-rustfix
fn main() {
- println!("●●");
- //~^ ERROR character literal may only contain one codepoint
+ println!("{}", "●●"); //~ ERROR character literal may only contain one codepoint
+ //~^ ERROR format argument must be a string literal
}
diff --git a/src/test/ui/str/str-as-char.rs b/src/test/ui/str/str-as-char.rs
index 710fa74..fb179ec 100644
--- a/src/test/ui/str/str-as-char.rs
+++ b/src/test/ui/str/str-as-char.rs
@@ -1,6 +1,6 @@
// run-rustfix
fn main() {
- println!('●●');
- //~^ ERROR character literal may only contain one codepoint
+ println!('●●'); //~ ERROR character literal may only contain one codepoint
+ //~^ ERROR format argument must be a string literal
}
diff --git a/src/test/ui/str/str-as-char.stderr b/src/test/ui/str/str-as-char.stderr
index 540a1b5..4ca430a 100644
--- a/src/test/ui/str/str-as-char.stderr
+++ b/src/test/ui/str/str-as-char.stderr
@@ -1,12 +1,22 @@
error: character literal may only contain one codepoint
--> $DIR/str-as-char.rs:4:14
|
-LL | println!('●●');
+LL | println!('●●'); //~ ERROR character literal may only contain one codepoint
| ^^^^
help: if you meant to write a `str` literal, use double quotes
|
-LL | println!("●●");
+LL | println!("●●"); //~ ERROR character literal may only contain one codepoint
| ^^^^
-error: aborting due to previous error
+error: format argument must be a string literal
+ --> $DIR/str-as-char.rs:4:14
+ |
+LL | println!('●●'); //~ ERROR character literal may only contain one codepoint
+ | ^^^^
+help: you might be missing a string literal to format with
+ |
+LL | println!("{}", '●●'); //~ ERROR character literal may only contain one codepoint
+ | ^^^^^
+
+error: aborting due to 2 previous errors
diff --git a/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.rs b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.rs
new file mode 100644
index 0000000..2ce1222
--- /dev/null
+++ b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.rs
@@ -0,0 +1,9 @@
+struct RGB { r: f64, g: f64, b: f64 }
+
+fn main() {
+ let (r, g, c): (f32, f32, f32) = (0., 0., 0.);
+ let _ = RGB { r, g, c };
+ //~^ ERROR mismatched types
+ //~| ERROR mismatched types
+ //~| ERROR struct `RGB` has no field named `c`
+}
diff --git a/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr
new file mode 100644
index 0000000..d0f9e1f
--- /dev/null
+++ b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr
@@ -0,0 +1,30 @@
+error[E0308]: mismatched types
+ --> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:19
+ |
+LL | let _ = RGB { r, g, c };
+ | ^ expected f64, found f32
+help: you can cast an `f32` to `f64` in a lossless way
+ |
+LL | let _ = RGB { r: r.into(), g, c };
+ | ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+ --> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:22
+ |
+LL | let _ = RGB { r, g, c };
+ | ^ expected f64, found f32
+help: you can cast an `f32` to `f64` in a lossless way
+ |
+LL | let _ = RGB { r, g: g.into(), c };
+ | ^^^^^^^^^^^
+
+error[E0560]: struct `RGB` has no field named `c`
+ --> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:25
+ |
+LL | let _ = RGB { r, g, c };
+ | ^ help: a field with a similar name exists: `b`
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0308, E0560.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.fixed b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.fixed
new file mode 100644
index 0000000..91758c0
--- /dev/null
+++ b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.fixed
@@ -0,0 +1,12 @@
+// run-rustfix
+#![allow(dead_code)]
+
+struct RGB { r: f64, g: f64, b: f64 }
+
+fn main() {
+ let (r, g, b): (f32, f32, f32) = (0., 0., 0.);
+ let _ = RGB { r: r.into(), g: g.into(), b: b.into() };
+ //~^ ERROR mismatched types
+ //~| ERROR mismatched types
+ //~| ERROR mismatched types
+}
diff --git a/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.rs b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.rs
new file mode 100644
index 0000000..9d3a17a
--- /dev/null
+++ b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.rs
@@ -0,0 +1,12 @@
+// run-rustfix
+#![allow(dead_code)]
+
+struct RGB { r: f64, g: f64, b: f64 }
+
+fn main() {
+ let (r, g, b): (f32, f32, f32) = (0., 0., 0.);
+ let _ = RGB { r, g, b };
+ //~^ ERROR mismatched types
+ //~| ERROR mismatched types
+ //~| ERROR mismatched types
+}
diff --git a/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.stderr b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.stderr
new file mode 100644
index 0000000..6bc16ba
--- /dev/null
+++ b/src/test/ui/suggestions/type-mismatch-struct-field-shorthand.stderr
@@ -0,0 +1,33 @@
+error[E0308]: mismatched types
+ --> $DIR/type-mismatch-struct-field-shorthand.rs:8:19
+ |
+LL | let _ = RGB { r, g, b };
+ | ^ expected f64, found f32
+help: you can cast an `f32` to `f64` in a lossless way
+ |
+LL | let _ = RGB { r: r.into(), g, b };
+ | ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+ --> $DIR/type-mismatch-struct-field-shorthand.rs:8:22
+ |
+LL | let _ = RGB { r, g, b };
+ | ^ expected f64, found f32
+help: you can cast an `f32` to `f64` in a lossless way
+ |
+LL | let _ = RGB { r, g: g.into(), b };
+ | ^^^^^^^^^^^
+
+error[E0308]: mismatched types
+ --> $DIR/type-mismatch-struct-field-shorthand.rs:8:25
+ |
+LL | let _ = RGB { r, g, b };
+ | ^ expected f64, found f32
+help: you can cast an `f32` to `f64` in a lossless way
+ |
+LL | let _ = RGB { r, g, b: b.into() };
+ | ^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/tail-typeck.stderr b/src/test/ui/tail-typeck.stderr
index eadf3d6..1170f5c 100644
--- a/src/test/ui/tail-typeck.stderr
+++ b/src/test/ui/tail-typeck.stderr
@@ -2,7 +2,9 @@
--> $DIR/tail-typeck.rs:3:26
|
LL | fn f() -> isize { return g(); }
- | ^^^ expected isize, found usize
+ | ----- ^^^ expected isize, found usize
+ | |
+ | expected `isize` because of return type
error: aborting due to previous error
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-bad-type.stderr b/src/test/ui/try-block/try-block-bad-type.stderr
index 202885e..df8e646 100644
--- a/src/test/ui/try-block/try-block-bad-type.stderr
+++ b/src/test/ui/try-block/try-block-bad-type.stderr
@@ -6,10 +6,10 @@
|
= help: the following implementations were found:
<i32 as std::convert::From<bool>>
+ <i32 as std::convert::From<core::num::NonZeroI32>>
<i32 as std::convert::From<i16>>
<i32 as std::convert::From<i8>>
- <i32 as std::convert::From<u16>>
- <i32 as std::convert::From<u8>>
+ and 2 others
= note: required by `std::convert::From::from`
error[E0271]: type mismatch resolving `<std::result::Result<i32, i32> as std::ops::Try>::Ok == &str`
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/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.rs b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.rs
index 5387dcb..c96a6fa 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.rs
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.rs
@@ -6,7 +6,8 @@
fn bar() {
let x: Box<Bar()> = panic!();
- //~^ ERROR parenthesized parameters may only be used with a trait
+ //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
+ //~| ERROR wrong number of type arguments: expected 1, found 0
}
fn main() { }
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr
index 3f1b37c..fa52e66 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-1.stderr
@@ -1,9 +1,16 @@
-error[E0214]: parenthesized parameters may only be used with a trait
+error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
--> $DIR/unboxed-closure-sugar-used-on-struct-1.rs:8:19
|
LL | let x: Box<Bar()> = panic!();
- | ^^ only traits may use parentheses
+ | ^^ only `Fn` traits may use parentheses
-error: aborting due to previous error
+error[E0107]: wrong number of type arguments: expected 1, found 0
+ --> $DIR/unboxed-closure-sugar-used-on-struct-1.rs:8:16
+ |
+LL | let x: Box<Bar()> = panic!();
+ | ^^^^^ expected 1 type argument
-For more information about this error, try `rustc --explain E0214`.
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0107, E0214.
+For more information about an error, try `rustc --explain E0107`.
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.rs b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.rs
index 3cada32..79ced1e 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.rs
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.rs
@@ -12,7 +12,7 @@
let b = Bar::<isize, usize>::new(); // OK
let b = Bar::(isize, usize)::new(); // OK too (for the parser)
- //~^ ERROR parenthesized parameters may only be used with a trait
+ //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
}
fn main() {}
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.stderr
index 395f659..7d05ca5 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct-3.stderr
@@ -1,8 +1,11 @@
-error[E0214]: parenthesized parameters may only be used with a trait
- --> $DIR/unboxed-closure-sugar-used-on-struct-3.rs:14:16
+error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
+ --> $DIR/unboxed-closure-sugar-used-on-struct-3.rs:14:18
|
LL | let b = Bar::(isize, usize)::new(); // OK too (for the parser)
- | ^^^^^^^^^^^^^^^^ only traits may use parentheses
+ | ^^^^^^^^^^^^^^
+ | |
+ | only `Fn` traits may use parentheses
+ | help: use angle brackets instead: `<isize, usize>`
error: aborting due to previous error
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.rs b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.rs
index e795650..1af7f55 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.rs
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.rs
@@ -5,8 +5,8 @@
}
fn foo(b: Box<Bar()>) {
- //~^ ERROR parenthesized parameters may only be used with a trait
- //~| ERROR the type placeholder `_` is not allowed within types on item signatures
+ //~^ ERROR parenthesized type parameters may only be used with a `Fn` trait
+ //~| ERROR wrong number of type arguments: expected 1, found 0
}
fn main() { }
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr
index d026709..b342379 100644
--- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-used-on-struct.stderr
@@ -1,16 +1,16 @@
-error[E0214]: parenthesized parameters may only be used with a trait
+error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
--> $DIR/unboxed-closure-sugar-used-on-struct.rs:7:18
|
LL | fn foo(b: Box<Bar()>) {
- | ^^ only traits may use parentheses
+ | ^^ only `Fn` traits may use parentheses
-error[E0121]: the type placeholder `_` is not allowed within types on item signatures
+error[E0107]: wrong number of type arguments: expected 1, found 0
--> $DIR/unboxed-closure-sugar-used-on-struct.rs:7:15
|
LL | fn foo(b: Box<Bar()>) {
- | ^^^^^ not allowed in type signatures
+ | ^^^^^ expected 1 type argument
error: aborting due to 2 previous errors
-Some errors occurred: E0121, E0214.
-For more information about an error, try `rustc --explain E0121`.
+Some errors occurred: E0107, E0214.
+For more information about an error, try `rustc --explain E0107`.
diff --git a/src/test/ui/wrong-ret-type.stderr b/src/test/ui/wrong-ret-type.stderr
index 221806f..cf59f42 100644
--- a/src/test/ui/wrong-ret-type.stderr
+++ b/src/test/ui/wrong-ret-type.stderr
@@ -2,7 +2,9 @@
--> $DIR/wrong-ret-type.rs:2:49
|
LL | fn mk_int() -> usize { let i: isize = 3; return i; }
- | ^ expected usize, found isize
+ | ----- ^ expected usize, found isize
+ | |
+ | expected `usize` because of return type
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",
diff --git a/src/tools/cargo b/src/tools/cargo
index 2b4a5f1..907c0fe 160000
--- a/src/tools/cargo
+++ b/src/tools/cargo
@@ -1 +1 @@
-Subproject commit 2b4a5f1f0bb6e13759e88ea9512527b0beba154f
+Subproject commit 907c0febe7045fa02dff2a35c5e36d3bd59ea50d
diff --git a/src/tools/clippy b/src/tools/clippy
index 1b89724..1838bfe 160000
--- a/src/tools/clippy
+++ b/src/tools/clippy
@@ -1 +1 @@
-Subproject commit 1b89724b4889aef631b40d52c0943bdc28e04d1d
+Subproject commit 1838bfe5a9ff951ffd716e4632156113d95d14a4
diff --git a/src/tools/miri b/src/tools/miri
index 97f4cff..1cd85d2 160000
--- a/src/tools/miri
+++ b/src/tools/miri
@@ -1 +1 @@
-Subproject commit 97f4cff8e904c268569d37922a27835209deff5d
+Subproject commit 1cd85d2a2767b37f9869b719a74e3da99087c31a