Auto merge of #57752 - Centril:rollup, r=Centril
Rollup of 10 pull requests
Successful merges:
- #57268 (Add a target option "merge-functions", and a corresponding -Z flag (works around #57356))
- #57476 (Move glob map use to query and get rid of CrateAnalysis)
- #57501 (High priority resolutions for associated variants)
- #57573 (Querify `entry_fn`)
- #57610 (Fix nested `?` matchers)
- #57634 (Remove an unused function argument)
- #57653 (Make the contribution doc reference the guide more)
- #57666 (Generalize `huge-enum.rs` test and expected stderr for more cross platform cases)
- #57698 (Fix typo bug in DepGraph::try_mark_green().)
- #57746 (Update README.md)
Failed merges:
r? @ghost
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/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index d1067b7..4cfebaa 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -586,6 +586,7 @@
[] CheckImplItemWellFormed(DefId),
[] ReachableNonGenerics(CrateNum),
[] NativeLibraries(CrateNum),
+ [] EntryFn(CrateNum),
[] PluginRegistrarFn(CrateNum),
[] ProcMacroDeclsStatic(CrateNum),
[input] CrateDisambiguator(CrateNum),
@@ -633,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/intravisit.rs b/src/librustc/hir/intravisit.rs
index f633703..041291e 100644
--- a/src/librustc/hir/intravisit.rs
+++ b/src/librustc/hir/intravisit.rs
@@ -35,11 +35,9 @@
use syntax_pos::Span;
use hir::*;
use hir::def::Def;
-use hir::map::{self, Map};
+use hir::map::Map;
use super::itemlikevisit::DeepVisitor;
-use std::cmp;
-
#[derive(Copy, Clone)]
pub enum FnKind<'a> {
/// `#[xxx] pub async/const/extern "Abi" fn foo()`
@@ -1133,57 +1131,3 @@
// the right thing to do, should content be added in the future,
// would be to walk it.
}
-
-#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)]
-pub struct IdRange {
- pub min: NodeId,
- pub max: NodeId,
-}
-
-impl IdRange {
- pub fn max() -> IdRange {
- IdRange {
- min: NodeId::MAX,
- max: NodeId::from_u32(0),
- }
- }
-
- pub fn empty(&self) -> bool {
- self.min >= self.max
- }
-
- pub fn contains(&self, id: NodeId) -> bool {
- id >= self.min && id < self.max
- }
-
- pub fn add(&mut self, id: NodeId) {
- self.min = cmp::min(self.min, id);
- self.max = cmp::max(self.max, NodeId::from_u32(id.as_u32() + 1));
- }
-}
-
-
-pub struct IdRangeComputingVisitor<'a, 'hir: 'a> {
- result: IdRange,
- map: &'a map::Map<'hir>,
-}
-
-impl<'a, 'hir> IdRangeComputingVisitor<'a, 'hir> {
- pub fn new(map: &'a map::Map<'hir>) -> IdRangeComputingVisitor<'a, 'hir> {
- IdRangeComputingVisitor { result: IdRange::max(), map: map }
- }
-
- pub fn result(&self) -> IdRange {
- self.result
- }
-}
-
-impl<'a, 'hir> Visitor<'hir> for IdRangeComputingVisitor<'a, 'hir> {
- fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'hir> {
- NestedVisitorMap::OnlyBodies(&self.map)
- }
-
- fn visit_id(&mut self, id: NodeId) {
- self.result.add(id);
- }
-}
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index c8d137a..a0bd4f0 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -368,6 +368,12 @@
report_in_external_macro: true
}
+declare_lint! {
+ pub AMBIGUOUS_ASSOCIATED_ITEMS,
+ Warn,
+ "ambiguous associated items"
+}
+
/// Does nothing as a lint pass, but registers some `Lint`s
/// that are used by other parts of the compiler.
#[derive(Copy, Clone)]
@@ -433,6 +439,7 @@
parser::QUESTION_MARK_MACRO_SEP,
parser::ILL_FORMED_ATTRIBUTE_INPUT,
DEPRECATED_IN_FUTURE,
+ AMBIGUOUS_ASSOCIATED_ITEMS,
)
}
}
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index 0c769c9..abbf0ae 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -409,7 +409,7 @@
}
}).chain(
// Seed entry point
- tcx.sess.entry_fn.borrow().map(|(id, _, _)| id)
+ tcx.entry_fn(LOCAL_CRATE).map(|(def_id, _)| tcx.hir().as_local_node_id(def_id).unwrap())
).collect::<Vec<_>>();
// Seed implemented trait items
diff --git a/src/librustc/middle/entry.rs b/src/librustc/middle/entry.rs
index 6b593a1..218ca3b 100644
--- a/src/librustc/middle/entry.rs
+++ b/src/librustc/middle/entry.rs
@@ -1,5 +1,5 @@
use hir::map as hir_map;
-use hir::def_id::{CRATE_DEF_INDEX};
+use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE};
use session::{config, Session};
use session::config::EntryFnType;
use syntax::ast::NodeId;
@@ -8,6 +8,8 @@
use syntax_pos::Span;
use hir::{Item, ItemKind, ImplItem, TraitItem};
use hir::itemlikevisit::ItemLikeVisitor;
+use ty::TyCtxt;
+use ty::query::Providers;
struct EntryContext<'a, 'tcx: 'a> {
session: &'a Session,
@@ -45,36 +47,34 @@
}
}
-pub fn find_entry_point(session: &Session,
- hir_map: &hir_map::Map<'_>,
- crate_name: &str) {
- let any_exe = session.crate_types.borrow().iter().any(|ty| {
+fn entry_fn(tcx: TyCtxt<'_, '_, '_>, cnum: CrateNum) -> Option<(DefId, EntryFnType)> {
+ assert_eq!(cnum, LOCAL_CRATE);
+
+ let any_exe = tcx.sess.crate_types.borrow().iter().any(|ty| {
*ty == config::CrateType::Executable
});
if !any_exe {
// No need to find a main function
- session.entry_fn.set(None);
- return
+ return None;
}
// If the user wants no main function at all, then stop here.
- if attr::contains_name(&hir_map.krate().attrs, "no_main") {
- session.entry_fn.set(None);
- return
+ if attr::contains_name(&tcx.hir().krate().attrs, "no_main") {
+ return None;
}
let mut ctxt = EntryContext {
- session,
- map: hir_map,
+ session: tcx.sess,
+ map: tcx.hir(),
main_fn: None,
attr_main_fn: None,
start_fn: None,
non_main_fns: Vec::new(),
};
- hir_map.krate().visit_all_item_likes(&mut ctxt);
+ tcx.hir().krate().visit_all_item_likes(&mut ctxt);
- configure_main(&mut ctxt, crate_name);
+ configure_main(tcx, &ctxt)
}
// Beware, this is duplicated in `libsyntax/entry.rs`, so make sure to keep
@@ -135,43 +135,58 @@
.span_label(item.span, "multiple `start` functions")
.emit();
}
- },
- EntryPointType::None => ()
+ }
+ EntryPointType::None => (),
}
}
-fn configure_main(this: &mut EntryContext<'_, '_>, crate_name: &str) {
- if let Some((node_id, span)) = this.start_fn {
- this.session.entry_fn.set(Some((node_id, span, EntryFnType::Start)));
- } else if let Some((node_id, span)) = this.attr_main_fn {
- this.session.entry_fn.set(Some((node_id, span, EntryFnType::Main)));
- } else if let Some((node_id, span)) = this.main_fn {
- this.session.entry_fn.set(Some((node_id, span, EntryFnType::Main)));
+fn configure_main(
+ tcx: TyCtxt<'_, '_, '_>,
+ visitor: &EntryContext<'_, '_>,
+) -> Option<(DefId, EntryFnType)> {
+ if let Some((node_id, _)) = visitor.start_fn {
+ Some((tcx.hir().local_def_id(node_id), EntryFnType::Start))
+ } else if let Some((node_id, _)) = visitor.attr_main_fn {
+ Some((tcx.hir().local_def_id(node_id), EntryFnType::Main))
+ } else if let Some((node_id, _)) = visitor.main_fn {
+ Some((tcx.hir().local_def_id(node_id), EntryFnType::Main))
} else {
// No main function
- this.session.entry_fn.set(None);
- let mut err = struct_err!(this.session, E0601,
- "`main` function not found in crate `{}`", crate_name);
- if !this.non_main_fns.is_empty() {
+ let mut err = struct_err!(tcx.sess, E0601,
+ "`main` function not found in crate `{}`", tcx.crate_name(LOCAL_CRATE));
+ if !visitor.non_main_fns.is_empty() {
// There were some functions named 'main' though. Try to give the user a hint.
err.note("the main function must be defined at the crate level \
but you have one or more functions named 'main' that are not \
defined at the crate level. Either move the definition or \
attach the `#[main]` attribute to override this behavior.");
- for &(_, span) in &this.non_main_fns {
+ for &(_, span) in &visitor.non_main_fns {
err.span_note(span, "here is a function named 'main'");
}
err.emit();
- this.session.abort_if_errors();
+ tcx.sess.abort_if_errors();
} else {
- if let Some(ref filename) = this.session.local_crate_source_file {
+ if let Some(ref filename) = tcx.sess.local_crate_source_file {
err.note(&format!("consider adding a `main` function to `{}`", filename.display()));
}
- if this.session.teach(&err.get_code().unwrap()) {
+ if tcx.sess.teach(&err.get_code().unwrap()) {
err.note("If you don't know the basics of Rust, you can go look to the Rust Book \
to get started: https://doc.rust-lang.org/book/");
}
err.emit();
}
+
+ None
}
}
+
+pub fn find_entry_point(tcx: TyCtxt<'_, '_, '_>) -> Option<(DefId, EntryFnType)> {
+ tcx.entry_fn(LOCAL_CRATE)
+}
+
+pub fn provide(providers: &mut Providers<'_>) {
+ *providers = Providers {
+ entry_fn,
+ ..*providers
+ };
+}
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 42adc6a..0f14049 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
+ }
}
) }
@@ -1376,6 +1387,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 +2408,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 +2451,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 +2544,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 +3199,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/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/mod.rs b/src/librustc/ty/mod.rs
index 26b4735..f1b36e8 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>,
diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs
index c20846a..ae41ca0 100644
--- a/src/librustc/ty/query/config.rs
+++ b/src/librustc/ty/query/config.rs
@@ -656,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 88c2054..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,
@@ -482,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,
@@ -547,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 5b7cb55..1cc9bbd 100644
--- a/src/librustc/ty/query/plumbing.rs
+++ b/src/librustc/ty/query/plumbing.rs
@@ -1332,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!()); }
@@ -1383,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_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 15cb5b0..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),
}
@@ -1165,6 +1151,7 @@
rustc_passes::provide(providers);
rustc_traits::provide(providers);
middle::region::provide(providers);
+ middle::entry::provide(providers);
cstore::provide(providers);
lint::provide(providers);
}
@@ -1182,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,
@@ -1192,7 +1178,6 @@
where
F: for<'a> FnOnce(
TyCtxt<'a, 'tcx, 'tcx>,
- ty::CrateAnalysis,
mpsc::Receiver<Box<dyn Any + Send>>,
CompileResult,
) -> R,
@@ -1201,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);
@@ -1234,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)
});
@@ -1256,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);
}
}
@@ -1309,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));
@@ -1320,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..d110830 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -190,7 +190,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 +222,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 +957,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 +969,6 @@
print_with_analysis(sess,
cstore,
hir_map,
- analysis,
resolutions,
crate_name,
output_filenames,
@@ -1010,7 +1006,6 @@
s.call_with_pp_support_hir(sess,
cstore,
hir_map,
- analysis,
resolutions,
output_filenames,
crate_name,
@@ -1033,7 +1028,6 @@
s.call_with_pp_support_hir(sess,
cstore,
hir_map,
- analysis,
resolutions,
output_filenames,
crate_name,
@@ -1048,7 +1042,6 @@
s.call_with_pp_support_hir(sess,
cstore,
hir_map,
- analysis,
resolutions,
output_filenames,
crate_name,
@@ -1081,7 +1074,6 @@
s.call_with_pp_support_hir(sess,
cstore,
hir_map,
- analysis,
resolutions,
output_filenames,
crate_name,
@@ -1103,13 +1095,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 +1125,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_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_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_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_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 8e5eaa1..534279e 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -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};
@@ -1278,29 +1279,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 +1335,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 +1400,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 +1803,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/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index 02687df..e71dc01 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -408,45 +408,36 @@
let tcx = self.tcx;
- let mode = probe::Mode::Path;
- match self.probe_for_name(span, mode, method_name, IsSuggestion(false),
- self_ty, expr_id, ProbeScope::TraitsInScope) {
- Ok(pick) => {
- debug!("resolve_ufcs: pick={:?}", pick);
- if let Some(import_id) = pick.import_id {
- let import_def_id = tcx.hir().local_def_id(import_id);
- debug!("resolve_ufcs: used_trait_import: {:?}", import_def_id);
- Lrc::get_mut(&mut self.tables.borrow_mut().used_trait_imports)
- .unwrap().insert(import_def_id);
+ // Check if we have an enum variant.
+ if let ty::Adt(adt_def, _) = self_ty.sty {
+ if adt_def.is_enum() {
+ let variant_def = adt_def.variants.iter().find(|vd| {
+ tcx.hygienic_eq(method_name, vd.ident, adt_def.did)
+ });
+ if let Some(variant_def) = variant_def {
+ check_type_alias_enum_variants_enabled(tcx, span);
+
+ let def = Def::VariantCtor(variant_def.did, variant_def.ctor_kind);
+ tcx.check_stability(def.def_id(), Some(expr_id), span);
+ return Ok(def);
}
-
- let def = pick.item.def();
- debug!("resolve_ufcs: def={:?}", def);
- tcx.check_stability(def.def_id(), Some(expr_id), span);
-
- Ok(def)
- }
- Err(err) => {
- // Check if we have an enum variant.
- match self_ty.sty {
- ty::Adt(adt_def, _) if adt_def.is_enum() => {
- let variant_def = adt_def.variants.iter().find(|vd| {
- tcx.hygienic_eq(method_name, vd.ident, adt_def.did)
- });
- if let Some(variant_def) = variant_def {
- check_type_alias_enum_variants_enabled(tcx, span);
-
- let def = Def::VariantCtor(variant_def.did, variant_def.ctor_kind);
- tcx.check_stability(def.def_id(), Some(expr_id), span);
- return Ok(def);
- }
- },
- _ => (),
- }
-
- Err(err)
}
}
+
+ let pick = self.probe_for_name(span, probe::Mode::Path, method_name, IsSuggestion(false),
+ self_ty, expr_id, ProbeScope::TraitsInScope)?;
+ debug!("resolve_ufcs: pick={:?}", pick);
+ if let Some(import_id) = pick.import_id {
+ let import_def_id = tcx.hir().local_def_id(import_id);
+ debug!("resolve_ufcs: used_trait_import: {:?}", import_def_id);
+ Lrc::get_mut(&mut self.tables.borrow_mut().used_trait_imports)
+ .unwrap().insert(import_def_id);
+ }
+
+ let def = pick.item.def();
+ debug!("resolve_ufcs: def={:?}", def);
+ tcx.check_stability(def.def_id(), Some(expr_id), span);
+ Ok(def)
}
/// Find item with name `item_name` defined in impl/trait `def_id`
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 1b07385..452fd24 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -132,7 +132,8 @@
use std::slice;
use require_c_abi_if_variadic;
-use session::{CompileIncomplete, config, Session};
+use session::{CompileIncomplete, Session};
+use session::config::EntryFnType;
use TypeAndSubsts;
use lint;
use util::captures::Captures;
@@ -1163,19 +1164,18 @@
// Check that the main return type implements the termination trait.
if let Some(term_id) = fcx.tcx.lang_items().termination() {
- if let Some((id, _, entry_type)) = *fcx.tcx.sess.entry_fn.borrow() {
- if id == fn_id {
- if let config::EntryFnType::Main = entry_type {
- let substs = fcx.tcx.mk_substs_trait(declared_ret_ty, &[]);
- let trait_ref = ty::TraitRef::new(term_id, substs);
- let return_ty_span = decl.output.span();
- let cause = traits::ObligationCause::new(
- return_ty_span, fn_id, ObligationCauseCode::MainFunctionType);
+ if let Some((def_id, EntryFnType::Main)) = fcx.tcx.entry_fn(LOCAL_CRATE) {
+ let main_id = fcx.tcx.hir().as_local_node_id(def_id).unwrap();
+ if main_id == fn_id {
+ let substs = fcx.tcx.mk_substs_trait(declared_ret_ty, &[]);
+ let trait_ref = ty::TraitRef::new(term_id, substs);
+ let return_ty_span = decl.output.span();
+ let cause = traits::ObligationCause::new(
+ return_ty_span, fn_id, ObligationCauseCode::MainFunctionType);
- inherited.register_predicate(
- traits::Obligation::new(
- cause, param_env, trait_ref.to_predicate()));
- }
+ inherited.register_predicate(
+ traits::Obligation::new(
+ cause, param_env, trait_ref.to_predicate()));
}
}
}
@@ -4724,8 +4724,8 @@
} else {
Def::Err
};
- let (ty, def) = AstConv::associated_path_def_to_ty(self, node_id, path_span,
- ty, def, segment);
+ let (ty, def) = AstConv::associated_path_to_ty(self, node_id, path_span,
+ ty, def, segment, true);
// Write back the new resolution.
let hir_id = self.tcx.hir().node_to_hir_id(node_id);
diff --git a/src/librustc_typeck/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/render.rs b/src/librustdoc/html/render.rs
index 06846d4..ad1659b 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -309,7 +309,7 @@
// Note that external items for which `doc(hidden)` applies to are shown as
// non-reachable while local items aren't. This is because we're reusing
- // the access levels from crateanalysis.
+ // the access levels from the privacy check pass.
pub access_levels: AccessLevels<DefId>,
/// The version of the crate being documented, if given from the `--crate-version` flag.
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/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/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-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-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/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
+