diff --git a/README.md b/README.md index b79c9703f44ef..7360651095bb5 100644 --- a/README.md +++ b/README.md @@ -127,7 +127,7 @@ ones from MSYS if you have it installed). You'll also need Visual Studio 2013 or newer with the C++ tools. Then all you need to do is to kick off rustbuild. ``` -python .\src\bootstrap\bootstrap.py +python x.py build ``` Currently rustbuild only works with some known versions of Visual Studio. If you @@ -137,7 +137,7 @@ by manually calling the appropriate vcvars file before running the bootstrap. ``` CALL "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\vcvars64.bat" -python .\src\bootstrap\bootstrap.py +python x.py build ``` ## Building Documentation diff --git a/RELEASES.md b/RELEASES.md index e6f18f9f7ba55..222ad3aa112af 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,30 @@ +Version 1.12.1 (2016-10-20) +=========================== + +Regression Fixes +---------------- + +* [ICE: 'rustc' panicked at 'assertion failed: concrete_substs.is_normalized_for_trans()' #36381][36381] +* [Confusion with double negation and booleans][36856] +* [rustc 1.12.0 fails with SIGSEGV in release mode (syn crate 0.8.0)][36875] +* [Rustc 1.12.0 Windows build of `ethcore` crate fails with LLVM error][36924] +* [1.12.0: High memory usage when linking in release mode with debug info][36926] +* [Corrupted memory after updated to 1.12][36936] +* ["Let NullaryConstructor = something;" causes internal compiler error: "tried to overwrite interned AdtDef"][37026] +* [Fix ICE: inject bitcast if types mismatch for invokes/calls/stores][37112] +* [debuginfo: Handle spread_arg case in MIR-trans in a more stable way.][37153] + +[36381]: https://github.com/rust-lang/rust/issues/36381 +[36856]: https://github.com/rust-lang/rust/issues/36856 +[36875]: https://github.com/rust-lang/rust/issues/36875 +[36924]: https://github.com/rust-lang/rust/issues/36924 +[36926]: https://github.com/rust-lang/rust/issues/36926 +[36936]: https://github.com/rust-lang/rust/issues/36936 +[37026]: https://github.com/rust-lang/rust/issues/37026 +[37112]: https://github.com/rust-lang/rust/issues/37112 +[37153]: https://github.com/rust-lang/rust/issues/37153 + + Version 1.12.0 (2016-09-29) =========================== diff --git a/configure b/configure index cd22229b7993a..85a3dd4b93484 100755 --- a/configure +++ b/configure @@ -868,13 +868,6 @@ then fi fi -if [ -n "$CFG_GDB" ] -then - # Store GDB's version - CFG_GDB_VERSION=$($CFG_GDB --version 2>/dev/null | head -1) - putvar CFG_GDB_VERSION -fi - if [ -n "$CFG_LLDB" ] then # Store LLDB's version diff --git a/mk/main.mk b/mk/main.mk index a5e3764122003..2fa8ccf3621e0 100644 --- a/mk/main.mk +++ b/mk/main.mk @@ -372,7 +372,7 @@ CFG_INFO := $(info cfg: disabling unstable features (CFG_DISABLE_UNSTABLE_FEATUR # Turn on feature-staging export CFG_DISABLE_UNSTABLE_FEATURES # Subvert unstable feature lints to do the self-build -export RUSTC_BOOTSTRAP +export RUSTC_BOOTSTRAP=1 endif ifdef CFG_MUSL_ROOT export CFG_MUSL_ROOT diff --git a/mk/tests.mk b/mk/tests.mk index 1957c989eb0d4..f3d8f0387bbd6 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -648,7 +648,7 @@ CTEST_COMMON_ARGS$(1)-T-$(2)-H-$(3) = \ --host $(3) \ --docck-python $$(CFG_PYTHON) \ --lldb-python $$(CFG_LLDB_PYTHON) \ - --gdb-version="$(CFG_GDB_VERSION)" \ + --gdb="$(CFG_GDB)" \ --lldb-version="$(CFG_LLDB_VERSION)" \ --llvm-version="$$(LLVM_VERSION_$(3))" \ --android-cross-path=$(CFG_ARM_LINUX_ANDROIDEABI_NDK) \ diff --git a/src/Cargo.lock b/src/Cargo.lock index 5826995cc3cfc..c3a8923c6de56 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -40,9 +40,9 @@ name = "bootstrap" version = "0.0.0" dependencies = [ "build_helper 0.1.0", - "cmake 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "gcc 0.3.38 (git+https://github.com/alexcrichton/gcc-rs)", + "gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", @@ -63,7 +63,7 @@ version = "0.1.0" [[package]] name = "cmake" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)", @@ -131,11 +131,6 @@ dependencies = [ name = "fmt_macros" version = "0.0.0" -[[package]] -name = "gcc" -version = "0.3.38" -source = "git+https://github.com/alexcrichton/gcc-rs#be620ac6d3ddb498cd0c700d5312c6a4c3c19597" - [[package]] name = "gcc" version = "0.3.38" @@ -189,7 +184,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "linkchecker" version = "0.1.0" dependencies = [ - "url 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -725,7 +720,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "url" -version = "1.2.2" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -743,10 +738,9 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] -"checksum cmake 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "dfcf5bcece56ef953b8ea042509e9dcbdfe97820b7e20d86beb53df30ed94978" +"checksum cmake 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0e5bcf27e097a184c1df4437654ed98df3d7a516e8508a6ba45d8b092bbdf283" "checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f" "checksum filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5363ab8e4139b8568a6237db5248646e5a8a2f89bd5ccb02092182b11fd3e922" -"checksum gcc 0.3.38 (git+https://github.com/alexcrichton/gcc-rs)" = "" "checksum gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)" = "553f11439bdefe755bf366b264820f1da70f3aaf3924e594b886beb9c831bcf5" "checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685" "checksum idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1053236e00ce4f668aeca4a769a09b3bf5a682d802abd6f3cb39374f6b162c11" @@ -760,6 +754,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum toml 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "0590d72182e50e879c4da3b11c6488dae18fccb1ae0c7a3eda18e16795844796" "checksum unicode-bidi 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c1f7ceb96afdfeedee42bade65a0d585a6a0106f681b6749c8ff4daa8df30b3f" "checksum unicode-normalization 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "26643a2f83bac55f1976fb716c10234485f9202dcd65cfbdf9da49867b271172" -"checksum url 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9ba5a45db1d2e0effb7a1c00cc73ffc63a973da8c7d1fcd5b46f24285ade6c54" +"checksum url 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "48ccf7bd87a81b769cf84ad556e034541fb90e1cd6d4bc375c822ed9500cd9d7" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index c96690754387b..9d44ca033e45d 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -27,7 +27,7 @@ num_cpus = "0.2" toml = "0.1" getopts = "0.2" rustc-serialize = "0.3" -gcc = { git = "https://github.com/alexcrichton/gcc-rs" } +gcc = "0.3.36" libc = "0.2" md5 = "0.1" diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md index 57d644d635cf7..f73f41ffae29d 100644 --- a/src/bootstrap/README.md +++ b/src/bootstrap/README.md @@ -10,24 +10,72 @@ system. ## Using rustbuild -When configuring Rust via `./configure`, pass the following to enable building -via this build system: +The rustbuild build system has a primary entry point, a top level `x.py` script: ``` -./configure --enable-rustbuild -make +python ./x.py build ``` -Afterwards the `Makefile` which is generated will have a few commands like -`make check`, `make tidy`, etc. For finer-grained control, the -`bootstrap.py` entry point can be used: +Note that if you're on Unix you should be able to execute the script directly: ``` -python src/bootstrap/bootstrap.py +./x.py build ``` -This accepts a number of options like `--stage` and `--step` which can configure -what's actually being done. +The script accepts commands, flags, and filters to determine what to do: + +* `build` - a general purpose command for compiling code. Alone `build` will + bootstrap the entire compiler, and otherwise arguments passed indicate what to + build. For example: + + ``` + # build the whole compiler + ./x.py build + + # build the stage1 compier + ./x.py build --stage 1 + + # build stage0 libstd + ./x.py build --stage 0 src/libstd + + # build a particular crate in stage0 + ./x.py build --stage 0 src/libtest + ``` + +* `test` - a command for executing unit tests. Like the `build` command this + will execute the entire test suite by default, and otherwise it can be used to + select which test suite is run: + + ``` + # run all unit tests + ./x.py test + + # execute the run-pass test suite + ./x.py test src/test/run-pass + + # execute only some tests in the run-pass test suite + ./x.py test src/test/run-pass --filter my-filter + + # execute tests in the standard library in stage0 + ./x.py test --stage 0 src/libstd + + # execute all doc tests + ./x.py test src/doc + ``` + +* `doc` - a command for building documentation. Like above can take arguments + for what to document. + +If you're more used to `./configure` and `make`, however, then you can also +configure the build system to use rustbuild instead of the old makefiles: + +``` +./configure --enable-rustbuild +make +``` + +Afterwards the `Makefile` which is generated will have a few commands like +`make check`, `make tidy`, etc. ## Configuring rustbuild @@ -47,7 +95,7 @@ being invoked manually (via the python script). The rustbuild build system goes through a few phases to actually build the compiler. What actually happens when you invoke rustbuild is: -1. The entry point script, `src/bootstrap/bootstrap.py` is run. This script is +1. The entry point script, `x.py` is run. This script is responsible for downloading the stage0 compiler/Cargo binaries, and it then compiles the build system itself (this folder). Finally, it then invokes the actual `bootstrap` binary build system. diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 2c2260a8e60c7..76bbb9d22e082 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -399,12 +399,10 @@ def main(): # Run the bootstrap args = [os.path.join(rb.build_dir, "bootstrap/debug/bootstrap")] - args.append('--src') - args.append(rb.rust_root) - args.append('--build') - args.append(rb.build) args.extend(sys.argv[1:]) env = os.environ.copy() + env["BUILD"] = rb.build + env["SRC"] = rb.rust_root env["BOOTSTRAP_PARENT_ID"] = str(os.getpid()) rb.run(args, env) diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 0a281b89c571f..611630c5730f9 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -13,44 +13,19 @@ //! This file implements the various regression test suites that we execute on //! our CI. -use std::collections::{HashMap, HashSet}; +use std::collections::HashSet; use std::env; use std::fs; use std::path::{PathBuf, Path}; use std::process::Command; use build_helper::output; -use rustc_serialize::json; use {Build, Compiler, Mode}; use util::{self, dylib_path, dylib_path_var}; const ADB_TEST_DIR: &'static str = "/data/tmp"; -#[derive(RustcDecodable)] -struct Output { - packages: Vec, - resolve: Resolve, -} - -#[derive(RustcDecodable)] -struct Package { - id: String, - name: String, - source: Option, -} - -#[derive(RustcDecodable)] -struct Resolve { - nodes: Vec, -} - -#[derive(RustcDecodable)] -struct ResolveNode { - id: String, - dependencies: Vec, -} - /// Runs the `linkchecker` tool as compiled in `stage` by the `host` compiler. /// /// This tool in `src/tools` will verify the validity of all our links in the @@ -168,8 +143,8 @@ pub fn compiletest(build: &Build, cmd.arg("--lldb-python").arg(python_default); } - if let Some(ref vers) = build.gdb_version { - cmd.arg("--gdb-version").arg(vers); + if let Some(ref gdb) = build.config.gdb { + cmd.arg("--gdb").arg(gdb); } if let Some(ref vers) = build.lldb_version { cmd.arg("--lldb-version").arg(vers); @@ -181,7 +156,7 @@ pub fn compiletest(build: &Build, let llvm_version = output(Command::new(&llvm_config).arg("--version")); cmd.arg("--llvm-version").arg(llvm_version); - cmd.args(&build.flags.args); + cmd.args(&build.flags.cmd.test_args()); if build.config.verbose || build.flags.verbose { cmd.arg("--verbose"); @@ -282,7 +257,7 @@ fn markdown_test(build: &Build, compiler: &Compiler, markdown: &Path) { cmd.arg("--test"); cmd.arg(markdown); - let mut test_args = build.flags.args.join(" "); + let mut test_args = build.flags.cmd.test_args().join(" "); if build.config.quiet_tests { test_args.push_str(" --quiet"); } @@ -302,7 +277,8 @@ fn markdown_test(build: &Build, compiler: &Compiler, markdown: &Path) { pub fn krate(build: &Build, compiler: &Compiler, target: &str, - mode: Mode) { + mode: Mode, + krate: Option<&str>) { let (name, path, features, root) = match mode { Mode::Libstd => { ("libstd", "src/rustc/std_shim", build.std_features(), "std_shim") @@ -318,24 +294,6 @@ pub fn krate(build: &Build, println!("Testing {} stage{} ({} -> {})", name, compiler.stage, compiler.host, target); - // Run `cargo metadata` to figure out what crates we're testing. - // - // Down below we're going to call `cargo test`, but to test the right set - // of packages we're going to have to know what `-p` arguments to pass it - // to know what crates to test. Here we run `cargo metadata` to learn about - // the dependency graph and what `-p` arguments there are. - let mut cargo = Command::new(&build.cargo); - cargo.arg("metadata") - .arg("--manifest-path").arg(build.src.join(path).join("Cargo.toml")); - let output = output(&mut cargo); - let output: Output = json::decode(&output).unwrap(); - let id2pkg = output.packages.iter() - .map(|pkg| (&pkg.id, pkg)) - .collect::>(); - let id2deps = output.resolve.nodes.iter() - .map(|node| (&node.id, &node.dependencies)) - .collect::>(); - // Build up the base `cargo test` command. // // Pass in some standard flags then iterate over the graph we've discovered @@ -346,24 +304,25 @@ pub fn krate(build: &Build, .arg(build.src.join(path).join("Cargo.toml")) .arg("--features").arg(features); - let mut visited = HashSet::new(); - let root_pkg = output.packages.iter().find(|p| p.name == root).unwrap(); - let mut next = vec![&root_pkg.id]; - while let Some(id) = next.pop() { - // Skip any packages with sources listed, as these come from crates.io - // and we shouldn't be testing them. - if id2pkg[id].source.is_some() { - continue - } - // Right now jemalloc is our only target-specific crate in the sense - // that it's not present on all platforms. Custom skip it here for now, - // but if we add more this probably wants to get more generalized. - if !id.contains("jemalloc") { - cargo.arg("-p").arg(&id2pkg[id].name); + match krate { + Some(krate) => { + cargo.arg("-p").arg(krate); } - for dep in id2deps[id] { - if visited.insert(dep) { - next.push(dep); + None => { + let mut visited = HashSet::new(); + let mut next = vec![root]; + while let Some(name) = next.pop() { + // Right now jemalloc is our only target-specific crate in the sense + // that it's not present on all platforms. Custom skip it here for now, + // but if we add more this probably wants to get more generalized. + if !name.contains("jemalloc") { + cargo.arg("-p").arg(name); + } + for dep in build.crates[name].deps.iter() { + if visited.insert(dep) { + next.push(dep); + } + } } } } @@ -389,7 +348,7 @@ pub fn krate(build: &Build, build.run(cargo.arg("--no-run")); krate_emscripten(build, compiler, target, mode); } else { - cargo.args(&build.flags.args); + cargo.args(&build.flags.cmd.test_args()); build.run(&mut cargo); } } @@ -421,7 +380,7 @@ fn krate_android(build: &Build, target = target, test = test_file_name, log = log, - args = build.flags.args.join(" ")); + args = build.flags.cmd.test_args().join(" ")); let output = output(Command::new("adb").arg("shell").arg(&program)); println!("{}", output); diff --git a/src/bootstrap/clean.rs b/src/bootstrap/clean.rs index a1e286e162ffa..d8b840297b810 100644 --- a/src/bootstrap/clean.rs +++ b/src/bootstrap/clean.rs @@ -16,6 +16,7 @@ //! directory as we want that cached between builds. use std::fs; +use std::io::{self, ErrorKind}; use std::path::Path; use Build; @@ -25,24 +26,57 @@ pub fn clean(build: &Build) { rm_rf(build, &build.out.join("tmp")); for host in build.config.host.iter() { + let entries = match build.out.join(host).read_dir() { + Ok(iter) => iter, + Err(_) => continue, + }; - let out = build.out.join(host); + for entry in entries { + let entry = t!(entry); + if entry.file_name().to_str() == Some("llvm") { + continue + } + rm_rf(build, &entry.path()); + } + } +} - rm_rf(build, &out.join("doc")); +fn rm_rf(build: &Build, path: &Path) { + if !path.exists() { + return + } - for stage in 0..4 { - rm_rf(build, &out.join(format!("stage{}", stage))); - rm_rf(build, &out.join(format!("stage{}-std", stage))); - rm_rf(build, &out.join(format!("stage{}-rustc", stage))); - rm_rf(build, &out.join(format!("stage{}-tools", stage))); - rm_rf(build, &out.join(format!("stage{}-test", stage))); + for file in t!(fs::read_dir(path)) { + let file = t!(file).path(); + + if file.is_dir() { + rm_rf(build, &file); + } else { + // On windows we can't remove a readonly file, and git will + // often clone files as readonly. As a result, we have some + // special logic to remove readonly files on windows. + do_op(&file, "remove file", |p| fs::remove_file(p)); } } + do_op(path, "remove dir", |p| fs::remove_dir(p)); } -fn rm_rf(build: &Build, path: &Path) { - if path.exists() { - build.verbose(&format!("removing `{}`", path.display())); - t!(fs::remove_dir_all(path)); +fn do_op(path: &Path, desc: &str, mut f: F) + where F: FnMut(&Path) -> io::Result<()> +{ + match f(path) { + Ok(()) => {} + Err(ref e) if cfg!(windows) && + e.kind() == ErrorKind::PermissionDenied => { + let mut p = t!(path.metadata()).permissions(); + p.set_readonly(false); + t!(fs::set_permissions(path, p)); + f(path).unwrap_or_else(|e| { + panic!("failed to {} {}: {}", desc, path.display(), e); + }) + } + Err(e) => { + panic!("failed to {} {}: {}", desc, path.display(), e); + } } } diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index ff8e4757bd1f1..5fc4f006729d3 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -64,8 +64,8 @@ pub fn std<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { } build.run(&mut cargo); - update_mtime(&libstd_stamp(build, compiler, target)); - std_link(build, target, compiler, compiler.host); + update_mtime(&libstd_stamp(build, &compiler, target)); + std_link(build, target, compiler.stage, compiler.host); } /// Link all libstd rlibs/dylibs into the sysroot location. @@ -74,11 +74,12 @@ pub fn std<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { /// by `compiler` into `host`'s sysroot. pub fn std_link(build: &Build, target: &str, - compiler: &Compiler, + stage: u32, host: &str) { + let compiler = Compiler::new(stage, &build.config.build); let target_compiler = Compiler::new(compiler.stage, host); let libdir = build.sysroot_libdir(&target_compiler, target); - let out_dir = build.cargo_out(compiler, Mode::Libstd, target); + let out_dir = build.cargo_out(&compiler, Mode::Libstd, target); // If we're linking one compiler host's output into another, then we weren't // called from the `std` method above. In that case we clean out what's @@ -146,7 +147,7 @@ pub fn test<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { .arg(build.src.join("src/rustc/test_shim/Cargo.toml")); build.run(&mut cargo); update_mtime(&libtest_stamp(build, compiler, target)); - test_link(build, target, compiler, compiler.host); + test_link(build, target, compiler.stage, compiler.host); } /// Link all libtest rlibs/dylibs into the sysroot location. @@ -155,11 +156,12 @@ pub fn test<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { /// by `compiler` into `host`'s sysroot. pub fn test_link(build: &Build, target: &str, - compiler: &Compiler, + stage: u32, host: &str) { + let compiler = Compiler::new(stage, &build.config.build); let target_compiler = Compiler::new(compiler.stage, host); let libdir = build.sysroot_libdir(&target_compiler, target); - let out_dir = build.cargo_out(compiler, Mode::Libtest, target); + let out_dir = build.cargo_out(&compiler, Mode::Libtest, target); add_to_sysroot(&out_dir, &libdir); } @@ -218,7 +220,7 @@ pub fn rustc<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { } build.run(&mut cargo); - rustc_link(build, target, compiler, compiler.host); + rustc_link(build, target, compiler.stage, compiler.host); } /// Link all librustc rlibs/dylibs into the sysroot location. @@ -227,11 +229,12 @@ pub fn rustc<'a>(build: &'a Build, target: &str, compiler: &Compiler<'a>) { /// by `compiler` into `host`'s sysroot. pub fn rustc_link(build: &Build, target: &str, - compiler: &Compiler, + stage: u32, host: &str) { + let compiler = Compiler::new(stage, &build.config.build); let target_compiler = Compiler::new(compiler.stage, host); let libdir = build.sysroot_libdir(&target_compiler, target); - let out_dir = build.cargo_out(compiler, Mode::Librustc, target); + let out_dir = build.cargo_out(&compiler, Mode::Librustc, target); add_to_sysroot(&out_dir, &libdir); } @@ -259,7 +262,10 @@ fn compiler_file(compiler: &Path, file: &str) -> PathBuf { /// must have been previously produced by the `stage - 1` build.config.build /// compiler. pub fn assemble_rustc(build: &Build, stage: u32, host: &str) { - assert!(stage > 0, "the stage0 compiler isn't assembled, it's downloaded"); + // nothing to do in stage0 + if stage == 0 { + return + } // The compiler that we're assembling let target_compiler = Compiler::new(stage, host); diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index abaa9389d809a..bb05b75a3fc2c 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -23,6 +23,7 @@ use std::process; use num_cpus; use rustc_serialize::Decodable; use toml::{Parser, Decoder, Value}; +use util::push_exe_path; /// Global configuration for the entire build and/or bootstrap. /// @@ -86,6 +87,7 @@ pub struct Config { pub mandir: Option, pub codegen_tests: bool, pub nodejs: Option, + pub gdb: Option, } /// Per-target configuration stored in the global configuration structure. @@ -123,6 +125,7 @@ struct Build { compiler_docs: Option, docs: Option, submodules: Option, + gdb: Option, } /// TOML representation of how the LLVM build is configured. @@ -227,6 +230,7 @@ impl Config { } config.rustc = build.rustc.map(PathBuf::from); config.cargo = build.cargo.map(PathBuf::from); + config.gdb = build.gdb.map(PathBuf::from); set(&mut config.compiler_docs, build.compiler_docs); set(&mut config.docs, build.docs); set(&mut config.submodules, build.submodules); @@ -356,37 +360,37 @@ impl Config { .collect(); } "CFG_MUSL_ROOT" if value.len() > 0 => { - self.musl_root = Some(PathBuf::from(value)); + self.musl_root = Some(parse_configure_path(value)); } "CFG_MUSL_ROOT_X86_64" if value.len() > 0 => { let target = "x86_64-unknown-linux-musl".to_string(); let target = self.target_config.entry(target) .or_insert(Target::default()); - target.musl_root = Some(PathBuf::from(value)); + target.musl_root = Some(parse_configure_path(value)); } "CFG_MUSL_ROOT_I686" if value.len() > 0 => { let target = "i686-unknown-linux-musl".to_string(); let target = self.target_config.entry(target) .or_insert(Target::default()); - target.musl_root = Some(PathBuf::from(value)); + target.musl_root = Some(parse_configure_path(value)); } "CFG_MUSL_ROOT_ARM" if value.len() > 0 => { let target = "arm-unknown-linux-musleabi".to_string(); let target = self.target_config.entry(target) .or_insert(Target::default()); - target.musl_root = Some(PathBuf::from(value)); + target.musl_root = Some(parse_configure_path(value)); } "CFG_MUSL_ROOT_ARMHF" if value.len() > 0 => { let target = "arm-unknown-linux-musleabihf".to_string(); let target = self.target_config.entry(target) .or_insert(Target::default()); - target.musl_root = Some(PathBuf::from(value)); + target.musl_root = Some(parse_configure_path(value)); } "CFG_MUSL_ROOT_ARMV7" if value.len() > 0 => { let target = "armv7-unknown-linux-musleabihf".to_string(); let target = self.target_config.entry(target) .or_insert(Target::default()); - target.musl_root = Some(PathBuf::from(value)); + target.musl_root = Some(parse_configure_path(value)); } "CFG_DEFAULT_AR" if value.len() > 0 => { self.rustc_default_ar = Some(value.to_string()); @@ -394,6 +398,9 @@ impl Config { "CFG_DEFAULT_LINKER" if value.len() > 0 => { self.rustc_default_linker = Some(value.to_string()); } + "CFG_GDB" if value.len() > 0 => { + self.gdb = Some(parse_configure_path(value)); + } "CFG_RELEASE_CHANNEL" => { self.channel = value.to_string(); } @@ -412,41 +419,42 @@ impl Config { "CFG_LLVM_ROOT" if value.len() > 0 => { let target = self.target_config.entry(self.build.clone()) .or_insert(Target::default()); - let root = PathBuf::from(value); - target.llvm_config = Some(root.join("bin/llvm-config")); + let root = parse_configure_path(value); + target.llvm_config = Some(push_exe_path(root, &["bin", "llvm-config"])); } "CFG_JEMALLOC_ROOT" if value.len() > 0 => { let target = self.target_config.entry(self.build.clone()) .or_insert(Target::default()); - target.jemalloc = Some(PathBuf::from(value)); + target.jemalloc = Some(parse_configure_path(value)); } "CFG_ARM_LINUX_ANDROIDEABI_NDK" if value.len() > 0 => { let target = "arm-linux-androideabi".to_string(); let target = self.target_config.entry(target) .or_insert(Target::default()); - target.ndk = Some(PathBuf::from(value)); + target.ndk = Some(parse_configure_path(value)); } "CFG_ARMV7_LINUX_ANDROIDEABI_NDK" if value.len() > 0 => { let target = "armv7-linux-androideabi".to_string(); let target = self.target_config.entry(target) .or_insert(Target::default()); - target.ndk = Some(PathBuf::from(value)); + target.ndk = Some(parse_configure_path(value)); } "CFG_I686_LINUX_ANDROID_NDK" if value.len() > 0 => { let target = "i686-linux-android".to_string(); let target = self.target_config.entry(target) .or_insert(Target::default()); - target.ndk = Some(PathBuf::from(value)); + target.ndk = Some(parse_configure_path(value)); } "CFG_AARCH64_LINUX_ANDROID_NDK" if value.len() > 0 => { let target = "aarch64-linux-android".to_string(); let target = self.target_config.entry(target) .or_insert(Target::default()); - target.ndk = Some(PathBuf::from(value)); + target.ndk = Some(parse_configure_path(value)); } "CFG_LOCAL_RUST_ROOT" if value.len() > 0 => { - self.rustc = Some(PathBuf::from(value).join("bin/rustc")); - self.cargo = Some(PathBuf::from(value).join("bin/cargo")); + let path = parse_configure_path(value); + self.rustc = Some(push_exe_path(path.clone(), &["bin", "rustc"])); + self.cargo = Some(push_exe_path(path, &["bin", "cargo"])); } _ => {} } @@ -454,6 +462,30 @@ impl Config { } } +#[cfg(not(windows))] +fn parse_configure_path(path: &str) -> PathBuf { + path.into() +} + +#[cfg(windows)] +fn parse_configure_path(path: &str) -> PathBuf { + // on windows, configure produces unix style paths e.g. /c/some/path but we + // only want real windows paths + + use std::process::Command; + use build_helper; + + // '/' is invalid in windows paths, so we can detect unix paths by the presence of it + if !path.contains('/') { + return path.into(); + } + + let win_path = build_helper::output(Command::new("cygpath").arg("-w").arg(path)); + let win_path = win_path.trim(); + + win_path.into() +} + fn set(field: &mut T, val: Option) { if let Some(v) = val { *field = v; diff --git a/src/bootstrap/config.toml.example b/src/bootstrap/config.toml.example index b4730c003d646..1289cdba59577 100644 --- a/src/bootstrap/config.toml.example +++ b/src/bootstrap/config.toml.example @@ -79,6 +79,9 @@ # Indicate whether submodules are managed and updated automatically. #submodules = true +# The path to (or name of) the GDB executable to use +#gdb = "gdb" + # ============================================================================= # Options for compiling Rust code itself # ============================================================================= diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index c2636384dbb2b..30c7fefad8745 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -19,7 +19,6 @@ use std::fs::{self, File}; use std::io::prelude::*; -use std::path::Path; use std::process::Command; use {Build, Compiler, Mode}; @@ -30,8 +29,9 @@ use util::{up_to_date, cp_r}; /// /// This will not actually generate any documentation if the documentation has /// already been generated. -pub fn rustbook(build: &Build, stage: u32, target: &str, name: &str, out: &Path) { - t!(fs::create_dir_all(out)); +pub fn rustbook(build: &Build, stage: u32, target: &str, name: &str) { + let out = build.doc_out(target); + t!(fs::create_dir_all(&out)); let out = out.join(name); let compiler = Compiler::new(stage, &build.config.build); @@ -57,9 +57,10 @@ pub fn rustbook(build: &Build, stage: u32, target: &str, name: &str, out: &Path) /// `STAMP` alongw ith providing the various header/footer HTML we've cutomized. /// /// In the end, this is just a glorified wrapper around rustdoc! -pub fn standalone(build: &Build, stage: u32, target: &str, out: &Path) { +pub fn standalone(build: &Build, stage: u32, target: &str) { println!("Documenting stage{} standalone ({})", stage, target); - t!(fs::create_dir_all(out)); + let out = build.doc_out(target); + t!(fs::create_dir_all(&out)); let compiler = Compiler::new(stage, &build.config.build); @@ -109,7 +110,7 @@ pub fn standalone(build: &Build, stage: u32, target: &str, out: &Path) { .arg("--html-in-header").arg(&favicon) .arg("--markdown-playground-url") .arg("https://play.rust-lang.org/") - .arg("-o").arg(out) + .arg("-o").arg(&out) .arg(&path); if filename == "reference.md" { @@ -131,9 +132,10 @@ pub fn standalone(build: &Build, stage: u32, target: &str, out: &Path) { /// /// This will generate all documentation for the standard library and its /// dependencies. This is largely just a wrapper around `cargo doc`. -pub fn std(build: &Build, stage: u32, target: &str, out: &Path) { +pub fn std(build: &Build, stage: u32, target: &str) { println!("Documenting stage{} std ({})", stage, target); - t!(fs::create_dir_all(out)); + let out = build.doc_out(target); + t!(fs::create_dir_all(&out)); let compiler = Compiler::new(stage, &build.config.build); let out_dir = build.stage_out(&compiler, Mode::Libstd) .join(target).join("doc"); @@ -146,16 +148,17 @@ pub fn std(build: &Build, stage: u32, target: &str, out: &Path) { .arg(build.src.join("src/rustc/std_shim/Cargo.toml")) .arg("--features").arg(build.std_features()); build.run(&mut cargo); - cp_r(&out_dir, out) + cp_r(&out_dir, &out) } /// Compile all libtest documentation. /// /// This will generate all documentation for libtest and its dependencies. This /// is largely just a wrapper around `cargo doc`. -pub fn test(build: &Build, stage: u32, target: &str, out: &Path) { +pub fn test(build: &Build, stage: u32, target: &str) { println!("Documenting stage{} test ({})", stage, target); - t!(fs::create_dir_all(out)); + let out = build.doc_out(target); + t!(fs::create_dir_all(&out)); let compiler = Compiler::new(stage, &build.config.build); let out_dir = build.stage_out(&compiler, Mode::Libtest) .join(target).join("doc"); @@ -167,16 +170,17 @@ pub fn test(build: &Build, stage: u32, target: &str, out: &Path) { cargo.arg("--manifest-path") .arg(build.src.join("src/rustc/test_shim/Cargo.toml")); build.run(&mut cargo); - cp_r(&out_dir, out) + cp_r(&out_dir, &out) } /// Generate all compiler documentation. /// /// This will generate all documentation for the compiler libraries and their /// dependencies. This is largely just a wrapper around `cargo doc`. -pub fn rustc(build: &Build, stage: u32, target: &str, out: &Path) { +pub fn rustc(build: &Build, stage: u32, target: &str) { println!("Documenting stage{} compiler ({})", stage, target); - t!(fs::create_dir_all(out)); + let out = build.doc_out(target); + t!(fs::create_dir_all(&out)); let compiler = Compiler::new(stage, &build.config.build); let out_dir = build.stage_out(&compiler, Mode::Librustc) .join(target).join("doc"); @@ -189,14 +193,15 @@ pub fn rustc(build: &Build, stage: u32, target: &str, out: &Path) { .arg(build.src.join("src/rustc/Cargo.toml")) .arg("--features").arg(build.rustc_features()); build.run(&mut cargo); - cp_r(&out_dir, out) + cp_r(&out_dir, &out) } /// Generates the HTML rendered error-index by running the /// `error_index_generator` tool. -pub fn error_index(build: &Build, stage: u32, target: &str, out: &Path) { +pub fn error_index(build: &Build, stage: u32, target: &str) { println!("Documenting stage{} error index ({})", stage, target); - t!(fs::create_dir_all(out)); + let out = build.doc_out(target); + t!(fs::create_dir_all(&out)); let compiler = Compiler::new(stage, &build.config.build); let mut index = build.tool_cmd(&compiler, "error_index_generator"); index.arg("html"); diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index d925997f36c21..d7516954f12d5 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -13,30 +13,46 @@ //! This module implements the command-line parsing of the build system which //! has various flags to configure how it's run. +use std::env; use std::fs; use std::path::PathBuf; use std::process; -use std::slice; -use getopts::Options; +use getopts::{Matches, Options}; + +use Build; +use config::Config; +use metadata; +use step; /// Deserialized version of all flags for this compile. pub struct Flags { pub verbose: bool, pub stage: Option, pub build: String, - pub host: Filter, - pub target: Filter, - pub step: Vec, + pub host: Vec, + pub target: Vec, pub config: Option, pub src: Option, pub jobs: Option, - pub args: Vec, - pub clean: bool, + pub cmd: Subcommand, } -pub struct Filter { - values: Vec, +pub enum Subcommand { + Build { + paths: Vec, + }, + Doc { + paths: Vec, + }, + Test { + paths: Vec, + test_args: Vec, + }, + Clean, + Dist { + install: bool, + }, } impl Flags { @@ -44,29 +60,177 @@ impl Flags { let mut opts = Options::new(); opts.optflag("v", "verbose", "use verbose output"); opts.optopt("", "config", "TOML configuration file for build", "FILE"); + opts.optopt("", "build", "build target of the stage0 compiler", "BUILD"); opts.optmulti("", "host", "host targets to build", "HOST"); - opts.reqopt("", "build", "build target of the stage0 compiler", "BUILD"); - opts.optmulti("", "target", "targets to build", "TARGET"); - opts.optmulti("s", "step", "build step to execute", "STEP"); + opts.optmulti("", "target", "target targets to build", "TARGET"); opts.optopt("", "stage", "stage to build", "N"); - opts.optopt("", "src", "path to repo root", "DIR"); + opts.optopt("", "src", "path to the root of the rust checkout", "DIR"); opts.optopt("j", "jobs", "number of jobs to run in parallel", "JOBS"); - opts.optflag("", "clean", "clean output directory"); opts.optflag("h", "help", "print this help message"); - let usage = |n| -> ! { - let brief = format!("Usage: rust.py [options]"); - print!("{}", opts.usage(&brief)); + let usage = |n, opts: &Options| -> ! { + let command = args.get(0).map(|s| &**s); + let brief = format!("Usage: x.py {} [options] [...]", + command.unwrap_or("")); + + println!("{}", opts.usage(&brief)); + match command { + Some("build") => { + println!("\ +Arguments: + This subcommand accepts a number of positional arguments of directories to + the crates and/or artifacts to compile. For example: + + ./x.py build src/libcore + ./x.py build src/libproc_macro + ./x.py build src/libstd --stage 1 + + If no arguments are passed then the complete artifacts for that stage are + also compiled. + + ./x.py build + ./x.py build --stage 1 + + For a quick build with a usable compile, you can pass: + + ./x.py build --stage 1 src/libtest +"); + } + + Some("test") => { + println!("\ +Arguments: + This subcommand accepts a number of positional arguments of directories to + tests that should be compiled and run. For example: + + ./x.py test src/test/run-pass + ./x.py test src/test/run-pass/assert-* + ./x.py test src/libstd --test-args hash_map + ./x.py test src/libstd --stage 0 + + If no arguments are passed then the complete artifacts for that stage are + compiled and tested. + + ./x.py test + ./x.py test --stage 1 +"); + } + + Some("doc") => { + println!("\ +Arguments: + This subcommand accepts a number of positional arguments of directories of + documentation to build. For example: + + ./x.py doc src/doc/book + ./x.py doc src/doc/nomicon + ./x.py doc src/libstd + + If no arguments are passed then everything is documented: + + ./x.py doc + ./x.py doc --stage 1 +"); + } + + _ => {} + } + + if let Some(command) = command { + if command == "build" || + command == "dist" || + command == "doc" || + command == "test" || + command == "clean" { + println!("Available invocations:"); + if args.iter().any(|a| a == "-v") { + let flags = Flags::parse(&["build".to_string()]); + let mut config = Config::default(); + config.build = flags.build.clone(); + let mut build = Build::new(flags, config); + metadata::build(&mut build); + step::build_rules(&build).print_help(command); + } else { + println!(" ... elided, run `./x.py {} -h -v` to see", + command); + } + + println!(""); + } + } + +println!("\ +Subcommands: + build Compile either the compiler or libraries + test Build and run some test suites + doc Build documentation + clean Clean out build directories + dist Build and/or install distribution artifacts + +To learn more about a subcommand, run `./x.py -h` +"); + process::exit(n); }; - - let m = opts.parse(args).unwrap_or_else(|e| { - println!("failed to parse options: {}", e); - usage(1); - }); - if m.opt_present("h") { - usage(0); + if args.len() == 0 { + println!("a command must be passed"); + usage(1, &opts); } + let parse = |opts: &Options| { + let m = opts.parse(&args[1..]).unwrap_or_else(|e| { + println!("failed to parse options: {}", e); + usage(1, opts); + }); + if m.opt_present("h") { + usage(0, opts); + } + return m + }; + + let cwd = t!(env::current_dir()); + let remaining_as_path = |m: &Matches| { + m.free.iter().map(|p| cwd.join(p)).collect::>() + }; + + let m: Matches; + let cmd = match &args[0][..] { + "build" => { + m = parse(&opts); + Subcommand::Build { paths: remaining_as_path(&m) } + } + "doc" => { + m = parse(&opts); + Subcommand::Doc { paths: remaining_as_path(&m) } + } + "test" => { + opts.optmulti("", "test-args", "extra arguments", "ARGS"); + m = parse(&opts); + Subcommand::Test { + paths: remaining_as_path(&m), + test_args: m.opt_strs("test-args"), + } + } + "clean" => { + m = parse(&opts); + if m.free.len() > 0 { + println!("clean takes no arguments"); + usage(1, &opts); + } + Subcommand::Clean + } + "dist" => { + opts.optflag("", "install", "run installer as well"); + m = parse(&opts); + Subcommand::Dist { + install: m.opt_present("install"), + } + } + cmd => { + println!("unknown command: {}", cmd); + usage(1, &opts); + } + }; + let cfg_file = m.opt_str("config").map(PathBuf::from).or_else(|| { if fs::metadata("config.toml").is_ok() { @@ -78,26 +242,27 @@ impl Flags { Flags { verbose: m.opt_present("v"), - clean: m.opt_present("clean"), stage: m.opt_str("stage").map(|j| j.parse().unwrap()), - build: m.opt_str("build").unwrap(), - host: Filter { values: m.opt_strs("host") }, - target: Filter { values: m.opt_strs("target") }, - step: m.opt_strs("step"), + build: m.opt_str("build").unwrap_or_else(|| { + env::var("BUILD").unwrap() + }), + host: m.opt_strs("host"), + target: m.opt_strs("target"), config: cfg_file, src: m.opt_str("src").map(PathBuf::from), jobs: m.opt_str("jobs").map(|j| j.parse().unwrap()), - args: m.free.clone(), + cmd: cmd, } } } -impl Filter { - pub fn contains(&self, name: &str) -> bool { - self.values.len() == 0 || self.values.iter().any(|s| s == name) - } - - pub fn iter(&self) -> slice::Iter { - self.values.iter() +impl Subcommand { + pub fn test_args(&self) -> Vec<&str> { + match *self { + Subcommand::Test { ref test_args, .. } => { + test_args.iter().flat_map(|s| s.split_whitespace()).collect() + } + _ => Vec::new(), + } } } diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 7c5a0c7373f88..3f8e3fe53128b 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -57,6 +57,7 @@ mod channel; mod check; mod clean; mod compile; +mod metadata; mod config; mod dist; mod doc; @@ -76,7 +77,7 @@ mod job { } pub use config::Config; -pub use flags::Flags; +pub use flags::{Flags, Subcommand}; /// A structure representing a Rust compiler. /// @@ -123,13 +124,23 @@ pub struct Build { bootstrap_key_stage0: String, // Probed tools at runtime - gdb_version: Option, lldb_version: Option, lldb_python_dir: Option, // Runtime state filled in later on cc: HashMap)>, cxx: HashMap, + crates: HashMap, +} + +#[derive(Debug)] +struct Crate { + name: String, + deps: Vec, + path: PathBuf, + doc_step: String, + build_step: String, + test_step: String, } /// The various "modes" of invoking Cargo. @@ -162,7 +173,9 @@ impl Build { /// By default all build output will be placed in the current directory. pub fn new(flags: Flags, config: Config) -> Build { let cwd = t!(env::current_dir()); - let src = flags.src.clone().unwrap_or(cwd.clone()); + let src = flags.src.clone().or_else(|| { + env::var_os("SRC").map(|x| x.into()) + }).unwrap_or(cwd.clone()); let out = cwd.join("build"); let stage0_root = out.join(&config.build).join("stage0/bin"); @@ -196,7 +209,7 @@ impl Build { package_vers: String::new(), cc: HashMap::new(), cxx: HashMap::new(), - gdb_version: None, + crates: HashMap::new(), lldb_version: None, lldb_python_dir: None, } @@ -204,13 +217,11 @@ impl Build { /// Executes the entire build, as configured by the flags and configuration. pub fn build(&mut self) { - use step::Source::*; - unsafe { job::setup(); } - if self.flags.clean { + if let Subcommand::Clean = self.flags.cmd { return clean::clean(self); } @@ -232,247 +243,10 @@ impl Build { } self.verbose("updating submodules"); self.update_submodules(); + self.verbose("learning about cargo"); + metadata::build(self); - // The main loop of the build system. - // - // The `step::all` function returns a topographically sorted list of all - // steps that need to be executed as part of this build. Each step has a - // corresponding entry in `step.rs` and indicates some unit of work that - // needs to be done as part of the build. - // - // Almost all of these are simple one-liners that shell out to the - // corresponding functionality in the extra modules, where more - // documentation can be found. - let steps = step::all(self); - - self.verbose("bootstrap build plan:"); - for step in &steps { - self.verbose(&format!("{:?}", step)); - } - - for target in steps { - let doc_out = self.out.join(&target.target).join("doc"); - match target.src { - Llvm { _dummy } => { - native::llvm(self, target.target); - } - TestHelpers { _dummy } => { - native::test_helpers(self, target.target); - } - Libstd { compiler } => { - compile::std(self, target.target, &compiler); - } - Libtest { compiler } => { - compile::test(self, target.target, &compiler); - } - Librustc { compiler } => { - compile::rustc(self, target.target, &compiler); - } - LibstdLink { compiler, host } => { - compile::std_link(self, target.target, &compiler, host); - } - LibtestLink { compiler, host } => { - compile::test_link(self, target.target, &compiler, host); - } - LibrustcLink { compiler, host } => { - compile::rustc_link(self, target.target, &compiler, host); - } - Rustc { stage: 0 } => { - // nothing to do... - } - Rustc { stage } => { - compile::assemble_rustc(self, stage, target.target); - } - ToolLinkchecker { stage } => { - compile::tool(self, stage, target.target, "linkchecker"); - } - ToolRustbook { stage } => { - compile::tool(self, stage, target.target, "rustbook"); - } - ToolErrorIndex { stage } => { - compile::tool(self, stage, target.target, - "error_index_generator"); - } - ToolCargoTest { stage } => { - compile::tool(self, stage, target.target, "cargotest"); - } - ToolTidy { stage } => { - compile::tool(self, stage, target.target, "tidy"); - } - ToolCompiletest { stage } => { - compile::tool(self, stage, target.target, "compiletest"); - } - DocBook { stage } => { - doc::rustbook(self, stage, target.target, "book", &doc_out); - } - DocNomicon { stage } => { - doc::rustbook(self, stage, target.target, "nomicon", - &doc_out); - } - DocStandalone { stage } => { - doc::standalone(self, stage, target.target, &doc_out); - } - DocStd { stage } => { - doc::std(self, stage, target.target, &doc_out); - } - DocTest { stage } => { - doc::test(self, stage, target.target, &doc_out); - } - DocRustc { stage } => { - doc::rustc(self, stage, target.target, &doc_out); - } - DocErrorIndex { stage } => { - doc::error_index(self, stage, target.target, &doc_out); - } - - CheckLinkcheck { stage } => { - check::linkcheck(self, stage, target.target); - } - CheckCargoTest { stage } => { - check::cargotest(self, stage, target.target); - } - CheckTidy { stage } => { - check::tidy(self, stage, target.target); - } - CheckRPass { compiler } => { - check::compiletest(self, &compiler, target.target, - "run-pass", "run-pass"); - } - CheckRPassFull { compiler } => { - check::compiletest(self, &compiler, target.target, - "run-pass", "run-pass-fulldeps"); - } - CheckCFail { compiler } => { - check::compiletest(self, &compiler, target.target, - "compile-fail", "compile-fail"); - } - CheckCFailFull { compiler } => { - check::compiletest(self, &compiler, target.target, - "compile-fail", "compile-fail-fulldeps") - } - CheckPFail { compiler } => { - check::compiletest(self, &compiler, target.target, - "parse-fail", "parse-fail"); - } - CheckRFail { compiler } => { - check::compiletest(self, &compiler, target.target, - "run-fail", "run-fail"); - } - CheckRFailFull { compiler } => { - check::compiletest(self, &compiler, target.target, - "run-fail", "run-fail-fulldeps"); - } - CheckPretty { compiler } => { - check::compiletest(self, &compiler, target.target, - "pretty", "pretty"); - } - CheckPrettyRPass { compiler } => { - check::compiletest(self, &compiler, target.target, - "pretty", "run-pass"); - } - CheckPrettyRPassFull { compiler } => { - check::compiletest(self, &compiler, target.target, - "pretty", "run-pass-fulldeps"); - } - CheckPrettyRFail { compiler } => { - check::compiletest(self, &compiler, target.target, - "pretty", "run-fail"); - } - CheckPrettyRFailFull { compiler } => { - check::compiletest(self, &compiler, target.target, - "pretty", "run-fail-fulldeps"); - } - CheckPrettyRPassValgrind { compiler } => { - check::compiletest(self, &compiler, target.target, - "pretty", "run-pass-valgrind"); - } - CheckMirOpt { compiler } => { - check::compiletest(self, &compiler, target.target, - "mir-opt", "mir-opt"); - } - CheckCodegen { compiler } => { - if self.config.codegen_tests { - check::compiletest(self, &compiler, target.target, - "codegen", "codegen"); - } - } - CheckCodegenUnits { compiler } => { - check::compiletest(self, &compiler, target.target, - "codegen-units", "codegen-units"); - } - CheckIncremental { compiler } => { - check::compiletest(self, &compiler, target.target, - "incremental", "incremental"); - } - CheckUi { compiler } => { - check::compiletest(self, &compiler, target.target, - "ui", "ui"); - } - CheckDebuginfo { compiler } => { - if target.target.contains("msvc") { - // nothing to do - } else if target.target.contains("apple") { - check::compiletest(self, &compiler, target.target, - "debuginfo-lldb", "debuginfo"); - } else { - check::compiletest(self, &compiler, target.target, - "debuginfo-gdb", "debuginfo"); - } - } - CheckRustdoc { compiler } => { - check::compiletest(self, &compiler, target.target, - "rustdoc", "rustdoc"); - } - CheckRPassValgrind { compiler } => { - check::compiletest(self, &compiler, target.target, - "run-pass-valgrind", "run-pass-valgrind"); - } - CheckDocs { compiler } => { - check::docs(self, &compiler); - } - CheckErrorIndex { compiler } => { - check::error_index(self, &compiler); - } - CheckRMake { compiler } => { - check::compiletest(self, &compiler, target.target, - "run-make", "run-make") - } - CheckCrateStd { compiler } => { - check::krate(self, &compiler, target.target, Mode::Libstd) - } - CheckCrateTest { compiler } => { - check::krate(self, &compiler, target.target, Mode::Libtest) - } - CheckCrateRustc { compiler } => { - check::krate(self, &compiler, target.target, Mode::Librustc) - } - - DistDocs { stage } => dist::docs(self, stage, target.target), - DistMingw { _dummy } => dist::mingw(self, target.target), - DistRustc { stage } => dist::rustc(self, stage, target.target), - DistStd { compiler } => dist::std(self, &compiler, target.target), - DistSrc { _dummy } => dist::rust_src(self), - - Install { stage } => install::install(self, stage, target.target), - - DebuggerScripts { stage } => { - let compiler = Compiler::new(stage, target.target); - dist::debugger_scripts(self, - &self.sysroot(&compiler), - target.target); - } - - AndroidCopyLibs { compiler } => { - check::android_copy_libs(self, &compiler, target.target); - } - - // pseudo-steps - Dist { .. } | - Doc { .. } | - CheckTarget { .. } | - Check { .. } => {} - } - } + step::run(self); } /// Updates all git submodules that we have. @@ -812,6 +586,11 @@ impl Build { self.out.join(target).join("llvm") } + /// Output directory for all documentation for a target + fn doc_out(&self, target: &str) -> PathBuf { + self.out.join(target).join("doc") + } + /// Returns true if no custom `llvm-config` is set for the specified target. /// /// If no custom `llvm-config` was specified then Rust's llvm will be used. @@ -873,7 +652,7 @@ impl Build { /// Adds the compiler's bootstrap key to the environment of `cmd`. fn add_bootstrap_key(&self, cmd: &mut Command) { - cmd.env("RUSTC_BOOTSTRAP", ""); + cmd.env("RUSTC_BOOTSTRAP", "1"); // FIXME: Transitionary measure to bootstrap using the old bootstrap logic. // Remove this once the bootstrap compiler uses the new login in Issue #36548. cmd.env("RUSTC_BOOTSTRAP_KEY", "62b3e239"); diff --git a/src/bootstrap/metadata.rs b/src/bootstrap/metadata.rs new file mode 100644 index 0000000000000..bf5cc6a4ad838 --- /dev/null +++ b/src/bootstrap/metadata.rs @@ -0,0 +1,95 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::collections::HashMap; +use std::process::Command; +use std::path::PathBuf; + +use build_helper::output; +use rustc_serialize::json; + +use {Build, Crate}; + +#[derive(RustcDecodable)] +struct Output { + packages: Vec, + resolve: Resolve, +} + +#[derive(RustcDecodable)] +struct Package { + id: String, + name: String, + source: Option, + manifest_path: String, +} + +#[derive(RustcDecodable)] +struct Resolve { + nodes: Vec, +} + +#[derive(RustcDecodable)] +struct ResolveNode { + id: String, + dependencies: Vec, +} + +pub fn build(build: &mut Build) { + build_krate(build, "src/rustc/std_shim"); + build_krate(build, "src/rustc/test_shim"); + build_krate(build, "src/rustc"); +} + +fn build_krate(build: &mut Build, krate: &str) { + // Run `cargo metadata` to figure out what crates we're testing. + // + // Down below we're going to call `cargo test`, but to test the right set + // of packages we're going to have to know what `-p` arguments to pass it + // to know what crates to test. Here we run `cargo metadata` to learn about + // the dependency graph and what `-p` arguments there are. + let mut cargo = Command::new(&build.cargo); + cargo.arg("metadata") + .arg("--manifest-path").arg(build.src.join(krate).join("Cargo.toml")); + let output = output(&mut cargo); + let output: Output = json::decode(&output).unwrap(); + let mut id2name = HashMap::new(); + for package in output.packages { + if package.source.is_none() { + id2name.insert(package.id, package.name.clone()); + let mut path = PathBuf::from(package.manifest_path); + path.pop(); + build.crates.insert(package.name.clone(), Crate { + build_step: format!("build-crate-{}", package.name), + doc_step: format!("doc-crate-{}", package.name), + test_step: format!("test-crate-{}", package.name), + name: package.name, + deps: Vec::new(), + path: path, + }); + } + } + + for node in output.resolve.nodes { + let name = match id2name.get(&node.id) { + Some(name) => name, + None => continue, + }; + + let krate = build.crates.get_mut(name).unwrap(); + for dep in node.dependencies.iter() { + let dep = match id2name.get(dep) { + Some(dep) => dep, + None => continue, + }; + krate.deps.push(dep.clone()); + } + } +} diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in index 0762ed98472be..d4031077639c5 100644 --- a/src/bootstrap/mk/Makefile.in +++ b/src/bootstrap/mk/Makefile.in @@ -17,47 +17,46 @@ else BOOTSTRAP_ARGS := endif -BOOTSTRAP := $(CFG_PYTHON) $(CFG_SRC_DIR)src/bootstrap/bootstrap.py $(BOOTSTRAP_ARGS) +BOOTSTRAP := $(CFG_PYTHON) $(CFG_SRC_DIR)src/bootstrap/bootstrap.py all: - $(Q)$(BOOTSTRAP) + $(Q)$(BOOTSTRAP) build $(BOOTSTRAP_ARGS) + $(Q)$(BOOTSTRAP) doc $(BOOTSTRAP_ARGS) # Don’t use $(Q) here, always show how to invoke the bootstrap script directly help: $(BOOTSTRAP) --help clean: - $(Q)$(BOOTSTRAP) --clean + $(Q)$(BOOTSTRAP) clean $(BOOTSTRAP_ARGS) rustc-stage1: - $(Q)$(BOOTSTRAP) --step libtest --stage 1 + $(Q)$(BOOTSTRAP) build --stage 1 src/libtest $(BOOTSTRAP_ARGS) rustc-stage2: - $(Q)$(BOOTSTRAP) --step libtest --stage 2 + $(Q)$(BOOTSTRAP) build --stage 2 src/libtest $(BOOTSTRAP_ARGS) docs: doc doc: - $(Q)$(BOOTSTRAP) --step doc -style: - $(Q)$(BOOTSTRAP) --step doc-style + $(Q)$(BOOTSTRAP) doc $(BOOTSTRAP_ARGS) nomicon: - $(Q)$(BOOTSTRAP) --step doc-nomicon + $(Q)$(BOOTSTRAP) doc src/doc/nomicon $(BOOTSTRAP_ARGS) book: - $(Q)$(BOOTSTRAP) --step doc-book + $(Q)$(BOOTSTRAP) doc src/doc/book $(BOOTSTRAP_ARGS) standalone-docs: - $(Q)$(BOOTSTRAP) --step doc-standalone + $(Q)$(BOOTSTRAP) doc src/doc $(BOOTSTRAP_ARGS) check: - $(Q)$(BOOTSTRAP) --step check + $(Q)$(BOOTSTRAP) test $(BOOTSTRAP_ARGS) check-cargotest: - $(Q)$(BOOTSTRAP) --step check-cargotest + $(Q)$(BOOTSTRAP) test src/tools/cargotest $(BOOTSTRAP_ARGS) dist: - $(Q)$(BOOTSTRAP) --step dist + $(Q)$(BOOTSTRAP) dist $(BOOTSTRAP_ARGS) install: ifeq (root user, $(USER) $(patsubst %,user,$(SUDO_USER))) $(Q)echo "'sudo make install' is not supported currently." else - $(Q)$(BOOTSTRAP) --step install + $(Q)$(BOOTSTRAP) dist --install $(BOOTSTRAP_ARGS) endif tidy: - $(Q)$(BOOTSTRAP) --step check-tidy --stage 0 + $(Q)$(BOOTSTRAP) test src/tools/tidy $(BOOTSTRAP_ARGS) .PHONY: dist diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index 969cd70fd57eb..cc1b7136d475f 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -92,6 +92,12 @@ pub fn check(build: &mut Build) { need_cmd(s.as_ref()); } + if let Some(ref gdb) = build.config.gdb { + need_cmd(gdb.as_ref()); + } else { + build.config.gdb = have_cmd("gdb".as_ref()); + } + // We're gonna build some custom C code here and there, host triples // also build some C++ shims for LLVM so we need a C++ compiler. for target in build.config.target.iter() { @@ -198,7 +204,6 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake .to_string() }) }; - build.gdb_version = run(Command::new("gdb").arg("--version")).ok(); build.lldb_version = run(Command::new("lldb").arg("--version")).ok(); if build.lldb_version.is_some() { build.lldb_python_dir = run(Command::new("lldb").arg("-P")).ok(); diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs index 3bf0f21192147..ef6f9c526390c 100644 --- a/src/bootstrap/step.rs +++ b/src/bootstrap/step.rs @@ -8,600 +8,683 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Major workhorse of rustbuild, definition and dependencies between stages of -//! the copmile. -//! -//! The primary purpose of this module is to define the various `Step`s of -//! execution of the build. Each `Step` has a corresponding `Source` indicating -//! what it's actually doing along with a number of dependencies which must be -//! executed first. -//! -//! This module will take the CLI as input and calculate the steps required for -//! the build requested, ensuring that all intermediate pieces are in place. -//! Essentially this module is a `make`-replacement, but not as good. - -use std::collections::HashSet; - -use {Build, Compiler}; - -#[derive(Hash, Eq, PartialEq, Clone, Debug)] -pub struct Step<'a> { - pub src: Source<'a>, - pub target: &'a str, +use std::collections::{HashMap, HashSet}; +use std::mem; + +use check; +use compile; +use dist; +use doc; +use flags::Subcommand; +use install; +use native; +use {Compiler, Build, Mode}; + +#[derive(PartialEq, Eq, Hash, Clone, Debug)] +struct Step<'a> { + name: &'a str, + stage: u32, + host: &'a str, + target: &'a str, } -/// Macro used to iterate over all targets that are recognized by the build -/// system. -/// -/// Whenever a new step is added it will involve adding an entry here, updating -/// the dependencies section below, and then adding an implementation of the -/// step in `build/mod.rs`. -/// -/// This macro takes another macro as an argument and then calls that macro with -/// all steps that the build system knows about. -macro_rules! targets { - ($m:ident) => { - $m! { - // Step representing building the stageN compiler. This is just the - // compiler executable itself, not any of the support libraries - (rustc, Rustc { stage: u32 }), - - // Steps for the two main cargo builds. These are parameterized over - // the compiler which is producing the artifact. - (libstd, Libstd { compiler: Compiler<'a> }), - (libtest, Libtest { compiler: Compiler<'a> }), - (librustc, Librustc { compiler: Compiler<'a> }), - - // Links the target produced by the compiler provided into the - // host's directory also provided. - (libstd_link, LibstdLink { - compiler: Compiler<'a>, - host: &'a str - }), - (libtest_link, LibtestLink { - compiler: Compiler<'a>, - host: &'a str - }), - (librustc_link, LibrustcLink { - compiler: Compiler<'a>, - host: &'a str - }), - - // Various tools that we can build as part of the build. - (tool_linkchecker, ToolLinkchecker { stage: u32 }), - (tool_rustbook, ToolRustbook { stage: u32 }), - (tool_error_index, ToolErrorIndex { stage: u32 }), - (tool_cargotest, ToolCargoTest { stage: u32 }), - (tool_tidy, ToolTidy { stage: u32 }), - (tool_compiletest, ToolCompiletest { stage: u32 }), - - // Steps for long-running native builds. Ideally these wouldn't - // actually exist and would be part of build scripts, but for now - // these are here. - // - // There aren't really any parameters to this, but empty structs - // with braces are unstable so we just pick something that works. - (llvm, Llvm { _dummy: () }), - (test_helpers, TestHelpers { _dummy: () }), - (debugger_scripts, DebuggerScripts { stage: u32 }), - - // Steps for various pieces of documentation that we can generate, - // the 'doc' step is just a pseudo target to depend on a bunch of - // others. - (doc, Doc { stage: u32 }), - (doc_book, DocBook { stage: u32 }), - (doc_nomicon, DocNomicon { stage: u32 }), - (doc_standalone, DocStandalone { stage: u32 }), - (doc_std, DocStd { stage: u32 }), - (doc_test, DocTest { stage: u32 }), - (doc_rustc, DocRustc { stage: u32 }), - (doc_error_index, DocErrorIndex { stage: u32 }), - - // Steps for running tests. The 'check' target is just a pseudo - // target to depend on a bunch of others. - (check, Check { stage: u32, compiler: Compiler<'a> }), - (check_target, CheckTarget { stage: u32, compiler: Compiler<'a> }), - (check_linkcheck, CheckLinkcheck { stage: u32 }), - (check_cargotest, CheckCargoTest { stage: u32 }), - (check_tidy, CheckTidy { stage: u32 }), - (check_rpass, CheckRPass { compiler: Compiler<'a> }), - (check_rpass_full, CheckRPassFull { compiler: Compiler<'a> }), - (check_rpass_valgrind, CheckRPassValgrind { compiler: Compiler<'a> }), - (check_rfail, CheckRFail { compiler: Compiler<'a> }), - (check_rfail_full, CheckRFailFull { compiler: Compiler<'a> }), - (check_cfail, CheckCFail { compiler: Compiler<'a> }), - (check_cfail_full, CheckCFailFull { compiler: Compiler<'a> }), - (check_pfail, CheckPFail { compiler: Compiler<'a> }), - (check_pretty, CheckPretty { compiler: Compiler<'a> }), - (check_pretty_rpass, CheckPrettyRPass { compiler: Compiler<'a> }), - (check_pretty_rpass_full, CheckPrettyRPassFull { compiler: Compiler<'a> }), - (check_pretty_rfail, CheckPrettyRFail { compiler: Compiler<'a> }), - (check_pretty_rfail_full, CheckPrettyRFailFull { compiler: Compiler<'a> }), - (check_pretty_rpass_valgrind, CheckPrettyRPassValgrind { compiler: Compiler<'a> }), - (check_codegen, CheckCodegen { compiler: Compiler<'a> }), - (check_codegen_units, CheckCodegenUnits { compiler: Compiler<'a> }), - (check_incremental, CheckIncremental { compiler: Compiler<'a> }), - (check_ui, CheckUi { compiler: Compiler<'a> }), - (check_mir_opt, CheckMirOpt { compiler: Compiler<'a> }), - (check_debuginfo, CheckDebuginfo { compiler: Compiler<'a> }), - (check_rustdoc, CheckRustdoc { compiler: Compiler<'a> }), - (check_docs, CheckDocs { compiler: Compiler<'a> }), - (check_error_index, CheckErrorIndex { compiler: Compiler<'a> }), - (check_rmake, CheckRMake { compiler: Compiler<'a> }), - (check_crate_std, CheckCrateStd { compiler: Compiler<'a> }), - (check_crate_test, CheckCrateTest { compiler: Compiler<'a> }), - (check_crate_rustc, CheckCrateRustc { compiler: Compiler<'a> }), - - // Distribution targets, creating tarballs - (dist, Dist { stage: u32 }), - (dist_docs, DistDocs { stage: u32 }), - (dist_mingw, DistMingw { _dummy: () }), - (dist_rustc, DistRustc { stage: u32 }), - (dist_std, DistStd { compiler: Compiler<'a> }), - (dist_src, DistSrc { _dummy: () }), - - // install target - (install, Install { stage: u32 }), - - // Misc targets - (android_copy_libs, AndroidCopyLibs { compiler: Compiler<'a> }), - } +impl<'a> Step<'a> { + fn name(&self, name: &'a str) -> Step<'a> { + Step { name: name, ..*self } } -} -// Define the `Source` enum by iterating over all the steps and peeling out just -// the types that we want to define. + fn stage(&self, stage: u32) -> Step<'a> { + Step { stage: stage, ..*self } + } -macro_rules! item { ($a:item) => ($a) } + fn host(&self, host: &'a str) -> Step<'a> { + Step { host: host, ..*self } + } -macro_rules! define_source { - ($(($short:ident, $name:ident { $($args:tt)* }),)*) => { - item! { - #[derive(Hash, Eq, PartialEq, Clone, Debug)] - pub enum Source<'a> { - $($name { $($args)* }),* - } - } + fn target(&self, target: &'a str) -> Step<'a> { + Step { target: target, ..*self } } -} -targets!(define_source); - -/// Calculate a list of all steps described by `build`. -/// -/// This will inspect the flags passed in on the command line and use that to -/// build up a list of steps to execute. These steps will then be transformed -/// into a topologically sorted list which when executed left-to-right will -/// correctly sequence the entire build. -pub fn all(build: &Build) -> Vec { - build.verbose("inferred build steps:"); - - let mut ret = Vec::new(); - let mut all = HashSet::new(); - for target in top_level(build) { - fill(build, &target, &mut ret, &mut all); - } - return ret; - - fn fill<'a>(build: &'a Build, - target: &Step<'a>, - ret: &mut Vec>, - set: &mut HashSet>) { - if set.insert(target.clone()) { - for dep in target.deps(build) { - build.verbose(&format!("{:?}\n -> {:?}", target, dep)); - fill(build, &dep, ret, set); - } - ret.push(target.clone()); - } + fn compiler(&self) -> Compiler<'a> { + Compiler::new(self.stage, self.host) } } -/// Determines what top-level targets are requested as part of this build, -/// returning them as a list. -fn top_level(build: &Build) -> Vec { - let mut targets = Vec::new(); - let stage = build.flags.stage.unwrap_or(2); +pub fn run(build: &Build) { + let rules = build_rules(build); + let steps = rules.plan(); + rules.run(&steps); +} - let host = Step { - src: Source::Llvm { _dummy: () }, - target: build.flags.host.iter().next() - .unwrap_or(&build.config.build), - }; - let target = Step { - src: Source::Llvm { _dummy: () }, - target: build.flags.target.iter().next().map(|x| &x[..]) - .unwrap_or(host.target) +pub fn build_rules(build: &Build) -> Rules { + let mut rules: Rules = Rules::new(build); + // dummy rule to do nothing, useful when a dep maps to no deps + rules.build("dummy", "path/to/nowhere"); + fn dummy<'a>(s: &Step<'a>, build: &'a Build) -> Step<'a> { + s.name("dummy").stage(0) + .target(&build.config.build) + .host(&build.config.build) + } + + // Helper for loading an entire DAG of crates, rooted at `name` + let krates = |name: &str| { + let mut ret = Vec::new(); + let mut list = vec![name]; + let mut visited = HashSet::new(); + while let Some(krate) = list.pop() { + let default = krate == name; + let krate = &build.crates[krate]; + let path = krate.path.strip_prefix(&build.src).unwrap(); + ret.push((krate, path.to_str().unwrap(), default)); + for dep in krate.deps.iter() { + if visited.insert(dep) && dep != "build_helper" { + list.push(dep); + } + } + } + return ret }; - // First, try to find steps on the command line. - add_steps(build, stage, &host, &target, &mut targets); + rules.build("rustc", "path/to/nowhere") + .dep(move |s| { + if s.stage == 0 { + dummy(s, build) + } else { + s.name("librustc") + .host(&build.config.build) + .stage(s.stage - 1) + } + }) + .run(move |s| compile::assemble_rustc(build, s.stage, s.target)); + rules.build("llvm", "src/llvm") + .host(true) + .run(move |s| native::llvm(build, s.target)); + + // ======================================================================== + // Crate compilations + // + // Tools used during the build system but not shipped + rules.build("libstd", "src/libstd") + .dep(|s| s.name("build-crate-std_shim")); + rules.build("libtest", "src/libtest") + .dep(|s| s.name("build-crate-test_shim")); + rules.build("librustc", "src/librustc") + .dep(|s| s.name("build-crate-rustc-main")); + for (krate, path, _default) in krates("std_shim") { + rules.build(&krate.build_step, path) + .dep(|s| s.name("rustc").target(s.host)) + .dep(move |s| { + if s.host == build.config.build { + dummy(s, build) + } else { + s.host(&build.config.build) + } + }) + .run(move |s| { + if s.host == build.config.build { + compile::std(build, s.target, &s.compiler()) + } else { + compile::std_link(build, s.target, s.stage, s.host) + } + }); + } + for (krate, path, default) in krates("test_shim") { + rules.build(&krate.build_step, path) + .dep(|s| s.name("libstd")) + .dep(move |s| { + if s.host == build.config.build { + dummy(s, build) + } else { + s.host(&build.config.build) + } + }) + .default(default) + .run(move |s| { + if s.host == build.config.build { + compile::test(build, s.target, &s.compiler()) + } else { + compile::test_link(build, s.target, s.stage, s.host) + } + }); + } + for (krate, path, default) in krates("rustc-main") { + rules.build(&krate.build_step, path) + .dep(|s| s.name("libtest")) + .dep(move |s| s.name("llvm").host(&build.config.build).stage(0)) + .dep(move |s| { + if s.host == build.config.build { + dummy(s, build) + } else { + s.host(&build.config.build) + } + }) + .host(true) + .default(default) + .run(move |s| { + if s.host == build.config.build { + compile::rustc(build, s.target, &s.compiler()) + } else { + compile::rustc_link(build, s.target, s.stage, s.host) + } + }); + } - // If none are specified, then build everything. - if targets.len() == 0 { - let t = Step { - src: Source::Llvm { _dummy: () }, - target: &build.config.build, + // ======================================================================== + // Test targets + // + // Various unit tests and tests suites we can run + { + let mut suite = |name, path, dir, mode| { + rules.test(name, path) + .dep(|s| s.name("libtest")) + .dep(|s| s.name("tool-compiletest").target(s.host)) + .dep(|s| s.name("test-helpers")) + .dep(move |s| { + if s.target.contains("android") { + s.name("android-copy-libs") + } else { + dummy(s, build) + } + }) + .default(true) + .run(move |s| { + check::compiletest(build, &s.compiler(), s.target, dir, mode) + }); }; - if build.config.docs { - targets.push(t.doc(stage)); - } - for host in build.config.host.iter() { - if !build.flags.host.contains(host) { - continue - } - let host = t.target(host); - if host.target == build.config.build { - targets.push(host.librustc(host.compiler(stage))); - } else { - targets.push(host.librustc_link(t.compiler(stage), host.target)); - } - for target in build.config.target.iter() { - if !build.flags.target.contains(target) { - continue - } - if host.target == build.config.build { - targets.push(host.target(target) - .libtest(host.compiler(stage))); - } else { - targets.push(host.target(target) - .libtest_link(t.compiler(stage), host.target)); - } - } + suite("check-rpass", "src/test/run-pass", "run-pass", "run-pass"); + suite("check-cfail", "src/test/compile-fail", "compile-fail", "compile-fail"); + suite("check-pfail", "src/test/parse-fail", "parse-fail", "parse-fail"); + suite("check-rfail", "src/test/run-fail", "run-fail", "run-fail"); + suite("check-rpass-valgrind", "src/test/run-pass-valgrind", + "run-pass-valgrind", "run-pass-valgrind"); + suite("check-mir-opt", "src/test/mir-opt", "mir-opt", "mir-opt"); + if build.config.codegen_tests { + suite("check-codegen", "src/test/codegen", "codegen", "codegen"); } + suite("check-codegen-units", "src/test/codegen-units", "codegen-units", + "codegen-units"); + suite("check-incremental", "src/test/incremental", "incremental", + "incremental"); + suite("check-ui", "src/test/ui", "ui", "ui"); + suite("check-pretty", "src/test/pretty", "pretty", "pretty"); + suite("check-pretty-rpass", "src/test/run-pass/pretty", "pretty", + "run-pass"); + suite("check-pretty-rfail", "src/test/run-pass/pretty", "pretty", + "run-fail"); + suite("check-pretty-valgrind", "src/test/run-pass-valgrind", "pretty", + "run-pass-valgrind"); } - targets -} + if build.config.build.contains("msvc") { + // nothing to do for debuginfo tests + } else if build.config.build.contains("apple") { + rules.test("check-debuginfo", "src/test/debuginfo") + .dep(|s| s.name("libtest")) + .dep(|s| s.name("tool-compiletest").host(s.host)) + .dep(|s| s.name("test-helpers")) + .dep(|s| s.name("debugger-scripts")) + .run(move |s| check::compiletest(build, &s.compiler(), s.target, + "debuginfo-lldb", "debuginfo")); + } else { + rules.test("check-debuginfo", "src/test/debuginfo") + .dep(|s| s.name("libtest")) + .dep(|s| s.name("tool-compiletest").host(s.host)) + .dep(|s| s.name("test-helpers")) + .dep(|s| s.name("debugger-scripts")) + .run(move |s| check::compiletest(build, &s.compiler(), s.target, + "debuginfo-gdb", "debuginfo")); + } -fn add_steps<'a>(build: &'a Build, - stage: u32, - host: &Step<'a>, - target: &Step<'a>, - targets: &mut Vec>) { - struct Context<'a> { - stage: u32, - compiler: Compiler<'a>, - _dummy: (), - host: &'a str, - } - for step in build.flags.step.iter() { - - // The macro below insists on hygienic access to all local variables, so - // we shove them all in a struct and subvert hygiene by accessing struct - // fields instead, - let cx = Context { - stage: stage, - compiler: host.target(&build.config.build).compiler(stage), - _dummy: (), - host: host.target, + rules.test("debugger-scripts", "src/etc/lldb_batchmode.py") + .run(move |s| dist::debugger_scripts(build, &build.sysroot(&s.compiler()), + s.target)); + + { + let mut suite = |name, path, dir, mode| { + rules.test(name, path) + .dep(|s| s.name("librustc")) + .dep(|s| s.name("tool-compiletest").target(s.host)) + .default(true) + .host(true) + .run(move |s| { + check::compiletest(build, &s.compiler(), s.target, dir, mode) + }); }; - macro_rules! add_step { - ($(($short:ident, $name:ident { $($arg:ident: $t:ty),* }),)*) => ({$( - let name = stringify!($short).replace("_", "-"); - if &step[..] == &name[..] { - targets.push(target.$short($(cx.$arg),*)); - continue - } - drop(name); - )*}) + + suite("check-rpass-full", "src/test/run-pass-fulldeps", + "run-pass", "run-pass-fulldeps"); + suite("check-cfail-full", "src/test/compile-fail-fulldeps", + "compile-fail", "compile-fail-fulldeps"); + suite("check-rmake", "src/test/run-make", "run-make", "run-make"); + suite("check-rustdoc", "src/test/rustdoc", "rustdoc", "rustdoc"); + suite("check-pretty-rpass-full", "src/test/run-pass-fulldeps", + "pretty", "run-pass-fulldeps"); + suite("check-pretty-rfail-full", "src/test/run-fail-fulldeps", + "pretty", "run-fail-fulldeps"); + } + + for (krate, path, _default) in krates("std_shim") { + rules.test(&krate.test_step, path) + .dep(|s| s.name("libtest")) + .run(move |s| check::krate(build, &s.compiler(), s.target, + Mode::Libstd, Some(&krate.name))); + } + rules.test("check-std-all", "path/to/nowhere") + .dep(|s| s.name("libtest")) + .default(true) + .run(move |s| check::krate(build, &s.compiler(), s.target, Mode::Libstd, + None)); + for (krate, path, _default) in krates("test_shim") { + rules.test(&krate.test_step, path) + .dep(|s| s.name("libtest")) + .run(move |s| check::krate(build, &s.compiler(), s.target, + Mode::Libtest, Some(&krate.name))); + } + rules.test("check-test-all", "path/to/nowhere") + .dep(|s| s.name("libtest")) + .default(true) + .run(move |s| check::krate(build, &s.compiler(), s.target, Mode::Libtest, + None)); + for (krate, path, _default) in krates("rustc-main") { + rules.test(&krate.test_step, path) + .dep(|s| s.name("librustc")) + .host(true) + .run(move |s| check::krate(build, &s.compiler(), s.target, + Mode::Librustc, Some(&krate.name))); + } + rules.test("check-rustc-all", "path/to/nowhere") + .dep(|s| s.name("librustc")) + .default(true) + .host(true) + .run(move |s| check::krate(build, &s.compiler(), s.target, Mode::Librustc, + None)); + + rules.test("check-linkchecker", "src/tools/linkchecker") + .dep(|s| s.name("tool-linkchecker")) + .dep(|s| s.name("default:doc")) + .default(true) + .run(move |s| check::linkcheck(build, s.stage, s.target)); + rules.test("check-cargotest", "src/tools/cargotest") + .dep(|s| s.name("tool-cargotest")) + .dep(|s| s.name("librustc")) + .run(move |s| check::cargotest(build, s.stage, s.target)); + rules.test("check-tidy", "src/tools/tidy") + .dep(|s| s.name("tool-tidy")) + .default(true) + .run(move |s| check::tidy(build, s.stage, s.target)); + rules.test("check-error-index", "src/tools/error_index_generator") + .dep(|s| s.name("libstd")) + .dep(|s| s.name("tool-error-index").host(s.host)) + .default(true) + .run(move |s| check::error_index(build, &s.compiler())); + rules.test("check-docs", "src/doc") + .dep(|s| s.name("libtest")) + .default(true) + .run(move |s| check::docs(build, &s.compiler())); + + rules.build("test-helpers", "src/rt/rust_test_helpers.c") + .run(move |s| native::test_helpers(build, s.target)); + rules.test("android-copy-libs", "path/to/nowhere") + .dep(|s| s.name("libtest")) + .run(move |s| check::android_copy_libs(build, &s.compiler(), s.target)); + + // ======================================================================== + // Build tools + // + // Tools used during the build system but not shipped + rules.build("tool-rustbook", "src/tools/rustbook") + .dep(|s| s.name("librustc")) + .run(move |s| compile::tool(build, s.stage, s.target, "rustbook")); + rules.build("tool-error-index", "src/tools/error_index_generator") + .dep(|s| s.name("librustc")) + .run(move |s| compile::tool(build, s.stage, s.target, "error_index_generator")); + rules.build("tool-tidy", "src/tools/tidy") + .dep(|s| s.name("libstd")) + .run(move |s| compile::tool(build, s.stage, s.target, "tidy")); + rules.build("tool-linkchecker", "src/tools/linkchecker") + .dep(|s| s.name("libstd")) + .run(move |s| compile::tool(build, s.stage, s.target, "linkchecker")); + rules.build("tool-cargotest", "src/tools/cargotest") + .dep(|s| s.name("libstd")) + .run(move |s| compile::tool(build, s.stage, s.target, "cargotest")); + rules.build("tool-compiletest", "src/tools/compiletest") + .dep(|s| s.name("libtest")) + .run(move |s| compile::tool(build, s.stage, s.target, "compiletest")); + + // ======================================================================== + // Documentation targets + rules.doc("doc-book", "src/doc/book") + .dep(move |s| s.name("tool-rustbook").target(&build.config.build)) + .default(build.config.docs) + .run(move |s| doc::rustbook(build, s.stage, s.target, "book")); + rules.doc("doc-nomicon", "src/doc/nomicon") + .dep(move |s| s.name("tool-rustbook").target(&build.config.build)) + .default(build.config.docs) + .run(move |s| doc::rustbook(build, s.stage, s.target, "nomicon")); + rules.doc("doc-standalone", "src/doc") + .dep(move |s| s.name("rustc").target(&build.config.build)) + .default(build.config.docs) + .run(move |s| doc::standalone(build, s.stage, s.target)); + rules.doc("doc-error-index", "src/tools/error_index_generator") + .dep(move |s| s.name("tool-error-index").target(&build.config.build)) + .default(build.config.docs) + .run(move |s| doc::error_index(build, s.stage, s.target)); + for (krate, path, default) in krates("std_shim") { + rules.doc(&krate.doc_step, path) + .dep(|s| s.name("libstd")) + .default(default && build.config.docs) + .run(move |s| doc::std(build, s.stage, s.target)); + } + for (krate, path, default) in krates("test_shim") { + rules.doc(&krate.doc_step, path) + .dep(|s| s.name("libtest")) + .default(default && build.config.docs) + .run(move |s| doc::test(build, s.stage, s.target)); + } + for (krate, path, default) in krates("rustc-main") { + rules.doc(&krate.doc_step, path) + .dep(|s| s.name("librustc")) + .host(true) + .default(default && build.config.compiler_docs) + .run(move |s| doc::rustc(build, s.stage, s.target)); + } + + // ======================================================================== + // Distribution targets + rules.dist("dist-rustc", "src/librustc") + .dep(|s| s.name("rustc")) + .host(true) + .default(true) + .run(move |s| dist::rustc(build, s.stage, s.target)); + rules.dist("dist-std", "src/libstd") + .dep(move |s| { + // We want to package up as many target libraries as possible + // for the `rust-std` package, so if this is a host target we + // depend on librustc and otherwise we just depend on libtest. + if build.config.host.iter().any(|t| t == s.target) { + s.name("librustc") + } else { + s.name("libtest") + } + }) + .default(true) + .run(move |s| dist::std(build, &s.compiler(), s.target)); + rules.dist("dist-mingw", "path/to/nowhere") + .run(move |s| dist::mingw(build, s.target)); + rules.dist("dist-src", "src") + .default(true) + .host(true) + .run(move |_| dist::rust_src(build)); + rules.dist("dist-docs", "src/doc") + .dep(|s| s.name("default:doc")) + .run(move |s| dist::docs(build, s.stage, s.target)); + rules.dist("install", "src") + .dep(|s| s.name("default:dist")) + .run(move |s| install::install(build, s.stage, s.target)); + + rules.verify(); + return rules +} + +struct Rule<'a> { + name: &'a str, + path: &'a str, + kind: Kind, + deps: Vec) -> Step<'a> + 'a>>, + run: Box) + 'a>, + default: bool, + host: bool, +} + +#[derive(PartialEq)] +enum Kind { + Build, + Test, + Dist, + Doc, +} + +impl<'a> Rule<'a> { + fn new(name: &'a str, path: &'a str, kind: Kind) -> Rule<'a> { + Rule { + name: name, + deps: Vec::new(), + run: Box::new(|_| ()), + path: path, + kind: kind, + default: false, + host: false, } + } +} + +struct RuleBuilder<'a: 'b, 'b> { + rules: &'b mut Rules<'a>, + rule: Rule<'a>, +} - targets!(add_step); +impl<'a, 'b> RuleBuilder<'a, 'b> { + fn dep(&mut self, f: F) -> &mut Self + where F: Fn(&Step<'a>) -> Step<'a> + 'a, + { + self.rule.deps.push(Box::new(f)); + self + } + + fn run(&mut self, f: F) -> &mut Self + where F: Fn(&Step<'a>) + 'a, + { + self.rule.run = Box::new(f); + self + } + + fn default(&mut self, default: bool) -> &mut Self { + self.rule.default = default; + self + } - panic!("unknown step: {}", step); + fn host(&mut self, host: bool) -> &mut Self { + self.rule.host = host; + self } } -macro_rules! constructors { - ($(($short:ident, $name:ident { $($arg:ident: $t:ty),* }),)*) => {$( - fn $short(&self, $($arg: $t),*) -> Step<'a> { - Step { - src: Source::$name { $($arg: $arg),* }, - target: self.target, - } +impl<'a, 'b> Drop for RuleBuilder<'a, 'b> { + fn drop(&mut self) { + let rule = mem::replace(&mut self.rule, Rule::new("", "", Kind::Build)); + let prev = self.rules.rules.insert(rule.name, rule); + if let Some(prev) = prev { + panic!("duplicate rule named: {}", prev.name); } - )*} + } } -impl<'a> Step<'a> { - fn compiler(&self, stage: u32) -> Compiler<'a> { - Compiler::new(stage, self.target) +pub struct Rules<'a> { + build: &'a Build, + sbuild: Step<'a>, + rules: HashMap<&'a str, Rule<'a>>, +} + +impl<'a> Rules<'a> { + fn new(build: &'a Build) -> Rules<'a> { + Rules { + build: build, + sbuild: Step { + stage: build.flags.stage.unwrap_or(2), + target: &build.config.build, + host: &build.config.build, + name: "", + }, + rules: HashMap::new(), + } } - fn target(&self, target: &'a str) -> Step<'a> { - Step { target: target, src: self.src.clone() } + fn build<'b>(&'b mut self, name: &'a str, path: &'a str) + -> RuleBuilder<'a, 'b> { + self.rule(name, path, Kind::Build) } - // Define ergonomic constructors for each step defined above so they can be - // easily constructed. - targets!(constructors); + fn test<'b>(&'b mut self, name: &'a str, path: &'a str) + -> RuleBuilder<'a, 'b> { + self.rule(name, path, Kind::Test) + } - /// Mapping of all dependencies for rustbuild. - /// - /// This function receives a step, the build that we're building for, and - /// then returns a list of all the dependencies of that step. - pub fn deps(&self, build: &'a Build) -> Vec> { - match self.src { - Source::Rustc { stage: 0 } => { - Vec::new() - } - Source::Rustc { stage } => { - let compiler = Compiler::new(stage - 1, &build.config.build); - vec![self.librustc(compiler)] - } - Source::Librustc { compiler } => { - vec![self.libtest(compiler), self.llvm(())] - } - Source::Libtest { compiler } => { - vec![self.libstd(compiler)] - } - Source::Libstd { compiler } => { - vec![self.rustc(compiler.stage).target(compiler.host)] - } - Source::LibrustcLink { compiler, host } => { - vec![self.librustc(compiler), - self.libtest_link(compiler, host)] - } - Source::LibtestLink { compiler, host } => { - vec![self.libtest(compiler), self.libstd_link(compiler, host)] - } - Source::LibstdLink { compiler, host } => { - vec![self.libstd(compiler), - self.target(host).rustc(compiler.stage)] - } - Source::Llvm { _dummy } => Vec::new(), - Source::TestHelpers { _dummy } => Vec::new(), - Source::DebuggerScripts { stage: _ } => Vec::new(), - - // Note that all doc targets depend on artifacts from the build - // architecture, not the target (which is where we're generating - // docs into). - Source::DocStd { stage } => { - let compiler = self.target(&build.config.build).compiler(stage); - vec![self.libstd(compiler)] - } - Source::DocTest { stage } => { - let compiler = self.target(&build.config.build).compiler(stage); - vec![self.libtest(compiler)] - } - Source::DocBook { stage } | - Source::DocNomicon { stage } => { - vec![self.target(&build.config.build).tool_rustbook(stage)] - } - Source::DocErrorIndex { stage } => { - vec![self.target(&build.config.build).tool_error_index(stage)] - } - Source::DocStandalone { stage } => { - vec![self.target(&build.config.build).rustc(stage)] - } - Source::DocRustc { stage } => { - vec![self.doc_test(stage)] - } - Source::Doc { stage } => { - let mut deps = vec![ - self.doc_book(stage), self.doc_nomicon(stage), - self.doc_standalone(stage), self.doc_std(stage), - self.doc_error_index(stage), - ]; - - if build.config.compiler_docs { - deps.push(self.doc_rustc(stage)); - } + fn doc<'b>(&'b mut self, name: &'a str, path: &'a str) + -> RuleBuilder<'a, 'b> { + self.rule(name, path, Kind::Doc) + } - deps - } - Source::Check { stage, compiler } => { - // Check is just a pseudo step which means check all targets, - // so just depend on checking all targets. - build.config.target.iter().map(|t| { - self.target(t).check_target(stage, compiler) - }).collect() - } - Source::CheckTarget { stage, compiler } => { - // CheckTarget here means run all possible test suites for this - // target. Most of the time, however, we can't actually run - // anything if we're not the build triple as we could be cross - // compiling. - // - // As a result, the base set of targets here is quite stripped - // down from the standard set of targets. These suites have - // their own internal logic to run in cross-compiled situations - // if they'll run at all. For example compiletest knows that - // when testing Android targets we ship artifacts to the - // emulator. - // - // When in doubt the rule of thumb for adding to this list is - // "should this test suite run on the android bot?" - let mut base = vec![ - self.check_rpass(compiler), - self.check_rfail(compiler), - self.check_crate_std(compiler), - self.check_crate_test(compiler), - self.check_debuginfo(compiler), - ]; - - // If we're testing the build triple, then we know we can - // actually run binaries and such, so we run all possible tests - // that we know about. - if self.target == build.config.build { - base.extend(vec![ - // docs-related - self.check_docs(compiler), - self.check_error_index(compiler), - self.check_rustdoc(compiler), - - // UI-related - self.check_cfail(compiler), - self.check_pfail(compiler), - self.check_ui(compiler), - - // codegen-related - self.check_incremental(compiler), - self.check_codegen(compiler), - self.check_codegen_units(compiler), - - // misc compiletest-test suites - self.check_rpass_full(compiler), - self.check_rfail_full(compiler), - self.check_cfail_full(compiler), - self.check_pretty_rpass_full(compiler), - self.check_pretty_rfail_full(compiler), - self.check_rpass_valgrind(compiler), - self.check_rmake(compiler), - self.check_mir_opt(compiler), - - // crates - self.check_crate_rustc(compiler), - - // pretty - self.check_pretty(compiler), - self.check_pretty_rpass(compiler), - self.check_pretty_rfail(compiler), - self.check_pretty_rpass_valgrind(compiler), - - // misc - self.check_linkcheck(stage), - self.check_tidy(stage), - - // can we make the distributables? - self.dist(stage), - ]); - } - base - } - Source::CheckLinkcheck { stage } => { - vec![self.tool_linkchecker(stage), self.doc(stage)] - } - Source::CheckCargoTest { stage } => { - vec![self.tool_cargotest(stage), - self.librustc(self.compiler(stage))] - } - Source::CheckTidy { stage } => { - vec![self.tool_tidy(stage)] - } - Source::CheckMirOpt { compiler} | - Source::CheckPrettyRPass { compiler } | - Source::CheckPrettyRFail { compiler } | - Source::CheckRFail { compiler } | - Source::CheckPFail { compiler } | - Source::CheckCodegen { compiler } | - Source::CheckCodegenUnits { compiler } | - Source::CheckIncremental { compiler } | - Source::CheckUi { compiler } | - Source::CheckPretty { compiler } | - Source::CheckCFail { compiler } | - Source::CheckRPassValgrind { compiler } | - Source::CheckRPass { compiler } => { - let mut base = vec![ - self.libtest(compiler), - self.target(compiler.host).tool_compiletest(compiler.stage), - self.test_helpers(()), - ]; - if self.target.contains("android") { - base.push(self.android_copy_libs(compiler)); - } - base - } - Source::CheckDebuginfo { compiler } => { - vec![ - self.libtest(compiler), - self.target(compiler.host).tool_compiletest(compiler.stage), - self.test_helpers(()), - self.debugger_scripts(compiler.stage), - ] - } - Source::CheckRustdoc { compiler } | - Source::CheckRPassFull { compiler } | - Source::CheckRFailFull { compiler } | - Source::CheckCFailFull { compiler } | - Source::CheckPrettyRPassFull { compiler } | - Source::CheckPrettyRFailFull { compiler } | - Source::CheckPrettyRPassValgrind { compiler } | - Source::CheckRMake { compiler } => { - vec![self.librustc(compiler), - self.target(compiler.host).tool_compiletest(compiler.stage)] - } - Source::CheckDocs { compiler } => { - vec![self.libtest(compiler)] - } - Source::CheckErrorIndex { compiler } => { - vec![self.libstd(compiler), - self.target(compiler.host).tool_error_index(compiler.stage)] - } - Source::CheckCrateStd { compiler } => { - vec![self.libtest(compiler)] - } - Source::CheckCrateTest { compiler } => { - vec![self.libtest(compiler)] - } - Source::CheckCrateRustc { compiler } => { - vec![self.libtest(compiler)] - } + fn dist<'b>(&'b mut self, name: &'a str, path: &'a str) + -> RuleBuilder<'a, 'b> { + self.rule(name, path, Kind::Dist) + } - Source::ToolLinkchecker { stage } | - Source::ToolTidy { stage } => { - vec![self.libstd(self.compiler(stage))] - } - Source::ToolErrorIndex { stage } | - Source::ToolRustbook { stage } => { - vec![self.librustc(self.compiler(stage))] - } - Source::ToolCargoTest { stage } => { - vec![self.libstd(self.compiler(stage))] - } - Source::ToolCompiletest { stage } => { - vec![self.libtest(self.compiler(stage))] - } + fn rule<'b>(&'b mut self, + name: &'a str, + path: &'a str, + kind: Kind) -> RuleBuilder<'a, 'b> { + RuleBuilder { + rules: self, + rule: Rule::new(name, path, kind), + } + } + + /// Verify the dependency graph defined by all our rules are correct, e.g. + /// everything points to a valid something else. + fn verify(&self) { + for rule in self.rules.values() { + for dep in rule.deps.iter() { + let dep = dep(&self.sbuild.name(rule.name)); + if self.rules.contains_key(&dep.name) || dep.name.starts_with("default:") { + continue } + panic!("\ + +invalid rule dependency graph detected, was a rule added and maybe typo'd? + + `{}` depends on `{}` which does not exist - Source::DistDocs { stage } => vec![self.doc(stage)], - Source::DistMingw { _dummy: _ } => Vec::new(), - Source::DistRustc { stage } => { - vec![self.rustc(stage)] +", rule.name, dep.name); } - Source::DistStd { compiler } => { - // We want to package up as many target libraries as possible - // for the `rust-std` package, so if this is a host target we - // depend on librustc and otherwise we just depend on libtest. - if build.config.host.iter().any(|t| t == self.target) { - vec![self.librustc(compiler)] + } + } + + pub fn print_help(&self, command: &str) { + let kind = match command { + "build" => Kind::Build, + "doc" => Kind::Doc, + "test" => Kind::Test, + "dist" => Kind::Dist, + _ => return, + }; + let rules = self.rules.values().filter(|r| r.kind == kind); + let rules = rules.filter(|r| !r.path.contains("nowhere")); + let mut rules = rules.collect::>(); + rules.sort_by_key(|r| r.path); + + println!("Available paths:\n"); + for rule in rules { + print!(" ./x.py {} {}", command, rule.path); + + println!(""); + } + } + + /// Construct the top-level build steps that we're going to be executing, + /// given the subcommand that our build is performing. + fn plan(&self) -> Vec> { + let (kind, paths) = match self.build.flags.cmd { + Subcommand::Build { ref paths } => (Kind::Build, &paths[..]), + Subcommand::Doc { ref paths } => (Kind::Doc, &paths[..]), + Subcommand::Test { ref paths, test_args: _ } => (Kind::Test, &paths[..]), + Subcommand::Dist { install } => { + if install { + return vec![self.sbuild.name("install")] } else { - vec![self.libtest(compiler)] - } - } - Source::DistSrc { _dummy: _ } => Vec::new(), - - Source::Dist { stage } => { - let mut base = Vec::new(); - - for host in build.config.host.iter() { - let host = self.target(host); - base.push(host.dist_src(())); - base.push(host.dist_rustc(stage)); - if host.target.contains("windows-gnu") { - base.push(host.dist_mingw(())); - } - - let compiler = self.compiler(stage); - for target in build.config.target.iter() { - let target = self.target(target); - if build.config.docs { - base.push(target.dist_docs(stage)); - } - base.push(target.dist_std(compiler)); - } + (Kind::Dist, &[][..]) } - base } + Subcommand::Clean => panic!(), + }; - Source::Install { stage } => { - vec![self.dist(stage)] - } + self.rules.values().filter(|rule| rule.kind == kind).filter(|rule| { + (paths.len() == 0 && rule.default) || paths.iter().any(|path| { + path.ends_with(rule.path) + }) + }).flat_map(|rule| { + let hosts = if self.build.flags.host.len() > 0 { + &self.build.flags.host + } else { + &self.build.config.host + }; + let targets = if self.build.flags.target.len() > 0 { + &self.build.flags.target + } else { + &self.build.config.target + }; + let arr = if rule.host {hosts} else {targets}; + + hosts.iter().flat_map(move |host| { + arr.iter().map(move |target| { + self.sbuild.name(rule.name).target(target).host(host) + }) + }) + }).collect() + } + + /// Execute all top-level targets indicated by `steps`. + /// + /// This will take the list returned by `plan` and then execute each step + /// along with all required dependencies as it goes up the chain. + fn run(&self, steps: &[Step<'a>]) { + self.build.verbose("bootstrap top targets:"); + for step in steps.iter() { + self.build.verbose(&format!("\t{:?}", step)); + } + + // Using `steps` as the top-level targets, make a topological ordering + // of what we need to do. + let mut order = Vec::new(); + let mut added = HashSet::new(); + for step in steps.iter().cloned() { + self.fill(step, &mut order, &mut added); + } - Source::AndroidCopyLibs { compiler } => { - vec![self.libtest(compiler)] + // Print out what we're doing for debugging + self.build.verbose("bootstrap build plan:"); + for step in order.iter() { + self.build.verbose(&format!("\t{:?}", step)); + } + + // And finally, iterate over everything and execute it. + for step in order.iter() { + (self.rules[step.name].run)(step); + } + } + + fn fill(&self, + step: Step<'a>, + order: &mut Vec>, + added: &mut HashSet>) { + if !added.insert(step.clone()) { + return + } + for dep in self.rules[step.name].deps.iter() { + let dep = dep(&step); + if dep.name.starts_with("default:") { + let kind = match &dep.name[8..] { + "doc" => Kind::Doc, + "dist" => Kind::Dist, + kind => panic!("unknown kind: `{}`", kind), + }; + let rules = self.rules.values().filter(|r| r.default); + for rule in rules.filter(|r| r.kind == kind) { + self.fill(dep.name(rule.name), order, added); + } + } else { + self.fill(dep, order, added); } } + order.push(step); } } diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index 6c0a32a54d919..e028c52236662 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -57,8 +57,7 @@ pub fn cp_r(src: &Path, dst: &Path) { let name = path.file_name().unwrap(); let dst = dst.join(name); if t!(f.file_type()).is_dir() { - let _ = fs::remove_dir_all(&dst); - t!(fs::create_dir(&dst)); + t!(fs::create_dir_all(&dst)); cp_r(&path, &dst); } else { let _ = fs::remove_file(&dst); @@ -172,3 +171,21 @@ pub fn dylib_path() -> Vec { env::split_paths(&env::var_os(dylib_path_var()).unwrap_or(OsString::new())) .collect() } + +/// `push` all components to `buf`. On windows, append `.exe` to the last component. +pub fn push_exe_path(mut buf: PathBuf, components: &[&str]) -> PathBuf { + let (&file, components) = components.split_last().expect("at least one component required"); + let mut file = file.to_owned(); + + if cfg!(windows) { + file.push_str(".exe"); + } + + for c in components { + buf.push(c); + } + + buf.push(file); + + buf +} diff --git a/src/compiler-rt b/src/compiler-rt index f03ba5a4e8bf1..ecd2b1f6d689d 160000 --- a/src/compiler-rt +++ b/src/compiler-rt @@ -1 +1 @@ -Subproject commit f03ba5a4e8bf16dcf42dd742a4ce255c36321356 +Subproject commit ecd2b1f6d689d5afbf5debe8afb3739337323852 diff --git a/src/doc/book/closures.md b/src/doc/book/closures.md index b7b67a9f1d098..fa9f66d43baa1 100644 --- a/src/doc/book/closures.md +++ b/src/doc/book/closures.md @@ -327,7 +327,7 @@ that takes a reference like so: fn call_with_ref(some_closure:F) -> i32 where F: Fn(&i32) -> i32 { - let mut value = 0; + let value = 0; some_closure(&value) } ``` @@ -340,14 +340,15 @@ fn call_with_ref<'a, F>(some_closure:F) -> i32 where F: Fn(&'a i32) -> i32 { ``` -However this presents a problem in our case. When you specify the explicit -lifetime on a function it binds that lifetime to the *entire* scope of the function -instead of just the invocation scope of our closure. This means that the borrow checker -will see a mutable reference in the same lifetime as our immutable reference and fail -to compile. +However, this presents a problem in our case. When a function has an explicit +lifetime parameter, that lifetime must be at least as long as the *entire* +call to that function. The borrow checker will complain that `value` doesn't +live long enough, because it is only in scope after its declaration inside the +function body. -In order to say that we only need the lifetime to be valid for the invocation scope -of the closure we can use Higher-Ranked Trait Bounds with the `for<...>` syntax: +What we need is a closure that can borrow its argument only for its own +invocation scope, not for the outer function's scope. In order to say that, +we can use Higher-Ranked Trait Bounds with the `for<...>` syntax: ```ignore fn call_with_ref(some_closure:F) -> i32 @@ -362,7 +363,7 @@ expect. fn call_with_ref(some_closure:F) -> i32 where F: for<'a> Fn(&'a i32) -> i32 { - let mut value = 0; + let value = 0; some_closure(&value) } ``` diff --git a/src/libcollections/borrow.rs b/src/libcollections/borrow.rs index 8f9c357833791..37618b7600a04 100644 --- a/src/libcollections/borrow.rs +++ b/src/libcollections/borrow.rs @@ -17,6 +17,7 @@ use core::hash::{Hash, Hasher}; use core::ops::{Add, AddAssign, Deref}; use fmt; +use string::String; use self::Cow::*; @@ -159,7 +160,10 @@ impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned { match *self { Borrowed(borrowed) => { *self = Owned(borrowed.to_owned()); - self.to_mut() + match *self { + Borrowed(..) => unreachable!(), + Owned(ref mut owned) => owned, + } } Owned(ref mut owned) => owned, } @@ -284,48 +288,60 @@ impl<'a, T: ?Sized + ToOwned> AsRef for Cow<'a, T> { } } -#[stable(feature = "cow_add", since = "1.13.0")] +#[stable(feature = "cow_add", since = "1.14.0")] impl<'a> Add<&'a str> for Cow<'a, str> { type Output = Cow<'a, str>; - fn add(self, rhs: &'a str) -> Self { - if self == "" { - Cow::Borrowed(rhs) - } else if rhs == "" { - self - } else { - Cow::Owned(self.into_owned() + rhs) - } + #[inline] + fn add(mut self, rhs: &'a str) -> Self::Output { + self += rhs; + self } } -#[stable(feature = "cow_add", since = "1.13.0")] +#[stable(feature = "cow_add", since = "1.14.0")] impl<'a> Add> for Cow<'a, str> { type Output = Cow<'a, str>; - fn add(self, rhs: Cow<'a, str>) -> Self { - if self == "" { - rhs - } else if rhs == "" { - self - } else { - Cow::Owned(self.into_owned() + rhs.borrow()) - } + #[inline] + fn add(mut self, rhs: Cow<'a, str>) -> Self::Output { + self += rhs; + self } } -#[stable(feature = "cow_add", since = "1.13.0")] +#[stable(feature = "cow_add", since = "1.14.0")] impl<'a> AddAssign<&'a str> for Cow<'a, str> { fn add_assign(&mut self, rhs: &'a str) { - if rhs == "" { return; } - self.to_mut().push_str(rhs); + if self.is_empty() { + *self = Cow::Borrowed(rhs) + } else if rhs.is_empty() { + return; + } else { + if let Cow::Borrowed(lhs) = *self { + let mut s = String::with_capacity(lhs.len() + rhs.len()); + s.push_str(lhs); + *self = Cow::Owned(s); + } + self.to_mut().push_str(rhs); + } } } -#[stable(feature = "cow_add", since = "1.13.0")] +#[stable(feature = "cow_add", since = "1.14.0")] impl<'a> AddAssign> for Cow<'a, str> { fn add_assign(&mut self, rhs: Cow<'a, str>) { - if rhs == "" { return; } - self.to_mut().push_str(rhs.borrow()); + if self.is_empty() { + *self = rhs + } else if rhs.is_empty() { + return; + } else { + if let Cow::Borrowed(lhs) = *self { + let mut s = String::with_capacity(lhs.len() + rhs.len()); + s.push_str(lhs); + *self = Cow::Owned(s); + } + self.to_mut().push_str(&rhs); + } } } diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 286f06b6fe32a..348eb6fb5ffa4 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -1904,10 +1904,10 @@ impl<'a> FromIterator for Cow<'a, str> { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl Into> for String { - fn into(self) -> Vec { - self.into_bytes() +#[stable(feature = "from_string_for_vec_u8", since = "1.14.0")] +impl From for Vec { + fn from(string : String) -> Vec { + string.into_bytes() } } diff --git a/src/libcollectionstest/cow_str.rs b/src/libcollectionstest/cow_str.rs index 82533ba077541..b29245121daad 100644 --- a/src/libcollectionstest/cow_str.rs +++ b/src/libcollectionstest/cow_str.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2013-2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -12,54 +12,130 @@ use std::borrow::Cow; // check that Cow<'a, str> implements addition #[test] -fn check_cow_add() { - borrowed1 = Cow::Borrowed("Hello, "); - borrowed2 = Cow::Borrowed("World!"); - borrow_empty = Cow::Borrowed(""); +fn check_cow_add_cow() { + let borrowed1 = Cow::Borrowed("Hello, "); + let borrowed2 = Cow::Borrowed("World!"); + let borrow_empty = Cow::Borrowed(""); - owned1 = Cow::Owned("Hi, ".into()); - owned2 = Cow::Owned("Rustaceans!".into()); - owned_empty = Cow::Owned("".into()); + let owned1: Cow = Cow::Owned(String::from("Hi, ")); + let owned2: Cow = Cow::Owned(String::from("Rustaceans!")); + let owned_empty: Cow = Cow::Owned(String::new()); - assert_eq!("Hello, World!", borrowed1 + borrowed2); - assert_eq!("Hello, Rustaceans!", borrowed1 + owned2); + assert_eq!("Hello, World!", borrowed1.clone() + borrowed2.clone()); + assert_eq!("Hello, Rustaceans!", borrowed1.clone() + owned2.clone()); - assert_eq!("Hello, World!", owned1 + borrowed2); - assert_eq!("Hello, Rustaceans!", owned1 + owned2); + assert_eq!("Hi, World!", owned1.clone() + borrowed2.clone()); + assert_eq!("Hi, Rustaceans!", owned1.clone() + owned2.clone()); - if let Cow::Owned(_) = borrowed1 + borrow_empty { + if let Cow::Owned(_) = borrowed1.clone() + borrow_empty.clone() { panic!("Adding empty strings to a borrow should note allocate"); } - if let Cow::Owned(_) = borrow_empty + borrowed1 { + if let Cow::Owned(_) = borrow_empty.clone() + borrowed1.clone() { panic!("Adding empty strings to a borrow should note allocate"); } - if let Cow::Owned(_) = borrowed1 + owned_empty { + if let Cow::Owned(_) = borrowed1.clone() + owned_empty.clone() { panic!("Adding empty strings to a borrow should note allocate"); } - if let Cow::Owned(_) = owned_empty + borrowed1 { + if let Cow::Owned(_) = owned_empty.clone() + borrowed1.clone() { panic!("Adding empty strings to a borrow should note allocate"); } } -fn check_cow_add_assign() { - borrowed1 = Cow::Borrowed("Hello, "); - borrowed2 = Cow::Borrowed("World!"); - borrow_empty = Cow::Borrowed(""); +#[test] +fn check_cow_add_str() { + let borrowed = Cow::Borrowed("Hello, "); + let borrow_empty = Cow::Borrowed(""); + + let owned: Cow = Cow::Owned(String::from("Hi, ")); + let owned_empty: Cow = Cow::Owned(String::new()); - owned1 = Cow::Owned("Hi, ".into()); - owned2 = Cow::Owned("Rustaceans!".into()); - owned_empty = Cow::Owned("".into()); + assert_eq!("Hello, World!", borrowed.clone() + "World!"); - let borrowed1clone = borrowed1.clone(); - borrowed1clone += borrow_empty; - assert_eq!((&borrowed1clone).as_ptr(), (&borrowed1).as_ptr()); + assert_eq!("Hi, World!", owned.clone() + "World!"); - borrowed1clone += owned_empty; - assert_eq!((&borrowed1clone).as_ptr(), (&borrowed1).as_ptr()); + if let Cow::Owned(_) = borrowed.clone() + "" { + panic!("Adding empty strings to a borrow should note allocate"); + } + if let Cow::Owned(_) = borrow_empty.clone() + "Hello, " { + panic!("Adding empty strings to a borrow should note allocate"); + } + if let Cow::Owned(_) = owned_empty.clone() + "Hello, " { + panic!("Adding empty strings to a borrow should note allocate"); + } +} + +#[test] +fn check_cow_add_assign_cow() { + let mut borrowed1 = Cow::Borrowed("Hello, "); + let borrowed2 = Cow::Borrowed("World!"); + let borrow_empty = Cow::Borrowed(""); + + let mut owned1: Cow = Cow::Owned(String::from("Hi, ")); + let owned2: Cow = Cow::Owned(String::from("Rustaceans!")); + let owned_empty: Cow = Cow::Owned(String::new()); + + let mut s = borrowed1.clone(); + s += borrow_empty.clone(); + assert_eq!("Hello, ", s); + if let Cow::Owned(_) = s { + panic!("Adding empty strings to a borrow should note allocate"); + } + let mut s = borrow_empty.clone(); + s += borrowed1.clone(); + assert_eq!("Hello, ", s); + if let Cow::Owned(_) = s { + panic!("Adding empty strings to a borrow should note allocate"); + } + let mut s = borrowed1.clone(); + s += owned_empty.clone(); + assert_eq!("Hello, ", s); + if let Cow::Owned(_) = s { + panic!("Adding empty strings to a borrow should note allocate"); + } + let mut s = owned_empty.clone(); + s += borrowed1.clone(); + assert_eq!("Hello, ", s); + if let Cow::Owned(_) = s { + panic!("Adding empty strings to a borrow should note allocate"); + } owned1 += borrowed2; borrowed1 += owned2; - assert_eq!("Hello, World!", owned1); + assert_eq!("Hi, World!", owned1); assert_eq!("Hello, Rustaceans!", borrowed1); } + +#[test] +fn check_cow_add_assign_str() { + let mut borrowed = Cow::Borrowed("Hello, "); + let borrow_empty = Cow::Borrowed(""); + + let mut owned: Cow = Cow::Owned(String::from("Hi, ")); + let owned_empty: Cow = Cow::Owned(String::new()); + + let mut s = borrowed.clone(); + s += ""; + assert_eq!("Hello, ", s); + if let Cow::Owned(_) = s { + panic!("Adding empty strings to a borrow should note allocate"); + } + let mut s = borrow_empty.clone(); + s += "World!"; + assert_eq!("World!", s); + if let Cow::Owned(_) = s { + panic!("Adding empty strings to a borrow should note allocate"); + } + let mut s = owned_empty.clone(); + s += "World!"; + assert_eq!("World!", s); + if let Cow::Owned(_) = s { + panic!("Adding empty strings to a borrow should note allocate"); + } + + owned += "World!"; + borrowed += "World!"; + + assert_eq!("Hi, World!", owned); + assert_eq!("Hello, World!", borrowed); +} diff --git a/src/libcollectionstest/lib.rs b/src/libcollectionstest/lib.rs index 5d3e03c2dee36..14ec8d58bef61 100644 --- a/src/libcollectionstest/lib.rs +++ b/src/libcollectionstest/lib.rs @@ -42,6 +42,7 @@ mod bench; mod binary_heap; mod btree; +mod cow_str; mod enum_set; mod fmt; mod linked_list; diff --git a/src/libcore/hash/sip.rs b/src/libcore/hash/sip.rs index 6b3ab64dfd88c..5f5d07b668237 100644 --- a/src/libcore/hash/sip.rs +++ b/src/libcore/hash/sip.rs @@ -24,7 +24,8 @@ use mem; /// /// See: https://131002.net/siphash/ #[unstable(feature = "sip_hash_13", issue = "34767")] -#[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")] +#[rustc_deprecated(since = "1.13.0", + reason = "use `std::collections::hash_map::DefaultHasher` instead")] #[derive(Debug, Clone, Default)] pub struct SipHasher13 { hasher: Hasher, @@ -34,7 +35,8 @@ pub struct SipHasher13 { /// /// See: https://131002.net/siphash/ #[unstable(feature = "sip_hash_13", issue = "34767")] -#[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")] +#[rustc_deprecated(since = "1.13.0", + reason = "use `std::collections::hash_map::DefaultHasher` instead")] #[derive(Debug, Clone, Default)] pub struct SipHasher24 { hasher: Hasher, @@ -53,7 +55,8 @@ pub struct SipHasher24 { /// it is not intended for cryptographic purposes. As such, all /// cryptographic uses of this implementation are _strongly discouraged_. #[stable(feature = "rust1", since = "1.0.0")] -#[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")] +#[rustc_deprecated(since = "1.13.0", + reason = "use `std::collections::hash_map::DefaultHasher` instead")] #[derive(Debug, Clone, Default)] pub struct SipHasher(SipHasher24); @@ -140,7 +143,8 @@ impl SipHasher { /// Creates a new `SipHasher` with the two initial keys set to 0. #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")] + #[rustc_deprecated(since = "1.13.0", + reason = "use `std::collections::hash_map::DefaultHasher` instead")] pub fn new() -> SipHasher { SipHasher::new_with_keys(0, 0) } @@ -148,7 +152,8 @@ impl SipHasher { /// Creates a `SipHasher` that is keyed off the provided keys. #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")] + #[rustc_deprecated(since = "1.13.0", + reason = "use `std::collections::hash_map::DefaultHasher` instead")] pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher { SipHasher(SipHasher24::new_with_keys(key0, key1)) } @@ -158,7 +163,8 @@ impl SipHasher13 { /// Creates a new `SipHasher13` with the two initial keys set to 0. #[inline] #[unstable(feature = "sip_hash_13", issue = "34767")] - #[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")] + #[rustc_deprecated(since = "1.13.0", + reason = "use `std::collections::hash_map::DefaultHasher` instead")] pub fn new() -> SipHasher13 { SipHasher13::new_with_keys(0, 0) } @@ -166,7 +172,8 @@ impl SipHasher13 { /// Creates a `SipHasher13` that is keyed off the provided keys. #[inline] #[unstable(feature = "sip_hash_13", issue = "34767")] - #[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")] + #[rustc_deprecated(since = "1.13.0", + reason = "use `std::collections::hash_map::DefaultHasher` instead")] pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher13 { SipHasher13 { hasher: Hasher::new_with_keys(key0, key1) @@ -178,7 +185,8 @@ impl SipHasher24 { /// Creates a new `SipHasher24` with the two initial keys set to 0. #[inline] #[unstable(feature = "sip_hash_13", issue = "34767")] - #[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")] + #[rustc_deprecated(since = "1.13.0", + reason = "use `std::collections::hash_map::DefaultHasher` instead")] pub fn new() -> SipHasher24 { SipHasher24::new_with_keys(0, 0) } @@ -186,7 +194,8 @@ impl SipHasher24 { /// Creates a `SipHasher24` that is keyed off the provided keys. #[inline] #[unstable(feature = "sip_hash_13", issue = "34767")] - #[rustc_deprecated(since = "1.13.0", reason = "use `DefaultHasher` instead")] + #[rustc_deprecated(since = "1.13.0", + reason = "use `std::collections::hash_map::DefaultHasher` instead")] pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher24 { SipHasher24 { hasher: Hasher::new_with_keys(key0, key1) diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index 57c1d783b64b2..cd2e0cb11d35e 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -1374,10 +1374,7 @@ impl Peekable { if self.peeked.is_none() { self.peeked = self.iter.next(); } - match self.peeked { - Some(ref value) => Some(value), - None => None, - } + self.peeked.as_ref() } } diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index 1b2976b7435d8..a2fc6e044e74c 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -311,11 +311,11 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { } hir::ExprIndex(ref l, ref r) | - hir::ExprBinary(_, ref l, ref r) if self.tcx.is_method_call(expr.id) => { + hir::ExprBinary(_, ref l, ref r) if self.tcx.tables().is_method_call(expr.id) => { self.call(expr, pred, &l, Some(&**r).into_iter()) } - hir::ExprUnary(_, ref e) if self.tcx.is_method_call(expr.id) => { + hir::ExprUnary(_, ref e) if self.tcx.tables().is_method_call(expr.id) => { self.call(expr, pred, &e, None::.iter()) } @@ -372,9 +372,9 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { func_or_rcvr: &hir::Expr, args: I) -> CFGIndex { let method_call = ty::MethodCall::expr(call_expr.id); - let fn_ty = match self.tcx.tables.borrow().method_map.get(&method_call) { + let fn_ty = match self.tcx.tables().method_map.get(&method_call) { Some(method) => method.ty, - None => self.tcx.expr_ty_adjusted(func_or_rcvr) + None => self.tcx.tables().expr_ty_adjusted(func_or_rcvr) }; let func_or_rcvr_exit = self.expr(func_or_rcvr, pred); diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 620ee30c95628..e1fec898e41e4 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -1208,38 +1208,32 @@ impl<'a> LoweringContext<'a> { ExprKind::Break(opt_ident) => hir::ExprBreak(self.lower_opt_sp_ident(opt_ident)), ExprKind::Continue(opt_ident) => hir::ExprAgain(self.lower_opt_sp_ident(opt_ident)), ExprKind::Ret(ref e) => hir::ExprRet(e.as_ref().map(|x| self.lower_expr(x))), - ExprKind::InlineAsm(InlineAsm { - ref inputs, - ref outputs, - ref asm, - asm_str_style, - ref clobbers, - volatile, - alignstack, - dialect, - expn_id, - }) => hir::ExprInlineAsm(P(hir::InlineAsm { - inputs: inputs.iter().map(|&(ref c, _)| c.clone()).collect(), - outputs: outputs.iter() - .map(|out| { - hir::InlineAsmOutput { - constraint: out.constraint.clone(), - is_rw: out.is_rw, - is_indirect: out.is_indirect, - } - }) - .collect(), - asm: asm.clone(), - asm_str_style: asm_str_style, - clobbers: clobbers.clone().into(), - volatile: volatile, - alignstack: alignstack, - dialect: dialect, - expn_id: expn_id, - }), outputs.iter().map(|out| self.lower_expr(&out.expr)).collect(), - inputs.iter().map(|&(_, ref input)| self.lower_expr(input)).collect()), + ExprKind::InlineAsm(ref asm) => { + let hir_asm = hir::InlineAsm { + inputs: asm.inputs.iter().map(|&(ref c, _)| c.clone()).collect(), + outputs: asm.outputs.iter().map(|out| { + hir::InlineAsmOutput { + constraint: out.constraint.clone(), + is_rw: out.is_rw, + is_indirect: out.is_indirect, + } + }).collect(), + asm: asm.asm.clone(), + asm_str_style: asm.asm_str_style, + clobbers: asm.clobbers.clone().into(), + volatile: asm.volatile, + alignstack: asm.alignstack, + dialect: asm.dialect, + expn_id: asm.expn_id, + }; + let outputs = + asm.outputs.iter().map(|out| self.lower_expr(&out.expr)).collect(); + let inputs = + asm.inputs.iter().map(|&(_, ref input)| self.lower_expr(input)).collect(); + hir::ExprInlineAsm(P(hir_asm), outputs, inputs) + } ExprKind::Struct(ref path, ref fields, ref maybe_expr) => { - hir::ExprStruct(self.lower_path(path), + hir::ExprStruct(P(self.lower_path(path)), fields.iter().map(|x| self.lower_field(x)).collect(), maybe_expr.as_ref().map(|x| self.lower_expr(x))) } @@ -1743,7 +1737,7 @@ impl<'a> LoweringContext<'a> { e: Option>, attrs: ThinVec) -> P { let def = self.resolver.resolve_generated_global_path(&path, false); - let expr = self.expr(sp, hir::ExprStruct(path, fields, e), attrs); + let expr = self.expr(sp, hir::ExprStruct(P(path), fields, e), attrs); self.resolver.record_resolution(expr.id, def); expr } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index c451a789193aa..5f57ceac353cc 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -840,8 +840,8 @@ pub enum UnsafeSource { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)] pub struct Expr { pub id: NodeId, - pub node: Expr_, pub span: Span, + pub node: Expr_, pub attrs: ThinVec, } @@ -946,7 +946,7 @@ pub enum Expr_ { /// /// For example, `Foo {x: 1, y: 2}`, or /// `Foo {x: 1, .. base}`, where `base` is the `Option`. - ExprStruct(Path, HirVec, Option>), + ExprStruct(P, HirVec, Option>), /// An array literal constructed from one repeated element. /// diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 35802aef5931f..bbcd87d9cabfc 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -1266,26 +1266,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.region_vars.new_bound(debruijn) } - /// Apply `adjustment` to the type of `expr` - pub fn adjust_expr_ty(&self, - expr: &hir::Expr, - adjustment: Option<&adjustment::AutoAdjustment<'tcx>>) - -> Ty<'tcx> - { - let raw_ty = self.expr_ty(expr); - let raw_ty = self.shallow_resolve(raw_ty); - let resolve_ty = |ty: Ty<'tcx>| self.resolve_type_vars_if_possible(&ty); - raw_ty.adjust(self.tcx, - expr.span, - expr.id, - adjustment, - |method_call| self.tables - .borrow() - .method_map - .get(&method_call) - .map(|method| resolve_ty(method.ty))) - } - /// True if errors have been reported since this infcx was /// created. This is sometimes used as a heuristic to skip /// reporting errors that often occur as a result of earlier @@ -1622,7 +1602,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } pub fn expr_ty_adjusted(&self, expr: &hir::Expr) -> McResult> { - let ty = self.adjust_expr_ty(expr, self.tables.borrow().adjustments.get(&expr.id)); + let ty = self.tables.borrow().expr_ty_adjusted(expr); self.resolve_type_vars_or_error(&ty) } @@ -1666,9 +1646,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { .map(|method| method.def_id) } - pub fn adjustments(&self) -> Ref>> { + pub fn adjustments(&self) -> Ref>> { fn project_adjustments<'a, 'tcx>(tables: &'a ty::Tables<'tcx>) - -> &'a NodeMap> { + -> &'a NodeMap> { &tables.adjustments } diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index dc634b08784a4..4212b1fb05ee3 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -92,7 +92,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { match def { Def::AssociatedTy(..) | Def::Method(_) | Def::AssociatedConst(_) if self.tcx.trait_of_item(def.def_id()).is_some() => { - if let Some(substs) = self.tcx.tables.borrow().item_substs.get(&id) { + if let Some(substs) = self.tcx.tables().item_substs.get(&id) { if let ty::TyAdt(tyid, _) = substs.substs.type_at(0).sty { self.check_def_id(tyid.did); } @@ -123,12 +123,12 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { fn lookup_and_handle_method(&mut self, id: ast::NodeId) { let method_call = ty::MethodCall::expr(id); - let method = self.tcx.tables.borrow().method_map[&method_call]; + let method = self.tcx.tables().method_map[&method_call]; self.check_def_id(method.def_id); } fn handle_field_access(&mut self, lhs: &hir::Expr, name: ast::Name) { - match self.tcx.expr_ty_adjusted(lhs).sty { + match self.tcx.tables().expr_ty_adjusted(lhs).sty { ty::TyAdt(def, _) => { self.insert_def_id(def.struct_variant().field_named(name).did); } @@ -137,7 +137,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { } fn handle_tup_field_access(&mut self, lhs: &hir::Expr, idx: usize) { - match self.tcx.expr_ty_adjusted(lhs).sty { + match self.tcx.tables().expr_ty_adjusted(lhs).sty { ty::TyAdt(def, _) => { self.insert_def_id(def.struct_variant().fields[idx].did); } @@ -148,7 +148,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { fn handle_field_pattern_match(&mut self, lhs: &hir::Pat, pats: &[codemap::Spanned]) { - let variant = match self.tcx.node_id_to_type(lhs.id).sty { + let variant = match self.tcx.tables().node_id_to_type(lhs.id).sty { ty::TyAdt(adt, _) => { adt.variant_of_def(self.tcx.expect_def(lhs.id)) } @@ -433,7 +433,7 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> { } fn should_warn_about_field(&mut self, field: &hir::StructField) -> bool { - let field_type = self.tcx.node_id_to_type(field.id); + let field_type = self.tcx.tables().node_id_to_type(field.id); let is_marker_field = match field_type.ty_to_def_id() { Some(def_id) => self.tcx.lang_items.items().iter().any(|item| *item == Some(def_id)), _ => false diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs index 2a75b6620fd61..8ca3c75eaa4b1 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -159,7 +159,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> { match expr.node { hir::ExprMethodCall(..) => { let method_call = MethodCall::expr(expr.id); - let base_type = self.tcx.tables.borrow().method_map[&method_call].ty; + let base_type = self.tcx.tables().method_map[&method_call].ty; debug!("effect: method call case, base type is {:?}", base_type); if type_is_unsafe_function(base_type) { @@ -168,7 +168,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> { } } hir::ExprCall(ref base, _) => { - let base_type = self.tcx.expr_ty_adjusted(base); + let base_type = self.tcx.tables().expr_ty_adjusted(base); debug!("effect: call case, base type is {:?}", base_type); if type_is_unsafe_function(base_type) { @@ -176,7 +176,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> { } } hir::ExprUnary(hir::UnDeref, ref base) => { - let base_type = self.tcx.expr_ty_adjusted(base); + let base_type = self.tcx.tables().expr_ty_adjusted(base); debug!("effect: unary case, base type is {:?}", base_type); if let ty::TyRawPtr(_) = base_type.sty { @@ -200,7 +200,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> { } } hir::ExprField(ref base_expr, field) => { - if let ty::TyAdt(adt, ..) = self.tcx.expr_ty_adjusted(base_expr).sty { + if let ty::TyAdt(adt, ..) = self.tcx.tables().expr_ty_adjusted(base_expr).sty { if adt.is_union() { self.require_unsafe(field.span, "access to union field"); } @@ -214,7 +214,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> { fn visit_pat(&mut self, pat: &hir::Pat) { if let PatKind::Struct(_, ref fields, _) = pat.node { - if let ty::TyAdt(adt, ..) = self.tcx.pat_ty(pat).sty { + if let ty::TyAdt(adt, ..) = self.tcx.tables().pat_ty(pat).sty { if adt.is_union() { for field in fields { self.require_unsafe(field.span, "matching on union field"); diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index c37b6df369dfc..0543d1303a5f1 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -720,11 +720,11 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { //NOTE(@jroesch): mixed RefCell borrow causes crash let adj = infcx.adjustments().get(&expr.id).map(|x| x.clone()); if let Some(adjustment) = adj { - match adjustment { - adjustment::AdjustNeverToAny(..) | - adjustment::AdjustReifyFnPointer | - adjustment::AdjustUnsafeFnPointer | - adjustment::AdjustMutToConstPointer => { + match adjustment.kind { + adjustment::Adjust::NeverToAny | + adjustment::Adjust::ReifyFnPointer | + adjustment::Adjust::UnsafeFnPointer | + adjustment::Adjust::MutToConstPointer => { // Creating a closure/fn-pointer or unsizing consumes // the input and stores it into the resulting rvalue. debug!("walk_adjustment: trivial adjustment"); @@ -732,8 +732,21 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { return_if_err!(self.mc.cat_expr_unadjusted(expr)); self.delegate_consume(expr.id, expr.span, cmt_unadjusted); } - adjustment::AdjustDerefRef(ref adj) => { - self.walk_autoderefref(expr, adj); + adjustment::Adjust::DerefRef { autoderefs, autoref, unsize } => { + debug!("walk_adjustment expr={:?} adj={:?}", expr, adjustment); + + self.walk_autoderefs(expr, autoderefs); + + let cmt_derefd = + return_if_err!(self.mc.cat_expr_autoderefd(expr, autoderefs)); + + let cmt_refd = + self.walk_autoref(expr, cmt_derefd, autoref); + + if unsize { + // Unsizing consumes the thin pointer and produces a fat one. + self.delegate_consume(expr.id, expr.span, cmt_refd); + } } } } @@ -770,28 +783,6 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { } } - fn walk_autoderefref(&mut self, - expr: &hir::Expr, - adj: &adjustment::AutoDerefRef<'tcx>) { - debug!("walk_autoderefref expr={:?} adj={:?}", - expr, - adj); - - self.walk_autoderefs(expr, adj.autoderefs); - - let cmt_derefd = - return_if_err!(self.mc.cat_expr_autoderefd(expr, adj.autoderefs)); - - let cmt_refd = - self.walk_autoref(expr, cmt_derefd, adj.autoref); - - if adj.unsize.is_some() { - // Unsizing consumes the thin pointer and produces a fat one. - self.delegate_consume(expr.id, expr.span, cmt_refd); - } - } - - /// Walks the autoref `opt_autoref` applied to the autoderef'd /// `expr`. `cmt_derefd` is the mem-categorized form of `expr` /// after all relevant autoderefs have occurred. Because AutoRefs @@ -803,7 +794,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { fn walk_autoref(&mut self, expr: &hir::Expr, cmt_base: mc::cmt<'tcx>, - opt_autoref: Option>) + opt_autoref: Option>) -> mc::cmt<'tcx> { debug!("walk_autoref(expr.id={} cmt_derefd={:?} opt_autoref={:?})", @@ -822,7 +813,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { }; match *autoref { - adjustment::AutoPtr(r, m) => { + adjustment::AutoBorrow::Ref(r, m) => { self.delegate.borrow(expr.id, expr.span, cmt_base, @@ -831,7 +822,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { AutoRef); } - adjustment::AutoUnsafe(m) => { + adjustment::AutoBorrow::RawPtr(m) => { debug!("walk_autoref: expr.id={} cmt_base={:?}", expr.id, cmt_base); diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs index 1acd0fb0f79c0..57503398cfe57 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc/middle/intrinsicck.rs @@ -163,7 +163,7 @@ impl<'a, 'gcx, 'tcx, 'v> Visitor<'v> for ExprVisitor<'a, 'gcx, 'tcx> { if let hir::ExprPath(..) = expr.node { match self.infcx.tcx.expect_def(expr.id) { Def::Fn(did) if self.def_id_is_transmute(did) => { - let typ = self.infcx.tcx.node_id_to_type(expr.id); + let typ = self.infcx.tcx.tables().node_id_to_type(expr.id); match typ.sty { ty::TyFnDef(.., ref bare_fn_ty) if bare_fn_ty.abi == RustIntrinsic => { let from = bare_fn_ty.sig.0.inputs[0]; diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 79396b9ca4dab..46bea00cca3cb 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -1081,7 +1081,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { hir::ExprAssignOp(_, ref l, ref r) => { // an overloaded assign op is like a method call - if self.ir.tcx.is_method_call(expr.id) { + if self.ir.tcx.tables().is_method_call(expr.id) { let succ = self.propagate_through_expr(&l, succ); self.propagate_through_expr(&r, succ) } else { @@ -1113,8 +1113,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { hir::ExprCall(ref f, ref args) => { // FIXME(canndrew): This is_never should really be an is_uninhabited - let diverges = !self.ir.tcx.is_method_call(expr.id) && - self.ir.tcx.expr_ty_adjusted(&f).fn_ret().0.is_never(); + let diverges = !self.ir.tcx.tables().is_method_call(expr.id) && + self.ir.tcx.tables().expr_ty_adjusted(&f).fn_ret().0.is_never(); let succ = if diverges { self.s.exit_ln } else { @@ -1126,7 +1126,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { hir::ExprMethodCall(.., ref args) => { let method_call = ty::MethodCall::expr(expr.id); - let method_ty = self.ir.tcx.tables.borrow().method_map[&method_call].ty; + let method_ty = self.ir.tcx.tables().method_map[&method_call].ty; // FIXME(canndrew): This is_never should really be an is_uninhabited let succ = if method_ty.fn_ret().0.is_never() { self.s.exit_ln @@ -1409,7 +1409,7 @@ fn check_expr(this: &mut Liveness, expr: &Expr) { } hir::ExprAssignOp(_, ref l, _) => { - if !this.ir.tcx.is_method_call(expr.id) { + if !this.ir.tcx.tables().is_method_call(expr.id) { this.check_lvalue(&l); } @@ -1459,7 +1459,7 @@ fn check_fn(_v: &Liveness, impl<'a, 'tcx> Liveness<'a, 'tcx> { fn fn_ret(&self, id: NodeId) -> ty::Binder> { - let fn_ty = self.ir.tcx.node_id_to_type(id); + let fn_ty = self.ir.tcx.tables().node_id_to_type(id); match fn_ty.sty { ty::TyClosure(closure_def_id, substs) => self.ir.tcx.closure_type(closure_def_id, substs).sig.output(), @@ -1502,7 +1502,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { None if !body.stmts.is_empty() => match body.stmts.last().unwrap().node { hir::StmtSemi(ref e, _) => { - self.ir.tcx.expr_ty(&e) == fn_ret + self.ir.tcx.tables().expr_ty(&e) == fn_ret }, _ => false }, diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 9214138d21077..e3ed13e1e4017 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -354,11 +354,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } fn expr_ty_adjusted(&self, expr: &hir::Expr) -> McResult> { - let unadjusted_ty = self.expr_ty(expr)?; - Ok(unadjusted_ty.adjust( - self.tcx(), expr.span, expr.id, - self.infcx.adjustments().get(&expr.id), - |method_call| self.infcx.node_method_ty(method_call))) + self.infcx.expr_ty_adjusted(expr) } fn node_ty(&self, id: ast::NodeId) -> McResult> { @@ -396,19 +392,21 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { } Some(adjustment) => { - match *adjustment { - adjustment::AdjustDerefRef( - adjustment::AutoDerefRef { - autoref: None, unsize: None, autoderefs, ..}) => { + match adjustment.kind { + adjustment::Adjust::DerefRef { + autoderefs, + autoref: None, + unsize: false + } => { // Equivalent to *expr or something similar. self.cat_expr_autoderefd(expr, autoderefs) } - adjustment::AdjustNeverToAny(..) | - adjustment::AdjustReifyFnPointer | - adjustment::AdjustUnsafeFnPointer | - adjustment::AdjustMutToConstPointer | - adjustment::AdjustDerefRef(_) => { + adjustment::Adjust::NeverToAny | + adjustment::Adjust::ReifyFnPointer | + adjustment::Adjust::UnsafeFnPointer | + adjustment::Adjust::MutToConstPointer | + adjustment::Adjust::DerefRef {..} => { debug!("cat_expr({:?}): {:?}", adjustment, expr); diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index a476d0f6f30a6..1a50d7aa0adc7 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -116,7 +116,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ReachableContext<'a, 'tcx> { } hir::ExprMethodCall(..) => { let method_call = ty::MethodCall::expr(expr.id); - let def_id = self.tcx.tables.borrow().method_map[&method_call].def_id; + let def_id = self.tcx.tables().method_map[&method_call].def_id; // Mark the trait item (and, possibly, its default impl) as reachable // Or mark inherent impl item as reachable diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 5192575972b02..fd17e378787a5 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -555,11 +555,11 @@ pub fn check_expr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, e: &hir::Expr, hir::ExprMethodCall(i, ..) => { span = i.span; let method_call = ty::MethodCall::expr(e.id); - tcx.tables.borrow().method_map[&method_call].def_id + tcx.tables().method_map[&method_call].def_id } hir::ExprField(ref base_e, ref field) => { span = field.span; - match tcx.expr_ty_adjusted(base_e).sty { + match tcx.tables().expr_ty_adjusted(base_e).sty { ty::TyAdt(def, _) => { def.struct_variant().field_named(field.node).did } @@ -569,7 +569,7 @@ pub fn check_expr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, e: &hir::Expr, } hir::ExprTupField(ref base_e, ref field) => { span = field.span; - match tcx.expr_ty_adjusted(base_e).sty { + match tcx.tables().expr_ty_adjusted(base_e).sty { ty::TyAdt(def, _) => { def.struct_variant().fields[field.node].did } @@ -580,7 +580,7 @@ pub fn check_expr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, e: &hir::Expr, } } hir::ExprStruct(_, ref expr_fields, _) => { - match tcx.expr_ty(e).sty { + match tcx.tables().expr_ty(e).sty { ty::TyAdt(adt, ..) => match adt.adt_kind() { AdtKind::Struct | AdtKind::Union => { // check the stability of each field that appears @@ -637,7 +637,7 @@ pub fn check_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pat: &hir::Pat, debug!("check_pat(pat = {:?})", pat); if is_internal(tcx, pat.span) { return; } - let v = match tcx.pat_ty_opt(pat).map(|ty| &ty.sty) { + let v = match tcx.tables().pat_ty_opt(pat).map(|ty| &ty.sty) { Some(&ty::TyAdt(adt, _)) if !adt.is_enum() => adt.struct_variant(), _ => return, }; diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 87a5c6410a841..63eabd5212fd0 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -918,6 +918,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "the directory the MIR is dumped into"), perf_stats: bool = (false, parse_bool, [UNTRACKED], "print some performance-related statistics"), + hir_stats: bool = (false, parse_bool, [UNTRACKED], + "print some statistics about AST and HIR"), } pub fn default_lib_output() -> CrateType { diff --git a/src/librustc/ty/adjustment.rs b/src/librustc/ty/adjustment.rs index cfe370343ae49..333a5c74cb45c 100644 --- a/src/librustc/ty/adjustment.rs +++ b/src/librustc/ty/adjustment.rs @@ -8,10 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub use self::AutoAdjustment::*; -pub use self::AutoRef::*; - -use ty::{self, Ty, TyCtxt, TypeAndMut, TypeFoldable}; +use ty::{self, Ty, TyCtxt, TypeAndMut}; use ty::LvaluePreference::{NoPreference}; use syntax::ast; @@ -20,116 +17,122 @@ use syntax_pos::Span; use hir; #[derive(Copy, Clone, RustcEncodable, RustcDecodable)] -pub enum AutoAdjustment<'tcx> { - AdjustNeverToAny(Ty<'tcx>), // go from ! to any type - AdjustReifyFnPointer, // go from a fn-item type to a fn-pointer type - AdjustUnsafeFnPointer, // go from a safe fn pointer to an unsafe fn pointer - AdjustMutToConstPointer, // go from a mut raw pointer to a const raw pointer - AdjustDerefRef(AutoDerefRef<'tcx>), +pub struct Adjustment<'tcx> { + pub kind: Adjust<'tcx>, + pub target: Ty<'tcx> } -/// Represents coercing a pointer to a different kind of pointer - where 'kind' -/// here means either or both of raw vs borrowed vs unique and fat vs thin. -/// -/// We transform pointers by following the following steps in order: -/// 1. Deref the pointer `self.autoderefs` times (may be 0). -/// 2. If `autoref` is `Some(_)`, then take the address and produce either a -/// `&` or `*` pointer. -/// 3. If `unsize` is `Some(_)`, then apply the unsize transformation, -/// which will do things like convert thin pointers to fat -/// pointers, or convert structs containing thin pointers to -/// structs containing fat pointers, or convert between fat -/// pointers. We don't store the details of how the transform is -/// done (in fact, we don't know that, because it might depend on -/// the precise type parameters). We just store the target -/// type. Trans figures out what has to be done at monomorphization -/// time based on the precise source/target type at hand. -/// -/// To make that more concrete, here are some common scenarios: -/// -/// 1. The simplest cases are where the pointer is not adjusted fat vs thin. -/// Here the pointer will be dereferenced N times (where a dereference can -/// happen to raw or borrowed pointers or any smart pointer which implements -/// Deref, including Box<_>). The number of dereferences is given by -/// `autoderefs`. It can then be auto-referenced zero or one times, indicated -/// by `autoref`, to either a raw or borrowed pointer. In these cases unsize is -/// None. -/// -/// 2. A thin-to-fat coercon involves unsizing the underlying data. We start -/// with a thin pointer, deref a number of times, unsize the underlying data, -/// then autoref. The 'unsize' phase may change a fixed length array to a -/// dynamically sized one, a concrete object to a trait object, or statically -/// sized struct to a dyncamically sized one. E.g., &[i32; 4] -> &[i32] is -/// represented by: -/// -/// ``` -/// AutoDerefRef { -/// autoderefs: 1, // &[i32; 4] -> [i32; 4] -/// autoref: Some(AutoPtr), // [i32] -> &[i32] -/// unsize: Some([i32]), // [i32; 4] -> [i32] -/// } -/// ``` -/// -/// Note that for a struct, the 'deep' unsizing of the struct is not recorded. -/// E.g., `struct Foo { x: T }` we can coerce &Foo<[i32; 4]> to &Foo<[i32]> -/// The autoderef and -ref are the same as in the above example, but the type -/// stored in `unsize` is `Foo<[i32]>`, we don't store any further detail about -/// the underlying conversions from `[i32; 4]` to `[i32]`. -/// -/// 3. Coercing a `Box` to `Box` is an interesting special case. In -/// that case, we have the pointer we need coming in, so there are no -/// autoderefs, and no autoref. Instead we just do the `Unsize` transformation. -/// At some point, of course, `Box` should move out of the compiler, in which -/// case this is analogous to transformating a struct. E.g., Box<[i32; 4]> -> -/// Box<[i32]> is represented by: -/// -/// ``` -/// AutoDerefRef { -/// autoderefs: 0, -/// autoref: None, -/// unsize: Some(Box<[i32]>), -/// } -/// ``` -#[derive(Copy, Clone, RustcEncodable, RustcDecodable)] -pub struct AutoDerefRef<'tcx> { - /// Step 1. Apply a number of dereferences, producing an lvalue. - pub autoderefs: usize, - - /// Step 2. Optionally produce a pointer/reference from the value. - pub autoref: Option>, - - /// Step 3. Unsize a pointer/reference value, e.g. `&[T; n]` to - /// `&[T]`. The stored type is the target pointer type. Note that - /// the source could be a thin or fat pointer. - pub unsize: Option>, +#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)] +pub enum Adjust<'tcx> { + /// Go from ! to any type. + NeverToAny, + + /// Go from a fn-item type to a fn-pointer type. + ReifyFnPointer, + + /// Go from a safe fn pointer to an unsafe fn pointer. + UnsafeFnPointer, + + /// Go from a mut raw pointer to a const raw pointer. + MutToConstPointer, + + /// Represents coercing a pointer to a different kind of pointer - where 'kind' + /// here means either or both of raw vs borrowed vs unique and fat vs thin. + /// + /// We transform pointers by following the following steps in order: + /// 1. Deref the pointer `self.autoderefs` times (may be 0). + /// 2. If `autoref` is `Some(_)`, then take the address and produce either a + /// `&` or `*` pointer. + /// 3. If `unsize` is `Some(_)`, then apply the unsize transformation, + /// which will do things like convert thin pointers to fat + /// pointers, or convert structs containing thin pointers to + /// structs containing fat pointers, or convert between fat + /// pointers. We don't store the details of how the transform is + /// done (in fact, we don't know that, because it might depend on + /// the precise type parameters). We just store the target + /// type. Trans figures out what has to be done at monomorphization + /// time based on the precise source/target type at hand. + /// + /// To make that more concrete, here are some common scenarios: + /// + /// 1. The simplest cases are where the pointer is not adjusted fat vs thin. + /// Here the pointer will be dereferenced N times (where a dereference can + /// happen to raw or borrowed pointers or any smart pointer which implements + /// Deref, including Box<_>). The number of dereferences is given by + /// `autoderefs`. It can then be auto-referenced zero or one times, indicated + /// by `autoref`, to either a raw or borrowed pointer. In these cases unsize is + /// None. + /// + /// 2. A thin-to-fat coercon involves unsizing the underlying data. We start + /// with a thin pointer, deref a number of times, unsize the underlying data, + /// then autoref. The 'unsize' phase may change a fixed length array to a + /// dynamically sized one, a concrete object to a trait object, or statically + /// sized struct to a dyncamically sized one. E.g., &[i32; 4] -> &[i32] is + /// represented by: + /// + /// ``` + /// Adjust::DerefRef { + /// autoderefs: 1, // &[i32; 4] -> [i32; 4] + /// autoref: Some(AutoBorrow::Ref), // [i32] -> &[i32] + /// unsize: Some([i32]), // [i32; 4] -> [i32] + /// } + /// ``` + /// + /// Note that for a struct, the 'deep' unsizing of the struct is not recorded. + /// E.g., `struct Foo { x: T }` we can coerce &Foo<[i32; 4]> to &Foo<[i32]> + /// The autoderef and -ref are the same as in the above example, but the type + /// stored in `unsize` is `Foo<[i32]>`, we don't store any further detail about + /// the underlying conversions from `[i32; 4]` to `[i32]`. + /// + /// 3. Coercing a `Box` to `Box` is an interesting special case. In + /// that case, we have the pointer we need coming in, so there are no + /// autoderefs, and no autoref. Instead we just do the `Unsize` transformation. + /// At some point, of course, `Box` should move out of the compiler, in which + /// case this is analogous to transformating a struct. E.g., Box<[i32; 4]> -> + /// Box<[i32]> is represented by: + /// + /// ``` + /// Adjust::DerefRef { + /// autoderefs: 0, + /// autoref: None, + /// unsize: Some(Box<[i32]>), + /// } + /// ``` + DerefRef { + /// Step 1. Apply a number of dereferences, producing an lvalue. + autoderefs: usize, + + /// Step 2. Optionally produce a pointer/reference from the value. + autoref: Option>, + + /// Step 3. Unsize a pointer/reference value, e.g. `&[T; n]` to + /// `&[T]`. Note that the source could be a thin or fat pointer. + unsize: bool, + } } -impl<'tcx> AutoAdjustment<'tcx> { +impl<'tcx> Adjustment<'tcx> { pub fn is_identity(&self) -> bool { - match *self { - AdjustNeverToAny(ty) => ty.is_never(), - AdjustReifyFnPointer | - AdjustUnsafeFnPointer | - AdjustMutToConstPointer => false, - AdjustDerefRef(ref r) => r.is_identity(), + match self.kind { + Adjust::NeverToAny => self.target.is_never(), + + Adjust::DerefRef { autoderefs: 0, autoref: None, unsize: false } => true, + + Adjust::ReifyFnPointer | + Adjust::UnsafeFnPointer | + Adjust::MutToConstPointer | + Adjust::DerefRef {..} => false, } } } -impl<'tcx> AutoDerefRef<'tcx> { - pub fn is_identity(&self) -> bool { - self.autoderefs == 0 && self.unsize.is_none() && self.autoref.is_none() - } -} - #[derive(Copy, Clone, PartialEq, Debug, RustcEncodable, RustcDecodable)] -pub enum AutoRef<'tcx> { +pub enum AutoBorrow<'tcx> { /// Convert from T to &T. - AutoPtr(&'tcx ty::Region, hir::Mutability), + Ref(&'tcx ty::Region, hir::Mutability), /// Convert from T to *T. - /// Value to thin pointer. - AutoUnsafe(hir::Mutability), + RawPtr(hir::Mutability), } #[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)] @@ -139,84 +142,6 @@ pub enum CustomCoerceUnsized { } impl<'a, 'gcx, 'tcx> ty::TyS<'tcx> { - /// See `expr_ty_adjusted` - pub fn adjust(&'tcx self, - tcx: TyCtxt<'a, 'gcx, 'tcx>, - span: Span, - expr_id: ast::NodeId, - adjustment: Option<&AutoAdjustment<'tcx>>, - mut method_type: F) - -> Ty<'tcx> where - F: FnMut(ty::MethodCall) -> Option>, - { - if let ty::TyError = self.sty { - return self; - } - - return match adjustment { - Some(adjustment) => { - match *adjustment { - AdjustNeverToAny(ref ty) => ty, - - AdjustReifyFnPointer => { - match self.sty { - ty::TyFnDef(.., f) => tcx.mk_fn_ptr(f), - _ => { - bug!("AdjustReifyFnPointer adjustment on non-fn-item: {:?}", - self); - } - } - } - - AdjustUnsafeFnPointer => { - match self.sty { - ty::TyFnPtr(b) => tcx.safe_to_unsafe_fn_ty(b), - ref b => { - bug!("AdjustUnsafeFnPointer adjustment on non-fn-ptr: {:?}", - b); - } - } - } - - AdjustMutToConstPointer => { - match self.sty { - ty::TyRawPtr(mt) => tcx.mk_ptr(ty::TypeAndMut { - ty: mt.ty, - mutbl: hir::MutImmutable - }), - ref b => { - bug!("AdjustMutToConstPointer on non-raw-ptr: {:?}", - b); - } - } - } - - AdjustDerefRef(ref adj) => { - let mut adjusted_ty = self; - - if !adjusted_ty.references_error() { - for i in 0..adj.autoderefs { - adjusted_ty = - adjusted_ty.adjust_for_autoderef(tcx, - expr_id, - span, - i as u32, - &mut method_type); - } - } - - if let Some(target) = adj.unsize { - target - } else { - adjusted_ty.adjust_for_autoref(tcx, adj.autoref) - } - } - } - } - None => self - }; - } - pub fn adjust_for_autoderef(&'tcx self, tcx: TyCtxt<'a, 'gcx, 'tcx>, expr_id: ast::NodeId, @@ -247,14 +172,14 @@ impl<'a, 'gcx, 'tcx> ty::TyS<'tcx> { } pub fn adjust_for_autoref(&'tcx self, tcx: TyCtxt<'a, 'gcx, 'tcx>, - autoref: Option>) + autoref: Option>) -> Ty<'tcx> { match autoref { None => self, - Some(AutoPtr(r, m)) => { + Some(AutoBorrow::Ref(r, m)) => { tcx.mk_ref(r, TypeAndMut { ty: self, mutbl: m }) } - Some(AutoUnsafe(m)) => { + Some(AutoBorrow::RawPtr(m)) => { tcx.mk_ptr(TypeAndMut { ty: self, mutbl: m }) } } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 62cc78141db46..7e5e10435d516 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -41,7 +41,7 @@ use rustc_data_structures::accumulate_vec::AccumulateVec; use arena::TypedArena; use std::borrow::Borrow; -use std::cell::{Cell, RefCell, Ref}; +use std::cell::{Cell, RefCell}; use std::hash::{Hash, Hasher}; use std::mem; use std::ops::Deref; @@ -212,7 +212,7 @@ pub struct Tables<'tcx> { /// other items. pub item_substs: NodeMap>, - pub adjustments: NodeMap>, + pub adjustments: NodeMap>, pub method_map: ty::MethodMap<'tcx>, @@ -255,6 +255,76 @@ impl<'a, 'gcx, 'tcx> Tables<'tcx> { fru_field_types: NodeMap() } } + + pub fn node_id_to_type(&self, id: NodeId) -> Ty<'tcx> { + match self.node_id_to_type_opt(id) { + Some(ty) => ty, + None => { + bug!("node_id_to_type: no type for node `{}`", + tls::with(|tcx| tcx.map.node_to_string(id))) + } + } + } + + pub fn node_id_to_type_opt(&self, id: NodeId) -> Option> { + self.node_types.get(&id).cloned() + } + + pub fn node_id_item_substs(&self, id: NodeId) -> Option<&'tcx Substs<'tcx>> { + self.item_substs.get(&id).map(|ts| ts.substs) + } + + // Returns the type of a pattern as a monotype. Like @expr_ty, this function + // doesn't provide type parameter substitutions. + pub fn pat_ty(&self, pat: &hir::Pat) -> Ty<'tcx> { + self.node_id_to_type(pat.id) + } + + pub fn pat_ty_opt(&self, pat: &hir::Pat) -> Option> { + self.node_id_to_type_opt(pat.id) + } + + // Returns the type of an expression as a monotype. + // + // NB (1): This is the PRE-ADJUSTMENT TYPE for the expression. That is, in + // some cases, we insert `Adjustment` annotations such as auto-deref or + // auto-ref. The type returned by this function does not consider such + // adjustments. See `expr_ty_adjusted()` instead. + // + // NB (2): This type doesn't provide type parameter substitutions; e.g. if you + // ask for the type of "id" in "id(3)", it will return "fn(&isize) -> isize" + // instead of "fn(ty) -> T with T = isize". + pub fn expr_ty(&self, expr: &hir::Expr) -> Ty<'tcx> { + self.node_id_to_type(expr.id) + } + + pub fn expr_ty_opt(&self, expr: &hir::Expr) -> Option> { + self.node_id_to_type_opt(expr.id) + } + + /// Returns the type of `expr`, considering any `Adjustment` + /// entry recorded for that expression. + pub fn expr_ty_adjusted(&self, expr: &hir::Expr) -> Ty<'tcx> { + self.adjustments.get(&expr.id) + .map_or_else(|| self.expr_ty(expr), |adj| adj.target) + } + + pub fn expr_ty_adjusted_opt(&self, expr: &hir::Expr) -> Option> { + self.adjustments.get(&expr.id) + .map(|adj| adj.target).or_else(|| self.expr_ty_opt(expr)) + } + + pub fn is_method_call(&self, expr_id: NodeId) -> bool { + self.method_map.contains_key(&ty::MethodCall::expr(expr_id)) + } + + pub fn is_overloaded_autoderef(&self, expr_id: NodeId, autoderefs: u32) -> bool { + self.method_map.contains_key(&ty::MethodCall::autoderef(expr_id, autoderefs)) + } + + pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option> { + Some(self.upvar_capture_map.get(&upvar_id).unwrap().clone()) + } } impl<'tcx> CommonTypes<'tcx> { @@ -599,14 +669,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.ty_param_defs.borrow().get(&node_id).unwrap().clone() } - pub fn node_types(self) -> Ref<'a, NodeMap>> { - fn projection<'a, 'tcx>(tables: &'a Tables<'tcx>) -> &'a NodeMap> { - &tables.node_types - } - - Ref::map(self.tables.borrow(), projection) - } - pub fn node_type_insert(self, id: NodeId, ty: Ty<'gcx>) { self.tables.borrow_mut().node_types.insert(id, ty); } diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index ae0a4a0e6bd11..b79ebdb14f552 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -176,8 +176,8 @@ pub trait TypeFolder<'gcx: 'tcx, 'tcx> : Sized { r.super_fold_with(self) } - fn fold_autoref(&mut self, ar: &adjustment::AutoRef<'tcx>) - -> adjustment::AutoRef<'tcx> { + fn fold_autoref(&mut self, ar: &adjustment::AutoBorrow<'tcx>) + -> adjustment::AutoBorrow<'tcx> { ar.super_fold_with(self) } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 588857e557c22..2c15f08e89822 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2120,80 +2120,8 @@ impl BorrowKind { } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { - pub fn node_id_to_type(self, id: NodeId) -> Ty<'gcx> { - match self.node_id_to_type_opt(id) { - Some(ty) => ty, - None => bug!("node_id_to_type: no type for node `{}`", - self.map.node_to_string(id)) - } - } - - pub fn node_id_to_type_opt(self, id: NodeId) -> Option> { - self.tables.borrow().node_types.get(&id).cloned() - } - - pub fn node_id_item_substs(self, id: NodeId) -> ItemSubsts<'gcx> { - match self.tables.borrow().item_substs.get(&id) { - None => ItemSubsts { - substs: self.global_tcx().intern_substs(&[]) - }, - Some(ts) => ts.clone(), - } - } - - // Returns the type of a pattern as a monotype. Like @expr_ty, this function - // doesn't provide type parameter substitutions. - pub fn pat_ty(self, pat: &hir::Pat) -> Ty<'gcx> { - self.node_id_to_type(pat.id) - } - pub fn pat_ty_opt(self, pat: &hir::Pat) -> Option> { - self.node_id_to_type_opt(pat.id) - } - - // Returns the type of an expression as a monotype. - // - // NB (1): This is the PRE-ADJUSTMENT TYPE for the expression. That is, in - // some cases, we insert `AutoAdjustment` annotations such as auto-deref or - // auto-ref. The type returned by this function does not consider such - // adjustments. See `expr_ty_adjusted()` instead. - // - // NB (2): This type doesn't provide type parameter substitutions; e.g. if you - // ask for the type of "id" in "id(3)", it will return "fn(&isize) -> isize" - // instead of "fn(ty) -> T with T = isize". - pub fn expr_ty(self, expr: &hir::Expr) -> Ty<'gcx> { - self.node_id_to_type(expr.id) - } - - pub fn expr_ty_opt(self, expr: &hir::Expr) -> Option> { - self.node_id_to_type_opt(expr.id) - } - - /// Returns the type of `expr`, considering any `AutoAdjustment` - /// entry recorded for that expression. - /// - /// It would almost certainly be better to store the adjusted ty in with - /// the `AutoAdjustment`, but I opted not to do this because it would - /// require serializing and deserializing the type and, although that's not - /// hard to do, I just hate that code so much I didn't want to touch it - /// unless it was to fix it properly, which seemed a distraction from the - /// thread at hand! -nmatsakis - pub fn expr_ty_adjusted(self, expr: &hir::Expr) -> Ty<'gcx> { - self.expr_ty(expr) - .adjust(self.global_tcx(), expr.span, expr.id, - self.tables.borrow().adjustments.get(&expr.id), - |method_call| { - self.tables.borrow().method_map.get(&method_call).map(|method| method.ty) - }) - } - - pub fn expr_ty_adjusted_opt(self, expr: &hir::Expr) -> Option> { - self.expr_ty_opt(expr).map(|t| t.adjust(self.global_tcx(), - expr.span, - expr.id, - self.tables.borrow().adjustments.get(&expr.id), - |method_call| { - self.tables.borrow().method_map.get(&method_call).map(|method| method.ty) - })) + pub fn tables(self) -> Ref<'a, Tables<'gcx>> { + self.tables.borrow() } pub fn expr_span(self, id: NodeId) -> Span { @@ -2908,19 +2836,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.mk_region(ty::ReScope(self.region_maps.node_extent(id))) } - pub fn is_method_call(self, expr_id: NodeId) -> bool { - self.tables.borrow().method_map.contains_key(&MethodCall::expr(expr_id)) - } - - pub fn is_overloaded_autoderef(self, expr_id: NodeId, autoderefs: u32) -> bool { - self.tables.borrow().method_map.contains_key(&MethodCall::autoderef(expr_id, - autoderefs)) - } - - pub fn upvar_capture(self, upvar_id: ty::UpvarId) -> Option> { - Some(self.tables.borrow().upvar_capture_map.get(&upvar_id).unwrap().clone()) - } - pub fn visit_all_items_in_krate(self, dep_node_fn: F, visitor: &mut V) diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 3165edebf1a46..9ca911837b517 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -218,15 +218,15 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ItemSubsts<'a> { } } -impl<'a, 'tcx> Lift<'tcx> for ty::adjustment::AutoRef<'a> { - type Lifted = ty::adjustment::AutoRef<'tcx>; +impl<'a, 'tcx> Lift<'tcx> for ty::adjustment::AutoBorrow<'a> { + type Lifted = ty::adjustment::AutoBorrow<'tcx>; fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { match *self { - ty::adjustment::AutoPtr(r, m) => { - tcx.lift(&r).map(|r| ty::adjustment::AutoPtr(r, m)) + ty::adjustment::AutoBorrow::Ref(r, m) => { + tcx.lift(&r).map(|r| ty::adjustment::AutoBorrow::Ref(r, m)) } - ty::adjustment::AutoUnsafe(m) => { - Some(ty::adjustment::AutoUnsafe(m)) + ty::adjustment::AutoBorrow::RawPtr(m) => { + Some(ty::adjustment::AutoBorrow::RawPtr(m)) } } } @@ -676,13 +676,13 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ItemSubsts<'tcx> { } } -impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::AutoRef<'tcx> { +impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::AutoBorrow<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { match *self { - ty::adjustment::AutoPtr(ref r, m) => { - ty::adjustment::AutoPtr(r.fold_with(folder), m) + ty::adjustment::AutoBorrow::Ref(ref r, m) => { + ty::adjustment::AutoBorrow::Ref(r.fold_with(folder), m) } - ty::adjustment::AutoUnsafe(m) => ty::adjustment::AutoUnsafe(m) + ty::adjustment::AutoBorrow::RawPtr(m) => ty::adjustment::AutoBorrow::RawPtr(m) } } @@ -692,8 +692,8 @@ impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::AutoRef<'tcx> { fn super_visit_with>(&self, visitor: &mut V) -> bool { match *self { - ty::adjustment::AutoPtr(r, _m) => r.visit_with(visitor), - ty::adjustment::AutoUnsafe(_m) => false, + ty::adjustment::AutoBorrow::Ref(r, _m) => r.visit_with(visitor), + ty::adjustment::AutoBorrow::RawPtr(_m) => false, } } } diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index 78f20b77f3185..7cd5fd78df528 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -75,6 +75,26 @@ pub fn duration_to_secs_str(dur: Duration) -> String { format!("{:.3}", secs) } +pub fn to_readable_str(mut val: usize) -> String { + let mut groups = vec![]; + loop { + let group = val % 1000; + + val /= 1000; + + if val == 0 { + groups.push(format!("{}", group)); + break + } else { + groups.push(format!("{:03}", group)); + } + } + + groups.reverse(); + + groups.join("_") +} + pub fn record_time(accu: &Cell, f: F) -> T where F: FnOnce() -> T, { @@ -264,3 +284,17 @@ pub fn path2cstr(p: &Path) -> CString { pub fn path2cstr(p: &Path) -> CString { CString::new(p.to_str().unwrap()).unwrap() } + + +#[test] +fn test_to_readable_str() { + assert_eq!("0", to_readable_str(0)); + assert_eq!("1", to_readable_str(1)); + assert_eq!("99", to_readable_str(99)); + assert_eq!("999", to_readable_str(999)); + assert_eq!("1_000", to_readable_str(1_000)); + assert_eq!("1_001", to_readable_str(1_001)); + assert_eq!("999_999", to_readable_str(999_999)); + assert_eq!("1_000_000", to_readable_str(1_000_000)); + assert_eq!("1_234_567", to_readable_str(1_234_567)); +} diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 954e3b1fc13ce..31304fb7b4993 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -447,32 +447,9 @@ impl<'tcx, 'container> fmt::Debug for ty::AdtDefData<'tcx, 'container> { } } -impl<'tcx> fmt::Debug for ty::adjustment::AutoAdjustment<'tcx> { +impl<'tcx> fmt::Debug for ty::adjustment::Adjustment<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - ty::adjustment::AdjustNeverToAny(ref target) => { - write!(f, "AdjustNeverToAny({:?})", target) - } - ty::adjustment::AdjustReifyFnPointer => { - write!(f, "AdjustReifyFnPointer") - } - ty::adjustment::AdjustUnsafeFnPointer => { - write!(f, "AdjustUnsafeFnPointer") - } - ty::adjustment::AdjustMutToConstPointer => { - write!(f, "AdjustMutToConstPointer") - } - ty::adjustment::AdjustDerefRef(ref data) => { - write!(f, "{:?}", data) - } - } - } -} - -impl<'tcx> fmt::Debug for ty::adjustment::AutoDerefRef<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "AutoDerefRef({}, unsize={:?}, {:?})", - self.autoderefs, self.unsize, self.autoref) + write!(f, "{:?} -> {}", self.kind, self.target) } } diff --git a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs index 9bdc6887f6d03..51574868f9bfb 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs @@ -37,7 +37,7 @@ pub fn gather_decl<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, decl_id: ast::NodeId, _decl_span: Span, var_id: ast::NodeId) { - let ty = bccx.tcx.node_id_to_type(var_id); + let ty = bccx.tcx.tables().node_id_to_type(var_id); let loan_path = Rc::new(LoanPath::new(LpVar(var_id), ty)); move_data.add_move(bccx.tcx, loan_path, decl_id, Declared); } diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index 9aa1ac62f5523..615aca90db8bf 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -201,7 +201,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { // Finally, check if the whole match expression is exhaustive. // Check for empty enum, because is_useful only works on inhabited types. - let pat_ty = self.tcx.node_id_to_type(scrut.id); + let pat_ty = self.tcx.tables().node_id_to_type(scrut.id); if inlined_arms.is_empty() { if !pat_ty.is_uninhabited(self.tcx) { // We know the type is inhabited, so this must be wrong @@ -262,7 +262,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { fn check_for_bindings_named_the_same_as_variants(cx: &MatchVisitor, pat: &Pat) { pat.walk(|p| { if let PatKind::Binding(hir::BindByValue(hir::MutImmutable), name, None) = p.node { - let pat_ty = cx.tcx.pat_ty(p); + let pat_ty = cx.tcx.tables().pat_ty(p); if let ty::TyAdt(edef, _) = pat_ty.sty { if edef.is_enum() { if let Def::Local(..) = cx.tcx.expect_def(p.id) { @@ -486,7 +486,7 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor, for pat in pats { pat.walk(|p| { if let PatKind::Binding(hir::BindByValue(..), _, ref sub) = p.node { - let pat_ty = cx.tcx.node_id_to_type(p.id); + let pat_ty = cx.tcx.tables().node_id_to_type(p.id); if pat_ty.moves_by_default(cx.tcx, cx.param_env, pat.span) { check_move(p, sub.as_ref().map(|p| &**p)); } diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index c02cca0da7225..57a5400ecadf8 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -27,7 +27,7 @@ use rustc::ty::util::IntTypeExt; use rustc::ty::subst::Substs; use rustc::traits::Reveal; use rustc::util::common::ErrorReported; -use rustc::util::nodemap::NodeMap; +use rustc::util::nodemap::DefIdMap; use rustc::lint; use graphviz::IntoCow; @@ -246,7 +246,7 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pat_id: ast::NodeId, span: Span) -> Result, DefId> { - let pat_ty = tcx.expr_ty(expr); + let pat_ty = tcx.tables().expr_ty(expr); debug!("expr={:?} pat_ty={:?} pat_id={}", expr, pat_ty, pat_id); match pat_ty.sty { ty::TyFloat(_) => { @@ -314,7 +314,7 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }, })) .collect::>()?; - PatKind::Struct(path.clone(), field_pats, false) + PatKind::Struct((**path).clone(), field_pats, false) } hir::ExprArray(ref exprs) => { @@ -329,7 +329,8 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, Def::StructCtor(_, CtorKind::Const) | Def::VariantCtor(_, CtorKind::Const) => PatKind::Path(None, path.clone()), Def::Const(def_id) | Def::AssociatedConst(def_id) => { - let substs = Some(tcx.node_id_item_substs(expr.id).substs); + let substs = Some(tcx.tables().node_id_item_substs(expr.id) + .unwrap_or_else(|| tcx.intern_substs(&[]))); let (expr, _ty) = lookup_const_by_id(tcx, def_id, substs).unwrap(); return const_expr_to_pat(tcx, expr, pat_id, span); }, @@ -413,7 +414,7 @@ pub fn eval_const_expr_checked<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, eval_const_expr_partial(tcx, e, ExprTypeChecked, None) } -pub type FnArgMap<'a> = Option<&'a NodeMap>; +pub type FnArgMap<'a> = Option<&'a DefIdMap>; #[derive(Clone, Debug)] pub struct ConstEvalErr { @@ -606,7 +607,7 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let ety = match ty_hint { ExprTypeChecked => { // After type-checking, expr_ty is guaranteed to succeed. - Some(tcx.expr_ty(e)) + Some(tcx.tables().expr_ty(e)) } UncheckedExprHint(ty) => { // Use the type hint; it's not guaranteed to be right, but it's @@ -617,7 +618,7 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // This expression might not be type-checked, and we have no hint. // Try to query the context for a type anyway; we might get lucky // (for example, if the expression was imported from another crate). - tcx.expr_ty_opt(e) + tcx.tables().expr_ty_opt(e) } }; let result = match e.node { @@ -759,7 +760,7 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let base_hint = if let ExprTypeChecked = ty_hint { ExprTypeChecked } else { - match tcx.expr_ty_opt(&base) { + match tcx.tables().expr_ty_opt(&base) { Some(t) => UncheckedExprHint(t), None => ty_hint } @@ -798,7 +799,8 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, Def::Const(def_id) | Def::AssociatedConst(def_id) => { let substs = if let ExprTypeChecked = ty_hint { - Some(tcx.node_id_item_substs(e.id).substs) + Some(tcx.tables().node_id_item_substs(e.id) + .unwrap_or_else(|| tcx.intern_substs(&[]))) } else { None }; @@ -835,9 +837,8 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ConstVal::Struct(e.id) } Def::Local(def_id) => { - let id = tcx.map.as_local_node_id(def_id).unwrap(); - debug!("Def::Local({:?}): {:?}", id, fn_args); - if let Some(val) = fn_args.and_then(|args| args.get(&id)) { + debug!("Def::Local({:?}): {:?}", def_id, fn_args); + if let Some(val) = fn_args.and_then(|args| args.get(&def_id)) { val.clone() } else { signal!(e, NonConstPath); @@ -863,7 +864,7 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let result = result.as_ref().expect("const fn has no result expression"); assert_eq!(decl.inputs.len(), args.len()); - let mut call_args = NodeMap(); + let mut call_args = DefIdMap(); for (arg, arg_expr) in decl.inputs.iter().zip(args.iter()) { let arg_hint = ty_hint.erase_hint(); let arg_val = eval_const_expr_partial( @@ -873,7 +874,7 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn_args )?; debug!("const call arg: {:?}", arg); - let old = call_args.insert(arg.pat.id, arg_val); + let old = call_args.insert(tcx.expect_def(arg.pat.id).def_id(), arg_val); assert!(old.is_none()); } debug!("const call({:?})", call_args); diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs index 946a397474765..10b2a7625cacf 100644 --- a/src/librustc_const_eval/pattern.rs +++ b/src/librustc_const_eval/pattern.rs @@ -128,7 +128,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { } pub fn lower_pattern(&mut self, pat: &hir::Pat) -> Pattern<'tcx> { - let mut ty = self.tcx.node_id_to_type(pat.id); + let mut ty = self.tcx.tables().node_id_to_type(pat.id); let kind = match pat.node { PatKind::Wild => PatternKind::Wild, @@ -167,8 +167,9 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { match self.tcx.expect_def(pat.id) { Def::Const(def_id) | Def::AssociatedConst(def_id) => { let tcx = self.tcx.global_tcx(); - let substs = Some(self.tcx.node_id_item_substs(pat.id).substs); - match eval::lookup_const_by_id(tcx, def_id, substs) { + let substs = tcx.tables().node_id_item_substs(pat.id) + .unwrap_or_else(|| tcx.intern_substs(&[])); + match eval::lookup_const_by_id(tcx, def_id, Some(substs)) { Some((const_expr, _const_ty)) => { match eval::const_expr_to_pat( tcx, const_expr, pat.id, pat.span) @@ -197,7 +198,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { } PatKind::Slice(ref prefix, ref slice, ref suffix) => { - let ty = self.tcx.node_id_to_type(pat.id); + let ty = self.tcx.tables().node_id_to_type(pat.id); match ty.sty { ty::TyRef(_, mt) => PatternKind::Deref { @@ -222,7 +223,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { } PatKind::Tuple(ref subpatterns, ddpos) => { - match self.tcx.node_id_to_type(pat.id).sty { + match self.tcx.tables().node_id_to_type(pat.id).sty { ty::TyTuple(ref tys) => { let subpatterns = subpatterns.iter() @@ -243,7 +244,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { PatKind::Binding(bm, ref ident, ref sub) => { let def_id = self.tcx.expect_def(pat.id).def_id(); let id = self.tcx.map.as_local_node_id(def_id).unwrap(); - let var_ty = self.tcx.node_id_to_type(pat.id); + let var_ty = self.tcx.tables().node_id_to_type(pat.id); let region = match var_ty.sty { ty::TyRef(r, _) => Some(r), _ => None, @@ -280,7 +281,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { } PatKind::TupleStruct(_, ref subpatterns, ddpos) => { - let pat_ty = self.tcx.node_id_to_type(pat.id); + let pat_ty = self.tcx.tables().node_id_to_type(pat.id); let adt_def = match pat_ty.sty { ty::TyAdt(adt_def, _) => adt_def, _ => span_bug!(pat.span, "tuple struct pattern not applied to an ADT"), @@ -299,7 +300,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> { } PatKind::Struct(_, ref fields, _) => { - let pat_ty = self.tcx.node_id_to_type(pat.id); + let pat_ty = self.tcx.tables().node_id_to_type(pat.id); let adt_def = match pat_ty.sty { ty::TyAdt(adt_def, _) => adt_def, _ => { diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index e33428a3e963b..d83918495676c 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -37,7 +37,8 @@ use rustc_typeck as typeck; use rustc_privacy; use rustc_plugin::registry::Registry; use rustc_plugin as plugin; -use rustc_passes::{ast_validation, no_asm, loops, consts, rvalues, static_recursion}; +use rustc_passes::{ast_validation, no_asm, loops, consts, rvalues, + static_recursion, hir_stats}; use rustc_const_eval::check_match; use super::Compilation; @@ -513,6 +514,10 @@ pub fn phase_1_parse_input<'a>(sess: &'a Session, input: &Input) -> PResult<'a, syntax::show_span::run(sess.diagnostic(), s, &krate); } + if sess.opts.debugging_opts.hir_stats { + hir_stats::print_ast_stats(&krate, "PRE EXPANSION AST STATS"); + } + Ok(krate) } @@ -718,6 +723,10 @@ pub fn phase_2_configure_and_expand<'a, F>(sess: &Session, println!("Post-expansion node count: {}", count_nodes(&krate)); } + if sess.opts.debugging_opts.hir_stats { + hir_stats::print_ast_stats(&krate, "POST EXPANSION AST STATS"); + } + if sess.opts.debugging_opts.ast_json { println!("{}", json::as_json(&krate)); } @@ -758,7 +767,13 @@ pub fn phase_2_configure_and_expand<'a, F>(sess: &Session, // Lower ast -> hir. let hir_forest = time(sess.time_passes(), "lowering ast -> hir", || { - hir_map::Forest::new(lower_crate(sess, &krate, &mut resolver), &sess.dep_graph) + let hir_crate = lower_crate(sess, &krate, &mut resolver); + + if sess.opts.debugging_opts.hir_stats { + hir_stats::print_hir_stats(&hir_crate); + } + + hir_map::Forest::new(hir_crate, &sess.dep_graph) }); // Discard hygiene data, which isn't required past lowering to HIR. diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 289a7348cc8dd..b4ab9da92e9d0 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -501,7 +501,7 @@ impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> { pp::space(&mut s.s)?; pp::word(&mut s.s, "as")?; pp::space(&mut s.s)?; - pp::word(&mut s.s, &self.tcx.expr_ty(expr).to_string())?; + pp::word(&mut s.s, &self.tcx.tables().expr_ty(expr).to_string())?; s.pclose() } _ => Ok(()), diff --git a/src/librustc_errors/Cargo.toml b/src/librustc_errors/Cargo.toml index 128c270eb359c..c92e4d8f5aba5 100644 --- a/src/librustc_errors/Cargo.toml +++ b/src/librustc_errors/Cargo.toml @@ -11,4 +11,4 @@ crate-type = ["dylib"] [dependencies] log = { path = "../liblog" } serialize = { path = "../libserialize" } -syntax_pos = { path = "../libsyntax_pos" } \ No newline at end of file +syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_incremental/calculate_svh/hasher.rs b/src/librustc_incremental/calculate_svh/hasher.rs index 49683a81227b1..d7d9c231a91f4 100644 --- a/src/librustc_incremental/calculate_svh/hasher.rs +++ b/src/librustc_incremental/calculate_svh/hasher.rs @@ -9,13 +9,16 @@ // except according to those terms. use std::mem; +use std::hash::Hasher; use rustc_data_structures::blake2b::Blake2bHasher; use rustc::ty::util::ArchIndependentHasher; use ich::Fingerprint; +use rustc_serialize::leb128::write_unsigned_leb128; #[derive(Debug)] pub struct IchHasher { state: ArchIndependentHasher, + leb128_helper: Vec, bytes_hashed: u64, } @@ -24,6 +27,7 @@ impl IchHasher { let hash_size = mem::size_of::(); IchHasher { state: ArchIndependentHasher::new(Blake2bHasher::new(hash_size, &[])), + leb128_helper: vec![], bytes_hashed: 0 } } @@ -37,9 +41,19 @@ impl IchHasher { fingerprint.0.copy_from_slice(self.state.into_inner().finalize()); fingerprint } + + #[inline] + fn write_uleb128(&mut self, value: u64) { + let len = write_unsigned_leb128(&mut self.leb128_helper, 0, value); + self.state.write(&self.leb128_helper[0..len]); + self.bytes_hashed += len as u64; + } } -impl ::std::hash::Hasher for IchHasher { +// For the non-u8 integer cases we leb128 encode them first. Because small +// integers dominate, this significantly and cheaply reduces the number of +// bytes hashed, which is good because blake2b is expensive. +impl Hasher for IchHasher { fn finish(&self) -> u64 { bug!("Use other finish() implementation to get the full 128-bit hash."); } @@ -49,4 +63,26 @@ impl ::std::hash::Hasher for IchHasher { self.state.write(bytes); self.bytes_hashed += bytes.len() as u64; } + + // There is no need to leb128-encode u8 values. + + #[inline] + fn write_u16(&mut self, i: u16) { + self.write_uleb128(i as u64); + } + + #[inline] + fn write_u32(&mut self, i: u32) { + self.write_uleb128(i as u64); + } + + #[inline] + fn write_u64(&mut self, i: u64) { + self.write_uleb128(i); + } + + #[inline] + fn write_usize(&mut self, i: usize) { + self.write_uleb128(i as u64); + } } diff --git a/src/librustc_incremental/calculate_svh/svh_visitor.rs b/src/librustc_incremental/calculate_svh/svh_visitor.rs index 80c41f855ba5c..2358d60d0de21 100644 --- a/src/librustc_incremental/calculate_svh/svh_visitor.rs +++ b/src/librustc_incremental/calculate_svh/svh_visitor.rs @@ -88,6 +88,8 @@ impl<'a, 'hash, 'tcx> StrictVersionHashVisitor<'a, 'hash, 'tcx> { // within the CodeMap. // Also note that we are hashing byte offsets for the column, not unicode // codepoint offsets. For the purpose of the hash that's sufficient. + // Also, hashing filenames is expensive so we avoid doing it twice when the + // span starts and ends in the same file, which is almost always the case. fn hash_span(&mut self, span: Span) { debug!("hash_span: st={:?}", self.st); @@ -103,21 +105,35 @@ impl<'a, 'hash, 'tcx> StrictVersionHashVisitor<'a, 'hash, 'tcx> { span.hi }; - let loc1 = self.codemap.byte_pos_to_line_and_col(span.lo); - let loc2 = self.codemap.byte_pos_to_line_and_col(span_hi); - - let expansion_kind = match span.expn_id { + let expn_kind = match span.expn_id { NO_EXPANSION => SawSpanExpnKind::NoExpansion, COMMAND_LINE_EXPN => SawSpanExpnKind::CommandLine, _ => SawSpanExpnKind::SomeExpansion, }; - SawSpan(loc1.as_ref().map(|&(ref fm, line, col)| (&fm.name[..], line, col)), - loc2.as_ref().map(|&(ref fm, line, col)| (&fm.name[..], line, col)), - expansion_kind) - .hash(self.st); + let loc1 = self.codemap.byte_pos_to_line_and_col(span.lo); + let loc1 = loc1.as_ref() + .map(|&(ref fm, line, col)| (&fm.name[..], line, col)) + .unwrap_or(("???", 0, BytePos(0))); + + let loc2 = self.codemap.byte_pos_to_line_and_col(span_hi); + let loc2 = loc2.as_ref() + .map(|&(ref fm, line, col)| (&fm.name[..], line, col)) + .unwrap_or(("???", 0, BytePos(0))); + + let saw = if loc1.0 == loc2.0 { + SawSpan(loc1.0, + loc1.1, loc1.2, + loc2.1, loc2.2, + expn_kind) + } else { + SawSpanTwoFiles(loc1.0, loc1.1, loc1.2, + loc2.0, loc2.1, loc2.2, + expn_kind) + }; + saw.hash(self.st); - if expansion_kind == SawSpanExpnKind::SomeExpansion { + if expn_kind == SawSpanExpnKind::SomeExpansion { let call_site = self.codemap.codemap().source_callsite(span); self.hash_span(call_site); } @@ -189,9 +205,13 @@ enum SawAbiComponent<'a> { SawAssocTypeBinding, SawAttribute(ast::AttrStyle), SawMacroDef, - SawSpan(Option<(&'a str, usize, BytePos)>, - Option<(&'a str, usize, BytePos)>, + SawSpan(&'a str, + usize, BytePos, + usize, BytePos, SawSpanExpnKind), + SawSpanTwoFiles(&'a str, usize, BytePos, + &'a str, usize, BytePos, + SawSpanExpnKind), } /// SawExprComponent carries all of the information that we want diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index a28109c147191..28dc71fd59bae 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -34,7 +34,6 @@ use middle::stability; use rustc::cfg; use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt}; -use rustc::ty::adjustment; use rustc::traits::{self, Reveal}; use rustc::hir::map as hir_map; use util::nodemap::NodeSet; @@ -118,7 +117,9 @@ impl LateLintPass for BoxPointers { hir::ItemTy(..) | hir::ItemEnum(..) | hir::ItemStruct(..) | - hir::ItemUnion(..) => self.check_heap_type(cx, it.span, cx.tcx.node_id_to_type(it.id)), + hir::ItemUnion(..) => { + self.check_heap_type(cx, it.span, cx.tcx.tables().node_id_to_type(it.id)) + } _ => (), } @@ -129,7 +130,7 @@ impl LateLintPass for BoxPointers { for struct_field in struct_def.fields() { self.check_heap_type(cx, struct_field.span, - cx.tcx.node_id_to_type(struct_field.id)); + cx.tcx.tables().node_id_to_type(struct_field.id)); } } _ => (), @@ -137,7 +138,7 @@ impl LateLintPass for BoxPointers { } fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) { - let ty = cx.tcx.node_id_to_type(e.id); + let ty = cx.tcx.tables().node_id_to_type(e.id); self.check_heap_type(cx, e.span, ty); } } @@ -585,7 +586,7 @@ impl LateLintPass for MissingDebugImplementations { let mut impls = NodeSet(); debug_def.for_each_impl(cx.tcx, |d| { if let Some(n) = cx.tcx.map.as_local_node_id(d) { - if let Some(ty_def) = cx.tcx.node_id_to_type(n).ty_to_def_id() { + if let Some(ty_def) = cx.tcx.tables().node_id_to_type(n).ty_to_def_id() { if let Some(node_id) = cx.tcx.map.as_local_node_id(ty_def) { impls.insert(node_id); } @@ -939,8 +940,10 @@ impl LateLintPass for UnconditionalRecursion { method: &ty::Method, id: ast::NodeId) -> bool { + use rustc::ty::adjustment::*; + // Check for method calls and overloaded operators. - let opt_m = tcx.tables.borrow().method_map.get(&ty::MethodCall::expr(id)).cloned(); + let opt_m = tcx.tables().method_map.get(&ty::MethodCall::expr(id)).cloned(); if let Some(m) = opt_m { if method_call_refers_to_method(tcx, method, m.def_id, m.substs, id) { return true; @@ -948,15 +951,12 @@ impl LateLintPass for UnconditionalRecursion { } // Check for overloaded autoderef method calls. - let opt_adj = tcx.tables.borrow().adjustments.get(&id).cloned(); - if let Some(adjustment::AdjustDerefRef(adj)) = opt_adj { - for i in 0..adj.autoderefs { + let opt_adj = tcx.tables().adjustments.get(&id).cloned(); + if let Some(Adjustment { kind: Adjust::DerefRef { autoderefs, .. }, .. }) = opt_adj { + for i in 0..autoderefs { let method_call = ty::MethodCall::autoderef(id, i as u32); - if let Some(m) = tcx.tables - .borrow() - .method_map - .get(&method_call) - .cloned() { + if let Some(m) = tcx.tables().method_map.get(&method_call) + .cloned() { if method_call_refers_to_method(tcx, method, m.def_id, m.substs, id) { return true; } @@ -971,12 +971,10 @@ impl LateLintPass for UnconditionalRecursion { // it doesn't necessarily have a definition. match tcx.expect_def_or_none(callee.id) { Some(Def::Method(def_id)) => { - let item_substs = tcx.node_id_item_substs(callee.id); - method_call_refers_to_method(tcx, - method, - def_id, - &item_substs.substs, - id) + let substs = tcx.tables().node_id_item_substs(callee.id) + .unwrap_or_else(|| tcx.intern_substs(&[])); + method_call_refers_to_method( + tcx, method, def_id, substs, id) } _ => false, } @@ -1213,7 +1211,7 @@ impl LateLintPass for MutableTransmutes { if !def_id_is_transmute(cx, did) { return None; } - let typ = cx.tcx.node_id_to_type(expr.id); + let typ = cx.tcx.tables().node_id_to_type(expr.id); match typ.sty { ty::TyFnDef(.., ref bare_fn) if bare_fn.abi == RustIntrinsic => { let from = bare_fn.sig.0.inputs[0]; @@ -1284,7 +1282,7 @@ impl LateLintPass for UnionsWithDropFields { if let hir::ItemUnion(ref vdata, _) = item.node { let param_env = &ty::ParameterEnvironment::for_item(ctx.tcx, item.id); for field in vdata.fields() { - let field_ty = ctx.tcx.node_id_to_type(field.id); + let field_ty = ctx.tcx.tables().node_id_to_type(field.id); if ctx.tcx.type_needs_drop_given_env(field_ty, param_env) { ctx.span_lint(UNIONS_WITH_DROP_FIELDS, field.span, diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 9464bf30b693f..b04759955a956 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -113,14 +113,14 @@ impl LateLintPass for TypeLimits { forbid_unsigned_negation(cx, e.span); } ast::LitKind::Int(_, ast::LitIntType::Unsuffixed) => { - if let ty::TyUint(_) = cx.tcx.node_id_to_type(e.id).sty { + if let ty::TyUint(_) = cx.tcx.tables().node_id_to_type(e.id).sty { forbid_unsigned_negation(cx, e.span); } } _ => (), } } else { - let t = cx.tcx.node_id_to_type(expr.id); + let t = cx.tcx.tables().node_id_to_type(expr.id); if let ty::TyUint(_) = t.sty { forbid_unsigned_negation(cx, e.span); } @@ -138,7 +138,7 @@ impl LateLintPass for TypeLimits { } if binop.node.is_shift() { - let opt_ty_bits = match cx.tcx.node_id_to_type(l.id).sty { + let opt_ty_bits = match cx.tcx.tables().node_id_to_type(l.id).sty { ty::TyInt(t) => Some(int_ty_bits(t, cx.sess().target.int_type)), ty::TyUint(t) => Some(uint_ty_bits(t, cx.sess().target.uint_type)), _ => None, @@ -171,7 +171,7 @@ impl LateLintPass for TypeLimits { } } hir::ExprLit(ref lit) => { - match cx.tcx.node_id_to_type(e.id).sty { + match cx.tcx.tables().node_id_to_type(e.id).sty { ty::TyInt(t) => { match lit.node { ast::LitKind::Int(v, ast::LitIntType::Signed(_)) | @@ -324,7 +324,7 @@ impl LateLintPass for TypeLimits { // Normalize the binop so that the literal is always on the RHS in // the comparison let norm_binop = if swap { rev_binop(binop) } else { binop }; - match tcx.node_id_to_type(expr.id).sty { + match tcx.tables().node_id_to_type(expr.id).sty { ty::TyInt(int_ty) => { let (min, max) = int_ty_range(int_ty); let lit_val: i64 = match lit.node { @@ -740,7 +740,7 @@ impl LateLintPass for VariantSizeDifferences { if let hir::ItemEnum(ref enum_definition, ref gens) = it.node { if gens.ty_params.is_empty() { // sizes only make sense for non-generic types - let t = cx.tcx.node_id_to_type(it.id); + let t = cx.tcx.tables().node_id_to_type(it.id); let layout = cx.tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| { let ty = cx.tcx.erase_regions(&t); ty.layout(&infcx) diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index a29ff18ab5318..15430a5c9f99d 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -140,7 +140,7 @@ impl LateLintPass for UnusedResults { return; } - let t = cx.tcx.expr_ty(&expr); + let t = cx.tcx.tables().expr_ty(&expr); let warned = match t.sty { ty::TyTuple(ref tys) if tys.is_empty() => return, ty::TyNever => return, @@ -441,16 +441,15 @@ impl LateLintPass for UnusedAllocation { _ => return, } - if let Some(adjustment) = cx.tcx.tables.borrow().adjustments.get(&e.id) { - if let adjustment::AdjustDerefRef(adjustment::AutoDerefRef { ref autoref, .. }) = - *adjustment { + if let Some(adjustment) = cx.tcx.tables().adjustments.get(&e.id) { + if let adjustment::Adjust::DerefRef { autoref, .. } = adjustment.kind { match autoref { - &Some(adjustment::AutoPtr(_, hir::MutImmutable)) => { + Some(adjustment::AutoBorrow::Ref(_, hir::MutImmutable)) => { cx.span_lint(UNUSED_ALLOCATION, e.span, "unnecessary allocation, use & instead"); } - &Some(adjustment::AutoPtr(_, hir::MutMutable)) => { + Some(adjustment::AutoBorrow::Ref(_, hir::MutMutable)) => { cx.span_lint(UNUSED_ALLOCATION, e.span, "unnecessary allocation, use &mut instead"); diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index f001f85131978..e009955b92ee4 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -38,7 +38,7 @@ enum TableEntry<'tcx> { Def(Def), NodeType(Ty<'tcx>), ItemSubsts(ty::ItemSubsts<'tcx>), - Adjustment(ty::adjustment::AutoAdjustment<'tcx>), + Adjustment(ty::adjustment::Adjustment<'tcx>), ConstQualif(ConstQualif), } @@ -94,9 +94,9 @@ impl<'a, 'b, 'tcx, 'v> Visitor<'v> for SideTableEncodingIdVisitor<'a, 'b, 'tcx> }; encode(tcx.expect_def_or_none(id).map(TableEntry::Def)); - encode(tcx.node_types().get(&id).cloned().map(TableEntry::NodeType)); - encode(tcx.tables.borrow().item_substs.get(&id).cloned().map(TableEntry::ItemSubsts)); - encode(tcx.tables.borrow().adjustments.get(&id).cloned().map(TableEntry::Adjustment)); + encode(tcx.tables().node_types.get(&id).cloned().map(TableEntry::NodeType)); + encode(tcx.tables().item_substs.get(&id).cloned().map(TableEntry::ItemSubsts)); + encode(tcx.tables().adjustments.get(&id).cloned().map(TableEntry::Adjustment)); encode(tcx.const_qualif_map.borrow().get(&id).cloned().map(TableEntry::ConstQualif)); } } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index e8734e4275712..fdb117ef81b13 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1016,7 +1016,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let data = ClosureData { kind: tcx.closure_kind(def_id), - ty: self.lazy(&tcx.tables.borrow().closure_tys[&def_id]), + ty: self.lazy(&tcx.tables().closure_tys[&def_id]), }; Entry { diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index d6fcc79a9a213..b37dd8dd0a907 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -191,7 +191,7 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, assert_eq!(block, builder.return_block()); let mut spread_arg = None; - match tcx.node_id_to_type(fn_id).sty { + match tcx.tables().node_id_to_type(fn_id).sty { ty::TyFnDef(_, _, f) if f.abi == Abi::RustCall => { // RustCall pseudo-ABI untuples the last argument. spread_arg = Some(Local::new(arguments.len())); @@ -203,7 +203,7 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, let upvar_decls: Vec<_> = tcx.with_freevars(fn_id, |freevars| { freevars.iter().map(|fv| { let var_id = tcx.map.as_local_node_id(fv.def.def_id()).unwrap(); - let by_ref = tcx.upvar_capture(ty::UpvarId { + let by_ref = tcx.tables().upvar_capture(ty::UpvarId { var_id: var_id, closure_expr_id: fn_id }).map_or(false, |capture| match capture { @@ -233,7 +233,7 @@ pub fn construct_const<'a, 'gcx, 'tcx>(hir: Cx<'a, 'gcx, 'tcx>, ast_expr: &'tcx hir::Expr) -> (Mir<'tcx>, ScopeAuxiliaryVec) { let tcx = hir.tcx(); - let ty = tcx.expr_ty_adjusted(ast_expr); + let ty = tcx.tables().expr_ty_adjusted(ast_expr); let span = tcx.map.span(item_id); let mut builder = Builder::new(hir, span, 0, ty); diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir/hair/cx/block.rs index ec1136368c135..cb69de2cb3cac 100644 --- a/src/librustc_mir/hair/cx/block.rs +++ b/src/librustc_mir/hair/cx/block.rs @@ -77,7 +77,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, pub fn to_expr_ref<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, block: &'tcx hir::Block) -> ExprRef<'tcx> { - let block_ty = cx.tcx.node_id_to_type(block.id); + let block_ty = cx.tcx.tables().node_id_to_type(block.id); let temp_lifetime = cx.tcx.region_maps.temporary_scope(block.id); let expr = Expr { ty: block_ty, diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 1b324ac3132fc..ba0d3b49a6c1a 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -35,15 +35,15 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { debug!("Expr::make_mirror(): id={}, span={:?}", self.id, self.span); let mut expr = make_mirror_unadjusted(cx, self); + let adj = cx.tcx.tables().adjustments.get(&self.id).cloned(); debug!("make_mirror: unadjusted-expr={:?} applying adjustments={:?}", - expr, cx.tcx.tables.borrow().adjustments.get(&self.id)); + expr, adj); // Now apply adjustments, if any. - match cx.tcx.tables.borrow().adjustments.get(&self.id) { + match adj.map(|adj| (adj.kind, adj.target)) { None => {} - Some(&ty::adjustment::AdjustReifyFnPointer) => { - let adjusted_ty = cx.tcx.expr_ty_adjusted(self); + Some((ty::adjustment::Adjust::ReifyFnPointer, adjusted_ty)) => { expr = Expr { temp_lifetime: temp_lifetime, ty: adjusted_ty, @@ -51,8 +51,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { kind: ExprKind::ReifyFnPointer { source: expr.to_ref() }, }; } - Some(&ty::adjustment::AdjustUnsafeFnPointer) => { - let adjusted_ty = cx.tcx.expr_ty_adjusted(self); + Some((ty::adjustment::Adjust::UnsafeFnPointer, adjusted_ty)) => { expr = Expr { temp_lifetime: temp_lifetime, ty: adjusted_ty, @@ -60,7 +59,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { kind: ExprKind::UnsafeFnPointer { source: expr.to_ref() }, }; } - Some(&ty::adjustment::AdjustNeverToAny(adjusted_ty)) => { + Some((ty::adjustment::Adjust::NeverToAny, adjusted_ty)) => { expr = Expr { temp_lifetime: temp_lifetime, ty: adjusted_ty, @@ -68,8 +67,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { kind: ExprKind::NeverToAny { source: expr.to_ref() }, }; } - Some(&ty::adjustment::AdjustMutToConstPointer) => { - let adjusted_ty = cx.tcx.expr_ty_adjusted(self); + Some((ty::adjustment::Adjust::MutToConstPointer, adjusted_ty)) => { expr = Expr { temp_lifetime: temp_lifetime, ty: adjusted_ty, @@ -77,8 +75,9 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { kind: ExprKind::Cast { source: expr.to_ref() }, }; } - Some(&ty::adjustment::AdjustDerefRef(ref adj)) => { - for i in 0..adj.autoderefs { + Some((ty::adjustment::Adjust::DerefRef { autoderefs, autoref, unsize }, + adjusted_ty)) => { + for i in 0..autoderefs { let i = i as u32; let adjusted_ty = expr.ty.adjust_for_autoderef( @@ -86,11 +85,11 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { self.id, self.span, i, - |mc| cx.tcx.tables.borrow().method_map.get(&mc).map(|m| m.ty)); + |mc| cx.tcx.tables().method_map.get(&mc).map(|m| m.ty)); debug!("make_mirror: autoderef #{}, adjusted_ty={:?}", i, adjusted_ty); let method_key = ty::MethodCall::autoderef(self.id, i); let meth_ty = - cx.tcx.tables.borrow().method_map.get(&method_key).map(|m| m.ty); + cx.tcx.tables().method_map.get(&method_key).map(|m| m.ty); let kind = if let Some(meth_ty) = meth_ty { debug!("make_mirror: overloaded autoderef (meth_ty={:?})", meth_ty); @@ -128,10 +127,10 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { }; } - if let Some(autoref) = adj.autoref { + if let Some(autoref) = autoref { let adjusted_ty = expr.ty.adjust_for_autoref(cx.tcx, Some(autoref)); match autoref { - ty::adjustment::AutoPtr(r, m) => { + ty::adjustment::AutoBorrow::Ref(r, m) => { expr = Expr { temp_lifetime: temp_lifetime, ty: adjusted_ty, @@ -143,7 +142,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { }, }; } - ty::adjustment::AutoUnsafe(m) => { + ty::adjustment::AutoBorrow::RawPtr(m) => { // Convert this to a suitable `&foo` and // then an unsafe coercion. Limit the region to be just this // expression. @@ -169,10 +168,10 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { } } - if let Some(target) = adj.unsize { + if unsize { expr = Expr { temp_lifetime: temp_lifetime, - ty: target, + ty: adjusted_ty, span: self.span, kind: ExprKind::Unsize { source: expr.to_ref() }, }; @@ -212,7 +211,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, expr: &'tcx hir::Expr) -> Expr<'tcx> { - let expr_ty = cx.tcx.expr_ty(expr); + let expr_ty = cx.tcx.tables().expr_ty(expr); let temp_lifetime = cx.tcx.region_maps.temporary_scope(expr.id); let kind = match expr.node { @@ -231,7 +230,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } hir::ExprCall(ref fun, ref args) => { - if cx.tcx.is_method_call(expr.id) { + if cx.tcx.tables().is_method_call(expr.id) { // The callee is something implementing Fn, FnMut, or FnOnce. // Find the actual method implementation being called and // build the appropriate UFCS call expression with the @@ -282,7 +281,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, }) } else { None }; if let Some((adt_def, index)) = adt_data { - let substs = cx.tcx.node_id_item_substs(fun.id).substs; + let substs = cx.tcx.tables().node_id_item_substs(fun.id) + .unwrap_or_else(|| cx.tcx.intern_substs(&[])); let field_refs = args.iter().enumerate().map(|(idx, e)| FieldExprRef { name: Field::new(idx), expr: e.to_ref() @@ -296,7 +296,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } } else { ExprKind::Call { - ty: cx.tcx.node_id_to_type(fun.id), + ty: cx.tcx.tables().node_id_to_type(fun.id), fun: fun.to_ref(), args: args.to_ref(), } @@ -328,7 +328,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } hir::ExprAssignOp(op, ref lhs, ref rhs) => { - if cx.tcx.is_method_call(expr.id) { + if cx.tcx.tables().is_method_call(expr.id) { let pass_args = if op.node.is_by_value() { PassArgs::ByValue } else { @@ -350,7 +350,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, }, hir::ExprBinary(op, ref lhs, ref rhs) => { - if cx.tcx.is_method_call(expr.id) { + if cx.tcx.tables().is_method_call(expr.id) { let pass_args = if op.node.is_by_value() { PassArgs::ByValue } else { @@ -406,7 +406,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } hir::ExprIndex(ref lhs, ref index) => { - if cx.tcx.is_method_call(expr.id) { + if cx.tcx.tables().is_method_call(expr.id) { overloaded_lvalue(cx, expr, ty::MethodCall::expr(expr.id), PassArgs::ByValue, lhs.to_ref(), vec![index]) } else { @@ -418,7 +418,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } hir::ExprUnary(hir::UnOp::UnDeref, ref arg) => { - if cx.tcx.is_method_call(expr.id) { + if cx.tcx.tables().is_method_call(expr.id) { overloaded_lvalue(cx, expr, ty::MethodCall::expr(expr.id), PassArgs::ByValue, arg.to_ref(), vec![]) } else { @@ -427,7 +427,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } hir::ExprUnary(hir::UnOp::UnNot, ref arg) => { - if cx.tcx.is_method_call(expr.id) { + if cx.tcx.tables().is_method_call(expr.id) { overloaded_operator(cx, expr, ty::MethodCall::expr(expr.id), PassArgs::ByValue, arg.to_ref(), vec![]) } else { @@ -439,7 +439,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } hir::ExprUnary(hir::UnOp::UnNeg, ref arg) => { - if cx.tcx.is_method_call(expr.id) { + if cx.tcx.tables().is_method_call(expr.id) { overloaded_operator(cx, expr, ty::MethodCall::expr(expr.id), PassArgs::ByValue, arg.to_ref(), vec![]) } else { @@ -470,10 +470,8 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, base: base.as_ref().map(|base| { FruInfo { base: base.to_ref(), - field_types: cx.tcx.tables - .borrow() - .fru_field_types[&expr.id] - .clone() + field_types: + cx.tcx.tables().fru_field_types[&expr.id].clone() } }) } @@ -512,7 +510,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, } hir::ExprClosure(..) => { - let closure_ty = cx.tcx.expr_ty(expr); + let closure_ty = cx.tcx.tables().expr_ty(expr); let (def_id, substs) = match closure_ty.sty { ty::TyClosure(def_id, substs) => (def_id, substs), _ => { @@ -551,7 +549,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, hir::ExprRepeat(ref v, ref c) => ExprKind::Repeat { value: v.to_ref(), count: TypedConstVal { - ty: cx.tcx.expr_ty(c), + ty: cx.tcx.tables().expr_ty(c), span: c.span, value: match const_eval::eval_const_expr(cx.tcx.global_tcx(), c) { ConstVal::Integral(ConstInt::Usize(u)) => u, @@ -579,7 +577,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, ExprKind::Loop { condition: None, body: block::to_expr_ref(cx, body) }, hir::ExprField(ref source, name) => { - let index = match cx.tcx.expr_ty_adjusted(source).sty { + let index = match cx.tcx.tables().expr_ty_adjusted(source).sty { ty::TyAdt(adt_def, _) => adt_def.variants[0].index_of_field_named(name.node), ref ty => @@ -631,8 +629,7 @@ fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, expr: &hir::Expr, method_call: ty::MethodCall) -> Expr<'tcx> { - let tables = cx.tcx.tables.borrow(); - let callee = &tables.method_map[&method_call]; + let callee = cx.tcx.tables().method_map[&method_call]; let temp_lifetime = cx.tcx.region_maps.temporary_scope(expr.id); Expr { temp_lifetime: temp_lifetime, @@ -666,8 +663,8 @@ fn convert_arm<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, expr: &'tcx hir::Expr) -> ExprKind<'tcx> { - let substs = cx.tcx.node_id_item_substs(expr.id).substs; - // Otherwise there may be def_map borrow conflicts + let substs = cx.tcx.tables().node_id_item_substs(expr.id) + .unwrap_or_else(|| cx.tcx.intern_substs(&[])); let def = cx.tcx.expect_def(expr.id); let def_id = match def { // A regular function, constructor function or a constant. @@ -677,18 +674,20 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, Def::Const(def_id) | Def::AssociatedConst(def_id) => def_id, Def::StructCtor(def_id, CtorKind::Const) | - Def::VariantCtor(def_id, CtorKind::Const) => match cx.tcx.node_id_to_type(expr.id).sty { - // A unit struct/variant which is used as a value. - // We return a completely different ExprKind here to account for this special case. - ty::TyAdt(adt_def, substs) => return ExprKind::Adt { - adt_def: adt_def, - variant_index: adt_def.variant_index_with_id(def_id), - substs: substs, - fields: vec![], - base: None, - }, - ref sty => bug!("unexpected sty: {:?}", sty) - }, + Def::VariantCtor(def_id, CtorKind::Const) => { + match cx.tcx.tables().node_id_to_type(expr.id).sty { + // A unit struct/variant which is used as a value. + // We return a completely different ExprKind here to account for this special case. + ty::TyAdt(adt_def, substs) => return ExprKind::Adt { + adt_def: adt_def, + variant_index: adt_def.variant_index_with_id(def_id), + substs: substs, + fields: vec![], + base: None, + }, + ref sty => bug!("unexpected sty: {:?}", sty) + } + } Def::Static(node_id, _) => return ExprKind::StaticRef { id: node_id, @@ -720,7 +719,7 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, Def::Upvar(def_id, index, closure_expr_id) => { let id_var = cx.tcx.map.as_local_node_id(def_id).unwrap(); debug!("convert_var(upvar({:?}, {:?}, {:?}))", id_var, index, closure_expr_id); - let var_ty = cx.tcx.node_id_to_type(id_var); + let var_ty = cx.tcx.tables().node_id_to_type(id_var); let body_id = match cx.tcx.map.find(closure_expr_id) { Some(map::NodeExpr(expr)) => { @@ -737,7 +736,7 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, }; // FIXME free regions in closures are not right - let closure_ty = cx.tcx.node_id_to_type(closure_expr_id); + let closure_ty = cx.tcx.tables().node_id_to_type(closure_expr_id); // FIXME we're just hard-coding the idea that the // signature will be &self or &mut self and hence will @@ -809,7 +808,7 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, var_id: id_var, closure_expr_id: closure_expr_id, }; - let upvar_capture = match cx.tcx.upvar_capture(upvar_id) { + let upvar_capture = match cx.tcx.tables().upvar_capture(upvar_id) { Some(c) => c, None => { span_bug!( @@ -893,7 +892,7 @@ fn overloaded_operator<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, argrefs.extend( args.iter() .map(|arg| { - let arg_ty = cx.tcx.expr_ty_adjusted(arg); + let arg_ty = cx.tcx.tables().expr_ty_adjusted(arg); let adjusted_ty = cx.tcx.mk_ref(region, ty::TypeAndMut { ty: arg_ty, @@ -931,9 +930,7 @@ fn overloaded_lvalue<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, // line up (this is because `*x` and `x[y]` represent lvalues): // to find the type &T of the content returned by the method; - let tables = cx.tcx.tables.borrow(); - let callee = &tables.method_map[&method_call]; - let ref_ty = callee.ty.fn_ret(); + let ref_ty = cx.tcx.tables().method_map[&method_call].ty.fn_ret(); let ref_ty = cx.tcx.no_late_bound_regions(&ref_ty).unwrap(); // callees always have all late-bound regions fully instantiated, @@ -962,9 +959,9 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, var_id: id_var, closure_expr_id: closure_expr.id, }; - let upvar_capture = cx.tcx.upvar_capture(upvar_id).unwrap(); + let upvar_capture = cx.tcx.tables().upvar_capture(upvar_id).unwrap(); let temp_lifetime = cx.tcx.region_maps.temporary_scope(closure_expr.id); - let var_ty = cx.tcx.node_id_to_type(id_var); + let var_ty = cx.tcx.tables().node_id_to_type(id_var); let captured_var = Expr { temp_lifetime: temp_lifetime, ty: var_ty, diff --git a/src/librustc_mir/mir_map.rs b/src/librustc_mir/mir_map.rs index b0e2d6e73d37a..0ffc59fe6bf45 100644 --- a/src/librustc_mir/mir_map.rs +++ b/src/librustc_mir/mir_map.rs @@ -214,7 +214,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> { id: ast::NodeId) { // fetch the fully liberated fn signature (that is, all bound // types/lifetimes replaced) - let fn_sig = match self.tcx.tables.borrow().liberated_fn_sigs.get(&id) { + let fn_sig = match self.tcx.tables().liberated_fn_sigs.get(&id) { Some(f) => f.clone(), None => { span_bug!(span, "no liberated fn sig for {:?}", id); @@ -248,7 +248,7 @@ fn closure_self_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, closure_expr_id: ast::NodeId, body_id: ast::NodeId) -> Ty<'tcx> { - let closure_ty = tcx.node_id_to_type(closure_expr_id); + let closure_ty = tcx.tables().node_id_to_type(closure_expr_id); // We're just hard-coding the idea that the signature will be // &self or &mut self and hence will have a bound region with diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs index 8ad4d7f57a6f0..f23539e88f78d 100644 --- a/src/librustc_passes/consts.rs +++ b/src/librustc_passes/consts.rs @@ -319,7 +319,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> { let mut outer = self.qualif; self.qualif = ConstQualif::empty(); - let node_ty = self.tcx.node_id_to_type(ex.id); + let node_ty = self.tcx.tables().node_id_to_type(ex.id); check_expr(self, ex, node_ty); check_adjustments(self, ex); @@ -449,14 +449,14 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node match e.node { hir::ExprUnary(..) | hir::ExprBinary(..) | - hir::ExprIndex(..) if v.tcx.tables.borrow().method_map.contains_key(&method_call) => { + hir::ExprIndex(..) if v.tcx.tables().method_map.contains_key(&method_call) => { v.add_qualif(ConstQualif::NOT_CONST); } hir::ExprBox(_) => { v.add_qualif(ConstQualif::NOT_CONST); } hir::ExprUnary(op, ref inner) => { - match v.tcx.node_id_to_type(inner.id).sty { + match v.tcx.tables().node_id_to_type(inner.id).sty { ty::TyRawPtr(_) => { assert!(op == hir::UnDeref); @@ -466,7 +466,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node } } hir::ExprBinary(op, ref lhs, _) => { - match v.tcx.node_id_to_type(lhs.id).sty { + match v.tcx.tables().node_id_to_type(lhs.id).sty { ty::TyRawPtr(_) => { assert!(op.node == hir::BiEq || op.node == hir::BiNe || op.node == hir::BiLe || op.node == hir::BiLt || @@ -503,7 +503,8 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node } } Def::Const(did) | Def::AssociatedConst(did) => { - let substs = Some(v.tcx.node_id_item_substs(e.id).substs); + let substs = Some(v.tcx.tables().node_id_item_substs(e.id) + .unwrap_or_else(|| v.tcx.intern_substs(&[]))); if let Some((expr, _)) = lookup_const_by_id(v.tcx, did, substs) { let inner = v.global_expr(Mode::Const, expr); v.add_qualif(inner); @@ -555,7 +556,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node } } hir::ExprMethodCall(..) => { - let method = v.tcx.tables.borrow().method_map[&method_call]; + let method = v.tcx.tables().method_map[&method_call]; let is_const = match v.tcx.impl_or_trait_item(method.def_id).container() { ty::ImplContainer(_) => v.handle_const_fn_call(e, method.def_id, node_ty), ty::TraitContainer(_) => false @@ -565,7 +566,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node } } hir::ExprStruct(..) => { - if let ty::TyAdt(adt, ..) = v.tcx.expr_ty(e).sty { + if let ty::TyAdt(adt, ..) = v.tcx.tables().expr_ty(e).sty { // unsafe_cell_type doesn't necessarily exist with no_core if Some(adt.did) == v.tcx.lang_items.unsafe_cell_type() { v.add_qualif(ConstQualif::MUTABLE_MEM); @@ -624,16 +625,18 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node /// Check the adjustments of an expression fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr) { - match v.tcx.tables.borrow().adjustments.get(&e.id) { + use rustc::ty::adjustment::*; + + match v.tcx.tables().adjustments.get(&e.id).map(|adj| adj.kind) { None | - Some(&ty::adjustment::AdjustNeverToAny(..)) | - Some(&ty::adjustment::AdjustReifyFnPointer) | - Some(&ty::adjustment::AdjustUnsafeFnPointer) | - Some(&ty::adjustment::AdjustMutToConstPointer) => {} + Some(Adjust::NeverToAny) | + Some(Adjust::ReifyFnPointer) | + Some(Adjust::UnsafeFnPointer) | + Some(Adjust::MutToConstPointer) => {} - Some(&ty::adjustment::AdjustDerefRef(ty::adjustment::AutoDerefRef { autoderefs, .. })) => { + Some(Adjust::DerefRef { autoderefs, .. }) => { if (0..autoderefs as u32) - .any(|autoderef| v.tcx.is_overloaded_autoderef(e.id, autoderef)) { + .any(|autoderef| v.tcx.tables().is_overloaded_autoderef(e.id, autoderef)) { v.add_qualif(ConstQualif::NOT_CONST); } } diff --git a/src/librustc_passes/hir_stats.rs b/src/librustc_passes/hir_stats.rs new file mode 100644 index 0000000000000..18586715894f5 --- /dev/null +++ b/src/librustc_passes/hir_stats.rs @@ -0,0 +1,374 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// The visitors in this module collect sizes and counts of the most important +// pieces of AST and HIR. The resulting numbers are good approximations but not +// completely accurate (some things might be counted twice, others missed). + +use rustc::hir; +use rustc::hir::intravisit as hir_visit; +use rustc::util::common::to_readable_str; +use rustc::util::nodemap::{FnvHashMap, FnvHashSet}; +use syntax::ast::{self, NodeId, AttrId}; +use syntax::visit as ast_visit; +use syntax_pos::Span; + +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +enum Id { + Node(NodeId), + Attr(AttrId), + None, +} + +struct NodeData { + count: usize, + size: usize, +} + +struct StatCollector<'k> { + krate: Option<&'k hir::Crate>, + data: FnvHashMap<&'static str, NodeData>, + seen: FnvHashSet, +} + +pub fn print_hir_stats(krate: &hir::Crate) { + let mut collector = StatCollector { + krate: Some(krate), + data: FnvHashMap(), + seen: FnvHashSet(), + }; + hir_visit::walk_crate(&mut collector, krate); + collector.print("HIR STATS"); +} + +pub fn print_ast_stats(krate: &ast::Crate, title: &str) { + let mut collector = StatCollector { + krate: None, + data: FnvHashMap(), + seen: FnvHashSet(), + }; + ast_visit::walk_crate(&mut collector, krate); + collector.print(title); +} + +impl<'k> StatCollector<'k> { + + fn record(&mut self, label: &'static str, id: Id, node: &T) { + if id != Id::None { + if !self.seen.insert(id) { + return + } + } + + let entry = self.data.entry(label).or_insert(NodeData { + count: 0, + size: 0, + }); + + entry.count += 1; + entry.size = ::std::mem::size_of_val(node); + } + + fn print(&self, title: &str) { + let mut stats: Vec<_> = self.data.iter().collect(); + + stats.sort_by_key(|&(_, ref d)| d.count * d.size); + + let mut total_size = 0; + + println!("\n{}\n", title); + + println!("{:<18}{:>18}{:>14}{:>14}", + "Name", "Accumulated Size", "Count", "Item Size"); + println!("----------------------------------------------------------------"); + + for (label, data) in stats { + println!("{:<18}{:>18}{:>14}{:>14}", + label, + to_readable_str(data.count * data.size), + to_readable_str(data.count), + to_readable_str(data.size)); + + total_size += data.count * data.size; + } + println!("----------------------------------------------------------------"); + println!("{:<18}{:>18}\n", + "Total", + to_readable_str(total_size)); + } +} + +impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { + + fn visit_nested_item(&mut self, id: hir::ItemId) { + let nested_item = self.krate.unwrap().item(id.id); + self.visit_item(nested_item) + } + + fn visit_item(&mut self, i: &'v hir::Item) { + self.record("Item", Id::Node(i.id), i); + hir_visit::walk_item(self, i) + } + + /////////////////////////////////////////////////////////////////////////// + + fn visit_mod(&mut self, m: &'v hir::Mod, _s: Span, n: NodeId) { + self.record("Mod", Id::None, m); + hir_visit::walk_mod(self, m, n) + } + fn visit_foreign_item(&mut self, i: &'v hir::ForeignItem) { + self.record("ForeignItem", Id::Node(i.id), i); + hir_visit::walk_foreign_item(self, i) + } + fn visit_local(&mut self, l: &'v hir::Local) { + self.record("Local", Id::Node(l.id), l); + hir_visit::walk_local(self, l) + } + fn visit_block(&mut self, b: &'v hir::Block) { + self.record("Block", Id::Node(b.id), b); + hir_visit::walk_block(self, b) + } + fn visit_stmt(&mut self, s: &'v hir::Stmt) { + self.record("Stmt", Id::Node(s.node.id()), s); + hir_visit::walk_stmt(self, s) + } + fn visit_arm(&mut self, a: &'v hir::Arm) { + self.record("Arm", Id::None, a); + hir_visit::walk_arm(self, a) + } + fn visit_pat(&mut self, p: &'v hir::Pat) { + self.record("Pat", Id::Node(p.id), p); + 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) + } + + fn visit_ty(&mut self, t: &'v hir::Ty) { + self.record("Ty", Id::Node(t.id), t); + hir_visit::walk_ty(self, t) + } + + fn visit_fn(&mut self, + fk: hir_visit::FnKind<'v>, + fd: &'v hir::FnDecl, + b: &'v hir::Block, + s: Span, + id: NodeId) { + self.record("FnDecl", Id::None, fd); + hir_visit::walk_fn(self, fk, fd, b, s, id) + } + + fn visit_where_predicate(&mut self, predicate: &'v hir::WherePredicate) { + self.record("WherePredicate", Id::None, predicate); + hir_visit::walk_where_predicate(self, predicate) + } + + fn visit_trait_item(&mut self, ti: &'v hir::TraitItem) { + self.record("TraitItem", Id::Node(ti.id), ti); + hir_visit::walk_trait_item(self, ti) + } + fn visit_impl_item(&mut self, ii: &'v hir::ImplItem) { + self.record("ImplItem", Id::Node(ii.id), ii); + hir_visit::walk_impl_item(self, ii) + } + + fn visit_ty_param_bound(&mut self, bounds: &'v hir::TyParamBound) { + self.record("TyParamBound", Id::None, bounds); + hir_visit::walk_ty_param_bound(self, bounds) + } + + fn visit_struct_field(&mut self, s: &'v hir::StructField) { + self.record("StructField", Id::Node(s.id), s); + hir_visit::walk_struct_field(self, s) + } + + fn visit_variant(&mut self, + v: &'v hir::Variant, + g: &'v hir::Generics, + item_id: NodeId) { + self.record("Variant", Id::None, v); + hir_visit::walk_variant(self, v, g, item_id) + } + fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) { + self.record("Lifetime", Id::Node(lifetime.id), lifetime); + hir_visit::walk_lifetime(self, lifetime) + } + fn visit_lifetime_def(&mut self, lifetime: &'v hir::LifetimeDef) { + self.record("LifetimeDef", Id::None, lifetime); + hir_visit::walk_lifetime_def(self, lifetime) + } + fn visit_path(&mut self, path: &'v hir::Path, _id: NodeId) { + self.record("Path", Id::None, path); + hir_visit::walk_path(self, path) + } + fn visit_path_list_item(&mut self, + prefix: &'v hir::Path, + item: &'v hir::PathListItem) { + self.record("PathListItem", Id::Node(item.node.id), item); + hir_visit::walk_path_list_item(self, prefix, item) + } + fn visit_path_segment(&mut self, + path_span: Span, + path_segment: &'v hir::PathSegment) { + self.record("PathSegment", Id::None, path_segment); + hir_visit::walk_path_segment(self, path_span, path_segment) + } + + fn visit_assoc_type_binding(&mut self, type_binding: &'v hir::TypeBinding) { + self.record("TypeBinding", Id::Node(type_binding.id), type_binding); + hir_visit::walk_assoc_type_binding(self, type_binding) + } + fn visit_attribute(&mut self, attr: &'v ast::Attribute) { + self.record("Attribute", Id::Attr(attr.node.id), attr); + } + fn visit_macro_def(&mut self, macro_def: &'v hir::MacroDef) { + self.record("MacroDef", Id::Node(macro_def.id), macro_def); + hir_visit::walk_macro_def(self, macro_def) + } +} + +impl<'v> ast_visit::Visitor for StatCollector<'v> { + + fn visit_mod(&mut self, m: &ast::Mod, _s: Span, _n: NodeId) { + self.record("Mod", Id::None, m); + ast_visit::walk_mod(self, m) + } + + fn visit_foreign_item(&mut self, i: &ast::ForeignItem) { + self.record("ForeignItem", Id::None, i); + ast_visit::walk_foreign_item(self, i) + } + + fn visit_item(&mut self, i: &ast::Item) { + self.record("Item", Id::None, i); + ast_visit::walk_item(self, i) + } + + fn visit_local(&mut self, l: &ast::Local) { + self.record("Local", Id::None, l); + ast_visit::walk_local(self, l) + } + + fn visit_block(&mut self, b: &ast::Block) { + self.record("Block", Id::None, b); + ast_visit::walk_block(self, b) + } + + fn visit_stmt(&mut self, s: &ast::Stmt) { + self.record("Stmt", Id::None, s); + ast_visit::walk_stmt(self, s) + } + + fn visit_arm(&mut self, a: &ast::Arm) { + self.record("Arm", Id::None, a); + ast_visit::walk_arm(self, a) + } + + fn visit_pat(&mut self, p: &ast::Pat) { + self.record("Pat", Id::None, p); + ast_visit::walk_pat(self, p) + } + + fn visit_expr(&mut self, ex: &ast::Expr) { + self.record("Expr", Id::None, ex); + ast_visit::walk_expr(self, ex) + } + + fn visit_ty(&mut self, t: &ast::Ty) { + self.record("Ty", Id::None, t); + ast_visit::walk_ty(self, t) + } + + fn visit_fn(&mut self, + fk: ast_visit::FnKind, + fd: &ast::FnDecl, + b: &ast::Block, + s: Span, + _: NodeId) { + self.record("FnDecl", Id::None, fd); + ast_visit::walk_fn(self, fk, fd, b, s) + } + + fn visit_trait_item(&mut self, ti: &ast::TraitItem) { + self.record("TraitItem", Id::None, ti); + ast_visit::walk_trait_item(self, ti) + } + + fn visit_impl_item(&mut self, ii: &ast::ImplItem) { + self.record("ImplItem", Id::None, ii); + ast_visit::walk_impl_item(self, ii) + } + + fn visit_ty_param_bound(&mut self, bounds: &ast::TyParamBound) { + self.record("TyParamBound", Id::None, bounds); + ast_visit::walk_ty_param_bound(self, bounds) + } + + fn visit_struct_field(&mut self, s: &ast::StructField) { + self.record("StructField", Id::None, s); + ast_visit::walk_struct_field(self, s) + } + + fn visit_variant(&mut self, + v: &ast::Variant, + g: &ast::Generics, + item_id: NodeId) { + self.record("Variant", Id::None, v); + ast_visit::walk_variant(self, v, g, item_id) + } + + fn visit_lifetime(&mut self, lifetime: &ast::Lifetime) { + self.record("Lifetime", Id::None, lifetime); + ast_visit::walk_lifetime(self, lifetime) + } + + fn visit_lifetime_def(&mut self, lifetime: &ast::LifetimeDef) { + self.record("LifetimeDef", Id::None, lifetime); + ast_visit::walk_lifetime_def(self, lifetime) + } + + fn visit_mac(&mut self, mac: &ast::Mac) { + self.record("Mac", Id::None, mac); + } + + fn visit_path_list_item(&mut self, + prefix: &ast::Path, + item: &ast::PathListItem) { + self.record("PathListItem", Id::None, item); + ast_visit::walk_path_list_item(self, prefix, item) + } + + fn visit_path_segment(&mut self, + path_span: Span, + path_segment: &ast::PathSegment) { + self.record("PathSegment", Id::None, path_segment); + ast_visit::walk_path_segment(self, path_span, path_segment) + } + + fn visit_assoc_type_binding(&mut self, type_binding: &ast::TypeBinding) { + self.record("TypeBinding", Id::None, type_binding); + ast_visit::walk_assoc_type_binding(self, type_binding) + } + + fn visit_attribute(&mut self, attr: &ast::Attribute) { + self.record("Attribute", Id::None, attr); + } + + fn visit_macro_def(&mut self, macro_def: &ast::MacroDef) { + self.record("MacroDef", Id::None, macro_def); + ast_visit::walk_macro_def(self, macro_def) + } +} diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index a4657251c9ce2..94816594878cc 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -45,6 +45,7 @@ pub mod diagnostics; pub mod ast_validation; pub mod consts; +pub mod hir_stats; pub mod loops; pub mod no_asm; pub mod rvalues; diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 77b3e76fc541f..8fdfecd4a5865 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -430,11 +430,11 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { match expr.node { hir::ExprMethodCall(..) => { let method_call = ty::MethodCall::expr(expr.id); - let method = self.tcx.tables.borrow().method_map[&method_call]; + let method = self.tcx.tables().method_map[&method_call]; self.check_method(expr.span, method.def_id); } hir::ExprStruct(_, ref expr_fields, _) => { - let adt = self.tcx.expr_ty(expr).ty_adt_def().unwrap(); + let adt = self.tcx.tables().expr_ty(expr).ty_adt_def().unwrap(); let variant = adt.variant_of_def(self.tcx.expect_def(expr.id)); // RFC 736: ensure all unmentioned fields are visible. // Rather than computing the set of unmentioned fields @@ -495,14 +495,14 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> { match pattern.node { PatKind::Struct(_, ref fields, _) => { - let adt = self.tcx.pat_ty(pattern).ty_adt_def().unwrap(); + let adt = self.tcx.tables().pat_ty(pattern).ty_adt_def().unwrap(); let variant = adt.variant_of_def(self.tcx.expect_def(pattern.id)); for field in fields { self.check_field(field.span, adt, variant.field_named(field.node.name)); } } PatKind::TupleStruct(_, ref fields, ddpos) => { - match self.tcx.pat_ty(pattern).sty { + match self.tcx.tables().pat_ty(pattern).sty { // enum fields have no privacy at this time ty::TyAdt(def, _) if !def.is_enum() => { let expected_len = def.struct_variant().fields.len(); diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 8a628289b7f94..db4788c3ceadb 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -356,7 +356,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { collector.visit_pat(&arg.pat); let span_utils = self.span.clone(); for &(id, ref p, ..) in &collector.collected_paths { - let typ = self.tcx.node_types().get(&id).unwrap().to_string(); + let typ = self.tcx.tables().node_types.get(&id).unwrap().to_string(); // get the span only for the name of the variable (I hope the path is only ever a // variable name, but who knows?) let sub_span = span_utils.span_for_last_ident(p.span); @@ -988,7 +988,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { match p.node { PatKind::Struct(ref path, ref fields, _) => { visit::walk_path(self, path); - let adt = self.tcx.node_id_to_type(p.id).ty_adt_def().unwrap(); + let adt = self.tcx.tables().node_id_to_type(p.id).ty_adt_def().unwrap(); let variant = adt.variant_of_def(self.tcx.expect_def(p.id)); for &Spanned { node: ref field, span } in fields { @@ -1023,8 +1023,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> { ast::Mutability::Immutable => value.to_string(), _ => String::new(), }; - let types = self.tcx.node_types(); - let typ = match types.get(&id) { + let typ = match self.tcx.tables().node_types.get(&id) { Some(typ) => { let typ = typ.to_string(); if !value.is_empty() { @@ -1355,7 +1354,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D> } ast::ExprKind::Struct(ref path, ref fields, ref base) => { let hir_expr = self.save_ctxt.tcx.map.expect_expr(ex.id); - let adt = self.tcx.expr_ty(&hir_expr).ty_adt_def().unwrap(); + let adt = self.tcx.tables().expr_ty(&hir_expr).ty_adt_def().unwrap(); let def = self.tcx.expect_def(hir_expr.id); self.process_struct_lit(ex, path, fields, adt.variant_of_def(def), base) } @@ -1381,7 +1380,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D> return; } }; - let ty = &self.tcx.expr_ty_adjusted(&hir_node).sty; + let ty = &self.tcx.tables().expr_ty_adjusted(&hir_node).sty; match *ty { ty::TyAdt(def, _) => { let sub_span = self.span.sub_span_after_token(ex.span, token::Dot); @@ -1468,7 +1467,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D> } else { "".to_string() }; - let typ = self.tcx.node_types() + let typ = self.tcx.tables().node_types .get(&id).map(|t| t.to_string()).unwrap_or(String::new()); value.push_str(": "); value.push_str(&typ); diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 15c74f2ed6ab5..7e008f741624b 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -286,7 +286,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { scope: NodeId) -> Option { if let Some(ident) = field.ident { let qualname = format!("::{}::{}", self.tcx.node_path_str(scope), ident); - let typ = self.tcx.node_types().get(&field.id).unwrap().to_string(); + let typ = self.tcx.tables().node_types.get(&field.id).unwrap().to_string(); let sub_span = self.span_utils.sub_span_before_token(field.span, token::Colon); filter!(self.span_utils, sub_span, field.span, None); Some(VariableData { @@ -418,7 +418,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { pub fn get_expr_data(&self, expr: &ast::Expr) -> Option { let hir_node = self.tcx.map.expect_expr(expr.id); - let ty = self.tcx.expr_ty_adjusted_opt(&hir_node); + let ty = self.tcx.tables().expr_ty_adjusted_opt(&hir_node); if ty.is_none() || ty.unwrap().sty == ty::TyError { return None; } @@ -432,7 +432,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { return None; } }; - match self.tcx.expr_ty_adjusted(&hir_node).sty { + match self.tcx.tables().expr_ty_adjusted(&hir_node).sty { ty::TyAdt(def, _) if !def.is_enum() => { let f = def.struct_variant().field_named(ident.node.name); let sub_span = self.span_utils.span_for_last_ident(expr.span); @@ -451,7 +451,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } } ast::ExprKind::Struct(ref path, ..) => { - match self.tcx.expr_ty_adjusted(&hir_node).sty { + match self.tcx.tables().expr_ty_adjusted(&hir_node).sty { ty::TyAdt(def, _) if !def.is_enum() => { let sub_span = self.span_utils.span_for_last_ident(path.span); filter!(self.span_utils, sub_span, path.span, None); @@ -472,7 +472,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } ast::ExprKind::MethodCall(..) => { let method_call = ty::MethodCall::expr(expr.id); - let method_id = self.tcx.tables.borrow().method_map[&method_call].def_id; + let method_id = self.tcx.tables().method_map[&method_call].def_id; let (def_id, decl_id) = match self.tcx.impl_or_trait_item(method_id).container() { ty::ImplContainer(_) => (Some(method_id), None), ty::TraitContainer(_) => (None, Some(method_id)), diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index e46bdbb5ccf4a..ad8e0c1ee59f6 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -636,7 +636,7 @@ fn link_natively(sess: &Session, { let mut linker = trans.linker_info.to_linker(&mut cmd, &sess); link_args(&mut *linker, sess, crate_type, tmpdir, - objects, out_filename, outputs); + objects, out_filename, outputs, trans); } cmd.args(&sess.target.target.options.late_link_args); for obj in &sess.target.target.options.post_link_objects { @@ -711,7 +711,8 @@ fn link_args(cmd: &mut Linker, tmpdir: &Path, objects: &[PathBuf], out_filename: &Path, - outputs: &OutputFilenames) { + outputs: &OutputFilenames, + trans: &CrateTranslation) { // The default library location, we need this to find the runtime. // The location of crates will be determined as needed. @@ -726,6 +727,13 @@ fn link_args(cmd: &mut Linker, } cmd.output_filename(out_filename); + if crate_type == config::CrateTypeExecutable && + sess.target.target.options.is_like_windows { + if let Some(ref s) = trans.windows_subsystem { + cmd.subsystem(s); + } + } + // If we're building a dynamic library then some platforms need to make sure // that all symbols are exported correctly from the dynamic library. if crate_type != config::CrateTypeExecutable { diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs index 3222571a76e17..860903d259fe5 100644 --- a/src/librustc_trans/back/linker.rs +++ b/src/librustc_trans/back/linker.rs @@ -92,6 +92,7 @@ pub trait Linker { fn whole_archives(&mut self); fn no_whole_archives(&mut self); fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType); + fn subsystem(&mut self, subsystem: &str); } pub struct GnuLinker<'a> { @@ -294,6 +295,10 @@ impl<'a> Linker for GnuLinker<'a> { self.cmd.arg(arg); } + + fn subsystem(&mut self, subsystem: &str) { + self.cmd.arg(&format!("-Wl,--subsystem,{}", subsystem)); + } } pub struct MsvcLinker<'a> { @@ -441,6 +446,30 @@ impl<'a> Linker for MsvcLinker<'a> { arg.push(path); self.cmd.arg(&arg); } + + fn subsystem(&mut self, subsystem: &str) { + // Note that previous passes of the compiler validated this subsystem, + // so we just blindly pass it to the linker. + self.cmd.arg(&format!("/SUBSYSTEM:{}", subsystem)); + + // Windows has two subsystems we're interested in right now, the console + // and windows subsystems. These both implicitly have different entry + // points (starting symbols). The console entry point starts with + // `mainCRTStartup` and the windows entry point starts with + // `WinMainCRTStartup`. These entry points, defined in system libraries, + // will then later probe for either `main` or `WinMain`, respectively to + // start the application. + // + // In Rust we just always generate a `main` function so we want control + // to always start there, so we force the entry point on the windows + // subsystem to be `mainCRTStartup` to get everything booted up + // correctly. + // + // For more information see RFC #1665 + if subsystem == "windows" { + self.cmd.arg("/ENTRY:mainCRTStartup"); + } + } } fn exported_symbols(scx: &SharedCrateContext, diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 977ababbf5688..bd15035b8a94e 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -1196,6 +1196,9 @@ pub fn maybe_create_entry_wrapper(ccx: &CrateContext) { } let llfn = declare::declare_cfn(ccx, "main", llfty); + // `main` should respect same config for frame pointer elimination as rest of code + attributes::set_frame_pointer_elimination(ccx, llfn); + let llbb = unsafe { llvm::LLVMAppendBasicBlockInContext(ccx.llcx(), llfn, "top\0".as_ptr() as *const _) }; @@ -1611,7 +1614,8 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, metadata: metadata, reachable: vec![], no_builtins: no_builtins, - linker_info: linker_info + linker_info: linker_info, + windows_subsystem: None, }; } @@ -1747,6 +1751,17 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let linker_info = LinkerInfo::new(&shared_ccx, &reachable_symbols); + let subsystem = attr::first_attr_value_str_by_name(&krate.attrs, + "windows_subsystem"); + let windows_subsystem = subsystem.map(|subsystem| { + if subsystem != "windows" && subsystem != "console" { + tcx.sess.fatal(&format!("invalid windows subsystem `{}`, only \ + `windows` and `console` are allowed", + subsystem)); + } + subsystem.to_string() + }); + CrateTranslation { modules: modules, metadata_module: metadata_module, @@ -1754,7 +1769,8 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, metadata: metadata, reachable: reachable_symbols, no_builtins: no_builtins, - linker_info: linker_info + linker_info: linker_info, + windows_subsystem: windows_subsystem, } } diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs index cd81d114eb770..ffb13a833a582 100644 --- a/src/librustc_trans/callee.rs +++ b/src/librustc_trans/callee.rs @@ -74,7 +74,7 @@ impl<'tcx> Callee<'tcx> { pub fn method_call<'blk>(bcx: Block<'blk, 'tcx>, method_call: ty::MethodCall) -> Callee<'tcx> { - let method = bcx.tcx().tables.borrow().method_map[&method_call]; + let method = bcx.tcx().tables().method_map[&method_call]; Callee::method(bcx, method) } diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index 8348da9f7b7bf..a439d415ede15 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -1082,10 +1082,7 @@ impl<'b, 'a, 'v> hir_visit::Visitor<'v> for RootCollector<'b, 'a, 'v> { hir::ItemStruct(_, ref generics) | hir::ItemUnion(_, ref generics) => { if !generics.is_parameterized() { - let ty = { - let tables = self.scx.tcx().tables.borrow(); - tables.node_types[&item.id] - }; + let ty = self.scx.tcx().tables().node_types[&item.id]; if self.mode == TransItemCollectionMode::Eager { debug!("RootCollector: ADT drop-glue for {}", diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index 863aecc824433..4bb34850e0870 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -1765,7 +1765,7 @@ pub fn create_global_var_metadata(cx: &CrateContext, }; let is_local_to_unit = is_node_local_to_unit(cx, node_id); - let variable_type = tcx.erase_regions(&tcx.node_id_to_type(node_id)); + let variable_type = tcx.erase_regions(&tcx.tables().node_id_to_type(node_id)); let type_metadata = type_metadata(cx, variable_type, span); let var_name = tcx.item_name(node_def_id).to_string(); let linkage_name = mangled_name_of_item(cx, node_def_id, ""); diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 07acc54962b87..37304f28e03f6 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -169,6 +169,7 @@ pub struct CrateTranslation { pub metadata: Vec, pub reachable: Vec, pub no_builtins: bool, + pub windows_subsystem: Option, pub linker_info: back::linker::LinkerInfo } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 1aa502fc443ec..c93f1c6c8e610 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1549,7 +1549,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { tcx.prohibit_type_params(base_segments); let impl_id = tcx.map.as_local_node_id(def_id).unwrap(); - let ty = tcx.node_id_to_type(impl_id); + let ty = tcx.tables().node_id_to_type(impl_id); if let Some(free_substs) = self.get_free_substs() { ty.subst(tcx, free_substs) } else { diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index c5a21d7dd91ce..3cf64fa439d7d 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -103,7 +103,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // If the callee is a bare function or a closure, then we're all set. match self.structurally_resolved_type(callee_expr.span, adjusted_ty).sty { ty::TyFnDef(..) | ty::TyFnPtr(_) => { - self.write_autoderef_adjustment(callee_expr.id, autoderefs); + self.write_autoderef_adjustment(callee_expr.id, autoderefs, adjusted_ty); return Some(CallStep::Builtin); } diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index ccc944813ff18..16493412d690b 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -65,10 +65,7 @@ use check::FnCtxt; use rustc::hir; use rustc::infer::{Coercion, InferOk, TypeOrigin, TypeTrace}; use rustc::traits::{self, ObligationCause}; -use rustc::ty::adjustment::{AutoAdjustment, AutoDerefRef, AdjustDerefRef}; -use rustc::ty::adjustment::{AutoPtr, AutoUnsafe, AdjustReifyFnPointer}; -use rustc::ty::adjustment::{AdjustUnsafeFnPointer, AdjustMutToConstPointer}; -use rustc::ty::adjustment::AdjustNeverToAny; +use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow}; use rustc::ty::{self, LvaluePreference, TypeAndMut, Ty}; use rustc::ty::fold::TypeFoldable; use rustc::ty::error::TypeError; @@ -93,7 +90,7 @@ impl<'a, 'gcx, 'tcx> Deref for Coerce<'a, 'gcx, 'tcx> { } } -type CoerceResult<'tcx> = RelateResult<'tcx, (Ty<'tcx>, AutoAdjustment<'tcx>)>; +type CoerceResult<'tcx> = RelateResult<'tcx, (Ty<'tcx>, Adjust<'tcx>)>; fn coerce_mutbls<'tcx>(from_mutbl: hir::Mutability, to_mutbl: hir::Mutability) @@ -144,12 +141,11 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { /// Synthesize an identity adjustment. fn identity(&self, ty: Ty<'tcx>) -> CoerceResult<'tcx> { - Ok((ty, - AdjustDerefRef(AutoDerefRef { - autoderefs: 0, - autoref: None, - unsize: None, - }))) + Ok((ty, Adjust::DerefRef { + autoderefs: 0, + autoref: None, + unsize: false, + })) } fn coerce<'a, E, I>(&self, exprs: &E, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> @@ -166,7 +162,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { } if a.is_never() { - return Ok((b, AdjustNeverToAny(b))); + return Ok((b, Adjust::NeverToAny)); } // Consider coercing the subtype to a DST @@ -396,17 +392,16 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { ty::TyRef(r_borrow, _) => r_borrow, _ => span_bug!(span, "expected a ref type, got {:?}", ty), }; - let autoref = Some(AutoPtr(r_borrow, mt_b.mutbl)); + let autoref = Some(AutoBorrow::Ref(r_borrow, mt_b.mutbl)); debug!("coerce_borrowed_pointer: succeeded ty={:?} autoderefs={:?} autoref={:?}", ty, autoderefs, autoref); - Ok((ty, - AdjustDerefRef(AutoDerefRef { - autoderefs: autoderefs, - autoref: autoref, - unsize: None, - }))) + Ok((ty, Adjust::DerefRef { + autoderefs: autoderefs, + autoref: autoref, + unsize: false, + })) } @@ -437,11 +432,11 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { let coercion = Coercion(self.origin.span()); let r_borrow = self.next_region_var(coercion); - (mt_a.ty, Some(AutoPtr(r_borrow, mt_b.mutbl))) + (mt_a.ty, Some(AutoBorrow::Ref(r_borrow, mt_b.mutbl))) } (&ty::TyRef(_, mt_a), &ty::TyRawPtr(mt_b)) => { coerce_mutbls(mt_a.mutbl, mt_b.mutbl)?; - (mt_a.ty, Some(AutoUnsafe(mt_b.mutbl))) + (mt_a.ty, Some(AutoBorrow::RawPtr(mt_b.mutbl))) } _ => (source, None), }; @@ -497,13 +492,13 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { *self.unsizing_obligations.borrow_mut() = leftover_predicates; - let adjustment = AutoDerefRef { + let adjustment = Adjust::DerefRef { autoderefs: if reborrow.is_some() { 1 } else { 0 }, autoref: reborrow, - unsize: Some(target), + unsize: true, }; debug!("Success, coerced with {:?}", adjustment); - Ok((target, AdjustDerefRef(adjustment))) + Ok((target, adjustment)) } fn coerce_from_safe_fn(&self, @@ -516,7 +511,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { (hir::Unsafety::Normal, hir::Unsafety::Unsafe) => { let unsafe_a = self.tcx.safe_to_unsafe_fn_ty(fn_ty_a); return self.unify_and_identity(unsafe_a, b) - .map(|(ty, _)| (ty, AdjustUnsafeFnPointer)); + .map(|(ty, _)| (ty, Adjust::UnsafeFnPointer)); } _ => {} } @@ -555,7 +550,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { ty::TyFnPtr(_) => { let a_fn_pointer = self.tcx.mk_fn_ptr(fn_ty_a); self.coerce_from_safe_fn(a_fn_pointer, fn_ty_a, b) - .map(|(ty, _)| (ty, AdjustReifyFnPointer)) + .map(|(ty, _)| (ty, Adjust::ReifyFnPointer)) } _ => self.unify_and_identity(a, b), } @@ -585,17 +580,17 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { coerce_mutbls(mt_a.mutbl, mutbl_b)?; // Although references and unsafe ptrs have the same - // representation, we still register an AutoDerefRef so that + // representation, we still register an Adjust::DerefRef so that // regionck knows that the region for `a` must be valid here. Ok((ty, if is_ref { - AdjustDerefRef(AutoDerefRef { + Adjust::DerefRef { autoderefs: 1, - autoref: Some(AutoUnsafe(mutbl_b)), - unsize: None, - }) + autoref: Some(AutoBorrow::RawPtr(mutbl_b)), + unsize: false, + } } else if mt_a.mutbl != mutbl_b { - AdjustMutToConstPointer + Adjust::MutToConstPointer } else { noop })) @@ -606,24 +601,25 @@ fn apply<'a, 'b, 'gcx, 'tcx, E, I>(coerce: &mut Coerce<'a, 'gcx, 'tcx>, exprs: &E, a: Ty<'tcx>, b: Ty<'tcx>) - -> CoerceResult<'tcx> + -> RelateResult<'tcx, Adjustment<'tcx>> where E: Fn() -> I, I: IntoIterator { - let (ty, adjustment) = indent(|| coerce.coerce(exprs, a, b))?; + let (ty, adjust) = indent(|| coerce.coerce(exprs, a, b))?; let fcx = coerce.fcx; - if let AdjustDerefRef(auto) = adjustment { - if auto.unsize.is_some() { - let mut obligations = coerce.unsizing_obligations.borrow_mut(); - for obligation in obligations.drain(..) { - fcx.register_predicate(obligation); - } + if let Adjust::DerefRef { unsize: true, .. } = adjust { + let mut obligations = coerce.unsizing_obligations.borrow_mut(); + for obligation in obligations.drain(..) { + fcx.register_predicate(obligation); } } - Ok((ty, adjustment)) + Ok(Adjustment { + kind: adjust, + target: ty + }) } impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { @@ -641,17 +637,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let mut coerce = Coerce::new(self, TypeOrigin::ExprAssignable(expr.span)); self.commit_if_ok(|_| { - let (ty, adjustment) = apply(&mut coerce, &|| Some(expr), source, target)?; + let adjustment = apply(&mut coerce, &|| Some(expr), source, target)?; if !adjustment.is_identity() { debug!("Success, coerced with {:?}", adjustment); match self.tables.borrow().adjustments.get(&expr.id) { None | - Some(&AdjustNeverToAny(..)) => (), + Some(&Adjustment { kind: Adjust::NeverToAny, .. }) => (), _ => bug!("expr already has an adjustment on it!"), }; self.write_adjustment(expr.id, adjustment); } - Ok(ty) + Ok(adjustment.target) }) } @@ -705,12 +701,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } // Reify both sides and return the reified fn pointer type. + let fn_ptr = self.tcx.mk_fn_ptr(fty); for expr in exprs().into_iter().chain(Some(new)) { // No adjustments can produce a fn item, so this should never trip. assert!(!self.tables.borrow().adjustments.contains_key(&expr.id)); - self.write_adjustment(expr.id, AdjustReifyFnPointer); + self.write_adjustment(expr.id, Adjustment { + kind: Adjust::ReifyFnPointer, + target: fn_ptr + }); } - return Ok(self.tcx.mk_fn_ptr(fty)); + return Ok(fn_ptr); } _ => {} } @@ -724,11 +724,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if !self.tables.borrow().adjustments.contains_key(&new.id) { let result = self.commit_if_ok(|_| apply(&mut coerce, &|| Some(new), new_ty, prev_ty)); match result { - Ok((ty, adjustment)) => { + Ok(adjustment) => { if !adjustment.is_identity() { self.write_adjustment(new.id, adjustment); } - return Ok(ty); + return Ok(adjustment.target); } Err(e) => first_error = Some(e), } @@ -738,10 +738,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // This requires ensuring there are no coercions applied to *any* of the // previous expressions, other than noop reborrows (ignoring lifetimes). for expr in exprs() { - let noop = match self.tables.borrow().adjustments.get(&expr.id) { - Some(&AdjustDerefRef(AutoDerefRef { autoderefs: 1, - autoref: Some(AutoPtr(_, mutbl_adj)), - unsize: None })) => { + let noop = match self.tables.borrow().adjustments.get(&expr.id).map(|adj| adj.kind) { + Some(Adjust::DerefRef { + autoderefs: 1, + autoref: Some(AutoBorrow::Ref(_, mutbl_adj)), + unsize: false + }) => { match self.node_ty(expr.id).sty { ty::TyRef(_, mt_orig) => { // Reborrow that we can safely ignore. @@ -750,7 +752,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { _ => false, } } - Some(&AdjustNeverToAny(_)) => true, + Some(Adjust::NeverToAny) => true, Some(_) => false, None => true, }; @@ -783,18 +785,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }) } } - Ok((ty, adjustment)) => { + Ok(adjustment) => { if !adjustment.is_identity() { + let mut tables = self.tables.borrow_mut(); for expr in exprs() { - let previous = self.tables.borrow().adjustments.get(&expr.id).cloned(); - if let Some(AdjustNeverToAny(_)) = previous { - self.write_adjustment(expr.id, AdjustNeverToAny(ty)); - } else { - self.write_adjustment(expr.id, adjustment); + if let Some(&mut Adjustment { + kind: Adjust::NeverToAny, + ref mut target + }) = tables.adjustments.get_mut(&expr.id) { + *target = adjustment.target; + continue; } + tables.adjustments.insert(expr.id, adjustment); } } - Ok(ty) + Ok(adjustment.target) } } } diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 722089cd50c0c..f88bb355d1270 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -15,7 +15,7 @@ use hir::def_id::DefId; use rustc::ty::subst::Substs; use rustc::traits; use rustc::ty::{self, LvaluePreference, NoPreference, PreferMutLvalue, Ty}; -use rustc::ty::adjustment::{AdjustDerefRef, AutoDerefRef, AutoPtr}; +use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow}; use rustc::ty::fold::TypeFoldable; use rustc::infer::{self, InferOk, TypeOrigin}; use syntax_pos::Span; @@ -140,20 +140,19 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { unadjusted_self_ty: Ty<'tcx>, pick: &probe::Pick<'tcx>) -> Ty<'tcx> { - let (autoref, unsize) = if let Some(mutbl) = pick.autoref { + let autoref = if let Some(mutbl) = pick.autoref { let region = self.next_region_var(infer::Autoref(self.span)); - let autoref = AutoPtr(region, mutbl); - (Some(autoref), - pick.unsize.map(|target| target.adjust_for_autoref(self.tcx, Some(autoref)))) + Some(AutoBorrow::Ref(region, mutbl)) } else { // No unsizing should be performed without autoref (at // least during method dispach). This is because we // currently only unsize `[T;N]` to `[T]`, and naturally // that must occur being a reference. assert!(pick.unsize.is_none()); - (None, None) + None }; + // Commit the autoderefs by calling `autoderef` again, but this // time writing the results into the various tables. let mut autoderef = self.autoderef(self.span, unadjusted_self_ty); @@ -163,19 +162,20 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { autoderef.unambiguous_final_ty(); autoderef.finalize(LvaluePreference::NoPreference, Some(self.self_expr)); + let target = pick.unsize.unwrap_or(autoderefd_ty); + let target = target.adjust_for_autoref(self.tcx, autoref); + // Write out the final adjustment. - self.write_adjustment(self.self_expr.id, - AdjustDerefRef(AutoDerefRef { - autoderefs: pick.autoderefs, - autoref: autoref, - unsize: unsize, - })); - - if let Some(target) = unsize { - target - } else { - autoderefd_ty.adjust_for_autoref(self.tcx, autoref) - } + self.write_adjustment(self.self_expr.id, Adjustment { + kind: Adjust::DerefRef { + autoderefs: pick.autoderefs, + autoref: autoref, + unsize: pick.unsize.is_some(), + }, + target: target + }); + + target } /////////////////////////////////////////////////////////////////////////// @@ -463,29 +463,23 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { // Fix up autoderefs and derefs. for (i, &expr) in exprs.iter().rev().enumerate() { + debug!("convert_lvalue_derefs_to_mutable: i={} expr={:?}", i, expr); + // Count autoderefs. - let autoderef_count = match self.tables - .borrow() - .adjustments - .get(&expr.id) { - Some(&AdjustDerefRef(ref adj)) => adj.autoderefs, - Some(_) | None => 0, - }; - - debug!("convert_lvalue_derefs_to_mutable: i={} expr={:?} \ - autoderef_count={}", - i, - expr, - autoderef_count); - - if autoderef_count > 0 { - let mut autoderef = self.autoderef(expr.span, self.node_ty(expr.id)); - autoderef.nth(autoderef_count).unwrap_or_else(|| { - span_bug!(expr.span, - "expr was deref-able {} times but now isn't?", - autoderef_count); - }); - autoderef.finalize(PreferMutLvalue, Some(expr)); + let adjustment = self.tables.borrow().adjustments.get(&expr.id).cloned(); + match adjustment { + Some(Adjustment { kind: Adjust::DerefRef { autoderefs, .. }, .. }) => { + if autoderefs > 0 { + let mut autoderef = self.autoderef(expr.span, self.node_ty(expr.id)); + autoderef.nth(autoderefs).unwrap_or_else(|| { + span_bug!(expr.span, + "expr was deref-able {} times but now isn't?", + autoderefs); + }); + autoderef.finalize(PreferMutLvalue, Some(expr)); + } + } + Some(_) | None => {} } // Don't retry the first one or we might infinite loop! @@ -503,45 +497,55 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { // ought to recode this routine so it doesn't // (ab)use the normal type checking paths. let adj = self.tables.borrow().adjustments.get(&base_expr.id).cloned(); - let (autoderefs, unsize) = match adj { - Some(AdjustDerefRef(adr)) => { - match adr.autoref { + let (autoderefs, unsize, adjusted_base_ty) = match adj { + Some(Adjustment { + kind: Adjust::DerefRef { autoderefs, autoref, unsize }, + target + }) => { + match autoref { None => { - assert!(adr.unsize.is_none()); - (adr.autoderefs, None) - } - Some(AutoPtr(..)) => { - (adr.autoderefs, - adr.unsize.map(|target| { - target.builtin_deref(false, NoPreference) - .expect("fixup: AutoPtr is not &T") - .ty - })) + assert!(!unsize); } + Some(AutoBorrow::Ref(..)) => {} Some(_) => { span_bug!(base_expr.span, "unexpected adjustment autoref {:?}", - adr); + adj); } } + + (autoderefs, unsize, if unsize { + target.builtin_deref(false, NoPreference) + .expect("fixup: AutoBorrow::Ref is not &T") + .ty + } else { + let ty = self.node_ty(base_expr.id); + let mut ty = self.shallow_resolve(ty); + let mut method_type = |method_call: ty::MethodCall| { + self.tables.borrow().method_map.get(&method_call).map(|m| { + self.resolve_type_vars_if_possible(&m.ty) + }) + }; + + if !ty.references_error() { + for i in 0..autoderefs { + ty = ty.adjust_for_autoderef(self.tcx, + base_expr.id, + base_expr.span, + i as u32, + &mut method_type); + } + } + + ty + }) } - None => (0, None), + None => (0, false, self.node_ty(base_expr.id)), Some(_) => { span_bug!(base_expr.span, "unexpected adjustment type"); } }; - let (adjusted_base_ty, unsize) = if let Some(target) = unsize { - (target, true) - } else { - (self.adjust_expr_ty(base_expr, - Some(&AdjustDerefRef(AutoDerefRef { - autoderefs: autoderefs, - autoref: None, - unsize: None, - }))), - false) - }; let index_expr_ty = self.node_ty(index_expr.id); let result = self.try_index_step(ty::MethodCall::expr(expr.id), diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index f084b85a45f81..2df562f9ade46 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -16,7 +16,7 @@ use hir::def_id::DefId; use rustc::ty::subst::Substs; use rustc::traits; use rustc::ty::{self, ToPredicate, ToPolyTraitRef, TraitRef, TypeFoldable}; -use rustc::ty::adjustment::{AdjustDerefRef, AutoDerefRef, AutoPtr}; +use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow}; use rustc::infer; use syntax::ast; @@ -294,11 +294,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { unsize, method_ty.explicit_self); - match method_ty.explicit_self { + let autoref = match method_ty.explicit_self { ty::ExplicitSelfCategory::ByValue => { // Trait method is fn(self), no transformation needed. assert!(!unsize); - self.write_autoderef_adjustment(self_expr.id, autoderefs); + None } ty::ExplicitSelfCategory::ByReference(..) => { @@ -306,16 +306,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // autoref. Pull the region etc out of the type of first argument. match transformed_self_ty.sty { ty::TyRef(region, ty::TypeAndMut { mutbl, ty: _ }) => { - self.write_adjustment(self_expr.id, - AdjustDerefRef(AutoDerefRef { - autoderefs: autoderefs, - autoref: Some(AutoPtr(region, mutbl)), - unsize: if unsize { - Some(transformed_self_ty) - } else { - None - }, - })); + Some(AutoBorrow::Ref(region, mutbl)) } _ => { @@ -331,7 +322,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { "unexpected explicit self type in operator method: {:?}", method_ty.explicit_self); } - } + }; + + self.write_adjustment(self_expr.id, Adjustment { + kind: Adjust::DerefRef { + autoderefs: autoderefs, + autoref: autoref, + unsize: unsize + }, + target: transformed_self_ty + }); } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 4e0f455e36238..d8314bd6c2aed 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -777,7 +777,7 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx hir::Item) { check_union(ccx, it.id, it.span); } hir::ItemTy(_, ref generics) => { - let pty_ty = ccx.tcx.node_id_to_type(it.id); + let pty_ty = ccx.tcx.tables().node_id_to_type(it.id); check_bounds_are_used(ccx, generics, pty_ty); } hir::ItemForeignMod(ref m) => { @@ -1205,7 +1205,7 @@ fn check_representable<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, item_id: ast::NodeId) -> bool { - let rty = tcx.node_id_to_type(item_id); + let rty = tcx.tables().node_id_to_type(item_id); // Check that it is possible to represent this type. This call identifies // (1) types that contain themselves and (2) types that contain a different @@ -1224,7 +1224,7 @@ fn check_representable<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } pub fn check_simd<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, id: ast::NodeId) { - let t = tcx.node_id_to_type(id); + let t = tcx.tables().node_id_to_type(id); match t.sty { ty::TyAdt(def, substs) if def.is_struct() => { let fields = &def.struct_variant().fields; @@ -1581,20 +1581,21 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn write_autoderef_adjustment(&self, node_id: ast::NodeId, - derefs: usize) { - self.write_adjustment( - node_id, - adjustment::AdjustDerefRef(adjustment::AutoDerefRef { + derefs: usize, + adjusted_ty: Ty<'tcx>) { + self.write_adjustment(node_id, adjustment::Adjustment { + kind: adjustment::Adjust::DerefRef { autoderefs: derefs, autoref: None, - unsize: None - }) - ); + unsize: false + }, + target: adjusted_ty + }); } pub fn write_adjustment(&self, node_id: ast::NodeId, - adj: adjustment::AutoAdjustment<'tcx>) { + adj: adjustment::Adjustment<'tcx>) { debug!("write_adjustment(node_id={}, adj={:?})", node_id, adj); if adj.is_identity() { @@ -1760,21 +1761,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { t } - /// Apply `adjustment` to the type of `expr` - pub fn adjust_expr_ty(&self, - expr: &hir::Expr, - adjustment: Option<&adjustment::AutoAdjustment<'tcx>>) - -> Ty<'tcx> - { - let raw_ty = self.node_ty(expr.id); - let raw_ty = self.shallow_resolve(raw_ty); - let resolve_ty = |ty: Ty<'tcx>| self.resolve_type_vars_if_possible(&ty); - raw_ty.adjust(self.tcx, expr.span, expr.id, adjustment, |method_call| { - self.tables.borrow().method_map.get(&method_call) - .map(|method| resolve_ty(method.ty)) - }) - } - pub fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> { match self.tables.borrow().node_types.get(&id) { Some(&t) => t, @@ -2311,7 +2297,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { debug!("try_index_step: success, using built-in indexing"); // If we had `[T; N]`, we should've caught it before unsizing to `[T]`. assert!(!unsize); - self.write_autoderef_adjustment(base_expr.id, autoderefs); + self.write_autoderef_adjustment(base_expr.id, autoderefs, adjusted_ty); return Some((tcx.types.usize, ty)); } _ => {} @@ -2867,9 +2853,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // In case we did perform an adjustment, we have to update // the type of the block, because old trans still uses it. - let adj = self.tables.borrow().adjustments.get(&then.id).cloned(); - if res.is_ok() && adj.is_some() { - self.write_ty(then_blk.id, self.adjust_expr_ty(then, adj.as_ref())); + if res.is_ok() { + let adj = self.tables.borrow().adjustments.get(&then.id).cloned(); + if let Some(adj) = adj { + self.write_ty(then_blk.id, adj.target); + } } res @@ -2930,7 +2918,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let field_ty = self.field_ty(expr.span, field, substs); if field.vis.is_accessible_from(self.body_id, &self.tcx().map) { autoderef.finalize(lvalue_pref, Some(base)); - self.write_autoderef_adjustment(base.id, autoderefs); + self.write_autoderef_adjustment(base.id, autoderefs, base_t); return field_ty; } private_candidate = Some((base_def.did, field_ty)); @@ -3048,7 +3036,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(field_ty) = field { autoderef.finalize(lvalue_pref, Some(base)); - self.write_autoderef_adjustment(base.id, autoderefs); + self.write_autoderef_adjustment(base.id, autoderefs, base_t); return field_ty; } } @@ -3252,6 +3240,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } Def::Struct(..) | Def::Union(..) | Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => { + match def { + Def::AssociatedTy(..) | Def::SelfTy(..) + if !self.tcx.sess.features.borrow().more_struct_aliases => { + emit_feature_err(&self.tcx.sess.parse_sess, + "more_struct_aliases", path.span, GateIssue::Language, + "`Self` and associated types in struct \ + expressions and patterns are unstable"); + } + _ => {} + } match ty.sty { ty::TyAdt(adt, substs) if !adt.is_enum() => { Some((adt.struct_variant(), adt.did, substs)) @@ -3358,8 +3356,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if ty.is_never() { if let Some(hir::map::NodeExpr(_)) = self.tcx.map.find(expr.id) { let adj_ty = self.next_diverging_ty_var(); - let adj = adjustment::AdjustNeverToAny(adj_ty); - self.write_adjustment(expr.id, adj); + self.write_adjustment(expr.id, adjustment::Adjustment { + kind: adjustment::Adjust::NeverToAny, + target: adj_ty + }); return adj_ty; } } diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 9bfe80dba9db1..6f6538254c46b 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -259,23 +259,10 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { self.resolve_type(t) } - fn resolve_method_type(&self, method_call: MethodCall) -> Option> { - let method_ty = self.tables.borrow().method_map - .get(&method_call).map(|method| method.ty); - method_ty.map(|method_ty| self.resolve_type(method_ty)) - } - /// Try to resolve the type for the given node. pub fn resolve_expr_type_adjusted(&mut self, expr: &hir::Expr) -> Ty<'tcx> { - let ty_unadjusted = self.resolve_node_type(expr.id); - if ty_unadjusted.references_error() { - ty_unadjusted - } else { - ty_unadjusted.adjust( - self.tcx, expr.span, expr.id, - self.tables.borrow().adjustments.get(&expr.id), - |method_call| self.resolve_method_type(method_call)) - } + let ty = self.tables.borrow().expr_ty_adjusted(expr); + self.resolve_type(ty) } fn visit_fn_body(&mut self, @@ -553,10 +540,8 @@ impl<'a, 'gcx, 'tcx, 'v> Visitor<'v> for RegionCtxt<'a, 'gcx, 'tcx> { let adjustment = self.tables.borrow().adjustments.get(&expr.id).map(|a| a.clone()); if let Some(adjustment) = adjustment { debug!("adjustment={:?}", adjustment); - match adjustment { - adjustment::AdjustDerefRef(adjustment::AutoDerefRef { - autoderefs, ref autoref, .. - }) => { + match adjustment.kind { + adjustment::Adjust::DerefRef { autoderefs, ref autoref, .. } => { let expr_ty = self.resolve_node_type(expr.id); self.constrain_autoderefs(expr, autoderefs, expr_ty); if let Some(ref autoref) = *autoref { @@ -946,7 +931,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { let origin = infer::ParameterOrigin::OverloadedDeref; self.substs_wf_in_scope(origin, method.substs, deref_expr.span, r_deref_expr); - // Treat overloaded autoderefs as if an AutoRef adjustment + // Treat overloaded autoderefs as if an AutoBorrow adjustment // was applied on the base type, as that is always the case. let fn_sig = method.ty.fn_sig(); let fn_sig = // late-bound regions should have been instantiated @@ -1060,15 +1045,12 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { id: ast::NodeId, minimum_lifetime: &'tcx ty::Region) { - let tcx = self.tcx; - // Try to resolve the type. If we encounter an error, then typeck // is going to fail anyway, so just stop here and let typeck // report errors later on in the writeback phase. let ty0 = self.resolve_node_type(id); - let ty = ty0.adjust(tcx, origin.span(), id, - self.tables.borrow().adjustments.get(&id), - |method_call| self.resolve_method_type(method_call)); + let ty = self.tables.borrow().adjustments.get(&id).map_or(ty0, |adj| adj.target); + let ty = self.resolve_type(ty); debug!("constrain_regions_in_type_of_node(\ ty={}, ty0={}, id={}, minimum_lifetime={:?})", ty, ty0, @@ -1165,7 +1147,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { fn link_autoref(&self, expr: &hir::Expr, autoderefs: usize, - autoref: &adjustment::AutoRef<'tcx>) + autoref: &adjustment::AutoBorrow<'tcx>) { debug!("link_autoref(autoref={:?})", autoref); let mc = mc::MemCategorizationContext::new(self); @@ -1173,12 +1155,12 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { debug!("expr_cmt={:?}", expr_cmt); match *autoref { - adjustment::AutoPtr(r, m) => { + adjustment::AutoBorrow::Ref(r, m) => { self.link_region(expr.span, r, ty::BorrowKind::from_mutbl(m), expr_cmt); } - adjustment::AutoUnsafe(m) => { + adjustment::AutoBorrow::RawPtr(m) => { let r = self.tcx.node_scope_region(expr.id); self.link_region(expr.span, r, ty::BorrowKind::from_mutbl(m), expr_cmt); } diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index e3634cfe5f5e3..be1f2e35679d7 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -416,7 +416,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { } } None => { - let self_ty = fcx.tcx.node_id_to_type(item.id); + let self_ty = fcx.tcx.tables().node_id_to_type(item.id); let self_ty = fcx.instantiate_type_scheme(item.span, free_substs, &self_ty); fcx.register_wf_obligation(self_ty, ast_self_ty.span, this.code.clone()); } @@ -519,7 +519,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { item: &hir::Item, ast_generics: &hir::Generics) { - let ty = self.tcx().node_id_to_type(item.id); + let ty = self.tcx().tables().node_id_to_type(item.id); if self.tcx().has_error_field(ty) { return; } @@ -649,7 +649,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let fields = struct_def.fields().iter() .map(|field| { - let field_ty = self.tcx.node_id_to_type(field.id); + let field_ty = self.tcx.tables().node_id_to_type(field.id); let field_ty = self.instantiate_type_scheme(field.span, &self.parameter_environment .free_substs, diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 8685f703a599c..5ef3e8699602b 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -229,7 +229,7 @@ impl<'cx, 'gcx, 'tcx, 'v> Visitor<'v> for WritebackCx<'cx, 'gcx, 'tcx> { debug!("Type for pattern binding {} (id {}) resolved to {:?}", pat_to_string(p), p.id, - self.tcx().node_id_to_type(p.id)); + self.tcx().tables().node_id_to_type(p.id)); intravisit::walk_pat(self, p); } @@ -381,36 +381,40 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { } Some(adjustment) => { - let resolved_adjustment = match adjustment { - adjustment::AdjustNeverToAny(ty) => { - adjustment::AdjustNeverToAny(self.resolve(&ty, reason)) + let resolved_adjustment = match adjustment.kind { + adjustment::Adjust::NeverToAny => { + adjustment::Adjust::NeverToAny } - adjustment::AdjustReifyFnPointer => { - adjustment::AdjustReifyFnPointer + adjustment::Adjust::ReifyFnPointer => { + adjustment::Adjust::ReifyFnPointer } - adjustment::AdjustMutToConstPointer => { - adjustment::AdjustMutToConstPointer + adjustment::Adjust::MutToConstPointer => { + adjustment::Adjust::MutToConstPointer } - adjustment::AdjustUnsafeFnPointer => { - adjustment::AdjustUnsafeFnPointer + adjustment::Adjust::UnsafeFnPointer => { + adjustment::Adjust::UnsafeFnPointer } - adjustment::AdjustDerefRef(adj) => { - for autoderef in 0..adj.autoderefs { + adjustment::Adjust::DerefRef { autoderefs, autoref, unsize } => { + for autoderef in 0..autoderefs { let method_call = MethodCall::autoderef(id, autoderef as u32); self.visit_method_map_entry(reason, method_call); } - adjustment::AdjustDerefRef(adjustment::AutoDerefRef { - autoderefs: adj.autoderefs, - autoref: self.resolve(&adj.autoref, reason), - unsize: self.resolve(&adj.unsize, reason), - }) + adjustment::Adjust::DerefRef { + autoderefs: autoderefs, + autoref: self.resolve(&autoref, reason), + unsize: unsize, + } } }; + let resolved_adjustment = adjustment::Adjustment { + kind: resolved_adjustment, + target: self.resolve(&adjustment.target, reason) + }; debug!("Adjustments for node {}: {:?}", id, resolved_adjustment); self.tcx().tables.borrow_mut().adjustments.insert( id, resolved_adjustment); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 202e176df0dbc..0e0f5cb1a7e15 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1724,16 +1724,15 @@ fn add_unsized_bound<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, match unbound { Some(ref tpb) => { // FIXME(#8559) currently requires the unbound to be built-in. - let trait_def_id = tcx.expect_def(tpb.ref_id).def_id(); - match kind_id { - Ok(kind_id) if trait_def_id != kind_id => { + if let Ok(kind_id) = kind_id { + let trait_def = tcx.expect_def(tpb.ref_id); + if trait_def != Def::Trait(kind_id) { tcx.sess.span_warn(span, "default bound relaxed for a type parameter, but \ this does nothing because the given bound is not \ a default. Only `?Sized` is supported"); tcx.try_add_builtin_trait(kind_id, bounds); } - _ => {} } } _ if kind_id.is_ok() => { diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index d636baca248df..671274a4057c0 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -211,7 +211,7 @@ fn check_main_fn_ty(ccx: &CrateCtxt, main_id: ast::NodeId, main_span: Span) { let tcx = ccx.tcx; - let main_t = tcx.node_id_to_type(main_id); + let main_t = tcx.tables().node_id_to_type(main_id); match main_t.sty { ty::TyFnDef(..) => { match tcx.map.find(main_id) { @@ -263,7 +263,7 @@ fn check_start_fn_ty(ccx: &CrateCtxt, start_id: ast::NodeId, start_span: Span) { let tcx = ccx.tcx; - let start_t = tcx.node_id_to_type(start_id); + let start_t = tcx.tables().node_id_to_type(start_id); match start_t.sty { ty::TyFnDef(..) => { match tcx.map.find(start_id) { diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index fb8a0c3c26554..ece51d6d82616 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -11,6 +11,7 @@ use self::Entry::*; use self::VacantEntryState::*; +use cell::Cell; use borrow::Borrow; use cmp::max; use fmt::{self, Debug}; @@ -2049,24 +2050,21 @@ impl RandomState { // many hash maps are created on a thread. To solve this performance // trap we cache the first set of randomly generated keys per-thread. // - // In doing this, however, we lose the property that all hash maps have - // nondeterministic iteration order as all of those created on the same - // thread would have the same hash keys. This property has been nice in - // the past as it allows for maximal flexibility in the implementation - // of `HashMap` itself. - // - // The constraint here (if there even is one) is just that maps created - // on the same thread have the same iteration order, and that *may* be - // relied upon even though it is not a documented guarantee at all of - // the `HashMap` type. In any case we've decided that this is reasonable - // for now, so caching keys thread-locally seems fine. - thread_local!(static KEYS: (u64, u64) = { + // Later in #36481 it was discovered that exposing a deterministic + // iteration order allows a form of DOS attack. To counter that we + // increment one of the seeds on every RandomState creation, giving + // every corresponding HashMap a different iteration order. + thread_local!(static KEYS: Cell<(u64, u64)> = { let r = rand::OsRng::new(); let mut r = r.expect("failed to create an OS RNG"); - (r.gen(), r.gen()) + Cell::new((r.gen(), r.gen())) }); - KEYS.with(|&(k0, k1)| RandomState { k0: k0, k1: k1 }) + KEYS.with(|keys| { + let (k0, k1) = keys.get(); + keys.set((k0.wrapping_add(1), k1)); + RandomState { k0: k0, k1: k1 } + }) } } diff --git a/src/libstd/io/error.rs b/src/libstd/io/error.rs index 659c8aa5aeafb..795c89c000747 100644 --- a/src/libstd/io/error.rs +++ b/src/libstd/io/error.rs @@ -126,23 +126,28 @@ pub enum ErrorKind { InvalidInput, /// Data not valid for the operation were encountered. /// - /// Unlike `InvalidInput`, this typically means that the operation + /// Unlike [`InvalidInput`], this typically means that the operation /// parameters were valid, however the error was caused by malformed /// input data. /// /// For example, a function that reads a file into a string will error with /// `InvalidData` if the file's contents are not valid UTF-8. + /// + /// [`InvalidInput`]: #variant.InvalidInput #[stable(feature = "io_invalid_data", since = "1.2.0")] InvalidData, /// The I/O operation's timeout expired, causing it to be canceled. #[stable(feature = "rust1", since = "1.0.0")] TimedOut, /// An error returned when an operation could not be completed because a - /// call to `write` returned `Ok(0)`. + /// call to [`write()`] returned [`Ok(0)`]. /// /// This typically means that an operation could only succeed if it wrote a /// particular number of bytes but only a smaller number of bytes could be /// written. + /// + /// [`write()`]: ../../std/io/trait.Write.html#tymethod.write + /// [`Ok(0)`]: ../../std/io/type.Result.html #[stable(feature = "rust1", since = "1.0.0")] WriteZero, /// This operation was interrupted. diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 9b7f9980cc0af..bb6883236e802 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -1173,6 +1173,13 @@ impl From for PathBuf { } } +#[stable(feature = "from_path_buf_for_os_string", since = "1.14.0")] +impl From for OsString { + fn from(path_buf : PathBuf) -> OsString { + path_buf.inner + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl From for PathBuf { fn from(s: String) -> PathBuf { @@ -1283,13 +1290,6 @@ impl AsRef for PathBuf { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl Into for PathBuf { - fn into(self) -> OsString { - self.inner - } -} - /// A slice of a path (akin to [`str`]). /// /// This type supports a number of operations for inspecting a path, including diff --git a/src/libstd/sys/unix/rand.rs b/src/libstd/sys/unix/rand.rs index 3aebb8c18ec86..9b1cf6ffd0e22 100644 --- a/src/libstd/sys/unix/rand.rs +++ b/src/libstd/sys/unix/rand.rs @@ -350,11 +350,19 @@ mod imp { #[link(name = "magenta")] extern { - fn mx_cprng_draw(buffer: *mut u8, len: usize) -> isize; + fn mx_cprng_draw(buffer: *mut u8, len: usize, actual: *mut usize) -> i32; } - fn getrandom(buf: &mut [u8]) -> isize { - unsafe { mx_cprng_draw(buf.as_mut_ptr(), buf.len()) } + fn getrandom(buf: &mut [u8]) -> Result { + unsafe { + let mut actual = 0; + let status = mx_cprng_draw(buf.as_mut_ptr(), buf.len(), &mut actual); + if status == 0 { + Ok(actual) + } else { + Err(status) + } + } } pub struct OsRng { @@ -381,12 +389,16 @@ mod imp { let mut buf = v; while !buf.is_empty() { let ret = getrandom(buf); - if ret < 0 { - panic!("kernel mx_cprng_draw call failed! (returned {}, buf.len() {})", - ret, buf.len()); + match ret { + Err(err) => { + panic!("kernel mx_cprng_draw call failed! (returned {}, buf.len() {})", + err, buf.len()) + } + Ok(actual) => { + let move_buf = buf; + buf = &mut move_buf[(actual as usize)..]; + } } - let move_buf = buf; - buf = &mut move_buf[(ret as usize)..]; } } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index f077ead1f8e07..f7581924eb19f 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1050,7 +1050,7 @@ pub enum ExprKind { Ret(Option>), /// Output of the `asm!()` macro - InlineAsm(InlineAsm), + InlineAsm(P), /// A macro invocation; pre-expansion Mac(Mac), diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index cc097ab0efadc..1f47a91fcc13e 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -615,7 +615,9 @@ impl<'a> ExtCtxt<'a> { pub fn new_parser_from_tts(&self, tts: &[tokenstream::TokenTree]) -> parser::Parser<'a> { - parse::tts_to_parser(self.parse_sess, tts.to_vec()) + let mut parser = parse::tts_to_parser(self.parse_sess, tts.to_vec()); + parser.allow_interpolated_tts = false; // FIXME(jseyfried) `quote!` can't handle these yet + parser } pub fn codemap(&self) -> &'a CodeMap { self.parse_sess.codemap() } pub fn parse_sess(&self) -> &'a parse::ParseSess { self.parse_sess } diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index f21360755bc26..969cfa292ce80 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -80,67 +80,71 @@ pub mod rt { impl ToTokens for ast::Path { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![TokenTree::Token(DUMMY_SP, - token::Interpolated(token::NtPath(Box::new(self.clone()))))] + let nt = token::NtPath(self.clone()); + vec![TokenTree::Token(DUMMY_SP, token::Interpolated(Rc::new(nt)))] } } impl ToTokens for ast::Ty { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![TokenTree::Token(self.span, token::Interpolated(token::NtTy(P(self.clone()))))] + let nt = token::NtTy(P(self.clone())); + vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))] } } impl ToTokens for ast::Block { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![TokenTree::Token(self.span, token::Interpolated(token::NtBlock(P(self.clone()))))] + let nt = token::NtBlock(P(self.clone())); + vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))] } } impl ToTokens for ast::Generics { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![TokenTree::Token(DUMMY_SP, token::Interpolated(token::NtGenerics(self.clone())))] + let nt = token::NtGenerics(self.clone()); + vec![TokenTree::Token(DUMMY_SP, token::Interpolated(Rc::new(nt)))] } } impl ToTokens for ast::WhereClause { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![TokenTree::Token(DUMMY_SP, - token::Interpolated(token::NtWhereClause(self.clone())))] + let nt = token::NtWhereClause(self.clone()); + vec![TokenTree::Token(DUMMY_SP, token::Interpolated(Rc::new(nt)))] } } impl ToTokens for P { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![TokenTree::Token(self.span, token::Interpolated(token::NtItem(self.clone())))] + let nt = token::NtItem(self.clone()); + vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))] } } impl ToTokens for ast::ImplItem { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![TokenTree::Token(self.span, - token::Interpolated(token::NtImplItem(P(self.clone()))))] + let nt = token::NtImplItem(self.clone()); + vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))] } } impl ToTokens for P { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![TokenTree::Token(self.span, token::Interpolated(token::NtImplItem(self.clone())))] + let nt = token::NtImplItem((**self).clone()); + vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))] } } impl ToTokens for ast::TraitItem { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![TokenTree::Token(self.span, - token::Interpolated(token::NtTraitItem(P(self.clone()))))] + let nt = token::NtTraitItem(self.clone()); + vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))] } } impl ToTokens for ast::Stmt { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - let mut tts = vec![ - TokenTree::Token(self.span, token::Interpolated(token::NtStmt(P(self.clone())))) - ]; + let nt = token::NtStmt(self.clone()); + let mut tts = vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))]; // Some statements require a trailing semicolon. if classify::stmt_ends_with_semi(&self.node) { @@ -153,31 +157,36 @@ pub mod rt { impl ToTokens for P { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![TokenTree::Token(self.span, token::Interpolated(token::NtExpr(self.clone())))] + let nt = token::NtExpr(self.clone()); + vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))] } } impl ToTokens for P { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![TokenTree::Token(self.span, token::Interpolated(token::NtPat(self.clone())))] + let nt = token::NtPat(self.clone()); + vec![TokenTree::Token(self.span, token::Interpolated(Rc::new(nt)))] } } impl ToTokens for ast::Arm { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![TokenTree::Token(DUMMY_SP, token::Interpolated(token::NtArm(self.clone())))] + let nt = token::NtArm(self.clone()); + vec![TokenTree::Token(DUMMY_SP, token::Interpolated(Rc::new(nt)))] } } impl ToTokens for ast::Arg { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![TokenTree::Token(DUMMY_SP, token::Interpolated(token::NtArg(self.clone())))] + let nt = token::NtArg(self.clone()); + vec![TokenTree::Token(DUMMY_SP, token::Interpolated(Rc::new(nt)))] } } impl ToTokens for P { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![TokenTree::Token(DUMMY_SP, token::Interpolated(token::NtBlock(self.clone())))] + let nt = token::NtBlock(self.clone()); + vec![TokenTree::Token(DUMMY_SP, token::Interpolated(Rc::new(nt)))] } } @@ -204,7 +213,8 @@ pub mod rt { impl ToTokens for P { fn to_tokens(&self, _cx: &ExtCtxt) -> Vec { - vec![TokenTree::Token(DUMMY_SP, token::Interpolated(token::NtMeta(self.clone())))] + let nt = token::NtMeta(self.clone()); + vec![TokenTree::Token(DUMMY_SP, token::Interpolated(Rc::new(nt)))] } } diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index 7e3fe3285695c..1066646aa8e8a 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -89,7 +89,6 @@ use parse::token::{DocComment, MatchNt, SubstNt}; use parse::token::{Token, Nonterminal}; use parse::token; use print::pprust; -use ptr::P; use tokenstream::{self, TokenTree}; use util::small_vector::SmallVector; @@ -198,7 +197,7 @@ pub fn initial_matcher_pos(ms: Vec, sep: Option, lo: BytePos) pub enum NamedMatch { MatchedSeq(Vec>, syntax_pos::Span), - MatchedNonterminal(Nonterminal) + MatchedNonterminal(Rc) } pub fn nameize(p_s: &ParseSess, ms: &[TokenTree], res: &[Rc]) @@ -279,17 +278,16 @@ pub fn token_name_eq(t1 : &Token, t2 : &Token) -> bool { } } -pub fn parse(sess: &ParseSess, mut rdr: TtReader, ms: &[TokenTree]) -> NamedParseResult { - let mut cur_eis = SmallVector::one(initial_matcher_pos(ms.to_owned(), - None, - rdr.peek().sp.lo)); +pub fn parse(sess: &ParseSess, rdr: TtReader, ms: &[TokenTree]) -> NamedParseResult { + let mut parser = Parser::new_with_doc_flag(sess, Box::new(rdr), true); + let mut cur_eis = SmallVector::one(initial_matcher_pos(ms.to_owned(), None, parser.span.lo)); loop { let mut bb_eis = Vec::new(); // black-box parsed by parser.rs let mut next_eis = Vec::new(); // or proceed normally let mut eof_eis = Vec::new(); - let TokenAndSpan { tok, sp } = rdr.peek(); + let (sp, tok) = (parser.span, parser.token.clone()); /* we append new items to this while we go */ loop { @@ -474,23 +472,19 @@ pub fn parse(sess: &ParseSess, mut rdr: TtReader, ms: &[TokenTree]) -> NamedPars while !next_eis.is_empty() { cur_eis.push(next_eis.pop().unwrap()); } - rdr.next_token(); + parser.bump(); } else /* bb_eis.len() == 1 */ { - rdr.next_tok = { - let mut rust_parser = Parser::new(sess, Box::new(&mut rdr)); - let mut ei = bb_eis.pop().unwrap(); - if let TokenTree::Token(span, MatchNt(_, ident)) = ei.top_elts.get_tt(ei.idx) { - let match_cur = ei.match_cur; - (&mut ei.matches[match_cur]).push(Rc::new(MatchedNonterminal( - parse_nt(&mut rust_parser, span, &ident.name.as_str())))); - ei.idx += 1; - ei.match_cur += 1; - } else { - unreachable!() - } - cur_eis.push(ei); - Some(TokenAndSpan { tok: rust_parser.token, sp: rust_parser.span }) - }; + let mut ei = bb_eis.pop().unwrap(); + if let TokenTree::Token(span, MatchNt(_, ident)) = ei.top_elts.get_tt(ei.idx) { + let match_cur = ei.match_cur; + (&mut ei.matches[match_cur]).push(Rc::new(MatchedNonterminal( + Rc::new(parse_nt(&mut parser, span, &ident.name.as_str()))))); + ei.idx += 1; + ei.match_cur += 1; + } else { + unreachable!() + } + cur_eis.push(ei); } } @@ -502,10 +496,19 @@ pub fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal { match name { "tt" => { p.quote_depth += 1; //but in theory, non-quoted tts might be useful - let res: ::parse::PResult<'a, _> = p.parse_token_tree(); - let res = token::NtTT(P(panictry!(res))); + let mut tt = panictry!(p.parse_token_tree()); p.quote_depth -= 1; - return res; + loop { + let nt = match tt { + TokenTree::Token(_, token::Interpolated(ref nt)) => nt.clone(), + _ => break, + }; + match *nt { + token::NtTT(ref sub_tt) => tt = sub_tt.clone(), + _ => break, + } + } + return token::NtTT(tt); } _ => {} } @@ -521,7 +524,7 @@ pub fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal { }, "block" => token::NtBlock(panictry!(p.parse_block())), "stmt" => match panictry!(p.parse_stmt()) { - Some(s) => token::NtStmt(P(s)), + Some(s) => token::NtStmt(s), None => { p.fatal("expected a statement").emit(); panic!(FatalError); @@ -534,7 +537,7 @@ pub fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal { "ident" => match p.token { token::Ident(sn) => { p.bump(); - token::NtIdent(Box::new(Spanned::{node: sn, span: p.span})) + token::NtIdent(Spanned::{node: sn, span: p.span}) } _ => { let token_str = pprust::token_to_string(&p.token); @@ -544,7 +547,7 @@ pub fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal { } }, "path" => { - token::NtPath(Box::new(panictry!(p.parse_path(PathStyle::Type)))) + token::NtPath(panictry!(p.parse_path(PathStyle::Type))) }, "meta" => token::NtMeta(panictry!(p.parse_meta_item())), // this is not supposed to happen, since it has been checked diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 431e757368c03..552d4de961740 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -236,12 +236,14 @@ pub fn compile(sess: &ParseSess, def: &ast::MacroDef) -> SyntaxExtension { // Extract the arguments: let lhses = match **argument_map.get(&lhs_nm).unwrap() { MatchedSeq(ref s, _) => { - s.iter().map(|m| match **m { - MatchedNonterminal(NtTT(ref tt)) => { - valid &= check_lhs_nt_follows(sess, tt); - (**tt).clone() + s.iter().map(|m| { + if let MatchedNonterminal(ref nt) = **m { + if let NtTT(ref tt) = **nt { + valid &= check_lhs_nt_follows(sess, tt); + return (*tt).clone(); + } } - _ => sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs") + sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs") }).collect::>() } _ => sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs") @@ -249,9 +251,13 @@ pub fn compile(sess: &ParseSess, def: &ast::MacroDef) -> SyntaxExtension { let rhses = match **argument_map.get(&rhs_nm).unwrap() { MatchedSeq(ref s, _) => { - s.iter().map(|m| match **m { - MatchedNonterminal(NtTT(ref tt)) => (**tt).clone(), - _ => sess.span_diagnostic.span_bug(def.span, "wrong-structured rhs") + s.iter().map(|m| { + if let MatchedNonterminal(ref nt) = **m { + if let NtTT(ref tt) = **nt { + return (*tt).clone(); + } + } + sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs") }).collect() } _ => sess.span_diagnostic.span_bug(def.span, "wrong-structured rhs") diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 8a6a8e53a3e4c..37e329e5d3b29 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -12,9 +12,7 @@ use self::LockstepIterSize::*; use ast::Ident; use errors::{Handler, DiagnosticBuilder}; use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal}; -use parse::token::{DocComment, MatchNt, SubstNt}; -use parse::token::{Token, Interpolated, NtIdent, NtTT}; -use parse::token; +use parse::token::{self, MatchNt, SubstNt, Token, NtIdent}; use parse::lexer::TokenAndSpan; use syntax_pos::{Span, DUMMY_SP}; use tokenstream::{self, TokenTree}; @@ -46,9 +44,7 @@ pub struct TtReader<'a> { /* cached: */ pub cur_tok: Token, pub cur_span: Span, - pub next_tok: Option, /// Transform doc comments. Only useful in macro invocations - pub desugar_doc_comments: bool, pub fatal_errs: Vec>, } @@ -59,20 +55,6 @@ pub fn new_tt_reader(sp_diag: &Handler, interp: Option>>, src: Vec) -> TtReader { - new_tt_reader_with_doc_flag(sp_diag, interp, src, false) -} - -/// The extra `desugar_doc_comments` flag enables reading doc comments -/// like any other attribute which consists of `meta` and surrounding #[ ] tokens. -/// -/// This can do Macro-By-Example transcription. On the other hand, if -/// `src` contains no `TokenTree::Sequence`s, `MatchNt`s or `SubstNt`s, `interp` can -/// (and should) be None. -pub fn new_tt_reader_with_doc_flag(sp_diag: &Handler, - interp: Option>>, - src: Vec, - desugar_doc_comments: bool) - -> TtReader { let mut r = TtReader { sp_diag: sp_diag, stack: SmallVector::one(TtFrame { @@ -91,11 +73,9 @@ pub fn new_tt_reader_with_doc_flag(sp_diag: &Handler, }, repeat_idx: Vec::new(), repeat_len: Vec::new(), - desugar_doc_comments: desugar_doc_comments, /* dummy values, never read: */ cur_tok: token::Eof, cur_span: DUMMY_SP, - next_tok: None, fatal_errs: Vec::new(), }; tt_next_token(&mut r); /* get cur_tok and cur_span set up */ @@ -174,9 +154,6 @@ fn lockstep_iter_size(t: &TokenTree, r: &TtReader) -> LockstepIterSize { /// Return the next token from the TtReader. /// EFFECT: advances the reader's token field pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { - if let Some(tok) = r.next_tok.take() { - return tok; - } // FIXME(pcwalton): Bad copy? let ret_val = TokenAndSpan { tok: r.cur_tok.clone(), @@ -269,47 +246,35 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { } // FIXME #2887: think about span stuff here TokenTree::Token(sp, SubstNt(ident)) => { + r.stack.last_mut().unwrap().idx += 1; match lookup_cur_matched(r, ident) { None => { - r.stack.last_mut().unwrap().idx += 1; r.cur_span = sp; r.cur_tok = SubstNt(ident); return ret_val; // this can't be 0 length, just like TokenTree::Delimited } - Some(cur_matched) => { - match *cur_matched { + Some(cur_matched) => if let MatchedNonterminal(ref nt) = *cur_matched { + match **nt { // sidestep the interpolation tricks for ident because // (a) idents can be in lots of places, so it'd be a pain // (b) we actually can, since it's a token. - MatchedNonterminal(NtIdent(ref sn)) => { - r.stack.last_mut().unwrap().idx += 1; + NtIdent(ref sn) => { r.cur_span = sn.span; r.cur_tok = token::Ident(sn.node); return ret_val; } - MatchedNonterminal(NtTT(ref tt)) => { - r.stack.push(TtFrame { - forest: TokenTree::Token(sp, Interpolated(NtTT(tt.clone()))), - idx: 0, - dotdotdoted: false, - sep: None, - }); - } - MatchedNonterminal(ref other_whole_nt) => { - r.stack.last_mut().unwrap().idx += 1; + _ => { // FIXME(pcwalton): Bad copy. r.cur_span = sp; - r.cur_tok = Interpolated((*other_whole_nt).clone()); + r.cur_tok = token::Interpolated(nt.clone()); return ret_val; } - MatchedSeq(..) => { - panic!(r.sp_diag.span_fatal( - sp, /* blame the macro writer */ - &format!("variable '{}' is still repeating at this depth", - ident))); - } } + } else { + panic!(r.sp_diag.span_fatal( + sp, /* blame the macro writer */ + &format!("variable '{}' is still repeating at this depth", ident))); } } } @@ -324,14 +289,6 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { }); // if this could be 0-length, we'd need to potentially recur here } - TokenTree::Token(sp, DocComment(name)) if r.desugar_doc_comments => { - r.stack.push(TtFrame { - forest: TokenTree::Token(sp, DocComment(name)), - idx: 0, - dotdotdoted: false, - sep: None - }); - } TokenTree::Token(sp, tok) => { r.cur_span = sp; r.cur_tok = tok; diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 129e4a8233803..ba16208715109 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -309,6 +309,12 @@ declare_features! ( // Allows field shorthands (`x` meaning `x: x`) in struct literal expressions. (active, field_init_shorthand, "1.14.0", Some(37340)), + + // The #![windows_subsystem] attribute + (active, windows_subsystem, "1.14.0", Some(37499)), + + // Allows using `Self` and associated types in struct expressions and patterns. + (active, more_struct_aliases, "1.14.0", Some(37544)), ); declare_features! ( @@ -713,6 +719,12 @@ pub const KNOWN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeGat "defining reflective traits is still evolving", cfg_fn!(reflect))), + ("windows_subsystem", Whitelisted, Gated(Stability::Unstable, + "windows_subsystem", + "the windows subsystem attribute \ + is currently unstable", + cfg_fn!(windows_subsystem))), + // Crate level attributes ("crate_name", CrateLevel, Ungated), ("crate_type", CrateLevel, Ungated), diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 4bf6e55d6743b..1deeaf422316c 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -576,7 +576,13 @@ pub fn noop_fold_token(t: token::Token, fld: &mut T) -> token::Token match t { token::Ident(id) => token::Ident(fld.fold_ident(id)), token::Lifetime(id) => token::Lifetime(fld.fold_ident(id)), - token::Interpolated(nt) => token::Interpolated(fld.fold_interpolated(nt)), + token::Interpolated(nt) => { + let nt = match Rc::try_unwrap(nt) { + Ok(nt) => nt, + Err(nt) => (*nt).clone(), + }; + token::Interpolated(Rc::new(fld.fold_interpolated(nt))) + } token::SubstNt(ident) => token::SubstNt(fld.fold_ident(ident)), token::MatchNt(name, kind) => token::MatchNt(fld.fold_ident(name), fld.fold_ident(kind)), _ => t @@ -614,26 +620,25 @@ pub fn noop_fold_interpolated(nt: token::Nonterminal, fld: &mut T) .expect_one("expected fold to produce exactly one item")), token::NtBlock(block) => token::NtBlock(fld.fold_block(block)), token::NtStmt(stmt) => - token::NtStmt(stmt.map(|stmt| fld.fold_stmt(stmt) + token::NtStmt(fld.fold_stmt(stmt) // this is probably okay, because the only folds likely // to peek inside interpolated nodes will be renamings/markings, // which map single items to single items - .expect_one("expected fold to produce exactly one statement"))), + .expect_one("expected fold to produce exactly one statement")), token::NtPat(pat) => token::NtPat(fld.fold_pat(pat)), token::NtExpr(expr) => token::NtExpr(fld.fold_expr(expr)), token::NtTy(ty) => token::NtTy(fld.fold_ty(ty)), - token::NtIdent(id) => - token::NtIdent(Box::new(Spanned::{node: fld.fold_ident(id.node), ..*id})), + token::NtIdent(id) => token::NtIdent(Spanned::{node: fld.fold_ident(id.node), ..id}), token::NtMeta(meta_item) => token::NtMeta(fld.fold_meta_item(meta_item)), - token::NtPath(path) => token::NtPath(Box::new(fld.fold_path(*path))), - token::NtTT(tt) => token::NtTT(P(fld.fold_tt(&tt))), + token::NtPath(path) => token::NtPath(fld.fold_path(path)), + token::NtTT(tt) => token::NtTT(fld.fold_tt(&tt)), token::NtArm(arm) => token::NtArm(fld.fold_arm(arm)), - token::NtImplItem(arm) => - token::NtImplItem(arm.map(|arm| fld.fold_impl_item(arm) - .expect_one("expected fold to produce exactly one item"))), - token::NtTraitItem(arm) => - token::NtTraitItem(arm.map(|arm| fld.fold_trait_item(arm) - .expect_one("expected fold to produce exactly one item"))), + token::NtImplItem(item) => + token::NtImplItem(fld.fold_impl_item(item) + .expect_one("expected fold to produce exactly one item")), + token::NtTraitItem(item) => + token::NtTraitItem(fld.fold_trait_item(item) + .expect_one("expected fold to produce exactly one item")), token::NtGenerics(generics) => token::NtGenerics(fld.fold_generics(generics)), token::NtWhereClause(where_clause) => token::NtWhereClause(fld.fold_where_clause(where_clause)), @@ -1244,36 +1249,22 @@ pub fn noop_fold_expr(Expr {id, node, span, attrs}: Expr, folder: &mu folder.fold_ident(label.node))) ), ExprKind::Ret(e) => ExprKind::Ret(e.map(|x| folder.fold_expr(x))), - ExprKind::InlineAsm(InlineAsm { - inputs, - outputs, - asm, - asm_str_style, - clobbers, - volatile, - alignstack, - dialect, - expn_id, - }) => ExprKind::InlineAsm(InlineAsm { - inputs: inputs.move_map(|(c, input)| { - (c, folder.fold_expr(input)) - }), - outputs: outputs.move_map(|out| { - InlineAsmOutput { - constraint: out.constraint, - expr: folder.fold_expr(out.expr), - is_rw: out.is_rw, - is_indirect: out.is_indirect, - } - }), - asm: asm, - asm_str_style: asm_str_style, - clobbers: clobbers, - volatile: volatile, - alignstack: alignstack, - dialect: dialect, - expn_id: expn_id, - }), + ExprKind::InlineAsm(asm) => ExprKind::InlineAsm(asm.map(|asm| { + InlineAsm { + inputs: asm.inputs.move_map(|(c, input)| { + (c, folder.fold_expr(input)) + }), + outputs: asm.outputs.move_map(|out| { + InlineAsmOutput { + constraint: out.constraint, + expr: folder.fold_expr(out.expr), + is_rw: out.is_rw, + is_indirect: out.is_indirect, + } + }), + ..asm + } + })), ExprKind::Mac(mac) => ExprKind::Mac(folder.fold_mac(mac)), ExprKind::Struct(path, fields, maybe_expr) => { ExprKind::Struct(folder.fold_path(path), diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index 3cb34fa3c91c5..983c882eafca3 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -215,7 +215,10 @@ impl<'a> Parser<'a> { /// meta_item_inner : (meta_item | UNSUFFIXED_LIT) (',' meta_item_inner)? ; pub fn parse_meta_item(&mut self) -> PResult<'a, P> { let nt_meta = match self.token { - token::Interpolated(token::NtMeta(ref e)) => Some(e.clone()), + token::Interpolated(ref nt) => match **nt { + token::NtMeta(ref e) => Some(e.clone()), + _ => None, + }, _ => None, }; diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 5e20f6e419276..cf48c445c80eb 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -22,7 +22,7 @@ use std::char; use std::mem::replace; use std::rc::Rc; -pub use ext::tt::transcribe::{TtReader, new_tt_reader, new_tt_reader_with_doc_flag}; +pub use ext::tt::transcribe::{TtReader, new_tt_reader}; pub mod comments; mod unicode_chars; @@ -171,31 +171,10 @@ impl<'a> Reader for TtReader<'a> { self.fatal_errs.clear(); } fn peek(&self) -> TokenAndSpan { - self.next_tok.clone().unwrap_or(TokenAndSpan { + TokenAndSpan { tok: self.cur_tok.clone(), sp: self.cur_span, - }) - } -} - -impl<'a, 'b> Reader for &'b mut TtReader<'a> { - fn is_eof(&self) -> bool { - (**self).is_eof() - } - fn try_next_token(&mut self) -> Result { - (**self).try_next_token() - } - fn fatal(&self, m: &str) -> FatalError { - (**self).fatal(m) - } - fn err(&self, m: &str) { - (**self).err(m) - } - fn emit_fatal_errors(&mut self) { - (**self).emit_fatal_errors() - } - fn peek(&self) -> TokenAndSpan { - (**self).peek() + } } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index b80aa667be6a1..b670a7384739b 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -107,125 +107,41 @@ pub enum SemiColonMode { /// be. The important thing is to make sure that lookahead doesn't balk at /// `token::Interpolated` tokens. macro_rules! maybe_whole_expr { - ($p:expr) => ( - { - let found = match $p.token { - token::Interpolated(token::NtExpr(ref e)) => { - Some((*e).clone()) + ($p:expr) => { + if let token::Interpolated(nt) = $p.token.clone() { + match *nt { + token::NtExpr(ref e) => { + $p.bump(); + return Ok((*e).clone()); } - token::Interpolated(token::NtPath(_)) => { - // FIXME: The following avoids an issue with lexical borrowck scopes, - // but the clone is unfortunate. - let pt = match $p.token { - token::Interpolated(token::NtPath(ref pt)) => (**pt).clone(), - _ => unreachable!() - }; + token::NtPath(ref path) => { + $p.bump(); let span = $p.span; - Some($p.mk_expr(span.lo, span.hi, ExprKind::Path(None, pt), ThinVec::new())) + let kind = ExprKind::Path(None, (*path).clone()); + return Ok($p.mk_expr(span.lo, span.hi, kind, ThinVec::new())); } - token::Interpolated(token::NtBlock(_)) => { - // FIXME: The following avoids an issue with lexical borrowck scopes, - // but the clone is unfortunate. - let b = match $p.token { - token::Interpolated(token::NtBlock(ref b)) => (*b).clone(), - _ => unreachable!() - }; + token::NtBlock(ref block) => { + $p.bump(); let span = $p.span; - Some($p.mk_expr(span.lo, span.hi, ExprKind::Block(b), ThinVec::new())) + let kind = ExprKind::Block((*block).clone()); + return Ok($p.mk_expr(span.lo, span.hi, kind, ThinVec::new())); } - _ => None + _ => {}, }; - match found { - Some(e) => { - $p.bump(); - return Ok(e); - } - None => () - } } - ) + } } /// As maybe_whole_expr, but for things other than expressions macro_rules! maybe_whole { - ($p:expr, $constructor:ident) => ( - { - let found = match ($p).token { - token::Interpolated(token::$constructor(_)) => { - Some(($p).bump_and_get()) - } - _ => None - }; - if let Some(token::Interpolated(token::$constructor(x))) = found { - return Ok(x.clone()); + ($p:expr, $constructor:ident, |$x:ident| $e:expr) => { + if let token::Interpolated(nt) = $p.token.clone() { + if let token::$constructor($x) = (*nt).clone() { + $p.bump(); + return Ok($e); } } - ); - (no_clone $p:expr, $constructor:ident) => ( - { - let found = match ($p).token { - token::Interpolated(token::$constructor(_)) => { - Some(($p).bump_and_get()) - } - _ => None - }; - if let Some(token::Interpolated(token::$constructor(x))) = found { - return Ok(x); - } - } - ); - (no_clone_from_p $p:expr, $constructor:ident) => ( - { - let found = match ($p).token { - token::Interpolated(token::$constructor(_)) => { - Some(($p).bump_and_get()) - } - _ => None - }; - if let Some(token::Interpolated(token::$constructor(x))) = found { - return Ok(x.unwrap()); - } - } - ); - (deref $p:expr, $constructor:ident) => ( - { - let found = match ($p).token { - token::Interpolated(token::$constructor(_)) => { - Some(($p).bump_and_get()) - } - _ => None - }; - if let Some(token::Interpolated(token::$constructor(x))) = found { - return Ok((*x).clone()); - } - } - ); - (Some deref $p:expr, $constructor:ident) => ( - { - let found = match ($p).token { - token::Interpolated(token::$constructor(_)) => { - Some(($p).bump_and_get()) - } - _ => None - }; - if let Some(token::Interpolated(token::$constructor(x))) = found { - return Ok(Some((*x).clone())); - } - } - ); - (pair_empty $p:expr, $constructor:ident) => ( - { - let found = match ($p).token { - token::Interpolated(token::$constructor(_)) => { - Some(($p).bump_and_get()) - } - _ => None - }; - if let Some(token::Interpolated(token::$constructor(x))) = found { - return Ok((Vec::new(), x)); - } - } - ) + }; } fn maybe_append(mut lhs: Vec, rhs: Option>) @@ -294,6 +210,9 @@ pub struct Parser<'a> { /// into modules, and sub-parsers have new values for this name. pub root_module_name: Option, pub expected_tokens: Vec, + pub tts: Vec<(TokenTree, usize)>, + pub desugar_doc_comments: bool, + pub allow_interpolated_tts: bool, } #[derive(PartialEq, Eq, Clone)] @@ -357,21 +276,18 @@ impl From> for LhsExpr { } impl<'a> Parser<'a> { - pub fn new(sess: &'a ParseSess, mut rdr: Box) -> Self { - let tok0 = rdr.real_token(); - let span = tok0.sp; - let mut directory = match span { - syntax_pos::DUMMY_SP => PathBuf::new(), - _ => PathBuf::from(sess.codemap().span_to_filename(span)), - }; - directory.pop(); + pub fn new(sess: &'a ParseSess, rdr: Box) -> Self { + Parser::new_with_doc_flag(sess, rdr, false) + } - Parser { + pub fn new_with_doc_flag(sess: &'a ParseSess, rdr: Box, desugar_doc_comments: bool) + -> Self { + let mut parser = Parser { reader: rdr, sess: sess, - token: tok0.tok, - span: span, - prev_span: span, + token: token::Underscore, + span: syntax_pos::DUMMY_SP, + prev_span: syntax_pos::DUMMY_SP, prev_token_kind: PrevTokenKind::Other, lookahead_buffer: Default::default(), tokens_consumed: 0, @@ -379,11 +295,63 @@ impl<'a> Parser<'a> { quote_depth: 0, parsing_token_tree: false, obsolete_set: HashSet::new(), - directory: directory, + directory: PathBuf::new(), open_braces: Vec::new(), owns_directory: true, root_module_name: None, expected_tokens: Vec::new(), + tts: Vec::new(), + desugar_doc_comments: desugar_doc_comments, + allow_interpolated_tts: true, + }; + + let tok = parser.next_tok(); + parser.token = tok.tok; + parser.span = tok.sp; + if parser.span != syntax_pos::DUMMY_SP { + parser.directory = PathBuf::from(sess.codemap().span_to_filename(parser.span)); + parser.directory.pop(); + } + parser + } + + fn next_tok(&mut self) -> TokenAndSpan { + 'outer: loop { + let mut tok = if let Some((tts, i)) = self.tts.pop() { + let tt = tts.get_tt(i); + if i + 1 < tts.len() { + self.tts.push((tts, i + 1)); + } + if let TokenTree::Token(sp, tok) = tt { + TokenAndSpan { tok: tok, sp: sp } + } else { + self.tts.push((tt, 0)); + continue + } + } else { + self.reader.real_token() + }; + + loop { + let nt = match tok.tok { + token::Interpolated(ref nt) => nt.clone(), + token::DocComment(name) if self.desugar_doc_comments => { + self.tts.push((TokenTree::Token(tok.sp, token::DocComment(name)), 0)); + continue 'outer + } + _ => return tok, + }; + match *nt { + token::NtTT(TokenTree::Token(sp, ref t)) => { + tok = TokenAndSpan { tok: t.clone(), sp: sp }; + } + token::NtTT(ref tt) => { + self.tts.push((tt.clone(), 0)); + continue 'outer + } + _ => return tok, + } + } } } @@ -516,9 +484,6 @@ impl<'a> Parser<'a> { self.bump(); Ok(i) } - token::Interpolated(token::NtIdent(..)) => { - self.bug("ident interpolation not converted to real token"); - } _ => { Err(if self.prev_token_kind == PrevTokenKind::DocComment { self.span_fatal_help(self.prev_span, @@ -935,7 +900,7 @@ impl<'a> Parser<'a> { }; let next = if self.lookahead_buffer.start == self.lookahead_buffer.end { - self.reader.real_token() + self.next_tok() } else { // Avoid token copies with `replace`. let old_start = self.lookahead_buffer.start; @@ -980,7 +945,7 @@ impl<'a> Parser<'a> { f(&self.token) } else if dist < LOOKAHEAD_BUFFER_CAPACITY { while self.lookahead_buffer.len() < dist { - self.lookahead_buffer.buffer[self.lookahead_buffer.end] = self.reader.real_token(); + self.lookahead_buffer.buffer[self.lookahead_buffer.end] = self.next_tok(); self.lookahead_buffer.end = (self.lookahead_buffer.end + 1) % LOOKAHEAD_BUFFER_CAPACITY; } @@ -1162,7 +1127,7 @@ impl<'a> Parser<'a> { /// Parse the items in a trait declaration pub fn parse_trait_item(&mut self) -> PResult<'a, TraitItem> { - maybe_whole!(no_clone_from_p self, NtTraitItem); + maybe_whole!(self, NtTraitItem, |x| x); let mut attrs = self.parse_outer_attributes()?; let lo = self.span.lo; @@ -1331,7 +1296,7 @@ impl<'a> Parser<'a> { /// Parse a type. pub fn parse_ty(&mut self) -> PResult<'a, P> { - maybe_whole!(no_clone self, NtTy); + maybe_whole!(self, NtTy, |x| x); let lo = self.span.lo; @@ -1476,7 +1441,7 @@ impl<'a> Parser<'a> { /// This version of parse arg doesn't necessarily require /// identifier names. pub fn parse_arg_general(&mut self, require_name: bool) -> PResult<'a, Arg> { - maybe_whole!(no_clone self, NtArg); + maybe_whole!(self, NtArg, |x| x); let pat = if require_name || self.is_named_argument() { debug!("parse_arg_general parse_pat (require_name:{})", @@ -1542,12 +1507,13 @@ impl<'a> Parser<'a> { /// Matches token_lit = LIT_INTEGER | ... pub fn parse_lit_token(&mut self) -> PResult<'a, LitKind> { let out = match self.token { - token::Interpolated(token::NtExpr(ref v)) => { - match v.node { + token::Interpolated(ref nt) => match **nt { + token::NtExpr(ref v) => match v.node { ExprKind::Lit(ref lit) => { lit.node.clone() } _ => { return self.unexpected_last(&self.token); } - } - } + }, + _ => { return self.unexpected_last(&self.token); } + }, token::Literal(lit, suf) => { let (suffix_illegal, out) = match lit { token::Byte(i) => (true, LitKind::Byte(parse::byte_lit(&i.as_str()).0)), @@ -1703,14 +1669,7 @@ impl<'a> Parser<'a> { /// bounds are permitted and whether `::` must precede type parameter /// groups. pub fn parse_path(&mut self, mode: PathStyle) -> PResult<'a, ast::Path> { - // Check for a whole path... - let found = match self.token { - token::Interpolated(token::NtPath(_)) => Some(self.bump_and_get()), - _ => None, - }; - if let Some(token::Interpolated(token::NtPath(path))) = found { - return Ok(*path); - } + maybe_whole!(self, NtPath, |x| x); let lo = self.span.lo; let is_global = self.eat(&token::ModSep); @@ -2746,8 +2705,6 @@ impl<'a> Parser<'a> { // and token::SubstNt's; it's too early to know yet // whether something will be a nonterminal or a seq // yet. - maybe_whole!(deref self, NtTT); - match self.token { token::Eof => { let mut err: DiagnosticBuilder<'a> = @@ -2760,6 +2717,17 @@ impl<'a> Parser<'a> { Err(err) }, token::OpenDelim(delim) => { + if self.tts.last().map(|&(_, i)| i == 1).unwrap_or(false) { + let tt = self.tts.pop().unwrap().0; + self.bump(); + return Ok(if self.allow_interpolated_tts { + // avoid needlessly reparsing token trees in recursive macro expansions + TokenTree::Token(tt.span(), token::Interpolated(Rc::new(token::NtTT(tt)))) + } else { + tt + }); + } + let parsing_token_tree = ::std::mem::replace(&mut self.parsing_token_tree, true); // The span for beginning of the delimited section let pre_span = self.span; @@ -2833,29 +2801,20 @@ impl<'a> Parser<'a> { close_span: close_span, }))) }, + token::CloseDelim(_) => { + // An unexpected closing delimiter (i.e., there is no + // matching opening delimiter). + let token_str = self.this_token_to_string(); + let err = self.diagnostic().struct_span_err(self.span, + &format!("unexpected close delimiter: `{}`", token_str)); + Err(err) + }, + /* we ought to allow different depths of unquotation */ + token::Dollar | token::SubstNt(..) if self.quote_depth > 0 => { + self.parse_unquoted() + } _ => { - // invariants: the current token is not a left-delimiter, - // not an EOF, and not the desired right-delimiter (if - // it were, parse_seq_to_before_end would have prevented - // reaching this point). - maybe_whole!(deref self, NtTT); - match self.token { - token::CloseDelim(_) => { - // An unexpected closing delimiter (i.e., there is no - // matching opening delimiter). - let token_str = self.this_token_to_string(); - let err = self.diagnostic().struct_span_err(self.span, - &format!("unexpected close delimiter: `{}`", token_str)); - Err(err) - }, - /* we ought to allow different depths of unquotation */ - token::Dollar | token::SubstNt(..) if self.quote_depth > 0 => { - self.parse_unquoted() - } - _ => { - Ok(TokenTree::Token(self.span, self.bump_and_get())) - } - } + Ok(TokenTree::Token(self.span, self.bump_and_get())) } } } @@ -3336,7 +3295,7 @@ impl<'a> Parser<'a> { } pub fn parse_arm(&mut self) -> PResult<'a, Arm> { - maybe_whole!(no_clone self, NtArm); + maybe_whole!(self, NtArm, |x| x); let attrs = self.parse_outer_attributes()?; let pats = self.parse_pats()?; @@ -3592,7 +3551,7 @@ impl<'a> Parser<'a> { /// Parse a pattern. pub fn parse_pat(&mut self) -> PResult<'a, P> { - maybe_whole!(self, NtPat); + maybe_whole!(self, NtPat, |x| x); let lo = self.span.lo; let pat; @@ -3897,7 +3856,7 @@ impl<'a> Parser<'a> { fn parse_stmt_without_recovery(&mut self, macro_legacy_warnings: bool) -> PResult<'a, Option> { - maybe_whole!(Some deref self, NtStmt); + maybe_whole!(self, NtStmt, |x| Some(x)); let attrs = self.parse_outer_attributes()?; let lo = self.span.lo; @@ -4086,7 +4045,7 @@ impl<'a> Parser<'a> { /// Parse a block. No inner attrs are allowed. pub fn parse_block(&mut self) -> PResult<'a, P> { - maybe_whole!(no_clone self, NtBlock); + maybe_whole!(self, NtBlock, |x| x); let lo = self.span.lo; @@ -4124,7 +4083,7 @@ impl<'a> Parser<'a> { /// Parse a block. Inner attrs are allowed. fn parse_inner_attrs_and_block(&mut self) -> PResult<'a, (Vec, P)> { - maybe_whole!(pair_empty self, NtBlock); + maybe_whole!(self, NtBlock, |x| (Vec::new(), x)); let lo = self.span.lo; self.expect(&token::OpenDelim(token::Brace))?; @@ -4299,7 +4258,7 @@ impl<'a> Parser<'a> { /// | ( < lifetimes , typaramseq ( , )? > ) /// where typaramseq = ( typaram ) | ( typaram , typaramseq ) pub fn parse_generics(&mut self) -> PResult<'a, ast::Generics> { - maybe_whole!(self, NtGenerics); + maybe_whole!(self, NtGenerics, |x| x); let span_lo = self.span.lo; if self.eat(&token::Lt) { @@ -4440,7 +4399,7 @@ impl<'a> Parser<'a> { /// where T : Trait + 'b, 'a : 'b /// ``` pub fn parse_where_clause(&mut self) -> PResult<'a, ast::WhereClause> { - maybe_whole!(self, NtWhereClause); + maybe_whole!(self, NtWhereClause, |x| x); let mut where_clause = WhereClause { id: ast::DUMMY_NODE_ID, @@ -4848,7 +4807,7 @@ impl<'a> Parser<'a> { /// Parse an impl item. pub fn parse_impl_item(&mut self) -> PResult<'a, ImplItem> { - maybe_whole!(no_clone_from_p self, NtImplItem); + maybe_whole!(self, NtImplItem, |x| x); let mut attrs = self.parse_outer_attributes()?; let lo = self.span.lo; @@ -5716,19 +5675,13 @@ impl<'a> Parser<'a> { /// extern crate. fn parse_item_(&mut self, attrs: Vec, macros_allowed: bool, attributes_allowed: bool) -> PResult<'a, Option>> { - let nt_item = match self.token { - token::Interpolated(token::NtItem(ref item)) => { - Some((**item).clone()) - } - _ => None - }; - if let Some(mut item) = nt_item { - self.bump(); + maybe_whole!(self, NtItem, |item| { + let mut item = item.unwrap(); let mut attrs = attrs; mem::swap(&mut item.attrs, &mut attrs); item.attrs.extend(attrs); - return Ok(Some(P(item))); - } + Some(P(item)) + }); let lo = self.span.lo; diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 4d0da660302ae..0198ee073d239 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -123,7 +123,7 @@ pub enum Token { Lifetime(ast::Ident), /* For interpolation */ - Interpolated(Nonterminal), + Interpolated(Rc), // Can be expanded into several tokens. /// Doc comment DocComment(ast::Name), @@ -172,12 +172,15 @@ impl Token { DotDot | DotDotDot => true, // range notation Lt | BinOp(Shl) => true, // associated path ModSep => true, - Interpolated(NtExpr(..)) => true, - Interpolated(NtIdent(..)) => true, - Interpolated(NtBlock(..)) => true, - Interpolated(NtPath(..)) => true, Pound => true, // for expression attributes - _ => false, + Interpolated(ref nt) => match **nt { + NtExpr(..) => true, + NtIdent(..) => true, + NtBlock(..) => true, + NtPath(..) => true, + _ => false, + }, + _ => false, } } @@ -215,10 +218,12 @@ impl Token { /// Returns `true` if the token is an interpolated path. pub fn is_path(&self) -> bool { - match *self { - Interpolated(NtPath(..)) => true, - _ => false, + if let Interpolated(ref nt) = *self { + if let NtPath(..) = **nt { + return true; + } } + false } /// Returns `true` if the token is a lifetime. @@ -290,19 +295,19 @@ impl Token { pub enum Nonterminal { NtItem(P), NtBlock(P), - NtStmt(P), + NtStmt(ast::Stmt), NtPat(P), NtExpr(P), NtTy(P), - NtIdent(Box), + NtIdent(ast::SpannedIdent), /// Stuff inside brackets for attributes NtMeta(P), - NtPath(Box), - NtTT(P), // needs P'ed to break a circularity + NtPath(ast::Path), + NtTT(tokenstream::TokenTree), // These are not exposed to macros, but are used by quasiquote. NtArm(ast::Arm), - NtImplItem(P), - NtTraitItem(P), + NtImplItem(ast::ImplItem), + NtTraitItem(ast::TraitItem), NtGenerics(ast::Generics), NtWhereClause(ast::WhereClause), NtArg(ast::Arg), diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index b0bd644674300..7352792a8a252 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -285,7 +285,7 @@ pub fn token_to_string(tok: &Token) -> String { token::Comment => "/* */".to_string(), token::Shebang(s) => format!("/* shebang: {}*/", s), - token::Interpolated(ref nt) => match *nt { + token::Interpolated(ref nt) => match **nt { token::NtExpr(ref e) => expr_to_string(&e), token::NtMeta(ref e) => meta_item_to_string(&e), token::NtTy(ref e) => ty_to_string(&e), diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index 9e644e59e86a7..9ef6c07e489dc 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -134,8 +134,10 @@ impl TokenTree { AttrStyle::Inner => 3, } } + TokenTree::Token(_, token::Interpolated(ref nt)) => { + if let Nonterminal::NtTT(..) = **nt { 1 } else { 0 } + }, TokenTree::Token(_, token::MatchNt(..)) => 3, - TokenTree::Token(_, token::Interpolated(Nonterminal::NtTT(..))) => 1, TokenTree::Delimited(_, ref delimed) => delimed.tts.len() + 2, TokenTree::Sequence(_, ref seq) => seq.tts.len(), TokenTree::Token(..) => 0, @@ -193,9 +195,6 @@ impl TokenTree { TokenTree::Token(sp, token::Ident(kind))]; v[index].clone() } - (&TokenTree::Token(_, token::Interpolated(Nonterminal::NtTT(ref tt))), _) => { - tt.clone().unwrap() - } (&TokenTree::Sequence(_, ref seq), _) => seq.tts[index].clone(), _ => panic!("Cannot expand a token tree"), } @@ -215,11 +214,9 @@ impl TokenTree { mtch: &[TokenTree], tts: &[TokenTree]) -> macro_parser::NamedParseResult { + let diag = &cx.parse_sess().span_diagnostic; // `None` is because we're not interpolating - let arg_rdr = lexer::new_tt_reader_with_doc_flag(&cx.parse_sess().span_diagnostic, - None, - tts.iter().cloned().collect(), - true); + let arg_rdr = lexer::new_tt_reader(diag, None, tts.iter().cloned().collect()); macro_parser::parse(cx.parse_sess(), arg_rdr, mtch) } diff --git a/src/libsyntax_ext/asm.rs b/src/libsyntax_ext/asm.rs index 24c515e502808..e4d0cb7404603 100644 --- a/src/libsyntax_ext/asm.rs +++ b/src/libsyntax_ext/asm.rs @@ -250,7 +250,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, MacEager::expr(P(ast::Expr { id: ast::DUMMY_NODE_ID, - node: ast::ExprKind::InlineAsm(ast::InlineAsm { + node: ast::ExprKind::InlineAsm(P(ast::InlineAsm { asm: token::intern_and_get_ident(&asm), asm_str_style: asm_str_style.unwrap(), outputs: outputs, @@ -260,7 +260,7 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, alignstack: alignstack, dialect: dialect, expn_id: expn_id, - }), + })), span: sp, attrs: ast::ThinVec::new(), })) diff --git a/src/libsyntax_ext/proc_macro_registrar.rs b/src/libsyntax_ext/proc_macro_registrar.rs index f49a5f0e0706e..a8accd63dcf0a 100644 --- a/src/libsyntax_ext/proc_macro_registrar.rs +++ b/src/libsyntax_ext/proc_macro_registrar.rs @@ -105,6 +105,17 @@ impl<'a> Visitor for CollectCustomDerives<'a> { match item.node { ast::ItemKind::Fn(..) => {} _ => { + // Check for invalid use of proc_macro_derive + let attr = item.attrs.iter() + .filter(|a| a.check_name("proc_macro_derive")) + .next(); + if let Some(attr) = attr { + self.handler.span_err(attr.span(), + "the `#[proc_macro_derive]` \ + attribute may only be used \ + on bare functions"); + return; + } self.check_not_pub_in_root(&item.vis, item.span); return visit::walk_item(self, item) } diff --git a/src/test/compile-fail-fulldeps/proc-macro/require-rustc-macro-crate-type.rs b/src/test/compile-fail-fulldeps/proc-macro/illegal-proc-macro-derive-use.rs similarity index 82% rename from src/test/compile-fail-fulldeps/proc-macro/require-rustc-macro-crate-type.rs rename to src/test/compile-fail-fulldeps/proc-macro/illegal-proc-macro-derive-use.rs index 44397cdde0c0a..405994b36e25e 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/require-rustc-macro-crate-type.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/illegal-proc-macro-derive-use.rs @@ -18,4 +18,10 @@ pub fn foo(a: proc_macro::TokenStream) -> proc_macro::TokenStream { a } +// Issue #37590 +#[proc_macro_derive(Foo)] +//~^ ERROR: the `#[proc_macro_derive]` attribute may only be used on bare functions +pub struct Foo { +} + fn main() {} diff --git a/src/test/compile-fail/issue-37534.rs b/src/test/compile-fail/issue-37534.rs new file mode 100644 index 0000000000000..eb676601e89ce --- /dev/null +++ b/src/test/compile-fail/issue-37534.rs @@ -0,0 +1,16 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct Foo { } +//~^ ERROR trait `Hash` is not in scope [E0405] +//~^^ ERROR parameter `T` is never used [E0392] +//~^^^ WARN default bound relaxed for a type parameter, but this does nothing + +fn main() { } diff --git a/src/test/compile-fail/struct-path-associated-type.rs b/src/test/compile-fail/struct-path-associated-type.rs index 660ac44ce0b53..ecaf269fcb1ae 100644 --- a/src/test/compile-fail/struct-path-associated-type.rs +++ b/src/test/compile-fail/struct-path-associated-type.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(more_struct_aliases)] + struct S; trait Tr { diff --git a/src/test/compile-fail/struct-path-self-feature-gate.rs b/src/test/compile-fail/struct-path-self-feature-gate.rs new file mode 100644 index 0000000000000..a2050182a7e30 --- /dev/null +++ b/src/test/compile-fail/struct-path-self-feature-gate.rs @@ -0,0 +1,29 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct S; + +trait Tr { + type A; +} + +fn f>() { + let _ = T::A {}; + //~^ ERROR `Self` and associated types in struct expressions and patterns are unstable +} + +impl S { + fn f() { + let _ = Self {}; + //~^ ERROR `Self` and associated types in struct expressions and patterns are unstable + } +} + +fn main() {} diff --git a/src/test/compile-fail/struct-path-self-type-mismatch.rs b/src/test/compile-fail/struct-path-self-type-mismatch.rs index f694e7d277c7f..8352bd6751f50 100644 --- a/src/test/compile-fail/struct-path-self-type-mismatch.rs +++ b/src/test/compile-fail/struct-path-self-type-mismatch.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(more_struct_aliases)] + struct Foo { inner: A } trait Bar { fn bar(); } diff --git a/src/test/compile-fail/struct-path-self.rs b/src/test/compile-fail/struct-path-self.rs index 067d6ac22dc6f..aeac199227b75 100644 --- a/src/test/compile-fail/struct-path-self.rs +++ b/src/test/compile-fail/struct-path-self.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(more_struct_aliases)] + struct S; trait Tr { diff --git a/src/test/compile-fail/windows-subsystem-gated.rs b/src/test/compile-fail/windows-subsystem-gated.rs new file mode 100644 index 0000000000000..4b563e78e55c8 --- /dev/null +++ b/src/test/compile-fail/windows-subsystem-gated.rs @@ -0,0 +1,14 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![windows_subsystem = "console"] +//~^ ERROR: the windows subsystem attribute is currently unstable + +fn main() {} diff --git a/src/test/compile-fail/windows-subsystem-invalid.rs b/src/test/compile-fail/windows-subsystem-invalid.rs new file mode 100644 index 0000000000000..e0003440719e6 --- /dev/null +++ b/src/test/compile-fail/windows-subsystem-invalid.rs @@ -0,0 +1,16 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// error-pattern: invalid windows subsystem `wrong`, only `windows` and `console` are allowed + +#![feature(windows_subsystem)] +#![windows_subsystem = "wrong"] + +fn main() {} diff --git a/src/test/debuginfo/associated-types.rs b/src/test/debuginfo/associated-types.rs index ebaad663bb4e7..ccd94022711cd 100644 --- a/src/test/debuginfo/associated-types.rs +++ b/src/test/debuginfo/associated-types.rs @@ -16,7 +16,8 @@ // gdb-command:run // gdb-command:print arg -// gdb-check:$1 = {b = -1, b1 = 0} +// gdbg-check:$1 = {b = -1, b1 = 0} +// gdbr-check:$1 = associated_types::Struct {b: -1, b1: 0} // gdb-command:continue // gdb-command:print inferred @@ -30,7 +31,8 @@ // gdb-command:continue // gdb-command:print arg -// gdb-check:$5 = {__0 = 4, __1 = 5} +// gdbg-check:$5 = {__0 = 4, __1 = 5} +// gdbr-check:$5 = (4, 5) // gdb-command:continue // gdb-command:print a diff --git a/src/test/debuginfo/basic-types-globals-metadata.rs b/src/test/debuginfo/basic-types-globals-metadata.rs index 8818063ddf4ba..fe687dabe9acb 100644 --- a/src/test/debuginfo/basic-types-globals-metadata.rs +++ b/src/test/debuginfo/basic-types-globals-metadata.rs @@ -12,33 +12,47 @@ // compile-flags:-g // gdb-command:run -// gdb-command:whatis 'basic_types_globals_metadata::B' +// gdbg-command:whatis 'basic_types_globals_metadata::B' +// gdbr-command:whatis basic_types_globals_metadata::B // gdb-check:type = bool -// gdb-command:whatis 'basic_types_globals_metadata::I' +// gdbg-command:whatis 'basic_types_globals_metadata::I' +// gdbr-command:whatis basic_types_globals_metadata::I // gdb-check:type = isize -// gdb-command:whatis 'basic_types_globals_metadata::C' +// gdbg-command:whatis 'basic_types_globals_metadata::C' +// gdbr-command:whatis basic_types_globals_metadata::C // gdb-check:type = char -// gdb-command:whatis 'basic_types_globals_metadata::I8' +// gdbg-command:whatis 'basic_types_globals_metadata::I8' +// gdbr-command:whatis basic_types_globals_metadata::I8 // gdb-check:type = i8 -// gdb-command:whatis 'basic_types_globals_metadata::I16' +// gdbg-command:whatis 'basic_types_globals_metadata::I16' +// gdbr-command:whatis basic_types_globals_metadata::I16 // gdb-check:type = i16 -// gdb-command:whatis 'basic_types_globals_metadata::I32' +// gdbg-command:whatis 'basic_types_globals_metadata::I32' +// gdbr-command:whatis basic_types_globals_metadata::I32 // gdb-check:type = i32 -// gdb-command:whatis 'basic_types_globals_metadata::I64' +// gdbg-command:whatis 'basic_types_globals_metadata::I64' +// gdbr-command:whatis basic_types_globals_metadata::I64 // gdb-check:type = i64 -// gdb-command:whatis 'basic_types_globals_metadata::U' +// gdbg-command:whatis 'basic_types_globals_metadata::U' +// gdbr-command:whatis basic_types_globals_metadata::U // gdb-check:type = usize -// gdb-command:whatis 'basic_types_globals_metadata::U8' +// gdbg-command:whatis 'basic_types_globals_metadata::U8' +// gdbr-command:whatis basic_types_globals_metadata::U8 // gdb-check:type = u8 -// gdb-command:whatis 'basic_types_globals_metadata::U16' +// gdbg-command:whatis 'basic_types_globals_metadata::U16' +// gdbr-command:whatis basic_types_globals_metadata::U16 // gdb-check:type = u16 -// gdb-command:whatis 'basic_types_globals_metadata::U32' +// gdbg-command:whatis 'basic_types_globals_metadata::U32' +// gdbr-command:whatis basic_types_globals_metadata::U32 // gdb-check:type = u32 -// gdb-command:whatis 'basic_types_globals_metadata::U64' +// gdbg-command:whatis 'basic_types_globals_metadata::U64' +// gdbr-command:whatis basic_types_globals_metadata::U64 // gdb-check:type = u64 -// gdb-command:whatis 'basic_types_globals_metadata::F32' +// gdbg-command:whatis 'basic_types_globals_metadata::F32' +// gdbr-command:whatis basic_types_globals_metadata::F32 // gdb-check:type = f32 -// gdb-command:whatis 'basic_types_globals_metadata::F64' +// gdbg-command:whatis 'basic_types_globals_metadata::F64' +// gdbr-command:whatis basic_types_globals_metadata::F64 // gdb-check:type = f64 // gdb-command:continue diff --git a/src/test/debuginfo/basic-types-globals.rs b/src/test/debuginfo/basic-types-globals.rs index ccf9508a3856c..20bc403fbbcdc 100644 --- a/src/test/debuginfo/basic-types-globals.rs +++ b/src/test/debuginfo/basic-types-globals.rs @@ -18,33 +18,48 @@ // compile-flags:-g // gdb-command:run -// gdb-command:print 'basic_types_globals::B' +// gdbg-command:print 'basic_types_globals::B' +// gdbr-command:print B // gdb-check:$1 = false -// gdb-command:print 'basic_types_globals::I' +// gdbg-command:print 'basic_types_globals::I' +// gdbr-command:print I // gdb-check:$2 = -1 -// gdb-command:print 'basic_types_globals::C' -// gdb-check:$3 = 97 -// gdb-command:print/d 'basic_types_globals::I8' +// gdbg-command:print 'basic_types_globals::C' +// gdbr-command:print C +// gdbg-check:$3 = 97 +// gdbr-check:$3 = 97 'a' +// gdbg-command:print/d 'basic_types_globals::I8' +// gdbr-command:print I8 // gdb-check:$4 = 68 -// gdb-command:print 'basic_types_globals::I16' +// gdbg-command:print 'basic_types_globals::I16' +// gdbr-command:print I16 // gdb-check:$5 = -16 -// gdb-command:print 'basic_types_globals::I32' +// gdbg-command:print 'basic_types_globals::I32' +// gdbr-command:print I32 // gdb-check:$6 = -32 -// gdb-command:print 'basic_types_globals::I64' +// gdbg-command:print 'basic_types_globals::I64' +// gdbr-command:print I64 // gdb-check:$7 = -64 -// gdb-command:print 'basic_types_globals::U' +// gdbg-command:print 'basic_types_globals::U' +// gdbr-command:print U // gdb-check:$8 = 1 -// gdb-command:print/d 'basic_types_globals::U8' +// gdbg-command:print/d 'basic_types_globals::U8' +// gdbr-command:print U8 // gdb-check:$9 = 100 -// gdb-command:print 'basic_types_globals::U16' +// gdbg-command:print 'basic_types_globals::U16' +// gdbr-command:print U16 // gdb-check:$10 = 16 -// gdb-command:print 'basic_types_globals::U32' +// gdbg-command:print 'basic_types_globals::U32' +// gdbr-command:print U32 // gdb-check:$11 = 32 -// gdb-command:print 'basic_types_globals::U64' +// gdbg-command:print 'basic_types_globals::U64' +// gdbr-command:print U64 // gdb-check:$12 = 64 -// gdb-command:print 'basic_types_globals::F32' +// gdbg-command:print 'basic_types_globals::F32' +// gdbr-command:print F32 // gdb-check:$13 = 2.5 -// gdb-command:print 'basic_types_globals::F64' +// gdbg-command:print 'basic_types_globals::F64' +// gdbr-command:print F64 // gdb-check:$14 = 3.5 // gdb-command:continue diff --git a/src/test/debuginfo/basic-types-metadata.rs b/src/test/debuginfo/basic-types-metadata.rs index 1a6b605d9d06a..8aec1a059bdc6 100644 --- a/src/test/debuginfo/basic-types-metadata.rs +++ b/src/test/debuginfo/basic-types-metadata.rs @@ -45,20 +45,29 @@ // gdb-command:whatis fnptr // gdb-check:type = [...] (*)([...]) // gdb-command:info functions _yyy -// gdb-check:[...]![...]_yyy([...]); +// gdbg-check:[...]![...]_yyy([...]); +// gdbr-check:static fn basic_types_metadata::_yyy() -> !; // gdb-command:ptype closure_0 -// gdb-check: type = struct closure { -// gdb-check: -// gdb-check: } +// gdbr-check: type = struct closure +// gdbg-check: type = struct closure { +// gdbg-check: +// gdbg-check: } // gdb-command:ptype closure_1 -// gdb-check: type = struct closure { -// gdb-check: bool *__0; -// gdb-check: } +// gdbg-check: type = struct closure { +// gdbg-check: bool *__0; +// gdbg-check: } +// gdbr-check: type = struct closure ( +// gdbr-check: bool *, +// gdbr-check: ) // gdb-command:ptype closure_2 -// gdb-check: type = struct closure { -// gdb-check: bool *__0; -// gdb-check: isize *__1; -// gdb-check: } +// gdbg-check: type = struct closure { +// gdbg-check: bool *__0; +// gdbg-check: isize *__1; +// gdbg-check: } +// gdbr-check: type = struct closure ( +// gdbr-check: bool *, +// gdbr-check: isize *, +// gdbr-check: ) // // gdb-command:continue diff --git a/src/test/debuginfo/basic-types-mut-globals.rs b/src/test/debuginfo/basic-types-mut-globals.rs index 4ebd0c9577029..62325aa53ab9f 100644 --- a/src/test/debuginfo/basic-types-mut-globals.rs +++ b/src/test/debuginfo/basic-types-mut-globals.rs @@ -21,64 +21,94 @@ // gdb-command:run // Check initializers -// gdb-command:print 'basic_types_mut_globals::B' +// gdbg-command:print 'basic_types_mut_globals::B' +// gdbr-command:print B // gdb-check:$1 = false -// gdb-command:print 'basic_types_mut_globals::I' +// gdbg-command:print 'basic_types_mut_globals::I' +// gdbr-command:print I // gdb-check:$2 = -1 -// gdb-command:print 'basic_types_mut_globals::C' -// gdb-check:$3 = 97 -// gdb-command:print/d 'basic_types_mut_globals::I8' +// gdbg-command:print/d 'basic_types_mut_globals::C' +// gdbr-command:print C +// gdbg-check:$3 = 97 +// gdbr-check:$3 = 97 'a' +// gdbg-command:print/d 'basic_types_mut_globals::I8' +// gdbr-command:print I8 // gdb-check:$4 = 68 -// gdb-command:print 'basic_types_mut_globals::I16' +// gdbg-command:print 'basic_types_mut_globals::I16' +// gdbr-command:print I16 // gdb-check:$5 = -16 -// gdb-command:print 'basic_types_mut_globals::I32' +// gdbg-command:print 'basic_types_mut_globals::I32' +// gdbr-command:print I32 // gdb-check:$6 = -32 -// gdb-command:print 'basic_types_mut_globals::I64' +// gdbg-command:print 'basic_types_mut_globals::I64' +// gdbr-command:print I64 // gdb-check:$7 = -64 -// gdb-command:print 'basic_types_mut_globals::U' +// gdbg-command:print 'basic_types_mut_globals::U' +// gdbr-command:print U // gdb-check:$8 = 1 -// gdb-command:print/d 'basic_types_mut_globals::U8' +// gdbg-command:print/d 'basic_types_mut_globals::U8' +// gdbr-command:print U8 // gdb-check:$9 = 100 -// gdb-command:print 'basic_types_mut_globals::U16' +// gdbg-command:print 'basic_types_mut_globals::U16' +// gdbr-command:print U16 // gdb-check:$10 = 16 -// gdb-command:print 'basic_types_mut_globals::U32' +// gdbg-command:print 'basic_types_mut_globals::U32' +// gdbr-command:print U32 // gdb-check:$11 = 32 -// gdb-command:print 'basic_types_mut_globals::U64' +// gdbg-command:print 'basic_types_mut_globals::U64' +// gdbr-command:print U64 // gdb-check:$12 = 64 -// gdb-command:print 'basic_types_mut_globals::F32' +// gdbg-command:print 'basic_types_mut_globals::F32' +// gdbr-command:print F32 // gdb-check:$13 = 2.5 -// gdb-command:print 'basic_types_mut_globals::F64' +// gdbg-command:print 'basic_types_mut_globals::F64' +// gdbr-command:print F64 // gdb-check:$14 = 3.5 // gdb-command:continue // Check new values -// gdb-command:print 'basic_types_mut_globals'::B +// gdbg-command:print 'basic_types_mut_globals'::B +// gdbr-command:print B // gdb-check:$15 = true -// gdb-command:print 'basic_types_mut_globals'::I +// gdbg-command:print 'basic_types_mut_globals'::I +// gdbr-command:print I // gdb-check:$16 = 2 -// gdb-command:print 'basic_types_mut_globals'::C -// gdb-check:$17 = 102 -// gdb-command:print/d 'basic_types_mut_globals'::I8 +// gdbg-command:print/d 'basic_types_mut_globals'::C +// gdbr-command:print C +// gdbg-check:$17 = 102 +// gdbr-check:$17 = 102 'f' +// gdbg-command:print/d 'basic_types_mut_globals'::I8 +// gdbr-command:print/d I8 // gdb-check:$18 = 78 -// gdb-command:print 'basic_types_mut_globals'::I16 +// gdbg-command:print 'basic_types_mut_globals'::I16 +// gdbr-command:print I16 // gdb-check:$19 = -26 -// gdb-command:print 'basic_types_mut_globals'::I32 +// gdbg-command:print 'basic_types_mut_globals'::I32 +// gdbr-command:print I32 // gdb-check:$20 = -12 -// gdb-command:print 'basic_types_mut_globals'::I64 +// gdbg-command:print 'basic_types_mut_globals'::I64 +// gdbr-command:print I64 // gdb-check:$21 = -54 -// gdb-command:print 'basic_types_mut_globals'::U +// gdbg-command:print 'basic_types_mut_globals'::U +// gdbr-command:print U // gdb-check:$22 = 5 -// gdb-command:print/d 'basic_types_mut_globals'::U8 +// gdbg-command:print/d 'basic_types_mut_globals'::U8 +// gdbr-command:print/d U8 // gdb-check:$23 = 20 -// gdb-command:print 'basic_types_mut_globals'::U16 +// gdbg-command:print 'basic_types_mut_globals'::U16 +// gdbr-command:print U16 // gdb-check:$24 = 32 -// gdb-command:print 'basic_types_mut_globals'::U32 +// gdbg-command:print 'basic_types_mut_globals'::U32 +// gdbr-command:print U32 // gdb-check:$25 = 16 -// gdb-command:print 'basic_types_mut_globals'::U64 +// gdbg-command:print 'basic_types_mut_globals'::U64 +// gdbr-command:print U64 // gdb-check:$26 = 128 -// gdb-command:print 'basic_types_mut_globals'::F32 +// gdbg-command:print 'basic_types_mut_globals'::F32 +// gdbr-command:print F32 // gdb-check:$27 = 5.75 -// gdb-command:print 'basic_types_mut_globals'::F64 +// gdbg-command:print 'basic_types_mut_globals'::F64 +// gdbr-command:print F64 // gdb-check:$28 = 9.25 #![allow(unused_variables)] diff --git a/src/test/debuginfo/basic-types.rs b/src/test/debuginfo/basic-types.rs index 998010832881b..01ce5bd31626e 100644 --- a/src/test/debuginfo/basic-types.rs +++ b/src/test/debuginfo/basic-types.rs @@ -26,7 +26,8 @@ // gdb-command:print i // gdb-check:$2 = -1 // gdb-command:print c -// gdb-check:$3 = 97 +// gdbg-check:$3 = 97 +// gdbr-check:$3 = 97 'a' // gdb-command:print/d i8 // gdb-check:$4 = 68 // gdb-command:print i16 diff --git a/src/test/debuginfo/borrowed-basic.rs b/src/test/debuginfo/borrowed-basic.rs index bada77b66293c..f6c0ff09efe93 100644 --- a/src/test/debuginfo/borrowed-basic.rs +++ b/src/test/debuginfo/borrowed-basic.rs @@ -25,10 +25,12 @@ // gdb-check:$2 = -1 // gdb-command:print *char_ref -// gdb-check:$3 = 97 +// gdbg-check:$3 = 97 +// gdbr-check:$3 = 97 'a' // gdb-command:print *i8_ref -// gdb-check:$4 = 68 'D' +// gdbg-check:$4 = 68 'D' +// gdbr-check:$4 = 68 // gdb-command:print *i16_ref // gdb-check:$5 = -16 @@ -43,7 +45,8 @@ // gdb-check:$8 = 1 // gdb-command:print *u8_ref -// gdb-check:$9 = 100 'd' +// gdbg-check:$9 = 100 'd' +// gdbr-check:$9 = 100 // gdb-command:print *u16_ref // gdb-check:$10 = 16 diff --git a/src/test/debuginfo/borrowed-c-style-enum.rs b/src/test/debuginfo/borrowed-c-style-enum.rs index c80783ef31068..d6f379634be5b 100644 --- a/src/test/debuginfo/borrowed-c-style-enum.rs +++ b/src/test/debuginfo/borrowed-c-style-enum.rs @@ -17,13 +17,16 @@ // gdb-command:run // gdb-command:print *the_a_ref -// gdb-check:$1 = TheA +// gdbg-check:$1 = TheA +// gdbr-check:$1 = borrowed_c_style_enum::ABC::TheA // gdb-command:print *the_b_ref -// gdb-check:$2 = TheB +// gdbg-check:$2 = TheB +// gdbr-check:$2 = borrowed_c_style_enum::ABC::TheB // gdb-command:print *the_c_ref -// gdb-check:$3 = TheC +// gdbg-check:$3 = TheC +// gdbr-check:$3 = borrowed_c_style_enum::ABC::TheC // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/borrowed-enum.rs b/src/test/debuginfo/borrowed-enum.rs index b21574e32866b..ddc29c6430270 100644 --- a/src/test/debuginfo/borrowed-enum.rs +++ b/src/test/debuginfo/borrowed-enum.rs @@ -18,13 +18,16 @@ // gdb-command:run // gdb-command:print *the_a_ref -// gdb-check:$1 = {{RUST$ENUM$DISR = TheA, x = 0, y = 8970181431921507452}, {RUST$ENUM$DISR = TheA, __0 = 0, __1 = 2088533116, __2 = 2088533116}} +// gdbg-check:$1 = {{RUST$ENUM$DISR = TheA, x = 0, y = 8970181431921507452}, {RUST$ENUM$DISR = TheA, __0 = 0, __1 = 2088533116, __2 = 2088533116}} +// gdbr-check:$1 = borrowed_enum::ABC::TheA{x: 0, y: 8970181431921507452} // gdb-command:print *the_b_ref -// gdb-check:$2 = {{RUST$ENUM$DISR = TheB, x = 0, y = 1229782938247303441}, {RUST$ENUM$DISR = TheB, __0 = 0, __1 = 286331153, __2 = 286331153}} +// gdbg-check:$2 = {{RUST$ENUM$DISR = TheB, x = 0, y = 1229782938247303441}, {RUST$ENUM$DISR = TheB, __0 = 0, __1 = 286331153, __2 = 286331153}} +// gdbr-check:$2 = borrowed_enum::ABC::TheB(0, 286331153, 286331153) // gdb-command:print *univariant_ref -// gdb-check:$3 = {{__0 = 4820353753753434}} +// gdbg-check:$3 = {{__0 = 4820353753753434}} +// gdbr-check:$3 = borrowed_enum::Univariant::TheOnlyCase(4820353753753434) // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/borrowed-struct.rs b/src/test/debuginfo/borrowed-struct.rs index ab41185cb7391..01428e515e27f 100644 --- a/src/test/debuginfo/borrowed-struct.rs +++ b/src/test/debuginfo/borrowed-struct.rs @@ -16,7 +16,8 @@ // gdb-command:run // gdb-command:print *stack_val_ref -// gdb-check:$1 = {x = 10, y = 23.5} +// gdbg-check:$1 = {x = 10, y = 23.5} +// gdbr-check:$1 = borrowed_struct::SomeStruct {x: 10, y: 23.5} // gdb-command:print *stack_val_interior_ref_1 // gdb-check:$2 = 10 @@ -25,10 +26,12 @@ // gdb-check:$3 = 23.5 // gdb-command:print *ref_to_unnamed -// gdb-check:$4 = {x = 11, y = 24.5} +// gdbg-check:$4 = {x = 11, y = 24.5} +// gdbr-check:$4 = borrowed_struct::SomeStruct {x: 11, y: 24.5} // gdb-command:print *unique_val_ref -// gdb-check:$5 = {x = 13, y = 26.5} +// gdbg-check:$5 = {x = 13, y = 26.5} +// gdbr-check:$5 = borrowed_struct::SomeStruct {x: 13, y: 26.5} // gdb-command:print *unique_val_interior_ref_1 // gdb-check:$6 = 13 diff --git a/src/test/debuginfo/borrowed-tuple.rs b/src/test/debuginfo/borrowed-tuple.rs index e3da3934f6d69..17db88ee37f53 100644 --- a/src/test/debuginfo/borrowed-tuple.rs +++ b/src/test/debuginfo/borrowed-tuple.rs @@ -17,13 +17,16 @@ // gdb-command:run // gdb-command:print *stack_val_ref -// gdb-check:$1 = {__0 = -14, __1 = -19} +// gdbg-check:$1 = {__0 = -14, __1 = -19} +// gdbr-check:$1 = (-14, -19) // gdb-command:print *ref_to_unnamed -// gdb-check:$2 = {__0 = -15, __1 = -20} +// gdbg-check:$2 = {__0 = -15, __1 = -20} +// gdbr-check:$2 = (-15, -20) // gdb-command:print *unique_val_ref -// gdb-check:$3 = {__0 = -17, __1 = -22} +// gdbg-check:$3 = {__0 = -17, __1 = -22} +// gdbr-check:$3 = (-17, -22) // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/borrowed-unique-basic.rs b/src/test/debuginfo/borrowed-unique-basic.rs index 88af94c53628c..9e95498b0c30e 100644 --- a/src/test/debuginfo/borrowed-unique-basic.rs +++ b/src/test/debuginfo/borrowed-unique-basic.rs @@ -26,7 +26,8 @@ // gdb-check:$2 = -1 // gdb-command:print *char_ref -// gdb-check:$3 = 97 +// gdbg-check:$3 = 97 +// gdbr-check:$3 = 97 'a' // gdb-command:print/d *i8_ref // gdb-check:$4 = 68 diff --git a/src/test/debuginfo/box.rs b/src/test/debuginfo/box.rs index 106d0b243eb26..98c09fe09de8f 100644 --- a/src/test/debuginfo/box.rs +++ b/src/test/debuginfo/box.rs @@ -19,7 +19,8 @@ // gdb-command:print *a // gdb-check:$1 = 1 // gdb-command:print *b -// gdb-check:$2 = {__0 = 2, __1 = 3.5} +// gdbg-check:$2 = {__0 = 2, __1 = 3.5} +// gdbr-check:$2 = (2, 3.5) // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/boxed-struct.rs b/src/test/debuginfo/boxed-struct.rs index dd543405e4c27..ac091b4a533db 100644 --- a/src/test/debuginfo/boxed-struct.rs +++ b/src/test/debuginfo/boxed-struct.rs @@ -17,10 +17,12 @@ // gdb-command:run // gdb-command:print *unique -// gdb-check:$1 = {x = 99, y = 999, z = 9999, w = 99999} +// gdbg-check:$1 = {x = 99, y = 999, z = 9999, w = 99999} +// gdbr-check:$1 = boxed_struct::StructWithSomePadding {x: 99, y: 999, z: 9999, w: 99999} // gdb-command:print *unique_dtor -// gdb-check:$2 = {x = 77, y = 777, z = 7777, w = 77777} +// gdbg-check:$2 = {x = 77, y = 777, z = 7777, w = 77777} +// gdbr-check:$2 = boxed_struct::StructWithDestructor {x: 77, y: 777, z: 7777, w: 77777} // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/by-value-non-immediate-argument.rs b/src/test/debuginfo/by-value-non-immediate-argument.rs index a329ef6d0e090..6d821dbc155d0 100644 --- a/src/test/debuginfo/by-value-non-immediate-argument.rs +++ b/src/test/debuginfo/by-value-non-immediate-argument.rs @@ -18,11 +18,13 @@ // gdb-command:run // gdb-command:print s -// gdb-check:$1 = {a = 1, b = 2.5} +// gdbg-check:$1 = {a = 1, b = 2.5} +// gdbr-check:$1 = by_value_non_immediate_argument::Struct {a: 1, b: 2.5} // gdb-command:continue // gdb-command:print x -// gdb-check:$2 = {a = 3, b = 4.5} +// gdbg-check:$2 = {a = 3, b = 4.5} +// gdbr-check:$2 = by_value_non_immediate_argument::Struct {a: 3, b: 4.5} // gdb-command:print y // gdb-check:$3 = 5 // gdb-command:print z @@ -30,15 +32,18 @@ // gdb-command:continue // gdb-command:print a -// gdb-check:$5 = {__0 = 7, __1 = 8, __2 = 9.5, __3 = 10.5} +// gdbg-check:$5 = {__0 = 7, __1 = 8, __2 = 9.5, __3 = 10.5} +// gdbr-check:$5 = (7, 8, 9.5, 10.5) // gdb-command:continue // gdb-command:print a -// gdb-check:$6 = {__0 = 11.5, __1 = 12.5, __2 = 13, __3 = 14} +// gdbg-check:$6 = {__0 = 11.5, __1 = 12.5, __2 = 13, __3 = 14} +// gdbr-check:$6 = by_value_non_immediate_argument::Newtype (11.5, 12.5, 13, 14) // gdb-command:continue // gdb-command:print x -// gdb-check:$7 = {{RUST$ENUM$DISR = Case1, x = 0, y = 8970181431921507452}, {RUST$ENUM$DISR = Case1, __0 = 0, __1 = 2088533116, __2 = 2088533116}} +// gdbg-check:$7 = {{RUST$ENUM$DISR = Case1, x = 0, y = 8970181431921507452}, {RUST$ENUM$DISR = Case1, __0 = 0, __1 = 2088533116, __2 = 2088533116}} +// gdbr-check:$7 = by_value_non_immediate_argument::Enum::Case1{x: 0, y: 8970181431921507452} // gdb-command:continue diff --git a/src/test/debuginfo/by-value-self-argument-in-trait-impl.rs b/src/test/debuginfo/by-value-self-argument-in-trait-impl.rs index a768bfdd16764..c14f8c7b354fc 100644 --- a/src/test/debuginfo/by-value-self-argument-in-trait-impl.rs +++ b/src/test/debuginfo/by-value-self-argument-in-trait-impl.rs @@ -21,11 +21,13 @@ // gdb-command:continue // gdb-command:print self -// gdb-check:$2 = {x = 2222, y = 3333} +// gdbg-check:$2 = {x = 2222, y = 3333} +// gdbr-check:$2 = by_value_self_argument_in_trait_impl::Struct {x: 2222, y: 3333} // gdb-command:continue // gdb-command:print self -// gdb-check:$3 = {__0 = 4444.5, __1 = 5555, __2 = 6666, __3 = 7777.5} +// gdbg-check:$3 = {__0 = 4444.5, __1 = 5555, __2 = 6666, __3 = 7777.5} +// gdbr-check:$3 = (4444.5, 5555, 6666, 7777.5) // gdb-command:continue diff --git a/src/test/debuginfo/c-style-enum-in-composite.rs b/src/test/debuginfo/c-style-enum-in-composite.rs index 83a22edc96fe1..004e15d1cc6c1 100644 --- a/src/test/debuginfo/c-style-enum-in-composite.rs +++ b/src/test/debuginfo/c-style-enum-in-composite.rs @@ -18,26 +18,32 @@ // gdb-command:run // gdb-command:print tuple_interior_padding -// gdb-check:$1 = {__0 = 0, __1 = OneHundred} +// gdbg-check:$1 = {__0 = 0, __1 = OneHundred} +// gdbr-check:$1 = (0, c_style_enum_in_composite::AnEnum::OneHundred) // gdb-command:print tuple_padding_at_end -// gdb-check:$2 = {__0 = {__0 = 1, __1 = OneThousand}, __1 = 2} +// gdbg-check:$2 = {__0 = {__0 = 1, __1 = OneThousand}, __1 = 2} +// gdbr-check:$2 = ((1, c_style_enum_in_composite::AnEnum::OneThousand), 2) // gdb-command:print tuple_different_enums -// gdb-check:$3 = {__0 = OneThousand, __1 = MountainView, __2 = OneMillion, __3 = Vienna} +// gdbg-check:$3 = {__0 = OneThousand, __1 = MountainView, __2 = OneMillion, __3 = Vienna} +// gdbr-check:$3 = (c_style_enum_in_composite::AnEnum::OneThousand, c_style_enum_in_composite::AnotherEnum::MountainView, c_style_enum_in_composite::AnEnum::OneMillion, c_style_enum_in_composite::AnotherEnum::Vienna) // gdb-command:print padded_struct -// gdb-check:$4 = {a = 3, b = OneMillion, c = 4, d = Toronto, e = 5} +// gdbg-check:$4 = {a = 3, b = OneMillion, c = 4, d = Toronto, e = 5} +// gdbr-check:$4 = c_style_enum_in_composite::PaddedStruct {a: 3, b: c_style_enum_in_composite::AnEnum::OneMillion, c: 4, d: c_style_enum_in_composite::AnotherEnum::Toronto, e: 5} // gdb-command:print packed_struct -// gdb-check:$5 = {a = 6, b = OneHundred, c = 7, d = Vienna, e = 8} +// gdbg-check:$5 = {a = 6, b = OneHundred, c = 7, d = Vienna, e = 8} +// gdbr-check:$5 = c_style_enum_in_composite::PackedStruct {a: 6, b: c_style_enum_in_composite::AnEnum::OneHundred, c: 7, d: c_style_enum_in_composite::AnotherEnum::Vienna, e: 8} // gdb-command:print non_padded_struct -// gdb-check:$6 = {a = OneMillion, b = MountainView, c = OneThousand, d = Toronto} +// gdbg-check:$6 = {a = OneMillion, b = MountainView, c = OneThousand, d = Toronto} +// gdbr-check:$6 = c_style_enum_in_composite::NonPaddedStruct {a: c_style_enum_in_composite::AnEnum::OneMillion, b: c_style_enum_in_composite::AnotherEnum::MountainView, c: c_style_enum_in_composite::AnEnum::OneThousand, d: c_style_enum_in_composite::AnotherEnum::Toronto} // gdb-command:print struct_with_drop -// gdb-check:$7 = {__0 = {a = OneHundred, b = Vienna}, __1 = 9} - +// gdbg-check:$7 = {__0 = {a = OneHundred, b = Vienna}, __1 = 9} +// gdbr-check:$7 = (c_style_enum_in_composite::StructWithDrop {a: c_style_enum_in_composite::AnEnum::OneHundred, b: c_style_enum_in_composite::AnotherEnum::Vienna}, 9) // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/c-style-enum.rs b/src/test/debuginfo/c-style-enum.rs index dbd336d2dc688..2452c18f54347 100644 --- a/src/test/debuginfo/c-style-enum.rs +++ b/src/test/debuginfo/c-style-enum.rs @@ -16,60 +16,82 @@ // === GDB TESTS =================================================================================== // gdb-command:print 'c_style_enum::SINGLE_VARIANT' -// gdb-check:$1 = TheOnlyVariant +// gdbg-check:$1 = TheOnlyVariant +// gdbr-check:$1 = c_style_enum::SingleVariant::TheOnlyVariant // gdb-command:print 'c_style_enum::AUTO_ONE' -// gdb-check:$2 = One +// gdbg-check:$2 = One +// gdbr-check:$2 = c_style_enum::AutoDiscriminant::One // gdb-command:print 'c_style_enum::AUTO_TWO' -// gdb-check:$3 = One +// gdbg-check:$3 = One +// gdbr-check:$3 = c_style_enum::AutoDiscriminant::One // gdb-command:print 'c_style_enum::AUTO_THREE' -// gdb-check:$4 = One +// gdbg-check:$4 = One +// gdbr-check:$4 = c_style_enum::AutoDiscriminant::One // gdb-command:print 'c_style_enum::MANUAL_ONE' -// gdb-check:$5 = OneHundred +// gdbg-check:$5 = OneHundred +// gdbr-check:$5 = c_style_enum::ManualDiscriminant::OneHundred // gdb-command:print 'c_style_enum::MANUAL_TWO' -// gdb-check:$6 = OneHundred +// gdbg-check:$6 = OneHundred +// gdbr-check:$6 = c_style_enum::ManualDiscriminant::OneHundred // gdb-command:print 'c_style_enum::MANUAL_THREE' -// gdb-check:$7 = OneHundred +// gdbg-check:$7 = OneHundred +// gdbr-check:$7 = c_style_enum::ManualDiscriminant::OneHundred // gdb-command:run // gdb-command:print auto_one -// gdb-check:$8 = One +// gdbg-check:$8 = One +// gdbr-check:$8 = c_style_enum::AutoDiscriminant::One // gdb-command:print auto_two -// gdb-check:$9 = Two +// gdbg-check:$9 = Two +// gdbr-check:$9 = c_style_enum::AutoDiscriminant::Two // gdb-command:print auto_three -// gdb-check:$10 = Three +// gdbg-check:$10 = Three +// gdbr-check:$10 = c_style_enum::AutoDiscriminant::Three // gdb-command:print manual_one_hundred -// gdb-check:$11 = OneHundred +// gdbg-check:$11 = OneHundred +// gdbr-check:$11 = c_style_enum::ManualDiscriminant::OneHundred // gdb-command:print manual_one_thousand -// gdb-check:$12 = OneThousand +// gdbg-check:$12 = OneThousand +// gdbr-check:$12 = c_style_enum::ManualDiscriminant::OneThousand // gdb-command:print manual_one_million -// gdb-check:$13 = OneMillion +// gdbg-check:$13 = OneMillion +// gdbr-check:$13 = c_style_enum::ManualDiscriminant::OneMillion // gdb-command:print single_variant -// gdb-check:$14 = TheOnlyVariant - -// gdb-command:print 'c_style_enum::AUTO_TWO' -// gdb-check:$15 = Two - -// gdb-command:print 'c_style_enum::AUTO_THREE' -// gdb-check:$16 = Three - -// gdb-command:print 'c_style_enum::MANUAL_TWO' -// gdb-check:$17 = OneThousand - -// gdb-command:print 'c_style_enum::MANUAL_THREE' -// gdb-check:$18 = OneMillion +// gdbg-check:$14 = TheOnlyVariant +// gdbr-check:$14 = c_style_enum::SingleVariant::TheOnlyVariant + +// gdbg-command:print 'c_style_enum::AUTO_TWO' +// gdbr-command:print AUTO_TWO +// gdbg-check:$15 = Two +// gdbr-check:$15 = c_style_enum::AutoDiscriminant::Two + +// gdbg-command:print 'c_style_enum::AUTO_THREE' +// gdbr-command:print AUTO_THREE +// gdbg-check:$16 = Three +// gdbr-check:$16 = c_style_enum::AutoDiscriminant::Three + +// gdbg-command:print 'c_style_enum::MANUAL_TWO' +// gdbr-command:print MANUAL_TWO +// gdbg-check:$17 = OneThousand +// gdbr-check:$17 = c_style_enum::ManualDiscriminant::OneThousand + +// gdbg-command:print 'c_style_enum::MANUAL_THREE' +// gdbr-command:print MANUAL_THREE +// gdbg-check:$18 = OneMillion +// gdbr-check:$18 = c_style_enum::ManualDiscriminant::OneMillion // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/cross-crate-spans.rs b/src/test/debuginfo/cross-crate-spans.rs index 544fe2c66d5e8..28728df928051 100644 --- a/src/test/debuginfo/cross-crate-spans.rs +++ b/src/test/debuginfo/cross-crate-spans.rs @@ -25,7 +25,8 @@ extern crate cross_crate_spans; // gdb-command:run // gdb-command:print result -// gdb-check:$1 = {__0 = 17, __1 = 17} +// gdbg-check:$1 = {__0 = 17, __1 = 17} +// gdbr-check:$1 = (17, 17) // gdb-command:print a_variable // gdb-check:$2 = 123456789 // gdb-command:print another_variable @@ -33,7 +34,8 @@ extern crate cross_crate_spans; // gdb-command:continue // gdb-command:print result -// gdb-check:$4 = {__0 = 1212, __1 = 1212} +// gdbg-check:$4 = {__0 = 1212, __1 = 1212} +// gdbr-check:$4 = (1212, 1212) // gdb-command:print a_variable // gdb-check:$5 = 123456789 // gdb-command:print another_variable diff --git a/src/test/debuginfo/destructured-fn-argument.rs b/src/test/debuginfo/destructured-fn-argument.rs index 954a7abe6323c..efa9ee59b22b2 100644 --- a/src/test/debuginfo/destructured-fn-argument.rs +++ b/src/test/debuginfo/destructured-fn-argument.rs @@ -33,13 +33,15 @@ // gdb-command:print a // gdb-check:$6 = 5 // gdb-command:print b -// gdb-check:$7 = {__0 = 6, __1 = 7} +// gdbg-check:$7 = {__0 = 6, __1 = 7} +// gdbr-check:$7 = (6, 7) // gdb-command:continue // gdb-command:print h // gdb-check:$8 = 8 // gdb-command:print i -// gdb-check:$9 = {a = 9, b = 10} +// gdbg-check:$9 = {a = 9, b = 10} +// gdbr-check:$9 = destructured_fn_argument::Struct {a: 9, b: 10} // gdb-command:print j // gdb-check:$10 = 11 // gdb-command:continue @@ -65,7 +67,8 @@ // gdb-command:print q // gdb-check:$17 = 20 // gdb-command:print r -// gdb-check:$18 = {a = 21, b = 22} +// gdbg-check:$18 = {a = 21, b = 22} +// gdbr-check:$18 = destructured_fn_argument::Struct {a: 21, b: 22} // gdb-command:continue // gdb-command:print s @@ -95,11 +98,13 @@ // gdb-command:continue // gdb-command:print aa -// gdb-check:$30 = {__0 = 34, __1 = 35} +// gdbg-check:$30 = {__0 = 34, __1 = 35} +// gdbr-check:$30 = (34, 35) // gdb-command:continue // gdb-command:print bb -// gdb-check:$31 = {__0 = 36, __1 = 37} +// gdbg-check:$31 = {__0 = 36, __1 = 37} +// gdbr-check:$31 = (36, 37) // gdb-command:continue // gdb-command:print cc @@ -107,17 +112,20 @@ // gdb-command:continue // gdb-command:print dd -// gdb-check:$33 = {__0 = 40, __1 = 41, __2 = 42} +// gdbg-check:$33 = {__0 = 40, __1 = 41, __2 = 42} +// gdbr-check:$33 = (40, 41, 42) // gdb-command:continue // gdb-command:print *ee -// gdb-check:$34 = {__0 = 43, __1 = 44, __2 = 45} +// gdbg-check:$34 = {__0 = 43, __1 = 44, __2 = 45} +// gdbr-check:$34 = (43, 44, 45) // gdb-command:continue // gdb-command:print *ff // gdb-check:$35 = 46 // gdb-command:print gg -// gdb-check:$36 = {__0 = 47, __1 = 48} +// gdbg-check:$36 = {__0 = 47, __1 = 48} +// gdbr-check:$36 = (47, 48) // gdb-command:continue // gdb-command:print *hh diff --git a/src/test/debuginfo/destructured-for-loop-variable.rs b/src/test/debuginfo/destructured-for-loop-variable.rs index a34d5d6adbfcb..e973c22fd4a85 100644 --- a/src/test/debuginfo/destructured-for-loop-variable.rs +++ b/src/test/debuginfo/destructured-for-loop-variable.rs @@ -73,11 +73,13 @@ // gdb-command:continue // gdb-command:print simple_struct_ident -// gdb-check:$23 = {x = 3537, y = 35437.5, z = true} +// gdbg-check:$23 = {x = 3537, y = 35437.5, z = true} +// gdbr-check:$23 = destructured_for_loop_variable::Struct {x: 3537, y: 35437.5, z: true} // gdb-command:continue // gdb-command:print simple_tuple_ident -// gdb-check:$24 = {__0 = 34903493, __1 = 232323} +// gdbg-check:$24 = {__0 = 34903493, __1 = 232323} +// gdbr-check:$24 = (34903493, 232323) // gdb-command:continue // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/destructured-local.rs b/src/test/debuginfo/destructured-local.rs index a43e4546d4f8f..1f18b77ab8f6f 100644 --- a/src/test/debuginfo/destructured-local.rs +++ b/src/test/debuginfo/destructured-local.rs @@ -31,12 +31,14 @@ // gdb-command:print f // gdb-check:$6 = 5 // gdb-command:print g -// gdb-check:$7 = {__0 = 6, __1 = 7} +// gdbg-check:$7 = {__0 = 6, __1 = 7} +// gdbr-check:$7 = (6, 7) // gdb-command:print h // gdb-check:$8 = 8 // gdb-command:print i -// gdb-check:$9 = {a = 9, b = 10} +// gdbg-check:$9 = {a = 9, b = 10} +// gdbr-check:$9 = destructured_local::Struct {a: 9, b: 10} // gdb-command:print j // gdb-check:$10 = 11 @@ -58,7 +60,8 @@ // gdb-command:print q // gdb-check:$17 = 20 // gdb-command:print r -// gdb-check:$18 = {a = 21, b = 22} +// gdbg-check:$18 = {a = 21, b = 22} +// gdbr-check:$18 = destructured_local::Struct {a: 21, b: 22} // gdb-command:print s // gdb-check:$19 = 24 @@ -85,25 +88,30 @@ // gdb-check:$29 = 33 // gdb-command:print aa -// gdb-check:$30 = {__0 = 34, __1 = 35} +// gdbg-check:$30 = {__0 = 34, __1 = 35} +// gdbr-check:$30 = (34, 35) // gdb-command:print bb -// gdb-check:$31 = {__0 = 36, __1 = 37} +// gdbg-check:$31 = {__0 = 36, __1 = 37} +// gdbr-check:$31 = (36, 37) // gdb-command:print cc // gdb-check:$32 = 38 // gdb-command:print dd -// gdb-check:$33 = {__0 = 40, __1 = 41, __2 = 42} +// gdbg-check:$33 = {__0 = 40, __1 = 41, __2 = 42} +// gdbr-check:$33 = (40, 41, 42) // gdb-command:print *ee -// gdb-check:$34 = {__0 = 43, __1 = 44, __2 = 45} +// gdbg-check:$34 = {__0 = 43, __1 = 44, __2 = 45} +// gdbr-check:$34 = (43, 44, 45) // gdb-command:print *ff // gdb-check:$35 = 46 // gdb-command:print gg -// gdb-check:$36 = {__0 = 47, __1 = 48} +// gdbg-check:$36 = {__0 = 47, __1 = 48} +// gdbr-check:$36 = (47, 48) // gdb-command:print *hh // gdb-check:$37 = 50 diff --git a/src/test/debuginfo/evec-in-struct.rs b/src/test/debuginfo/evec-in-struct.rs index 8624a0cba0256..2e151577590b3 100644 --- a/src/test/debuginfo/evec-in-struct.rs +++ b/src/test/debuginfo/evec-in-struct.rs @@ -17,18 +17,23 @@ // gdb-command:run // gdb-command:print no_padding1 -// gdb-check:$1 = {x = {0, 1, 2}, y = -3, z = {4.5, 5.5}} +// gdbg-check:$1 = {x = {0, 1, 2}, y = -3, z = {4.5, 5.5}} +// gdbr-check:$1 = evec_in_struct::NoPadding1 {x: [0, 1, 2], y: -3, z: [4.5, 5.5]} // gdb-command:print no_padding2 -// gdb-check:$2 = {x = {6, 7, 8}, y = {{9, 10}, {11, 12}}} +// gdbg-check:$2 = {x = {6, 7, 8}, y = {{9, 10}, {11, 12}}} +// gdbr-check:$2 = evec_in_struct::NoPadding2 {x: [6, 7, 8], y: [[9, 10], [11, 12]]} // gdb-command:print struct_internal_padding -// gdb-check:$3 = {x = {13, 14}, y = {15, 16}} +// gdbg-check:$3 = {x = {13, 14}, y = {15, 16}} +// gdbr-check:$3 = evec_in_struct::StructInternalPadding {x: [13, 14], y: [15, 16]} // gdb-command:print single_vec -// gdb-check:$4 = {x = {17, 18, 19, 20, 21}} +// gdbg-check:$4 = {x = {17, 18, 19, 20, 21}} +// gdbr-check:$4 = evec_in_struct::SingleVec {x: [17, 18, 19, 20, 21]} // gdb-command:print struct_padded_at_end -// gdb-check:$5 = {x = {22, 23}, y = {24, 25}} +// gdbg-check:$5 = {x = {22, 23}, y = {24, 25}} +// gdbr-check:$5 = evec_in_struct::StructPaddedAtEnd {x: [22, 23], y: [24, 25]} // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/extern-c-fn.rs b/src/test/debuginfo/extern-c-fn.rs index c93db41dc55bf..01901b2c42b8e 100644 --- a/src/test/debuginfo/extern-c-fn.rs +++ b/src/test/debuginfo/extern-c-fn.rs @@ -16,7 +16,8 @@ // gdb-command:run // gdb-command:print s -// gdb-check:$1 = [...]"abcd" +// gdbg-check:$1 = [...]"abcd" +// gdbr-check:$1 = [...]"abcd\000" // gdb-command:print len // gdb-check:$2 = 20 // gdb-command:print local0 diff --git a/src/test/debuginfo/function-arg-initialization.rs b/src/test/debuginfo/function-arg-initialization.rs index 57654acaf73d8..21fdc4e5e88a6 100644 --- a/src/test/debuginfo/function-arg-initialization.rs +++ b/src/test/debuginfo/function-arg-initialization.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-tidy-linelength + // min-lldb-version: 310 // This test case checks if function arguments already have the correct value @@ -34,9 +36,11 @@ // NON IMMEDIATE ARGS // gdb-command:print a -// gdb-check:$4 = {a = 3, b = 4, c = 5, d = 6, e = 7, f = 8, g = 9, h = 10} +// gdbg-check:$4 = {a = 3, b = 4, c = 5, d = 6, e = 7, f = 8, g = 9, h = 10} +// gdbt-check:$4 = function_arg_initialization::BigStruct {a: 3, b: 4, c: 5, d: 6, e: 7, f: 8, g: 9, h: 10} // gdb-command:print b -// gdb-check:$5 = {a = 11, b = 12, c = 13, d = 14, e = 15, f = 16, g = 17, h = 18} +// gdbg-check:$5 = {a = 11, b = 12, c = 13, d = 14, e = 15, f = 16, g = 17, h = 18} +// gdbt-check:$5 = function_arg_initialization::BigStruct {a: 11, b: 12, c: 13, d: 14, e: 15, f: 16, g: 17, h: 18} // gdb-command:continue // BINDING diff --git a/src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs b/src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs index 81743a367e40f..158a1f17fc03d 100644 --- a/src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs +++ b/src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs @@ -26,13 +26,16 @@ // gdb-check:$2 = EmptyStruct // gdb-command: print c_style_enum1 -// gdb-check:$3 = CStyleEnumVar1 +// gdbg-check:$3 = CStyleEnumVar1 +// gdbr-check:$3 = gdb_pretty_struct_and_enums_pre_gdb_7_7::CStyleEnum::CStyleEnumVar1 // gdb-command: print c_style_enum2 -// gdb-check:$4 = CStyleEnumVar2 +// gdbg-check:$4 = CStyleEnumVar2 +// gdbr-check:$4 = gdb_pretty_struct_and_enums_pre_gdb_7_7::CStyleEnum::CStyleEnumVar2 // gdb-command: print c_style_enum3 -// gdb-check:$5 = CStyleEnumVar3 +// gdbg-check:$5 = CStyleEnumVar3 +// gdbr-check:$5 = gdb_pretty_struct_and_enums_pre_gdb_7_7::CStyleEnum::CStyleEnumVar3 #![allow(dead_code, unused_variables)] diff --git a/src/test/debuginfo/generic-enum-with-different-disr-sizes.rs b/src/test/debuginfo/generic-enum-with-different-disr-sizes.rs index 3115b3f7e761c..1fc05b3752f04 100644 --- a/src/test/debuginfo/generic-enum-with-different-disr-sizes.rs +++ b/src/test/debuginfo/generic-enum-with-different-disr-sizes.rs @@ -18,22 +18,37 @@ // gdb-command:run // gdb-command:print eight_bytes1 -// gdb-check:$1 = {{RUST$ENUM$DISR = Variant1, __0 = 100}, {RUST$ENUM$DISR = Variant1, __0 = 100}} +// gdbg-check:$1 = {{RUST$ENUM$DISR = Variant1, __0 = 100}, {RUST$ENUM$DISR = Variant1, __0 = 100}} +// gdbr-check:$1 = generic_enum_with_different_disr_sizes::Enum::Variant1(100) + // gdb-command:print four_bytes1 -// gdb-check:$2 = {{RUST$ENUM$DISR = Variant1, __0 = 101}, {RUST$ENUM$DISR = Variant1, __0 = 101}} +// gdbg-check:$2 = {{RUST$ENUM$DISR = Variant1, __0 = 101}, {RUST$ENUM$DISR = Variant1, __0 = 101}} +// gdbr-check:$2 = generic_enum_with_different_disr_sizes::Enum::Variant1(101) + // gdb-command:print two_bytes1 -// gdb-check:$3 = {{RUST$ENUM$DISR = Variant1, __0 = 102}, {RUST$ENUM$DISR = Variant1, __0 = 102}} +// gdbg-check:$3 = {{RUST$ENUM$DISR = Variant1, __0 = 102}, {RUST$ENUM$DISR = Variant1, __0 = 102}} +// gdbr-check:$3 = generic_enum_with_different_disr_sizes::Enum::Variant1(102) + // gdb-command:print one_byte1 -// gdb-check:$4 = {{RUST$ENUM$DISR = Variant1, __0 = 65 'A'}, {RUST$ENUM$DISR = Variant1, __0 = 65 'A'}} +// gdbg-check:$4 = {{RUST$ENUM$DISR = Variant1, __0 = 65 'A'}, {RUST$ENUM$DISR = Variant1, __0 = 65 'A'}} +// gdbr-check:$4 = generic_enum_with_different_disr_sizes::Enum::Variant1(65) + // gdb-command:print eight_bytes2 -// gdb-check:$5 = {{RUST$ENUM$DISR = Variant2, __0 = 100}, {RUST$ENUM$DISR = Variant2, __0 = 100}} +// gdbg-check:$5 = {{RUST$ENUM$DISR = Variant2, __0 = 100}, {RUST$ENUM$DISR = Variant2, __0 = 100}} +// gdbr-check:$5 = generic_enum_with_different_disr_sizes::Enum::Variant2(100) + // gdb-command:print four_bytes2 -// gdb-check:$6 = {{RUST$ENUM$DISR = Variant2, __0 = 101}, {RUST$ENUM$DISR = Variant2, __0 = 101}} +// gdbg-check:$6 = {{RUST$ENUM$DISR = Variant2, __0 = 101}, {RUST$ENUM$DISR = Variant2, __0 = 101}} +// gdbr-check:$6 = generic_enum_with_different_disr_sizes::Enum::Variant2(101) + // gdb-command:print two_bytes2 -// gdb-check:$7 = {{RUST$ENUM$DISR = Variant2, __0 = 102}, {RUST$ENUM$DISR = Variant2, __0 = 102}} +// gdbg-check:$7 = {{RUST$ENUM$DISR = Variant2, __0 = 102}, {RUST$ENUM$DISR = Variant2, __0 = 102}} +// gdbr-check:$7 = generic_enum_with_different_disr_sizes::Enum::Variant2(102) + // gdb-command:print one_byte2 -// gdb-check:$8 = {{RUST$ENUM$DISR = Variant2, __0 = 65 'A'}, {RUST$ENUM$DISR = Variant2, __0 = 65 'A'}} +// gdbg-check:$8 = {{RUST$ENUM$DISR = Variant2, __0 = 65 'A'}, {RUST$ENUM$DISR = Variant2, __0 = 65 'A'}} +// gdbr-check:$8 = generic_enum_with_different_disr_sizes::Enum::Variant2(65) // gdb-command:continue diff --git a/src/test/debuginfo/generic-function.rs b/src/test/debuginfo/generic-function.rs index 415dd36212a44..f1bfc08915edd 100644 --- a/src/test/debuginfo/generic-function.rs +++ b/src/test/debuginfo/generic-function.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-tidy-linelength + // min-lldb-version: 310 // compile-flags:-g @@ -21,7 +23,8 @@ // gdb-command:print *t1 // gdb-check:$2 = 2.5 // gdb-command:print ret -// gdb-check:$3 = {__0 = {__0 = 1, __1 = 2.5}, __1 = {__0 = 2.5, __1 = 1}} +// gdbg-check:$3 = {__0 = {__0 = 1, __1 = 2.5}, __1 = {__0 = 2.5, __1 = 1}} +// gdbr-check:$3 = ((1, 2.5), (2.5, 1)) // gdb-command:continue // gdb-command:print *t0 @@ -29,15 +32,18 @@ // gdb-command:print *t1 // gdb-check:$5 = 4 // gdb-command:print ret -// gdb-check:$6 = {__0 = {__0 = 3.5, __1 = 4}, __1 = {__0 = 4, __1 = 3.5}} +// gdbg-check:$6 = {__0 = {__0 = 3.5, __1 = 4}, __1 = {__0 = 4, __1 = 3.5}} +// gdbr-check:$6 = ((3.5, 4), (4, 3.5)) // gdb-command:continue // gdb-command:print *t0 // gdb-check:$7 = 5 // gdb-command:print *t1 -// gdb-check:$8 = {a = 6, b = 7.5} +// gdbg-check:$8 = {a = 6, b = 7.5} +// gdbr-check:$8 = generic_function::Struct {a: 6, b: 7.5} // gdb-command:print ret -// gdb-check:$9 = {__0 = {__0 = 5, __1 = {a = 6, b = 7.5}}, __1 = {__0 = {a = 6, b = 7.5}, __1 = 5}} +// gdbg-check:$9 = {__0 = {__0 = 5, __1 = {a = 6, b = 7.5}}, __1 = {__0 = {a = 6, b = 7.5}, __1 = 5}} +// gdbr-check:$9 = ((5, generic_function::Struct {a: 6, b: 7.5}), (generic_function::Struct {a: 6, b: 7.5}, 5)) // gdb-command:continue diff --git a/src/test/debuginfo/generic-method-on-generic-struct.rs b/src/test/debuginfo/generic-method-on-generic-struct.rs index 968cb2e159716..4f3f6dfc821ee 100644 --- a/src/test/debuginfo/generic-method-on-generic-struct.rs +++ b/src/test/debuginfo/generic-method-on-generic-struct.rs @@ -18,7 +18,8 @@ // STACK BY REF // gdb-command:print *self -// gdb-check:$1 = {x = {__0 = 8888, __1 = -8888}} +// gdbg-check:$1 = {x = {__0 = 8888, __1 = -8888}} +// gdbr-check:$1 = generic_method_on_generic_struct::Struct<(u32, i32)> {x: (8888, -8888)} // gdb-command:print arg1 // gdb-check:$2 = -1 // gdb-command:print arg2 @@ -27,7 +28,8 @@ // STACK BY VAL // gdb-command:print self -// gdb-check:$4 = {x = {__0 = 8888, __1 = -8888}} +// gdbg-check:$4 = {x = {__0 = 8888, __1 = -8888}} +// gdbr-check:$4 = generic_method_on_generic_struct::Struct<(u32, i32)> {x: (8888, -8888)} // gdb-command:print arg1 // gdb-check:$5 = -3 // gdb-command:print arg2 @@ -36,7 +38,8 @@ // OWNED BY REF // gdb-command:print *self -// gdb-check:$7 = {x = 1234.5} +// gdbg-check:$7 = {x = 1234.5} +// gdbr-check:$7 = generic_method_on_generic_struct::Struct {x: 1234.5} // gdb-command:print arg1 // gdb-check:$8 = -5 // gdb-command:print arg2 @@ -45,7 +48,8 @@ // OWNED BY VAL // gdb-command:print self -// gdb-check:$10 = {x = 1234.5} +// gdbg-check:$10 = {x = 1234.5} +// gdbr-check:$10 = generic_method_on_generic_struct::Struct {x: 1234.5} // gdb-command:print arg1 // gdb-check:$11 = -7 // gdb-command:print arg2 @@ -54,7 +58,8 @@ // OWNED MOVED // gdb-command:print *self -// gdb-check:$13 = {x = 1234.5} +// gdbg-check:$13 = {x = 1234.5} +// gdbr-check:$13 = generic_method_on_generic_struct::Struct {x: 1234.5} // gdb-command:print arg1 // gdb-check:$14 = -9 // gdb-command:print arg2 diff --git a/src/test/debuginfo/generic-struct-style-enum.rs b/src/test/debuginfo/generic-struct-style-enum.rs index 991404f56eff9..dba9422721a96 100644 --- a/src/test/debuginfo/generic-struct-style-enum.rs +++ b/src/test/debuginfo/generic-struct-style-enum.rs @@ -17,16 +17,20 @@ // gdb-command:run // gdb-command:print case1 -// gdb-check:$1 = {{RUST$ENUM$DISR = Case1, a = 0, b = 31868, c = 31868, d = 31868, e = 31868}, {RUST$ENUM$DISR = Case1, a = 0, b = 2088533116, c = 2088533116}, {RUST$ENUM$DISR = Case1, a = 0, b = 8970181431921507452}} +// gdbg-check:$1 = {{RUST$ENUM$DISR = Case1, a = 0, b = 31868, c = 31868, d = 31868, e = 31868}, {RUST$ENUM$DISR = Case1, a = 0, b = 2088533116, c = 2088533116}, {RUST$ENUM$DISR = Case1, a = 0, b = 8970181431921507452}} +// gdbr-check:$1 = generic_struct_style_enum::Regular::Case1{a: 0, b: 31868, c: 31868, d: 31868, e: 31868} // gdb-command:print case2 -// gdb-check:$2 = {{RUST$ENUM$DISR = Case2, a = 0, b = 4369, c = 4369, d = 4369, e = 4369}, {RUST$ENUM$DISR = Case2, a = 0, b = 286331153, c = 286331153}, {RUST$ENUM$DISR = Case2, a = 0, b = 1229782938247303441}} +// gdbg-check:$2 = {{RUST$ENUM$DISR = Case2, a = 0, b = 4369, c = 4369, d = 4369, e = 4369}, {RUST$ENUM$DISR = Case2, a = 0, b = 286331153, c = 286331153}, {RUST$ENUM$DISR = Case2, a = 0, b = 1229782938247303441}} +// gdbr-check:$2 = generic_struct_style_enum::Regular::Case2{a: 0, b: 286331153, c: 286331153} // gdb-command:print case3 -// gdb-check:$3 = {{RUST$ENUM$DISR = Case3, a = 0, b = 22873, c = 22873, d = 22873, e = 22873}, {RUST$ENUM$DISR = Case3, a = 0, b = 1499027801, c = 1499027801}, {RUST$ENUM$DISR = Case3, a = 0, b = 6438275382588823897}} +// gdbg-check:$3 = {{RUST$ENUM$DISR = Case3, a = 0, b = 22873, c = 22873, d = 22873, e = 22873}, {RUST$ENUM$DISR = Case3, a = 0, b = 1499027801, c = 1499027801}, {RUST$ENUM$DISR = Case3, a = 0, b = 6438275382588823897}} +// gdbr-check:$3 = generic_struct_style_enum::Regular::Case3{a: 0, b: 6438275382588823897} // gdb-command:print univariant -// gdb-check:$4 = {{a = -1}} +// gdbg-check:$4 = {{a = -1}} +// gdbr-check:$4 = generic_struct_style_enum::Univariant::TheOnlyCase{a: -1} #![feature(omit_gdb_pretty_printer_section)] diff --git a/src/test/debuginfo/generic-struct.rs b/src/test/debuginfo/generic-struct.rs index 92a67a2344d1c..35f00ce78717b 100644 --- a/src/test/debuginfo/generic-struct.rs +++ b/src/test/debuginfo/generic-struct.rs @@ -18,13 +18,17 @@ // gdb-command:run // gdb-command:print int_int -// gdb-check:$1 = {key = 0, value = 1} +// gdbg-check:$1 = {key = 0, value = 1} +// gdbr-check:$1 = generic_struct::AGenericStruct {key: 0, value: 1} // gdb-command:print int_float -// gdb-check:$2 = {key = 2, value = 3.5} +// gdbg-check:$2 = {key = 2, value = 3.5} +// gdbr-check:$2 = generic_struct::AGenericStruct {key: 2, value: 3.5} // gdb-command:print float_int -// gdb-check:$3 = {key = 4.5, value = 5} +// gdbg-check:$3 = {key = 4.5, value = 5} +// gdbr-check:$3 = generic_struct::AGenericStruct {key: 4.5, value: 5} // gdb-command:print float_int_float -// gdb-check:$4 = {key = 6.5, value = {key = 7, value = 8.5}} +// gdbg-check:$4 = {key = 6.5, value = {key = 7, value = 8.5}} +// gdbr-check:$4 = generic_struct::AGenericStruct> {key: 6.5, value: generic_struct::AGenericStruct {key: 7, value: 8.5}} // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/generic-tuple-style-enum.rs b/src/test/debuginfo/generic-tuple-style-enum.rs index e2727fbe7df4a..01d2ff4e33439 100644 --- a/src/test/debuginfo/generic-tuple-style-enum.rs +++ b/src/test/debuginfo/generic-tuple-style-enum.rs @@ -19,16 +19,20 @@ // gdb-command:run // gdb-command:print case1 -// gdb-check:$1 = {{RUST$ENUM$DISR = Case1, __0 = 0, __1 = 31868, __2 = 31868, __3 = 31868, __4 = 31868}, {RUST$ENUM$DISR = Case1, __0 = 0, __1 = 2088533116, __2 = 2088533116}, {RUST$ENUM$DISR = Case1, __0 = 0, __1 = 8970181431921507452}} +// gdbg-check:$1 = {{RUST$ENUM$DISR = Case1, __0 = 0, __1 = 31868, __2 = 31868, __3 = 31868, __4 = 31868}, {RUST$ENUM$DISR = Case1, __0 = 0, __1 = 2088533116, __2 = 2088533116}, {RUST$ENUM$DISR = Case1, __0 = 0, __1 = 8970181431921507452}} +// gdbr-check:$1 = generic_tuple_style_enum::Regular::Case1(0, 31868, 31868, 31868, 31868) // gdb-command:print case2 -// gdb-check:$2 = {{RUST$ENUM$DISR = Case2, __0 = 0, __1 = 4369, __2 = 4369, __3 = 4369, __4 = 4369}, {RUST$ENUM$DISR = Case2, __0 = 0, __1 = 286331153, __2 = 286331153}, {RUST$ENUM$DISR = Case2, __0 = 0, __1 = 1229782938247303441}} +// gdbg-check:$2 = {{RUST$ENUM$DISR = Case2, __0 = 0, __1 = 4369, __2 = 4369, __3 = 4369, __4 = 4369}, {RUST$ENUM$DISR = Case2, __0 = 0, __1 = 286331153, __2 = 286331153}, {RUST$ENUM$DISR = Case2, __0 = 0, __1 = 1229782938247303441}} +// gdbr-check:$2 = generic_tuple_style_enum::Regular::Case2(0, 286331153, 286331153) // gdb-command:print case3 -// gdb-check:$3 = {{RUST$ENUM$DISR = Case3, __0 = 0, __1 = 22873, __2 = 22873, __3 = 22873, __4 = 22873}, {RUST$ENUM$DISR = Case3, __0 = 0, __1 = 1499027801, __2 = 1499027801}, {RUST$ENUM$DISR = Case3, __0 = 0, __1 = 6438275382588823897}} +// gdbg-check:$3 = {{RUST$ENUM$DISR = Case3, __0 = 0, __1 = 22873, __2 = 22873, __3 = 22873, __4 = 22873}, {RUST$ENUM$DISR = Case3, __0 = 0, __1 = 1499027801, __2 = 1499027801}, {RUST$ENUM$DISR = Case3, __0 = 0, __1 = 6438275382588823897}} +// gdbr-check:$3 = generic_tuple_style_enum::Regular::Case3(0, 6438275382588823897) // gdb-command:print univariant -// gdb-check:$4 = {{__0 = -1}} +// gdbg-check:$4 = {{__0 = -1}} +// gdbr-check:$4 = generic_tuple_style_enum::Univariant::TheOnlyCase(-1) // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/lexical-scopes-in-block-expression.rs b/src/test/debuginfo/lexical-scopes-in-block-expression.rs index 841786f930daf..8e8a194e37841 100644 --- a/src/test/debuginfo/lexical-scopes-in-block-expression.rs +++ b/src/test/debuginfo/lexical-scopes-in-block-expression.rs @@ -16,7 +16,8 @@ // gdb-command:run -// gdb-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbg-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbr-command:print lexical_scopes_in_block_expression::MUT_INT // gdb-check:$1 = 0 // STRUCT EXPRESSION @@ -28,7 +29,8 @@ // gdb-command:print val // gdb-check:$4 = 11 -// gdb-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbg-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbr-command:print lexical_scopes_in_block_expression::MUT_INT // gdb-check:$5 = 1 // gdb-command:print ten // gdb-check:$6 = 10 @@ -49,7 +51,8 @@ // gdb-command:print val // gdb-check:$11 = 12 -// gdb-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbg-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbr-command:print lexical_scopes_in_block_expression::MUT_INT // gdb-check:$12 = 2 // gdb-command:print ten // gdb-check:$13 = 10 @@ -70,7 +73,8 @@ // gdb-command:print val // gdb-check:$18 = 13 -// gdb-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbg-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbr-command:print lexical_scopes_in_block_expression::MUT_INT // gdb-check:$19 = 3 // gdb-command:print ten // gdb-check:$20 = 10 @@ -91,7 +95,8 @@ // gdb-command:print val // gdb-check:$25 = 14 -// gdb-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbg-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbr-command:print lexical_scopes_in_block_expression::MUT_INT // gdb-check:$26 = 4 // gdb-command:print ten // gdb-check:$27 = 10 @@ -112,7 +117,8 @@ // gdb-command:print val // gdb-check:$32 = 15 -// gdb-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbg-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbr-command:print lexical_scopes_in_block_expression::MUT_INT // gdb-check:$33 = 5 // gdb-command:print ten // gdb-check:$34 = 10 @@ -133,7 +139,8 @@ // gdb-command:print val // gdb-check:$39 = 16 -// gdb-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbg-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbr-command:print lexical_scopes_in_block_expression::MUT_INT // gdb-check:$40 = 6 // gdb-command:print ten // gdb-check:$41 = 10 @@ -155,7 +162,8 @@ // gdb-command:print val // gdb-check:$46 = 17 -// gdb-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbg-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbr-command:print lexical_scopes_in_block_expression::MUT_INT // gdb-check:$47 = 7 // gdb-command:print ten // gdb-check:$48 = 10 @@ -176,7 +184,8 @@ // gdb-command:print val // gdb-check:$53 = 18 -// gdb-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbg-command:print 'lexical_scopes_in_block_expression::MUT_INT' +// gdbr-command:print lexical_scopes_in_block_expression::MUT_INT // gdb-check:$54 = 8 // gdb-command:print ten // gdb-check:$55 = 10 diff --git a/src/test/debuginfo/method-on-enum.rs b/src/test/debuginfo/method-on-enum.rs index 6437b3bb900f8..7dbc0d3c5130d 100644 --- a/src/test/debuginfo/method-on-enum.rs +++ b/src/test/debuginfo/method-on-enum.rs @@ -19,7 +19,8 @@ // STACK BY REF // gdb-command:print *self -// gdb-check:$1 = {{RUST$ENUM$DISR = Variant2, [...]}, {RUST$ENUM$DISR = Variant2, __0 = 117901063}} +// gdbg-check:$1 = {{RUST$ENUM$DISR = Variant2, [...]}, {RUST$ENUM$DISR = Variant2, __0 = 117901063}} +// gdbr-check:$1 = method_on_enum::Enum::Variant2(117901063) // gdb-command:print arg1 // gdb-check:$2 = -1 // gdb-command:print arg2 @@ -28,7 +29,8 @@ // STACK BY VAL // gdb-command:print self -// gdb-check:$4 = {{RUST$ENUM$DISR = Variant2, [...]}, {RUST$ENUM$DISR = Variant2, __0 = 117901063}} +// gdbg-check:$4 = {{RUST$ENUM$DISR = Variant2, [...]}, {RUST$ENUM$DISR = Variant2, __0 = 117901063}} +// gdbr-check:$4 = method_on_enum::Enum::Variant2(117901063) // gdb-command:print arg1 // gdb-check:$5 = -3 // gdb-command:print arg2 @@ -37,7 +39,8 @@ // OWNED BY REF // gdb-command:print *self -// gdb-check:$7 = {{RUST$ENUM$DISR = Variant1, x = 1799, y = 1799}, {RUST$ENUM$DISR = Variant1, [...]}} +// gdbg-check:$7 = {{RUST$ENUM$DISR = Variant1, x = 1799, y = 1799}, {RUST$ENUM$DISR = Variant1, [...]}} +// gdbr-check:$7 = method_on_enum::Enum::Variant1{x: 1799, y: 1799} // gdb-command:print arg1 // gdb-check:$8 = -5 // gdb-command:print arg2 @@ -46,7 +49,8 @@ // OWNED BY VAL // gdb-command:print self -// gdb-check:$10 = {{RUST$ENUM$DISR = Variant1, x = 1799, y = 1799}, {RUST$ENUM$DISR = Variant1, [...]}} +// gdbg-check:$10 = {{RUST$ENUM$DISR = Variant1, x = 1799, y = 1799}, {RUST$ENUM$DISR = Variant1, [...]}} +// gdbr-check:$10 = method_on_enum::Enum::Variant1{x: 1799, y: 1799} // gdb-command:print arg1 // gdb-check:$11 = -7 // gdb-command:print arg2 @@ -55,7 +59,8 @@ // OWNED MOVED // gdb-command:print *self -// gdb-check:$13 = {{RUST$ENUM$DISR = Variant1, x = 1799, y = 1799}, {RUST$ENUM$DISR = Variant1, [...]}} +// gdbg-check:$13 = {{RUST$ENUM$DISR = Variant1, x = 1799, y = 1799}, {RUST$ENUM$DISR = Variant1, [...]}} +// gdbr-check:$13 = method_on_enum::Enum::Variant1{x: 1799, y: 1799} // gdb-command:print arg1 // gdb-check:$14 = -9 // gdb-command:print arg2 diff --git a/src/test/debuginfo/method-on-generic-struct.rs b/src/test/debuginfo/method-on-generic-struct.rs index 5b697f859d4ed..20d419b4ac088 100644 --- a/src/test/debuginfo/method-on-generic-struct.rs +++ b/src/test/debuginfo/method-on-generic-struct.rs @@ -18,7 +18,8 @@ // STACK BY REF // gdb-command:print *self -// gdb-check:$1 = {x = {__0 = 8888, __1 = -8888}} +// gdbg-check:$1 = {x = {__0 = 8888, __1 = -8888}} +// gdbr-check:$1 = method_on_generic_struct::Struct<(u32, i32)> {x: (8888, -8888)} // gdb-command:print arg1 // gdb-check:$2 = -1 // gdb-command:print arg2 @@ -27,7 +28,8 @@ // STACK BY VAL // gdb-command:print self -// gdb-check:$4 = {x = {__0 = 8888, __1 = -8888}} +// gdbg-check:$4 = {x = {__0 = 8888, __1 = -8888}} +// gdbr-check:$4 = method_on_generic_struct::Struct<(u32, i32)> {x: (8888, -8888)} // gdb-command:print arg1 // gdb-check:$5 = -3 // gdb-command:print arg2 @@ -36,7 +38,8 @@ // OWNED BY REF // gdb-command:print *self -// gdb-check:$7 = {x = 1234.5} +// gdbg-check:$7 = {x = 1234.5} +// gdbr-check:$7 = method_on_generic_struct::Struct {x: 1234.5} // gdb-command:print arg1 // gdb-check:$8 = -5 // gdb-command:print arg2 @@ -45,7 +48,8 @@ // OWNED BY VAL // gdb-command:print self -// gdb-check:$10 = {x = 1234.5} +// gdbg-check:$10 = {x = 1234.5} +// gdbr-check:$10 = method_on_generic_struct::Struct {x: 1234.5} // gdb-command:print arg1 // gdb-check:$11 = -7 // gdb-command:print arg2 @@ -54,7 +58,8 @@ // OWNED MOVED // gdb-command:print *self -// gdb-check:$13 = {x = 1234.5} +// gdbg-check:$13 = {x = 1234.5} +// gdbr-check:$13 = method_on_generic_struct::Struct {x: 1234.5} // gdb-command:print arg1 // gdb-check:$14 = -9 // gdb-command:print arg2 diff --git a/src/test/debuginfo/method-on-struct.rs b/src/test/debuginfo/method-on-struct.rs index 3bf2e775e7791..c7546fe2221ff 100644 --- a/src/test/debuginfo/method-on-struct.rs +++ b/src/test/debuginfo/method-on-struct.rs @@ -18,7 +18,8 @@ // STACK BY REF // gdb-command:print *self -// gdb-check:$1 = {x = 100} +// gdbg-check:$1 = {x = 100} +// gdbr-check:$1 = method_on_struct::Struct {x: 100} // gdb-command:print arg1 // gdb-check:$2 = -1 // gdb-command:print arg2 @@ -27,7 +28,8 @@ // STACK BY VAL // gdb-command:print self -// gdb-check:$4 = {x = 100} +// gdbg-check:$4 = {x = 100} +// gdbr-check:$4 = method_on_struct::Struct {x: 100} // gdb-command:print arg1 // gdb-check:$5 = -3 // gdb-command:print arg2 @@ -36,7 +38,8 @@ // OWNED BY REF // gdb-command:print *self -// gdb-check:$7 = {x = 200} +// gdbg-check:$7 = {x = 200} +// gdbr-check:$7 = method_on_struct::Struct {x: 200} // gdb-command:print arg1 // gdb-check:$8 = -5 // gdb-command:print arg2 @@ -45,7 +48,8 @@ // OWNED BY VAL // gdb-command:print self -// gdb-check:$10 = {x = 200} +// gdbg-check:$10 = {x = 200} +// gdbr-check:$10 = method_on_struct::Struct {x: 200} // gdb-command:print arg1 // gdb-check:$11 = -7 // gdb-command:print arg2 @@ -54,7 +58,8 @@ // OWNED MOVED // gdb-command:print *self -// gdb-check:$13 = {x = 200} +// gdbg-check:$13 = {x = 200} +// gdbr-check:$13 = method_on_struct::Struct {x: 200} // gdb-command:print arg1 // gdb-check:$14 = -9 // gdb-command:print arg2 diff --git a/src/test/debuginfo/method-on-trait.rs b/src/test/debuginfo/method-on-trait.rs index 5ce4a7905a1d0..1dc37bb06ac40 100644 --- a/src/test/debuginfo/method-on-trait.rs +++ b/src/test/debuginfo/method-on-trait.rs @@ -18,7 +18,8 @@ // STACK BY REF // gdb-command:print *self -// gdb-check:$1 = {x = 100} +// gdbg-check:$1 = {x = 100} +// gdbr-check:$1 = method_on_trait::Struct {x: 100} // gdb-command:print arg1 // gdb-check:$2 = -1 // gdb-command:print arg2 @@ -27,7 +28,8 @@ // STACK BY VAL // gdb-command:print self -// gdb-check:$4 = {x = 100} +// gdbg-check:$4 = {x = 100} +// gdbr-check:$4 = method_on_trait::Struct {x: 100} // gdb-command:print arg1 // gdb-check:$5 = -3 // gdb-command:print arg2 @@ -36,7 +38,8 @@ // OWNED BY REF // gdb-command:print *self -// gdb-check:$7 = {x = 200} +// gdbg-check:$7 = {x = 200} +// gdbr-check:$7 = method_on_trait::Struct {x: 200} // gdb-command:print arg1 // gdb-check:$8 = -5 // gdb-command:print arg2 @@ -45,7 +48,8 @@ // OWNED BY VAL // gdb-command:print self -// gdb-check:$10 = {x = 200} +// gdbg-check:$10 = {x = 200} +// gdbr-check:$10 = method_on_trait::Struct {x: 200} // gdb-command:print arg1 // gdb-check:$11 = -7 // gdb-command:print arg2 @@ -54,7 +58,8 @@ // OWNED MOVED // gdb-command:print *self -// gdb-check:$13 = {x = 200} +// gdbg-check:$13 = {x = 200} +// gdbr-check:$13 = method_on_trait::Struct {x: 200} // gdb-command:print arg1 // gdb-check:$14 = -9 // gdb-command:print arg2 diff --git a/src/test/debuginfo/method-on-tuple-struct.rs b/src/test/debuginfo/method-on-tuple-struct.rs index d8644a3934f10..dac762ae0c35b 100644 --- a/src/test/debuginfo/method-on-tuple-struct.rs +++ b/src/test/debuginfo/method-on-tuple-struct.rs @@ -18,7 +18,8 @@ // STACK BY REF // gdb-command:print *self -// gdb-check:$1 = {__0 = 100, __1 = -100.5} +// gdbg-check:$1 = {__0 = 100, __1 = -100.5} +// gdbr-check:$1 = method_on_tuple_struct::TupleStruct (100, -100.5) // gdb-command:print arg1 // gdb-check:$2 = -1 // gdb-command:print arg2 @@ -27,7 +28,8 @@ // STACK BY VAL // gdb-command:print self -// gdb-check:$4 = {__0 = 100, __1 = -100.5} +// gdbg-check:$4 = {__0 = 100, __1 = -100.5} +// gdbr-check:$4 = method_on_tuple_struct::TupleStruct (100, -100.5) // gdb-command:print arg1 // gdb-check:$5 = -3 // gdb-command:print arg2 @@ -36,7 +38,8 @@ // OWNED BY REF // gdb-command:print *self -// gdb-check:$7 = {__0 = 200, __1 = -200.5} +// gdbg-check:$7 = {__0 = 200, __1 = -200.5} +// gdbr-check:$7 = method_on_tuple_struct::TupleStruct (200, -200.5) // gdb-command:print arg1 // gdb-check:$8 = -5 // gdb-command:print arg2 @@ -45,7 +48,8 @@ // OWNED BY VAL // gdb-command:print self -// gdb-check:$10 = {__0 = 200, __1 = -200.5} +// gdbg-check:$10 = {__0 = 200, __1 = -200.5} +// gdbr-check:$10 = method_on_tuple_struct::TupleStruct (200, -200.5) // gdb-command:print arg1 // gdb-check:$11 = -7 // gdb-command:print arg2 @@ -54,7 +58,8 @@ // OWNED MOVED // gdb-command:print *self -// gdb-check:$13 = {__0 = 200, __1 = -200.5} +// gdbg-check:$13 = {__0 = 200, __1 = -200.5} +// gdbr-check:$13 = method_on_tuple_struct::TupleStruct (200, -200.5) // gdb-command:print arg1 // gdb-check:$14 = -9 // gdb-command:print arg2 diff --git a/src/test/debuginfo/nil-enum.rs b/src/test/debuginfo/nil-enum.rs index 81399ec590b14..94377421c0b0c 100644 --- a/src/test/debuginfo/nil-enum.rs +++ b/src/test/debuginfo/nil-enum.rs @@ -16,10 +16,12 @@ // gdb-command:run // gdb-command:print first -// gdb-check:$1 = {} +// gdbg-check:$1 = {} +// gdbr-check:$1 = // gdb-command:print second -// gdb-check:$2 = {} +// gdbg-check:$2 = {} +// gdbr-check:$2 = #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] @@ -28,8 +30,9 @@ enum ANilEnum {} enum AnotherNilEnum {} -// This test relies on gdb printing the string "{}" for empty +// This test relies on gdbg printing the string "{}" for empty // structs (which may change some time) +// The error from gdbr is expected since nil enums are not supposed to exist. fn main() { unsafe { let first: ANilEnum = ::std::mem::zeroed(); diff --git a/src/test/debuginfo/option-like-enum.rs b/src/test/debuginfo/option-like-enum.rs index f103294a94a07..39e6a4e4facf9 100644 --- a/src/test/debuginfo/option-like-enum.rs +++ b/src/test/debuginfo/option-like-enum.rs @@ -18,28 +18,36 @@ // gdb-command:run // gdb-command:print some -// gdb-check:$1 = {RUST$ENCODED$ENUM$0$None = {__0 = 0x12345678}} +// gdbg-check:$1 = {RUST$ENCODED$ENUM$0$None = {__0 = 0x12345678}} +// gdbr-check:$1 = core::option::Option<&u32>::Some(0x12345678) // gdb-command:print none -// gdb-check:$2 = {RUST$ENCODED$ENUM$0$None = {__0 = 0x0}} +// gdbg-check:$2 = {RUST$ENCODED$ENUM$0$None = {__0 = 0x0}} +// gdbr-check:$2 = core::option::Option<&u32>::None // gdb-command:print full -// gdb-check:$3 = {RUST$ENCODED$ENUM$1$Empty = {__0 = 454545, __1 = 0x87654321, __2 = 9988}} +// gdbg-check:$3 = {RUST$ENCODED$ENUM$1$Empty = {__0 = 454545, __1 = 0x87654321, __2 = 9988}} +// gdbr-check:$3 = option_like_enum::MoreFields::Full(454545, 0x87654321, 9988) -// gdb-command:print empty_gdb->discr +// gdbg-command:print empty_gdb->discr +// gdbr-command:print empty_gdb.discr // gdb-check:$4 = (isize *) 0x0 // gdb-command:print droid -// gdb-check:$5 = {RUST$ENCODED$ENUM$2$Void = {id = 675675, range = 10000001, internals = 0x43218765}} +// gdbg-check:$5 = {RUST$ENCODED$ENUM$2$Void = {id = 675675, range = 10000001, internals = 0x43218765}} +// gdbr-check:$5 = option_like_enum::NamedFields::Droid{id: 675675, range: 10000001, internals: 0x43218765} -// gdb-command:print void_droid_gdb->internals +// gdbg-command:print void_droid_gdb->internals +// gdbr-command:print void_droid_gdb.internals // gdb-check:$6 = (isize *) 0x0 // gdb-command:print nested_non_zero_yep -// gdb-check:$7 = {RUST$ENCODED$ENUM$1$2$Nope = {__0 = 10.5, __1 = {a = 10, b = 20, c = [...]}}} +// gdbg-check:$7 = {RUST$ENCODED$ENUM$1$2$Nope = {__0 = 10.5, __1 = {a = 10, b = 20, c = [...]}}} +// gdbr-check:$7 = option_like_enum::NestedNonZero::Yep(10.5, option_like_enum::NestedNonZeroField {a: 10, b: 20, c: 0x[...] "x[...]"}) // gdb-command:print nested_non_zero_nope -// gdb-check:$8 = {RUST$ENCODED$ENUM$1$2$Nope = {__0 = [...], __1 = {a = [...], b = [...], c = 0x0}}} +// gdbg-check:$8 = {RUST$ENCODED$ENUM$1$2$Nope = {__0 = [...], __1 = {a = [...], b = [...], c = 0x0}}} +// gdbr-check:$8 = option_like_enum::NestedNonZero::Nope // gdb-command:continue diff --git a/src/test/debuginfo/packed-struct-with-destructor.rs b/src/test/debuginfo/packed-struct-with-destructor.rs index 9d37cb3012b7d..50bd857d46076 100644 --- a/src/test/debuginfo/packed-struct-with-destructor.rs +++ b/src/test/debuginfo/packed-struct-with-destructor.rs @@ -18,29 +18,37 @@ // gdb-command:run // gdb-command:print packed -// gdb-check:$1 = {x = 123, y = 234, z = 345} +// gdbg-check:$1 = {x = 123, y = 234, z = 345} +// gdbr-check:$1 = packed_struct_with_destructor::Packed {x: 123, y: 234, z: 345} // gdb-command:print packedInPacked -// gdb-check:$2 = {a = 1111, b = {x = 2222, y = 3333, z = 4444}, c = 5555, d = {x = 6666, y = 7777, z = 8888}} +// gdbg-check:$2 = {a = 1111, b = {x = 2222, y = 3333, z = 4444}, c = 5555, d = {x = 6666, y = 7777, z = 8888}} +// gdbr-check:$2 = packed_struct_with_destructor::PackedInPacked {a: 1111, b: packed_struct_with_destructor::Packed {x: 2222, y: 3333, z: 4444}, c: 5555, d: packed_struct_with_destructor::Packed {x: 6666, y: 7777, z: 8888}} // gdb-command:print packedInUnpacked -// gdb-check:$3 = {a = -1111, b = {x = -2222, y = -3333, z = -4444}, c = -5555, d = {x = -6666, y = -7777, z = -8888}} +// gdbg-check:$3 = {a = -1111, b = {x = -2222, y = -3333, z = -4444}, c = -5555, d = {x = -6666, y = -7777, z = -8888}} +// gdbr-check:$3 = packed_struct_with_destructor::PackedInUnpacked {a: -1111, b: packed_struct_with_destructor::Packed {x: -2222, y: -3333, z: -4444}, c: -5555, d: packed_struct_with_destructor::Packed {x: -6666, y: -7777, z: -8888}} // gdb-command:print unpackedInPacked -// gdb-check:$4 = {a = 987, b = {x = 876, y = 765, z = 654}, c = {x = 543, y = 432, z = 321}, d = 210} +// gdbg-check:$4 = {a = 987, b = {x = 876, y = 765, z = 654}, c = {x = 543, y = 432, z = 321}, d = 210} +// gdbr-check:$4 = packed_struct_with_destructor::UnpackedInPacked {a: 987, b: packed_struct_with_destructor::Unpacked {x: 876, y: 765, z: 654}, c: packed_struct_with_destructor::Unpacked {x: 543, y: 432, z: 321}, d: 210} // gdb-command:print packedInPackedWithDrop -// gdb-check:$5 = {a = 11, b = {x = 22, y = 33, z = 44}, c = 55, d = {x = 66, y = 77, z = 88}} +// gdbg-check:$5 = {a = 11, b = {x = 22, y = 33, z = 44}, c = 55, d = {x = 66, y = 77, z = 88}} +// gdbr-check:$5 = packed_struct_with_destructor::PackedInPackedWithDrop {a: 11, b: packed_struct_with_destructor::Packed {x: 22, y: 33, z: 44}, c: 55, d: packed_struct_with_destructor::Packed {x: 66, y: 77, z: 88}} // gdb-command:print packedInUnpackedWithDrop -// gdb-check:$6 = {a = -11, b = {x = -22, y = -33, z = -44}, c = -55, d = {x = -66, y = -77, z = -88}} +// gdbg-check:$6 = {a = -11, b = {x = -22, y = -33, z = -44}, c = -55, d = {x = -66, y = -77, z = -88}} +// gdbr-check:$6 = packed_struct_with_destructor::PackedInUnpackedWithDrop {a: -11, b: packed_struct_with_destructor::Packed {x: -22, y: -33, z: -44}, c: -55, d: packed_struct_with_destructor::Packed {x: -66, y: -77, z: -88}} // gdb-command:print unpackedInPackedWithDrop -// gdb-check:$7 = {a = 98, b = {x = 87, y = 76, z = 65}, c = {x = 54, y = 43, z = 32}, d = 21} +// gdbg-check:$7 = {a = 98, b = {x = 87, y = 76, z = 65}, c = {x = 54, y = 43, z = 32}, d = 21} +// gdbr-check:$7 = packed_struct_with_destructor::UnpackedInPackedWithDrop {a: 98, b: packed_struct_with_destructor::Unpacked {x: 87, y: 76, z: 65}, c: packed_struct_with_destructor::Unpacked {x: 54, y: 43, z: 32}, d: 21} // gdb-command:print deeplyNested -// gdb-check:$8 = {a = {a = 1, b = {x = 2, y = 3, z = 4}, c = 5, d = {x = 6, y = 7, z = 8}}, b = {a = 9, b = {x = 10, y = 11, z = 12}, c = {x = 13, y = 14, z = 15}, d = 16}, c = {a = 17, b = {x = 18, y = 19, z = 20}, c = 21, d = {x = 22, y = 23, z = 24}}, d = {a = 25, b = {x = 26, y = 27, z = 28}, c = 29, d = {x = 30, y = 31, z = 32}}, e = {a = 33, b = {x = 34, y = 35, z = 36}, c = {x = 37, y = 38, z = 39}, d = 40}, f = {a = 41, b = {x = 42, y = 43, z = 44}, c = 45, d = {x = 46, y = 47, z = 48}}} +// gdbg-check:$8 = {a = {a = 1, b = {x = 2, y = 3, z = 4}, c = 5, d = {x = 6, y = 7, z = 8}}, b = {a = 9, b = {x = 10, y = 11, z = 12}, c = {x = 13, y = 14, z = 15}, d = 16}, c = {a = 17, b = {x = 18, y = 19, z = 20}, c = 21, d = {x = 22, y = 23, z = 24}}, d = {a = 25, b = {x = 26, y = 27, z = 28}, c = 29, d = {x = 30, y = 31, z = 32}}, e = {a = 33, b = {x = 34, y = 35, z = 36}, c = {x = 37, y = 38, z = 39}, d = 40}, f = {a = 41, b = {x = 42, y = 43, z = 44}, c = 45, d = {x = 46, y = 47, z = 48}}} +// gdbr-check:$8 = packed_struct_with_destructor::DeeplyNested {a: packed_struct_with_destructor::PackedInPacked {a: 1, b: packed_struct_with_destructor::Packed {x: 2, y: 3, z: 4}, c: 5, d: packed_struct_with_destructor::Packed {x: 6, y: 7, z: 8}}, b: packed_struct_with_destructor::UnpackedInPackedWithDrop {a: 9, b: packed_struct_with_destructor::Unpacked {x: 10, y: 11, z: 12}, c: packed_struct_with_destructor::Unpacked {x: 13, y: 14, z: 15}, d: 16}, c: packed_struct_with_destructor::PackedInUnpacked {a: 17, b: packed_struct_with_destructor::Packed {x: 18, y: 19, z: 20}, c: 21, d: packed_struct_with_destructor::Packed {x: 22, y: 23, z: 24}}, d: packed_struct_with_destructor::PackedInUnpackedWithDrop {a: 25, b: packed_struct_with_destructor::Packed {x: 26, y: 27, z: 28}, c: 29, d: packed_struct_with_destructor::Packed {x: 30, y: 31, z: 32}}, e: packed_struct_with_destructor::UnpackedInPacked {a: 33, b: packed_struct_with_destructor::Unpacked {x: 34, y: 35, z: 36}, c: packed_struct_with_destructor::Unpacked {x: 37, y: 38, z: 39}, d: 40}, f: packed_struct_with_destructor::PackedInPackedWithDrop {a: 41, b: packed_struct_with_destructor::Packed {x: 42, y: 43, z: 44}, c: 45, d: packed_struct_with_destructor::Packed {x: 46, y: 47, z: 48}}} // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/packed-struct.rs b/src/test/debuginfo/packed-struct.rs index e86e963f38cdd..b84161c36a557 100644 --- a/src/test/debuginfo/packed-struct.rs +++ b/src/test/debuginfo/packed-struct.rs @@ -18,16 +18,20 @@ // gdb-command:run // gdb-command:print packed -// gdb-check:$1 = {x = 123, y = 234, z = 345} +// gdbg-check:$1 = {x = 123, y = 234, z = 345} +// gdbr-check:$1 = packed_struct::Packed {x: 123, y: 234, z: 345} // gdb-command:print packedInPacked -// gdb-check:$2 = {a = 1111, b = {x = 2222, y = 3333, z = 4444}, c = 5555, d = {x = 6666, y = 7777, z = 8888}} +// gdbg-check:$2 = {a = 1111, b = {x = 2222, y = 3333, z = 4444}, c = 5555, d = {x = 6666, y = 7777, z = 8888}} +// gdbr-check:$2 = packed_struct::PackedInPacked {a: 1111, b: packed_struct::Packed {x: 2222, y: 3333, z: 4444}, c: 5555, d: packed_struct::Packed {x: 6666, y: 7777, z: 8888}} // gdb-command:print packedInUnpacked -// gdb-check:$3 = {a = -1111, b = {x = -2222, y = -3333, z = -4444}, c = -5555, d = {x = -6666, y = -7777, z = -8888}} +// gdbg-check:$3 = {a = -1111, b = {x = -2222, y = -3333, z = -4444}, c = -5555, d = {x = -6666, y = -7777, z = -8888}} +// gdbr-check:$3 = packed_struct::PackedInUnpacked {a: -1111, b: packed_struct::Packed {x: -2222, y: -3333, z: -4444}, c: -5555, d: packed_struct::Packed {x: -6666, y: -7777, z: -8888}} // gdb-command:print unpackedInPacked -// gdb-check:$4 = {a = 987, b = {x = 876, y = 765, z = 654, w = 543}, c = {x = 432, y = 321, z = 210, w = 109}, d = -98} +// gdbg-check:$4 = {a = 987, b = {x = 876, y = 765, z = 654, w = 543}, c = {x = 432, y = 321, z = 210, w = 109}, d = -98} +// gdbr-check:$4 = packed_struct::UnpackedInPacked {a: 987, b: packed_struct::Unpacked {x: 876, y: 765, z: 654, w: 543}, c: packed_struct::Unpacked {x: 432, y: 321, z: 210, w: 109}, d: -98} // gdb-command:print sizeof(packed) // gdb-check:$5 = 14 diff --git a/src/test/debuginfo/pretty-std.rs b/src/test/debuginfo/pretty-std.rs index 576621737e6b6..153f0c8271fc4 100644 --- a/src/test/debuginfo/pretty-std.rs +++ b/src/test/debuginfo/pretty-std.rs @@ -35,7 +35,8 @@ // gdb-check:$5 = Some = {8} // gdb-command: print none -// gdb-check:$6 = None +// gdbg-check:$6 = None +// gdbr-check:$6 = core::option::Option::None // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/recursive-struct.rs b/src/test/debuginfo/recursive-struct.rs index ea067d5bffbec..80147b14174da 100644 --- a/src/test/debuginfo/recursive-struct.rs +++ b/src/test/debuginfo/recursive-struct.rs @@ -12,57 +12,72 @@ // ignore-lldb // compile-flags:-g + // gdb-command:run // gdb-command:print stack_unique.value // gdb-check:$1 = 0 -// gdb-command:print stack_unique.next.RUST$ENCODED$ENUM$0$Empty.val->value +// gdbg-command:print stack_unique.next.RUST$ENCODED$ENUM$0$Empty.val->value +// gdbr-command:print stack_unique.next.val.value // gdb-check:$2 = 1 -// gdb-command:print unique_unique->value +// gdbg-command:print unique_unique->value +// gdbr-command:print unique_unique.value // gdb-check:$3 = 2 -// gdb-command:print unique_unique->next.RUST$ENCODED$ENUM$0$Empty.val->value +// gdbg-command:print unique_unique->next.RUST$ENCODED$ENUM$0$Empty.val->value +// gdbr-command:print unique_unique.next.val.value // gdb-check:$4 = 3 // gdb-command:print vec_unique[0].value // gdb-check:$5 = 6.5 -// gdb-command:print vec_unique[0].next.RUST$ENCODED$ENUM$0$Empty.val->value +// gdbg-command:print vec_unique[0].next.RUST$ENCODED$ENUM$0$Empty.val->value +// gdbr-command:print vec_unique[0].next.val.value // gdb-check:$6 = 7.5 -// gdb-command:print borrowed_unique->value +// gdbg-command:print borrowed_unique->value +// gdbr-command:print borrowed_unique.value // gdb-check:$7 = 8.5 -// gdb-command:print borrowed_unique->next.RUST$ENCODED$ENUM$0$Empty.val->value +// gdbg-command:print borrowed_unique->next.RUST$ENCODED$ENUM$0$Empty.val->value +// gdbr-command:print borrowed_unique.next.val.value // gdb-check:$8 = 9.5 // LONG CYCLE // gdb-command:print long_cycle1.value // gdb-check:$9 = 20 -// gdb-command:print long_cycle1.next->value +// gdbg-command:print long_cycle1.next->value +// gdbr-command:print long_cycle1.next.value // gdb-check:$10 = 21 -// gdb-command:print long_cycle1.next->next->value +// gdbg-command:print long_cycle1.next->next->value +// gdbr-command:print long_cycle1.next.next.value // gdb-check:$11 = 22 -// gdb-command:print long_cycle1.next->next->next->value +// gdbg-command:print long_cycle1.next->next->next->value +// gdbr-command:print long_cycle1.next.next.next.value // gdb-check:$12 = 23 // gdb-command:print long_cycle2.value // gdb-check:$13 = 24 -// gdb-command:print long_cycle2.next->value +// gdbg-command:print long_cycle2.next->value +// gdbr-command:print long_cycle2.next.value // gdb-check:$14 = 25 -// gdb-command:print long_cycle2.next->next->value +// gdbg-command:print long_cycle2.next->next->value +// gdbr-command:print long_cycle2.next.next.value // gdb-check:$15 = 26 // gdb-command:print long_cycle3.value // gdb-check:$16 = 27 -// gdb-command:print long_cycle3.next->value +// gdbg-command:print long_cycle3.next->value +// gdbr-command:print long_cycle3.next.value // gdb-check:$17 = 28 // gdb-command:print long_cycle4.value // gdb-check:$18 = 29.5 -// gdb-command:print (*****long_cycle_w_anonymous_types).value +// gdbg-command:print (*****long_cycle_w_anonymous_types).value +// gdbr-command:print long_cycle_w_anonymous_types.value // gdb-check:$19 = 30 -// gdb-command:print (*****((*****long_cycle_w_anonymous_types).next.RUST$ENCODED$ENUM$0$Empty.val)).value +// gdbg-command:print (*****((*****long_cycle_w_anonymous_types).next.RUST$ENCODED$ENUM$0$Empty.val)).value +// gdbr-command:print long_cycle_w_anonymous_types.next.val.value // gdb-check:$20 = 31 // gdb-command:continue diff --git a/src/test/debuginfo/self-in-default-method.rs b/src/test/debuginfo/self-in-default-method.rs index 6d3f93c5d5014..796d122cd66ba 100644 --- a/src/test/debuginfo/self-in-default-method.rs +++ b/src/test/debuginfo/self-in-default-method.rs @@ -18,7 +18,8 @@ // STACK BY REF // gdb-command:print *self -// gdb-check:$1 = {x = 100} +// gdbg-check:$1 = {x = 100} +// gdbr-check:$1 = self_in_default_method::Struct {x: 100} // gdb-command:print arg1 // gdb-check:$2 = -1 // gdb-command:print arg2 @@ -27,7 +28,8 @@ // STACK BY VAL // gdb-command:print self -// gdb-check:$4 = {x = 100} +// gdbg-check:$4 = {x = 100} +// gdbr-check:$4 = self_in_default_method::Struct {x: 100} // gdb-command:print arg1 // gdb-check:$5 = -3 // gdb-command:print arg2 @@ -36,7 +38,8 @@ // OWNED BY REF // gdb-command:print *self -// gdb-check:$7 = {x = 200} +// gdbg-check:$7 = {x = 200} +// gdbr-check:$7 = self_in_default_method::Struct {x: 200} // gdb-command:print arg1 // gdb-check:$8 = -5 // gdb-command:print arg2 @@ -45,7 +48,8 @@ // OWNED BY VAL // gdb-command:print self -// gdb-check:$10 = {x = 200} +// gdbg-check:$10 = {x = 200} +// gdbr-check:$10 = self_in_default_method::Struct {x: 200} // gdb-command:print arg1 // gdb-check:$11 = -7 // gdb-command:print arg2 @@ -54,7 +58,8 @@ // OWNED MOVED // gdb-command:print *self -// gdb-check:$13 = {x = 200} +// gdbg-check:$13 = {x = 200} +// gdbr-check:$13 = self_in_default_method::Struct {x: 200} // gdb-command:print arg1 // gdb-check:$14 = -9 // gdb-command:print arg2 diff --git a/src/test/debuginfo/self-in-generic-default-method.rs b/src/test/debuginfo/self-in-generic-default-method.rs index aea3bae4bfc1b..b07d7ca5fb7b7 100644 --- a/src/test/debuginfo/self-in-generic-default-method.rs +++ b/src/test/debuginfo/self-in-generic-default-method.rs @@ -18,7 +18,8 @@ // STACK BY REF // gdb-command:print *self -// gdb-check:$1 = {x = 987} +// gdbg-check:$1 = {x = 987} +// gdbr-check:$1 = self_in_generic_default_method::Struct {x: 987} // gdb-command:print arg1 // gdb-check:$2 = -1 // gdb-command:print arg2 @@ -27,7 +28,8 @@ // STACK BY VAL // gdb-command:print self -// gdb-check:$4 = {x = 987} +// gdbg-check:$4 = {x = 987} +// gdbr-check:$4 = self_in_generic_default_method::Struct {x: 987} // gdb-command:print arg1 // gdb-check:$5 = -3 // gdb-command:print arg2 @@ -36,7 +38,8 @@ // OWNED BY REF // gdb-command:print *self -// gdb-check:$7 = {x = 879} +// gdbg-check:$7 = {x = 879} +// gdbr-check:$7 = self_in_generic_default_method::Struct {x: 879} // gdb-command:print arg1 // gdb-check:$8 = -5 // gdb-command:print arg2 @@ -45,7 +48,8 @@ // OWNED BY VAL // gdb-command:print self -// gdb-check:$10 = {x = 879} +// gdbg-check:$10 = {x = 879} +// gdbr-check:$10 = self_in_generic_default_method::Struct {x: 879} // gdb-command:print arg1 // gdb-check:$11 = -7 // gdb-command:print arg2 @@ -54,7 +58,8 @@ // OWNED MOVED // gdb-command:print *self -// gdb-check:$13 = {x = 879} +// gdbg-check:$13 = {x = 879} +// gdbr-check:$13 = self_in_generic_default_method::Struct {x: 879} // gdb-command:print arg1 // gdb-check:$14 = -9 // gdb-command:print arg2 diff --git a/src/test/debuginfo/simd.rs b/src/test/debuginfo/simd.rs index 80ac901b60fd3..75e68f7efedef 100644 --- a/src/test/debuginfo/simd.rs +++ b/src/test/debuginfo/simd.rs @@ -20,28 +20,46 @@ // compile-flags:-g // gdb-command:run -// gdb-command:print/d vi8x16 -// gdb-check:$1 = {__0 = 0, __1 = 1, __2 = 2, __3 = 3, __4 = 4, __5 = 5, __6 = 6, __7 = 7, __8 = 8, __9 = 9, __10 = 10, __11 = 11, __12 = 12, __13 = 13, __14 = 14, __15 = 15} -// gdb-command:print/d vi16x8 -// gdb-check:$2 = {__0 = 16, __1 = 17, __2 = 18, __3 = 19, __4 = 20, __5 = 21, __6 = 22, __7 = 23} -// gdb-command:print/d vi32x4 -// gdb-check:$3 = {__0 = 24, __1 = 25, __2 = 26, __3 = 27} -// gdb-command:print/d vi64x2 -// gdb-check:$4 = {__0 = 28, __1 = 29} - -// gdb-command:print/d vu8x16 -// gdb-check:$5 = {__0 = 30, __1 = 31, __2 = 32, __3 = 33, __4 = 34, __5 = 35, __6 = 36, __7 = 37, __8 = 38, __9 = 39, __10 = 40, __11 = 41, __12 = 42, __13 = 43, __14 = 44, __15 = 45} -// gdb-command:print/d vu16x8 -// gdb-check:$6 = {__0 = 46, __1 = 47, __2 = 48, __3 = 49, __4 = 50, __5 = 51, __6 = 52, __7 = 53} -// gdb-command:print/d vu32x4 -// gdb-check:$7 = {__0 = 54, __1 = 55, __2 = 56, __3 = 57} -// gdb-command:print/d vu64x2 -// gdb-check:$8 = {__0 = 58, __1 = 59} +// gdbg-command:print/d vi8x16 +// gdbr-command:print vi8x16 +// gdbg-check:$1 = {__0 = 0, __1 = 1, __2 = 2, __3 = 3, __4 = 4, __5 = 5, __6 = 6, __7 = 7, __8 = 8, __9 = 9, __10 = 10, __11 = 11, __12 = 12, __13 = 13, __14 = 14, __15 = 15} +// gdbr-check:$1 = simd::i8x16 (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15) +// gdbg-command:print/d vi16x8 +// gdbr-command:print vi16x8 +// gdbg-check:$2 = {__0 = 16, __1 = 17, __2 = 18, __3 = 19, __4 = 20, __5 = 21, __6 = 22, __7 = 23} +// gdbr-check:$2 = simd::i16x8 (16, 17, 18, 19, 20, 21, 22, 23) +// gdbg-command:print/d vi32x4 +// gdbr-command:print vi32x4 +// gdbg-check:$3 = {__0 = 24, __1 = 25, __2 = 26, __3 = 27} +// gdbr-check:$3 = simd::i32x4 (24, 25, 26, 27) +// gdbg-command:print/d vi64x2 +// gdbr-command:print vi64x2 +// gdbg-check:$4 = {__0 = 28, __1 = 29} +// gdbr-check:$4 = simd::i64x2 (28, 29) + +// gdbg-command:print/d vu8x16 +// gdbr-command:print vu8x16 +// gdbg-check:$5 = {__0 = 30, __1 = 31, __2 = 32, __3 = 33, __4 = 34, __5 = 35, __6 = 36, __7 = 37, __8 = 38, __9 = 39, __10 = 40, __11 = 41, __12 = 42, __13 = 43, __14 = 44, __15 = 45} +// gdbr-check:$5 = simd::u8x16 (30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45) +// gdbg-command:print/d vu16x8 +// gdbr-command:print vu16x8 +// gdbg-check:$6 = {__0 = 46, __1 = 47, __2 = 48, __3 = 49, __4 = 50, __5 = 51, __6 = 52, __7 = 53} +// gdbr-check:$6 = simd::u16x8 (46, 47, 48, 49, 50, 51, 52, 53) +// gdbg-command:print/d vu32x4 +// gdbr-command:print vu32x4 +// gdbg-check:$7 = {__0 = 54, __1 = 55, __2 = 56, __3 = 57} +// gdbr-check:$7 = simd::u32x4 (54, 55, 56, 57) +// gdbg-command:print/d vu64x2 +// gdbr-command:print vu64x2 +// gdbg-check:$8 = {__0 = 58, __1 = 59} +// gdbr-check:$8 = simd::u64x2 (58, 59) // gdb-command:print vf32x4 -// gdb-check:$9 = {__0 = 60.5, __1 = 61.5, __2 = 62.5, __3 = 63.5} +// gdbg-check:$9 = {__0 = 60.5, __1 = 61.5, __2 = 62.5, __3 = 63.5} +// gdbr-check:$9 = simd::f32x4 (60.5, 61.5, 62.5, 63.5) // gdb-command:print vf64x2 -// gdb-check:$10 = {__0 = 64.5, __1 = 65.5} +// gdbg-check:$10 = {__0 = 64.5, __1 = 65.5} +// gdbr-check:$10 = simd::f64x2 (64.5, 65.5) // gdb-command:continue diff --git a/src/test/debuginfo/simple-struct.rs b/src/test/debuginfo/simple-struct.rs index d25cd4d7c047f..4956313ad2214 100644 --- a/src/test/debuginfo/simple-struct.rs +++ b/src/test/debuginfo/simple-struct.rs @@ -14,61 +14,94 @@ // === GDB TESTS =================================================================================== -// gdb-command:print 'simple_struct::NO_PADDING_16' -// gdb-check:$1 = {x = 1000, y = -1001} - -// gdb-command:print 'simple_struct::NO_PADDING_32' -// gdb-check:$2 = {x = 1, y = 2, z = 3} - -// gdb-command:print 'simple_struct::NO_PADDING_64' -// gdb-check:$3 = {x = 4, y = 5, z = 6} - -// gdb-command:print 'simple_struct::NO_PADDING_163264' -// gdb-check:$4 = {a = 7, b = 8, c = 9, d = 10} - -// gdb-command:print 'simple_struct::INTERNAL_PADDING' -// gdb-check:$5 = {x = 11, y = 12} - -// gdb-command:print 'simple_struct::PADDING_AT_END' -// gdb-check:$6 = {x = 13, y = 14} +// there's no frame yet for gdb to reliably detect the language, set it explicitly +// gdbr-command:set language rust + +// gdbg-command:print 'simple_struct::NO_PADDING_16' +// gdbr-command:print simple_struct::NO_PADDING_16 +// gdbg-check:$1 = {x = 1000, y = -1001} +// gdbr-check:$1 = simple_struct::NoPadding16 {x: 1000, y: -1001} + +// gdbg-command:print 'simple_struct::NO_PADDING_32' +// gdbr-command:print simple_struct::NO_PADDING_32 +// gdbg-check:$2 = {x = 1, y = 2, z = 3} +// gdbr-check:$2 = simple_struct::NoPadding32 {x: 1, y: 2, z: 3} + +// gdbg-command:print 'simple_struct::NO_PADDING_64' +// gdbr-command:print simple_struct::NO_PADDING_64 +// gdbg-check:$3 = {x = 4, y = 5, z = 6} +// gdbr-check:$3 = simple_struct::NoPadding64 {x: 4, y: 5, z: 6} + +// gdbg-command:print 'simple_struct::NO_PADDING_163264' +// gdbr-command:print simple_struct::NO_PADDING_163264 +// gdbg-check:$4 = {a = 7, b = 8, c = 9, d = 10} +// gdbr-check:$4 = simple_struct::NoPadding163264 {a: 7, b: 8, c: 9, d: 10} + +// gdbg-command:print 'simple_struct::INTERNAL_PADDING' +// gdbr-command:print simple_struct::INTERNAL_PADDING +// gdbg-check:$5 = {x = 11, y = 12} +// gdbr-check:$5 = simple_struct::InternalPadding {x: 11, y: 12} + +// gdbg-command:print 'simple_struct::PADDING_AT_END' +// gdbr-command:print simple_struct::PADDING_AT_END +// gdbg-check:$6 = {x = 13, y = 14} +// gdbr-check:$6 = simple_struct::PaddingAtEnd {x: 13, y: 14} // gdb-command:run // gdb-command:print no_padding16 -// gdb-check:$7 = {x = 10000, y = -10001} +// gdbg-check:$7 = {x = 10000, y = -10001} +// gdbr-check:$7 = simple_struct::NoPadding16 {x: 10000, y: -10001} // gdb-command:print no_padding32 -// gdb-check:$8 = {x = -10002, y = -10003.5, z = 10004} +// gdbg-check:$8 = {x = -10002, y = -10003.5, z = 10004} +// gdbr-check:$8 = simple_struct::NoPadding32 {x: -10002, y: -10003.5, z: 10004} // gdb-command:print no_padding64 -// gdb-check:$9 = {x = -10005.5, y = 10006, z = 10007} +// gdbg-check:$9 = {x = -10005.5, y = 10006, z = 10007} +// gdbr-check:$9 = simple_struct::NoPadding64 {x: -10005.5, y: 10006, z: 10007} // gdb-command:print no_padding163264 -// gdb-check:$10 = {a = -10008, b = 10009, c = 10010, d = 10011} +// gdbg-check:$10 = {a = -10008, b = 10009, c = 10010, d = 10011} +// gdbr-check:$10 = simple_struct::NoPadding163264 {a: -10008, b: 10009, c: 10010, d: 10011} // gdb-command:print internal_padding -// gdb-check:$11 = {x = 10012, y = -10013} +// gdbg-check:$11 = {x = 10012, y = -10013} +// gdbr-check:$11 = simple_struct::InternalPadding {x: 10012, y: -10013} // gdb-command:print padding_at_end -// gdb-check:$12 = {x = -10014, y = 10015} - -// gdb-command:print 'simple_struct::NO_PADDING_16' -// gdb-check:$13 = {x = 100, y = -101} - -// gdb-command:print 'simple_struct::NO_PADDING_32' -// gdb-check:$14 = {x = -15, y = -16, z = 17} - -// gdb-command:print 'simple_struct::NO_PADDING_64' -// gdb-check:$15 = {x = -18, y = 19, z = 20} - -// gdb-command:print 'simple_struct::NO_PADDING_163264' -// gdb-check:$16 = {a = -21, b = 22, c = 23, d = 24} - -// gdb-command:print 'simple_struct::INTERNAL_PADDING' -// gdb-check:$17 = {x = 25, y = -26} - -// gdb-command:print 'simple_struct::PADDING_AT_END' -// gdb-check:$18 = {x = -27, y = 28} +// gdbg-check:$12 = {x = -10014, y = 10015} +// gdbr-check:$12 = simple_struct::PaddingAtEnd {x: -10014, y: 10015} + +// gdbg-command:print 'simple_struct::NO_PADDING_16' +// gdbr-command:print simple_struct::NO_PADDING_16 +// gdbg-check:$13 = {x = 100, y = -101} +// gdbr-check:$13 = simple_struct::NoPadding16 {x: 100, y: -101} + +// gdbg-command:print 'simple_struct::NO_PADDING_32' +// gdbr-command:print simple_struct::NO_PADDING_32 +// gdbg-check:$14 = {x = -15, y = -16, z = 17} +// gdbr-check:$14 = simple_struct::NoPadding32 {x: -15, y: -16, z: 17} + +// gdbg-command:print 'simple_struct::NO_PADDING_64' +// gdbr-command:print simple_struct::NO_PADDING_64 +// gdbg-check:$15 = {x = -18, y = 19, z = 20} +// gdbr-check:$15 = simple_struct::NoPadding64 {x: -18, y: 19, z: 20} + +// gdbg-command:print 'simple_struct::NO_PADDING_163264' +// gdbr-command:print simple_struct::NO_PADDING_163264 +// gdbg-check:$16 = {a = -21, b = 22, c = 23, d = 24} +// gdbr-check:$16 = simple_struct::NoPadding163264 {a: -21, b: 22, c: 23, d: 24} + +// gdbg-command:print 'simple_struct::INTERNAL_PADDING' +// gdbr-command:print simple_struct::INTERNAL_PADDING +// gdbg-check:$17 = {x = 25, y = -26} +// gdbr-check:$17 = simple_struct::InternalPadding {x: 25, y: -26} + +// gdbg-command:print 'simple_struct::PADDING_AT_END' +// gdbr-command:print simple_struct::PADDING_AT_END +// gdbg-check:$18 = {x = -27, y = 28} +// gdbr-check:$18 = simple_struct::PaddingAtEnd {x: -27, y: 28} // gdb-command:continue diff --git a/src/test/debuginfo/simple-tuple.rs b/src/test/debuginfo/simple-tuple.rs index 1b85ecc537a34..354a2c26cb36d 100644 --- a/src/test/debuginfo/simple-tuple.rs +++ b/src/test/debuginfo/simple-tuple.rs @@ -14,58 +14,97 @@ // === GDB TESTS =================================================================================== -// gdb-command:print/d 'simple_tuple::NO_PADDING_8' -// gdb-check:$1 = {__0 = -50, __1 = 50} -// gdb-command:print 'simple_tuple::NO_PADDING_16' -// gdb-check:$2 = {__0 = -1, __1 = 2, __2 = 3} -// gdb-command:print 'simple_tuple::NO_PADDING_32' -// gdb-check:$3 = {__0 = 4, __1 = 5, __2 = 6} -// gdb-command:print 'simple_tuple::NO_PADDING_64' -// gdb-check:$4 = {__0 = 7, __1 = 8, __2 = 9} - -// gdb-command:print 'simple_tuple::INTERNAL_PADDING_1' -// gdb-check:$5 = {__0 = 10, __1 = 11} -// gdb-command:print 'simple_tuple::INTERNAL_PADDING_2' -// gdb-check:$6 = {__0 = 12, __1 = 13, __2 = 14, __3 = 15} - -// gdb-command:print 'simple_tuple::PADDING_AT_END' -// gdb-check:$7 = {__0 = 16, __1 = 17} +// there's no frame yet for gdb to reliably detect the language, set it explicitly +// gdbr-command:set language rust + +// gdbg-command:print/d 'simple_tuple::NO_PADDING_8' +// gdbr-command:print simple_tuple::NO_PADDING_8 +// gdbg-check:$1 = {__0 = -50, __1 = 50} +// gdbr-check:$1 = (-50, 50) +// gdbg-command:print 'simple_tuple::NO_PADDING_16' +// gdbr-command:print simple_tuple::NO_PADDING_16 +// gdbg-check:$2 = {__0 = -1, __1 = 2, __2 = 3} +// gdbr-check:$2 = (-1, 2, 3) +// gdbg-command:print 'simple_tuple::NO_PADDING_32' +// gdbr-command:print simple_tuple::NO_PADDING_32 +// gdbg-check:$3 = {__0 = 4, __1 = 5, __2 = 6} +// gdbr-check:$3 = (4, 5, 6) +// gdbg-command:print 'simple_tuple::NO_PADDING_64' +// gdbr-command:print simple_tuple::NO_PADDING_64 +// gdbg-check:$4 = {__0 = 7, __1 = 8, __2 = 9} +// gdbr-check:$4 = (7, 8, 9) + +// gdbg-command:print 'simple_tuple::INTERNAL_PADDING_1' +// gdbr-command:print simple_tuple::INTERNAL_PADDING_1 +// gdbg-check:$5 = {__0 = 10, __1 = 11} +// gdbr-check:$5 = (10, 11) +// gdbg-command:print 'simple_tuple::INTERNAL_PADDING_2' +// gdbr-command:print simple_tuple::INTERNAL_PADDING_2 +// gdbg-check:$6 = {__0 = 12, __1 = 13, __2 = 14, __3 = 15} +// gdbr-check:$6 = (12, 13, 14, 15) + +// gdbg-command:print 'simple_tuple::PADDING_AT_END' +// gdbr-command:print simple_tuple::PADDING_AT_END +// gdbg-check:$7 = {__0 = 16, __1 = 17} +// gdbr-check:$7 = (16, 17) // gdb-command:run -// gdb-command:print/d noPadding8 -// gdb-check:$8 = {__0 = -100, __1 = 100} +// gdbg-command:print/d noPadding8 +// gdbr-command:print noPadding8 +// gdbg-check:$8 = {__0 = -100, __1 = 100} +// gdbr-check:$8 = (-100, 100) // gdb-command:print noPadding16 -// gdb-check:$9 = {__0 = 0, __1 = 1, __2 = 2} +// gdbg-check:$9 = {__0 = 0, __1 = 1, __2 = 2} +// gdbr-check:$9 = (0, 1, 2) // gdb-command:print noPadding32 -// gdb-check:$10 = {__0 = 3, __1 = 4.5, __2 = 5} +// gdbg-check:$10 = {__0 = 3, __1 = 4.5, __2 = 5} +// gdbr-check:$10 = (3, 4.5, 5) // gdb-command:print noPadding64 -// gdb-check:$11 = {__0 = 6, __1 = 7.5, __2 = 8} +// gdbg-check:$11 = {__0 = 6, __1 = 7.5, __2 = 8} +// gdbr-check:$11 = (6, 7.5, 8) // gdb-command:print internalPadding1 -// gdb-check:$12 = {__0 = 9, __1 = 10} +// gdbg-check:$12 = {__0 = 9, __1 = 10} +// gdbr-check:$12 = (9, 10) // gdb-command:print internalPadding2 -// gdb-check:$13 = {__0 = 11, __1 = 12, __2 = 13, __3 = 14} +// gdbg-check:$13 = {__0 = 11, __1 = 12, __2 = 13, __3 = 14} +// gdbr-check:$13 = (11, 12, 13, 14) // gdb-command:print paddingAtEnd -// gdb-check:$14 = {__0 = 15, __1 = 16} - -// gdb-command:print/d 'simple_tuple::NO_PADDING_8' -// gdb-check:$15 = {__0 = -127, __1 = 127} -// gdb-command:print 'simple_tuple::NO_PADDING_16' -// gdb-check:$16 = {__0 = -10, __1 = 10, __2 = 9} -// gdb-command:print 'simple_tuple::NO_PADDING_32' -// gdb-check:$17 = {__0 = 14, __1 = 15, __2 = 16} -// gdb-command:print 'simple_tuple::NO_PADDING_64' -// gdb-check:$18 = {__0 = 17, __1 = 18, __2 = 19} - -// gdb-command:print 'simple_tuple::INTERNAL_PADDING_1' -// gdb-check:$19 = {__0 = 110, __1 = 111} -// gdb-command:print 'simple_tuple::INTERNAL_PADDING_2' -// gdb-check:$20 = {__0 = 112, __1 = 113, __2 = 114, __3 = 115} - -// gdb-command:print 'simple_tuple::PADDING_AT_END' -// gdb-check:$21 = {__0 = 116, __1 = 117} +// gdbg-check:$14 = {__0 = 15, __1 = 16} +// gdbr-check:$14 = (15, 16) + +// gdbg-command:print/d 'simple_tuple::NO_PADDING_8' +// gdbr-command:print simple_tuple::NO_PADDING_8 +// gdbg-check:$15 = {__0 = -127, __1 = 127} +// gdbr-check:$15 = (-127, 127) +// gdbg-command:print 'simple_tuple::NO_PADDING_16' +// gdbr-command:print simple_tuple::NO_PADDING_16 +// gdbg-check:$16 = {__0 = -10, __1 = 10, __2 = 9} +// gdbr-check:$16 = (-10, 10, 9) +// gdbg-command:print 'simple_tuple::NO_PADDING_32' +// gdbr-command:print simple_tuple::NO_PADDING_32 +// gdbg-check:$17 = {__0 = 14, __1 = 15, __2 = 16} +// gdbr-check:$17 = (14, 15, 16) +// gdbg-command:print 'simple_tuple::NO_PADDING_64' +// gdbr-command:print simple_tuple::NO_PADDING_64 +// gdbg-check:$18 = {__0 = 17, __1 = 18, __2 = 19} +// gdbr-check:$18 = (17, 18, 19) + +// gdbg-command:print 'simple_tuple::INTERNAL_PADDING_1' +// gdbr-command:print simple_tuple::INTERNAL_PADDING_1 +// gdbg-check:$19 = {__0 = 110, __1 = 111} +// gdbr-check:$19 = (110, 111) +// gdbg-command:print 'simple_tuple::INTERNAL_PADDING_2' +// gdbr-command:print simple_tuple::INTERNAL_PADDING_2 +// gdbg-check:$20 = {__0 = 112, __1 = 113, __2 = 114, __3 = 115} +// gdbr-check:$20 = (112, 113, 114, 115) + +// gdbg-command:print 'simple_tuple::PADDING_AT_END' +// gdbr-command:print simple_tuple::PADDING_AT_END +// gdbg-check:$21 = {__0 = 116, __1 = 117} +// gdbr-check:$21 = (116, 117) // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/struct-in-enum.rs b/src/test/debuginfo/struct-in-enum.rs index 98b90de600516..d0aceaa4f3f9c 100644 --- a/src/test/debuginfo/struct-in-enum.rs +++ b/src/test/debuginfo/struct-in-enum.rs @@ -19,13 +19,16 @@ // gdb-command:run // gdb-command:print case1 -// gdb-check:$1 = {{RUST$ENUM$DISR = Case1, __0 = 0, __1 = {x = 2088533116, y = 2088533116, z = 31868}}, {RUST$ENUM$DISR = Case1, __0 = 0, __1 = 8970181431921507452, __2 = 31868}} +// gdbg-check:$1 = {{RUST$ENUM$DISR = Case1, __0 = 0, __1 = {x = 2088533116, y = 2088533116, z = 31868}}, {RUST$ENUM$DISR = Case1, __0 = 0, __1 = 8970181431921507452, __2 = 31868}} +// gdbr-check:$1 = struct_in_enum::Regular::Case1(0, struct_in_enum::Struct {x: 2088533116, y: 2088533116, z: 31868}) // gdb-command:print case2 -// gdb-check:$2 = {{RUST$ENUM$DISR = Case2, __0 = 0, __1 = {x = 286331153, y = 286331153, z = 4369}}, {RUST$ENUM$DISR = Case2, __0 = 0, __1 = 1229782938247303441, __2 = 4369}} +// gdbg-check:$2 = {{RUST$ENUM$DISR = Case2, __0 = 0, __1 = {x = 286331153, y = 286331153, z = 4369}}, {RUST$ENUM$DISR = Case2, __0 = 0, __1 = 1229782938247303441, __2 = 4369}} +// gdbr-check:$2 = struct_in_enum::Regular::Case2(0, 1229782938247303441, 4369) // gdb-command:print univariant -// gdb-check:$3 = {{__0 = {x = 123, y = 456, z = 789}}} +// gdbg-check:$3 = {{__0 = {x = 123, y = 456, z = 789}}} +// gdbr-check:$3 = struct_in_enum::Univariant::TheOnlyCase(struct_in_enum::Struct {x: 123, y: 456, z: 789}) // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/struct-in-struct.rs b/src/test/debuginfo/struct-in-struct.rs index 76a1613c23146..46524cf1d029a 100644 --- a/src/test/debuginfo/struct-in-struct.rs +++ b/src/test/debuginfo/struct-in-struct.rs @@ -18,13 +18,16 @@ // gdb-command:run // gdb-command:print three_simple_structs -// gdb-check:$1 = {x = {x = 1}, y = {x = 2}, z = {x = 3}} +// gdbg-check:$1 = {x = {x = 1}, y = {x = 2}, z = {x = 3}} +// gdbr-check:$1 = struct_in_struct::ThreeSimpleStructs {x: struct_in_struct::Simple {x: 1}, y: struct_in_struct::Simple {x: 2}, z: struct_in_struct::Simple {x: 3}} // gdb-command:print internal_padding_parent -// gdb-check:$2 = {x = {x = 4, y = 5}, y = {x = 6, y = 7}, z = {x = 8, y = 9}} +// gdbg-check:$2 = {x = {x = 4, y = 5}, y = {x = 6, y = 7}, z = {x = 8, y = 9}} +// gdbr-check:$2 = struct_in_struct::InternalPaddingParent {x: struct_in_struct::InternalPadding {x: 4, y: 5}, y: struct_in_struct::InternalPadding {x: 6, y: 7}, z: struct_in_struct::InternalPadding {x: 8, y: 9}} // gdb-command:print padding_at_end_parent -// gdb-check:$3 = {x = {x = 10, y = 11}, y = {x = 12, y = 13}, z = {x = 14, y = 15}} +// gdbg-check:$3 = {x = {x = 10, y = 11}, y = {x = 12, y = 13}, z = {x = 14, y = 15}} +// gdbr-check:$3 = struct_in_struct::PaddingAtEndParent {x: struct_in_struct::PaddingAtEnd {x: 10, y: 11}, y: struct_in_struct::PaddingAtEnd {x: 12, y: 13}, z: struct_in_struct::PaddingAtEnd {x: 14, y: 15}} // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/struct-style-enum.rs b/src/test/debuginfo/struct-style-enum.rs index 3376fc9bbd450..8abc139eb1172 100644 --- a/src/test/debuginfo/struct-style-enum.rs +++ b/src/test/debuginfo/struct-style-enum.rs @@ -19,16 +19,20 @@ // gdb-command:run // gdb-command:print case1 -// gdb-check:$1 = {{RUST$ENUM$DISR = Case1, a = 0, b = 31868, c = 31868, d = 31868, e = 31868}, {RUST$ENUM$DISR = Case1, a = 0, b = 2088533116, c = 2088533116}, {RUST$ENUM$DISR = Case1, a = 0, b = 8970181431921507452}} +// gdbg-check:$1 = {{RUST$ENUM$DISR = Case1, a = 0, b = 31868, c = 31868, d = 31868, e = 31868}, {RUST$ENUM$DISR = Case1, a = 0, b = 2088533116, c = 2088533116}, {RUST$ENUM$DISR = Case1, a = 0, b = 8970181431921507452}} +// gdbr-check:$1 = struct_style_enum::Regular::Case1{a: 0, b: 31868, c: 31868, d: 31868, e: 31868} // gdb-command:print case2 -// gdb-check:$2 = {{RUST$ENUM$DISR = Case2, a = 0, b = 4369, c = 4369, d = 4369, e = 4369}, {RUST$ENUM$DISR = Case2, a = 0, b = 286331153, c = 286331153}, {RUST$ENUM$DISR = Case2, a = 0, b = 1229782938247303441}} +// gdbg-check:$2 = {{RUST$ENUM$DISR = Case2, a = 0, b = 4369, c = 4369, d = 4369, e = 4369}, {RUST$ENUM$DISR = Case2, a = 0, b = 286331153, c = 286331153}, {RUST$ENUM$DISR = Case2, a = 0, b = 1229782938247303441}} +// gdbr-check:$2 = struct_style_enum::Regular::Case2{a: 0, b: 286331153, c: 286331153} // gdb-command:print case3 -// gdb-check:$3 = {{RUST$ENUM$DISR = Case3, a = 0, b = 22873, c = 22873, d = 22873, e = 22873}, {RUST$ENUM$DISR = Case3, a = 0, b = 1499027801, c = 1499027801}, {RUST$ENUM$DISR = Case3, a = 0, b = 6438275382588823897}} +// gdbg-check:$3 = {{RUST$ENUM$DISR = Case3, a = 0, b = 22873, c = 22873, d = 22873, e = 22873}, {RUST$ENUM$DISR = Case3, a = 0, b = 1499027801, c = 1499027801}, {RUST$ENUM$DISR = Case3, a = 0, b = 6438275382588823897}} +// gdbr-check:$3 = struct_style_enum::Regular::Case3{a: 0, b: 6438275382588823897} // gdb-command:print univariant -// gdb-check:$4 = {{a = -1}} +// gdbg-check:$4 = {{a = -1}} +// gdbr-check:$4 = struct_style_enum::Univariant::TheOnlyCase{a: -1} // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/struct-with-destructor.rs b/src/test/debuginfo/struct-with-destructor.rs index ad8731997abd7..af70b4a63fd27 100644 --- a/src/test/debuginfo/struct-with-destructor.rs +++ b/src/test/debuginfo/struct-with-destructor.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// ignore-tidy-linelength + // min-lldb-version: 310 // compile-flags:-g @@ -16,16 +18,20 @@ // gdb-command:run // gdb-command:print simple -// gdb-check:$1 = {x = 10, y = 20} +// gdbg-check:$1 = {x = 10, y = 20} +// gdbr-check:$1 = struct_with_destructor::WithDestructor {x: 10, y: 20} // gdb-command:print noDestructor -// gdb-check:$2 = {a = {x = 10, y = 20}, guard = -1} +// gdbg-check:$2 = {a = {x = 10, y = 20}, guard = -1} +// gdbr-check:$2 = struct_with_destructor::NoDestructorGuarded {a: struct_with_destructor::NoDestructor {x: 10, y: 20}, guard: -1} // gdb-command:print withDestructor -// gdb-check:$3 = {a = {x = 10, y = 20}, guard = -1} +// gdbg-check:$3 = {a = {x = 10, y = 20}, guard = -1} +// gdbr-check:$3 = struct_with_destructor::WithDestructorGuarded {a: struct_with_destructor::WithDestructor {x: 10, y: 20}, guard: -1} // gdb-command:print nested -// gdb-check:$4 = {a = {a = {x = 7890, y = 9870}}} +// gdbg-check:$4 = {a = {a = {x = 7890, y = 9870}}} +// gdbr-check:$4 = struct_with_destructor::NestedOuter {a: struct_with_destructor::NestedInner {a: struct_with_destructor::WithDestructor {x: 7890, y: 9870}}} // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/tuple-in-struct.rs b/src/test/debuginfo/tuple-in-struct.rs index 1a7fde766f0d8..dae1f5da542f5 100644 --- a/src/test/debuginfo/tuple-in-struct.rs +++ b/src/test/debuginfo/tuple-in-struct.rs @@ -17,29 +17,39 @@ // gdb-command:run // gdb-command:print no_padding1 -// gdb-check:$1 = {x = {__0 = 0, __1 = 1}, y = 2, z = {__0 = 3, __1 = 4, __2 = 5}} +// gdbg-check:$1 = {x = {__0 = 0, __1 = 1}, y = 2, z = {__0 = 3, __1 = 4, __2 = 5}} +// gdbr-check:$1 = tuple_in_struct::NoPadding1 {x: (0, 1), y: 2, z: (3, 4, 5)} // gdb-command:print no_padding2 -// gdb-check:$2 = {x = {__0 = 6, __1 = 7}, y = {__0 = {__0 = 8, __1 = 9}, __1 = 10}} +// gdbg-check:$2 = {x = {__0 = 6, __1 = 7}, y = {__0 = {__0 = 8, __1 = 9}, __1 = 10}} +// gdbr-check:$2 = tuple_in_struct::NoPadding2 {x: (6, 7), y: ((8, 9), 10)} // gdb-command:print tuple_internal_padding -// gdb-check:$3 = {x = {__0 = 11, __1 = 12}, y = {__0 = 13, __1 = 14}} +// gdbg-check:$3 = {x = {__0 = 11, __1 = 12}, y = {__0 = 13, __1 = 14}} +// gdbr-check:$3 = tuple_in_struct::TupleInternalPadding {x: (11, 12), y: (13, 14)} // gdb-command:print struct_internal_padding -// gdb-check:$4 = {x = {__0 = 15, __1 = 16}, y = {__0 = 17, __1 = 18}} +// gdbg-check:$4 = {x = {__0 = 15, __1 = 16}, y = {__0 = 17, __1 = 18}} +// gdbr-check:$4 = tuple_in_struct::StructInternalPadding {x: (15, 16), y: (17, 18)} // gdb-command:print both_internally_padded -// gdb-check:$5 = {x = {__0 = 19, __1 = 20, __2 = 21}, y = {__0 = 22, __1 = 23}} +// gdbg-check:$5 = {x = {__0 = 19, __1 = 20, __2 = 21}, y = {__0 = 22, __1 = 23}} +// gdbr-check:$5 = tuple_in_struct::BothInternallyPadded {x: (19, 20, 21), y: (22, 23)} // gdb-command:print single_tuple -// gdb-check:$6 = {x = {__0 = 24, __1 = 25, __2 = 26}} +// gdbg-check:$6 = {x = {__0 = 24, __1 = 25, __2 = 26}} +// gdbr-check:$6 = tuple_in_struct::SingleTuple {x: (24, 25, 26)} // gdb-command:print tuple_padded_at_end -// gdb-check:$7 = {x = {__0 = 27, __1 = 28}, y = {__0 = 29, __1 = 30}} +// gdbg-check:$7 = {x = {__0 = 27, __1 = 28}, y = {__0 = 29, __1 = 30}} +// gdbr-check:$7 = tuple_in_struct::TuplePaddedAtEnd {x: (27, 28), y: (29, 30)} // gdb-command:print struct_padded_at_end -// gdb-check:$8 = {x = {__0 = 31, __1 = 32}, y = {__0 = 33, __1 = 34}} +// gdbg-check:$8 = {x = {__0 = 31, __1 = 32}, y = {__0 = 33, __1 = 34}} +// gdbr-check:$8 = tuple_in_struct::StructPaddedAtEnd {x: (31, 32), y: (33, 34)} // gdb-command:print both_padded_at_end -// gdb-check:$9 = {x = {__0 = 35, __1 = 36, __2 = 37}, y = {__0 = 38, __1 = 39}} +// gdbg-check:$9 = {x = {__0 = 35, __1 = 36, __2 = 37}, y = {__0 = 38, __1 = 39}} +// gdbr-check:$9 = tuple_in_struct::BothPaddedAtEnd {x: (35, 36, 37), y: (38, 39)} // gdb-command:print mixed_padding -// gdb-check:$10 = {x = {__0 = {__0 = 40, __1 = 41, __2 = 42}, __1 = {__0 = 43, __1 = 44}}, y = {__0 = 45, __1 = 46, __2 = 47, __3 = 48}} +// gdbg-check:$10 = {x = {__0 = {__0 = 40, __1 = 41, __2 = 42}, __1 = {__0 = 43, __1 = 44}}, y = {__0 = 45, __1 = 46, __2 = 47, __3 = 48}} +// gdbr-check:$10 = tuple_in_struct::MixedPadding {x: ((40, 41, 42), (43, 44)), y: (45, 46, 47, 48)} #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] diff --git a/src/test/debuginfo/tuple-in-tuple.rs b/src/test/debuginfo/tuple-in-tuple.rs index a514b69a2d31d..4ebc740b9c0f7 100644 --- a/src/test/debuginfo/tuple-in-tuple.rs +++ b/src/test/debuginfo/tuple-in-tuple.rs @@ -17,21 +17,28 @@ // gdb-command:run // gdb-command:print no_padding1 -// gdb-check:$1 = {__0 = {__0 = 0, __1 = 1}, __1 = 2, __2 = 3} +// gdbg-check:$1 = {__0 = {__0 = 0, __1 = 1}, __1 = 2, __2 = 3} +// gdbr-check:$1 = ((0, 1), 2, 3) // gdb-command:print no_padding2 -// gdb-check:$2 = {__0 = 4, __1 = {__0 = 5, __1 = 6}, __2 = 7} +// gdbg-check:$2 = {__0 = 4, __1 = {__0 = 5, __1 = 6}, __2 = 7} +// gdbr-check:$2 = (4, (5, 6), 7) // gdb-command:print no_padding3 -// gdb-check:$3 = {__0 = 8, __1 = 9, __2 = {__0 = 10, __1 = 11}} +// gdbg-check:$3 = {__0 = 8, __1 = 9, __2 = {__0 = 10, __1 = 11}} +// gdbr-check:$3 = (8, 9, (10, 11)) // gdb-command:print internal_padding1 -// gdb-check:$4 = {__0 = 12, __1 = {__0 = 13, __1 = 14}} +// gdbg-check:$4 = {__0 = 12, __1 = {__0 = 13, __1 = 14}} +// gdbr-check:$4 = (12, (13, 14)) // gdb-command:print internal_padding2 -// gdb-check:$5 = {__0 = 15, __1 = {__0 = 16, __1 = 17}} +// gdbg-check:$5 = {__0 = 15, __1 = {__0 = 16, __1 = 17}} +// gdbr-check:$5 = (15, (16, 17)) // gdb-command:print padding_at_end1 -// gdb-check:$6 = {__0 = 18, __1 = {__0 = 19, __1 = 20}} +// gdbg-check:$6 = {__0 = 18, __1 = {__0 = 19, __1 = 20}} +// gdbr-check:$6 = (18, (19, 20)) // gdb-command:print padding_at_end2 -// gdb-check:$7 = {__0 = {__0 = 21, __1 = 22}, __1 = 23} +// gdbg-check:$7 = {__0 = {__0 = 21, __1 = 22}, __1 = 23} +// gdbr-check:$7 = ((21, 22), 23) // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/tuple-struct.rs b/src/test/debuginfo/tuple-struct.rs index a2ca8c2237b42..aa644d8419b54 100644 --- a/src/test/debuginfo/tuple-struct.rs +++ b/src/test/debuginfo/tuple-struct.rs @@ -17,22 +17,28 @@ // gdb-command:run // gdb-command:print no_padding16 -// gdb-check:$1 = {__0 = 10000, __1 = -10001} +// gdbg-check:$1 = {__0 = 10000, __1 = -10001} +// gdbr-check:$1 = tuple_struct::NoPadding16 (10000, -10001) // gdb-command:print no_padding32 -// gdb-check:$2 = {__0 = -10002, __1 = -10003.5, __2 = 10004} +// gdbg-check:$2 = {__0 = -10002, __1 = -10003.5, __2 = 10004} +// gdbr-check:$2 = tuple_struct::NoPadding32 (-10002, -10003.5, 10004) // gdb-command:print no_padding64 -// gdb-check:$3 = {__0 = -10005.5, __1 = 10006, __2 = 10007} +// gdbg-check:$3 = {__0 = -10005.5, __1 = 10006, __2 = 10007} +// gdbr-check:$3 = tuple_struct::NoPadding64 (-10005.5, 10006, 10007) // gdb-command:print no_padding163264 -// gdb-check:$4 = {__0 = -10008, __1 = 10009, __2 = 10010, __3 = 10011} +// gdbg-check:$4 = {__0 = -10008, __1 = 10009, __2 = 10010, __3 = 10011} +// gdbr-check:$4 = tuple_struct::NoPadding163264 (-10008, 10009, 10010, 10011) // gdb-command:print internal_padding -// gdb-check:$5 = {__0 = 10012, __1 = -10013} +// gdbg-check:$5 = {__0 = 10012, __1 = -10013} +// gdbr-check:$5 = tuple_struct::InternalPadding (10012, -10013) // gdb-command:print padding_at_end -// gdb-check:$6 = {__0 = -10014, __1 = 10015} +// gdbg-check:$6 = {__0 = -10014, __1 = 10015} +// gdbr-check:$6 = tuple_struct::PaddingAtEnd (-10014, 10015) // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/tuple-style-enum.rs b/src/test/debuginfo/tuple-style-enum.rs index 52f171434b037..d05edec3e737d 100644 --- a/src/test/debuginfo/tuple-style-enum.rs +++ b/src/test/debuginfo/tuple-style-enum.rs @@ -19,16 +19,20 @@ // gdb-command:run // gdb-command:print case1 -// gdb-check:$1 = {{RUST$ENUM$DISR = Case1, __0 = 0, __1 = 31868, __2 = 31868, __3 = 31868, __4 = 31868}, {RUST$ENUM$DISR = Case1, __0 = 0, __1 = 2088533116, __2 = 2088533116}, {RUST$ENUM$DISR = Case1, __0 = 0, __1 = 8970181431921507452}} +// gdbg-check:$1 = {{RUST$ENUM$DISR = Case1, __0 = 0, __1 = 31868, __2 = 31868, __3 = 31868, __4 = 31868}, {RUST$ENUM$DISR = Case1, __0 = 0, __1 = 2088533116, __2 = 2088533116}, {RUST$ENUM$DISR = Case1, __0 = 0, __1 = 8970181431921507452}} +// gdbr-check:$1 = tuple_style_enum::Regular::Case1(0, 31868, 31868, 31868, 31868) // gdb-command:print case2 -// gdb-check:$2 = {{RUST$ENUM$DISR = Case2, __0 = 0, __1 = 4369, __2 = 4369, __3 = 4369, __4 = 4369}, {RUST$ENUM$DISR = Case2, __0 = 0, __1 = 286331153, __2 = 286331153}, {RUST$ENUM$DISR = Case2, __0 = 0, __1 = 1229782938247303441}} +// gdbg-check:$2 = {{RUST$ENUM$DISR = Case2, __0 = 0, __1 = 4369, __2 = 4369, __3 = 4369, __4 = 4369}, {RUST$ENUM$DISR = Case2, __0 = 0, __1 = 286331153, __2 = 286331153}, {RUST$ENUM$DISR = Case2, __0 = 0, __1 = 1229782938247303441}} +// gdbr-check:$2 = tuple_style_enum::Regular::Case2(0, 286331153, 286331153) // gdb-command:print case3 -// gdb-check:$3 = {{RUST$ENUM$DISR = Case3, __0 = 0, __1 = 22873, __2 = 22873, __3 = 22873, __4 = 22873}, {RUST$ENUM$DISR = Case3, __0 = 0, __1 = 1499027801, __2 = 1499027801}, {RUST$ENUM$DISR = Case3, __0 = 0, __1 = 6438275382588823897}} +// gdbg-check:$3 = {{RUST$ENUM$DISR = Case3, __0 = 0, __1 = 22873, __2 = 22873, __3 = 22873, __4 = 22873}, {RUST$ENUM$DISR = Case3, __0 = 0, __1 = 1499027801, __2 = 1499027801}, {RUST$ENUM$DISR = Case3, __0 = 0, __1 = 6438275382588823897}} +// gdbr-check:$3 = tuple_style_enum::Regular::Case3(0, 6438275382588823897) // gdb-command:print univariant -// gdb-check:$4 = {{__0 = -1}} +// gdbg-check:$4 = {{__0 = -1}} +// gdbr-check:$4 = tuple_style_enum::Univariant::TheOnlyCase(-1) // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/type-names.rs b/src/test/debuginfo/type-names.rs index 2419625cbd374..438a78743bb1e 100644 --- a/src/test/debuginfo/type-names.rs +++ b/src/test/debuginfo/type-names.rs @@ -20,160 +20,206 @@ // STRUCTS // gdb-command:whatis simple_struct -// gdb-check:type = struct Struct1 +// gdbg-check:type = struct Struct1 +// gdbr-check:type = type_names::Struct1 // gdb-command:whatis generic_struct1 -// gdb-check:type = struct GenericStruct +// gdbg-check:type = struct GenericStruct +// gdbr-check:type = type_names::GenericStruct // gdb-command:whatis generic_struct2 -// gdb-check:type = struct GenericStruct usize> +// gdbg-check:type = struct GenericStruct usize> +// gdbr-check:type = type_names::GenericStruct usize> // gdb-command:whatis mod_struct -// gdb-check:type = struct Struct2 +// gdbg-check:type = struct Struct2 +// gdbr-check:type = type_names::mod1::Struct2 // ENUMS // gdb-command:whatis simple_enum_1 -// gdb-check:type = union Enum1 +// gdbg-check:type = union Enum1 +// gdbr-check:type = type_names::Enum1 // gdb-command:whatis simple_enum_2 -// gdb-check:type = union Enum1 +// gdbg-check:type = union Enum1 +// gdbr-check:type = type_names::Enum1 // gdb-command:whatis simple_enum_3 -// gdb-check:type = union Enum2 +// gdbg-check:type = union Enum2 +// gdbr-check:type = type_names::mod1::Enum2 // gdb-command:whatis generic_enum_1 -// gdb-check:type = union Enum3 +// gdbg-check:type = union Enum3 +// gdbr-check:type = type_names::mod1::mod2::Enum3 // gdb-command:whatis generic_enum_2 -// gdb-check:type = union Enum3 +// gdbg-check:type = union Enum3 +// gdbr-check:type = type_names::mod1::mod2::Enum3 // TUPLES // gdb-command:whatis tuple1 -// gdb-check:type = struct (u32, type_names::Struct1, type_names::mod1::mod2::Enum3) +// gdbg-check:type = struct (u32, type_names::Struct1, type_names::mod1::mod2::Enum3) +// gdbr-check:type = (u32, type_names::Struct1, type_names::mod1::mod2::Enum3) // gdb-command:whatis tuple2 -// gdb-check:type = struct ((type_names::Struct1, type_names::mod1::mod2::Struct3), type_names::mod1::Enum2, char) +// gdbg-check:type = struct ((type_names::Struct1, type_names::mod1::mod2::Struct3), type_names::mod1::Enum2, char) +// gdbr-check:type = ((type_names::Struct1, type_names::mod1::mod2::Struct3), type_names::mod1::Enum2, char) // BOX // gdb-command:whatis box1 -// gdb-check:type = struct (Box, i32) +// gdbg-check:type = struct (Box, i32) +// gdbr-check:type = (Box, i32) // gdb-command:whatis box2 -// gdb-check:type = struct (Box>, i32) +// gdbg-check:type = struct (Box>, i32) +// gdbr-check:type = (Box>, i32) // REFERENCES // gdb-command:whatis ref1 -// gdb-check:type = struct (&type_names::Struct1, i32) +// gdbg-check:type = struct (&type_names::Struct1, i32) +// gdbr-check:type = (&type_names::Struct1, i32) // gdb-command:whatis ref2 -// gdb-check:type = struct (&type_names::GenericStruct, i32) +// gdbg-check:type = struct (&type_names::GenericStruct, i32) +// gdbr-check:type = (&type_names::GenericStruct, i32) // gdb-command:whatis mut_ref1 -// gdb-check:type = struct (&mut type_names::Struct1, i32) +// gdbg-check:type = struct (&mut type_names::Struct1, i32) +// gdbr-check:type = (&mut type_names::Struct1, i32) // gdb-command:whatis mut_ref2 -// gdb-check:type = struct (&mut type_names::GenericStruct, i32) +// gdbg-check:type = struct (&mut type_names::GenericStruct, i32) +// gdbr-check:type = (&mut type_names::GenericStruct, i32) // RAW POINTERS // gdb-command:whatis mut_ptr1 -// gdb-check:type = struct (*mut type_names::Struct1, isize) +// gdbg-check:type = struct (*mut type_names::Struct1, isize) +// gdbr-check:type = (*mut type_names::Struct1, isize) // gdb-command:whatis mut_ptr2 -// gdb-check:type = struct (*mut isize, isize) +// gdbg-check:type = struct (*mut isize, isize) +// gdbr-check:type = (*mut isize, isize) // gdb-command:whatis mut_ptr3 -// gdb-check:type = struct (*mut type_names::mod1::mod2::Enum3, isize) +// gdbg-check:type = struct (*mut type_names::mod1::mod2::Enum3, isize) +// gdbr-check:type = (*mut type_names::mod1::mod2::Enum3, isize) // gdb-command:whatis const_ptr1 -// gdb-check:type = struct (*const type_names::Struct1, isize) +// gdbg-check:type = struct (*const type_names::Struct1, isize) +// gdbr-check:type = (*const type_names::Struct1, isize) // gdb-command:whatis const_ptr2 -// gdb-check:type = struct (*const isize, isize) +// gdbg-check:type = struct (*const isize, isize) +// gdbr-check:type = (*const isize, isize) // gdb-command:whatis const_ptr3 -// gdb-check:type = struct (*const type_names::mod1::mod2::Enum3, isize) +// gdbg-check:type = struct (*const type_names::mod1::mod2::Enum3, isize) +// gdbr-check:type = (*const type_names::mod1::mod2::Enum3, isize) // VECTORS // gdb-command:whatis fixed_size_vec1 -// gdb-check:type = struct ([type_names::Struct1; 3], i16) +// gdbg-check:type = struct ([type_names::Struct1; 3], i16) +// gdbr-check:type = ([type_names::Struct1; 3], i16) // gdb-command:whatis fixed_size_vec2 -// gdb-check:type = struct ([usize; 3], i16) +// gdbg-check:type = struct ([usize; 3], i16) +// gdbr-check:type = ([usize; 3], i16) // gdb-command:whatis slice1 -// gdb-check:type = struct &[usize] +// gdbg-check:type = struct &[usize] +// gdbr-check:type = &[usize] // gdb-command:whatis slice2 -// gdb-check:type = struct &[type_names::mod1::Enum2] +// gdbg-check:type = struct &[type_names::mod1::Enum2] +// gdbr-check:type = &[type_names::mod1::Enum2] // TRAITS // gdb-command:whatis box_trait -// gdb-check:type = struct Box +// gdbg-check:type = struct Box +// gdbr-check:type = type_names::Box // gdb-command:whatis ref_trait -// gdb-check:type = struct &Trait1 +// gdbg-check:type = struct &Trait1 +// gdbr-check:type = type_names::&Trait1 // gdb-command:whatis mut_ref_trait -// gdb-check:type = struct &mut Trait1 +// gdbg-check:type = struct &mut Trait1 +// gdbr-check:type = type_names::&mut Trait1 // gdb-command:whatis generic_box_trait -// gdb-check:type = struct Box> +// gdbg-check:type = struct Box> +// gdbr-check:type = type_names::Box> // gdb-command:whatis generic_ref_trait -// gdb-check:type = struct &Trait2 +// gdbg-check:type = struct &Trait2 +// gdbr-check:type = type_names::&Trait2 // gdb-command:whatis generic_mut_ref_trait -// gdb-check:type = struct &mut Trait2> +// gdbg-check:type = struct &mut Trait2> +// gdbr-check:type = type_names::&mut Trait2> // BARE FUNCTIONS // gdb-command:whatis rust_fn -// gdb-check:type = struct (fn(core::option::Option, core::option::Option<&type_names::mod1::Struct2>), usize) +// gdbg-check:type = struct (fn(core::option::Option, core::option::Option<&type_names::mod1::Struct2>), usize) +// gdbr-check:type = (fn(core::option::Option, core::option::Option<&type_names::mod1::Struct2>), usize) // gdb-command:whatis extern_c_fn -// gdb-check:type = struct (extern "C" fn(isize), usize) +// gdbg-check:type = struct (extern "C" fn(isize), usize) +// gdbr-check:type = (extern "C" fn(isize), usize) // gdb-command:whatis unsafe_fn -// gdb-check:type = struct (unsafe fn(core::result::Result), usize) +// gdbg-check:type = struct (unsafe fn(core::result::Result), usize) +// gdbr-check:type = (unsafe fn(core::result::Result), usize) // gdb-command:whatis extern_stdcall_fn -// gdb-check:type = struct (extern "stdcall" fn(), usize) +// gdbg-check:type = struct (extern "stdcall" fn(), usize) +// gdbr-check:type = (extern "stdcall" fn(), usize) // gdb-command:whatis rust_fn_with_return_value -// gdb-check:type = struct (fn(f64) -> usize, usize) +// gdbg-check:type = struct (fn(f64) -> usize, usize) +// gdbr-check:type = (fn(f64) -> usize, usize) // gdb-command:whatis extern_c_fn_with_return_value -// gdb-check:type = struct (extern "C" fn() -> type_names::Struct1, usize) +// gdbg-check:type = struct (extern "C" fn() -> type_names::Struct1, usize) +// gdbr-check:type = (extern "C" fn() -> type_names::Struct1, usize) // gdb-command:whatis unsafe_fn_with_return_value -// gdb-check:type = struct (unsafe fn(type_names::GenericStruct) -> type_names::mod1::Struct2, usize) +// gdbg-check:type = struct (unsafe fn(type_names::GenericStruct) -> type_names::mod1::Struct2, usize) +// gdbr-check:type = (unsafe fn(type_names::GenericStruct) -> type_names::mod1::Struct2, usize) // gdb-command:whatis extern_stdcall_fn_with_return_value -// gdb-check:type = struct (extern "stdcall" fn(Box) -> usize, usize) +// gdbg-check:type = struct (extern "stdcall" fn(Box) -> usize, usize) +// gdbr-check:type = (extern "stdcall" fn(Box) -> usize, usize) // gdb-command:whatis generic_function_int -// gdb-check:type = struct (fn(isize) -> isize, usize) +// gdbg-check:type = struct (fn(isize) -> isize, usize) +// gdbr-check:type = (fn(isize) -> isize, usize) // gdb-command:whatis generic_function_struct3 -// gdb-check:type = struct (fn(type_names::mod1::mod2::Struct3) -> type_names::mod1::mod2::Struct3, usize) +// gdbg-check:type = struct (fn(type_names::mod1::mod2::Struct3) -> type_names::mod1::mod2::Struct3, usize) +// gdbr-check:type = (fn(type_names::mod1::mod2::Struct3) -> type_names::mod1::mod2::Struct3, usize) // gdb-command:whatis variadic_function -// gdb-check:type = struct (unsafe extern "C" fn(*const u8, ...) -> isize, usize) +// gdbg-check:type = struct (unsafe extern "C" fn(*const u8, ...) -> isize, usize) +// gdbr-check:type = (unsafe extern "C" fn(*const u8, ...) -> isize, usize) // CLOSURES // gdb-command:whatis closure1 -// gdb-check:type = struct (closure, usize) +// gdbg-check:type = struct (closure, usize) +// gdbr-check:type = (closure, usize) // gdb-command:whatis closure2 -// gdb-check:type = struct (closure, usize) +// gdbg-check:type = struct (closure, usize) +// gdbr-check:type = (closure, usize) #![feature(box_syntax)] #![allow(unused_variables)] diff --git a/src/test/debuginfo/union-smoke.rs b/src/test/debuginfo/union-smoke.rs index 319927c979bf8..26e73a08ea137 100644 --- a/src/test/debuginfo/union-smoke.rs +++ b/src/test/debuginfo/union-smoke.rs @@ -16,9 +16,11 @@ // gdb-command:run // gdb-command:print u -// gdb-check:$1 = {a = {__0 = 2 '\002', __1 = 2 '\002'}, b = 514} +// gdbg-check:$1 = {a = {__0 = 2 '\002', __1 = 2 '\002'}, b = 514} +// gdbr-check:$1 = union_smoke::U {a: (2, 2), b: 514} // gdb-command:print union_smoke::SU -// gdb-check:$2 = {a = {__0 = 1 '\001', __1 = 1 '\001'}, b = 257} +// gdbg-check:$2 = {a = {__0 = 1 '\001', __1 = 1 '\001'}, b = 257} +// gdbr-check:$2 = union_smoke::U {a: (1, 1), b: 257} // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/unique-enum.rs b/src/test/debuginfo/unique-enum.rs index bbf13ec756ad8..e882544b802bd 100644 --- a/src/test/debuginfo/unique-enum.rs +++ b/src/test/debuginfo/unique-enum.rs @@ -18,13 +18,16 @@ // gdb-command:run // gdb-command:print *the_a -// gdb-check:$1 = {{RUST$ENUM$DISR = TheA, x = 0, y = 8970181431921507452}, {RUST$ENUM$DISR = TheA, __0 = 0, __1 = 2088533116, __2 = 2088533116}} +// gdbg-check:$1 = {{RUST$ENUM$DISR = TheA, x = 0, y = 8970181431921507452}, {RUST$ENUM$DISR = TheA, __0 = 0, __1 = 2088533116, __2 = 2088533116}} +// gdbr-check:$1 = unique_enum::ABC::TheA{x: 0, y: 8970181431921507452} // gdb-command:print *the_b -// gdb-check:$2 = {{RUST$ENUM$DISR = TheB, x = 0, y = 1229782938247303441}, {RUST$ENUM$DISR = TheB, __0 = 0, __1 = 286331153, __2 = 286331153}} +// gdbg-check:$2 = {{RUST$ENUM$DISR = TheB, x = 0, y = 1229782938247303441}, {RUST$ENUM$DISR = TheB, __0 = 0, __1 = 286331153, __2 = 286331153}} +// gdbr-check:$2 = unique_enum::ABC::TheB(0, 286331153, 286331153) // gdb-command:print *univariant -// gdb-check:$3 = {{__0 = 123234}} +// gdbg-check:$3 = {{__0 = 123234}} +// gdbr-check:$3 = unique_enum::Univariant::TheOnlyCase(123234) // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/var-captured-in-nested-closure.rs b/src/test/debuginfo/var-captured-in-nested-closure.rs index 7090377e5db1b..b9a1d73b6d869 100644 --- a/src/test/debuginfo/var-captured-in-nested-closure.rs +++ b/src/test/debuginfo/var-captured-in-nested-closure.rs @@ -21,9 +21,11 @@ // gdb-command:print constant // gdb-check:$2 = 2 // gdb-command:print a_struct -// gdb-check:$3 = {a = -3, b = 4.5, c = 5} +// gdbg-check:$3 = {a = -3, b = 4.5, c = 5} +// gdbr-check:$3 = var_captured_in_nested_closure::Struct {a: -3, b: 4.5, c: 5} // gdb-command:print *struct_ref -// gdb-check:$4 = {a = -3, b = 4.5, c = 5} +// gdbg-check:$4 = {a = -3, b = 4.5, c = 5} +// gdbr-check:$4 = var_captured_in_nested_closure::Struct {a: -3, b: 4.5, c: 5} // gdb-command:print *owned // gdb-check:$5 = 6 // gdb-command:print closure_local @@ -35,9 +37,11 @@ // gdb-command:print constant // gdb-check:$8 = 2 // gdb-command:print a_struct -// gdb-check:$9 = {a = -3, b = 4.5, c = 5} +// gdbg-check:$9 = {a = -3, b = 4.5, c = 5} +// gdbr-check:$9 = var_captured_in_nested_closure::Struct {a: -3, b: 4.5, c: 5} // gdb-command:print *struct_ref -// gdb-check:$10 = {a = -3, b = 4.5, c = 5} +// gdbg-check:$10 = {a = -3, b = 4.5, c = 5} +// gdbr-check:$10 = var_captured_in_nested_closure::Struct {a: -3, b: 4.5, c: 5} // gdb-command:print *owned // gdb-check:$11 = 6 // gdb-command:print closure_local diff --git a/src/test/debuginfo/var-captured-in-sendable-closure.rs b/src/test/debuginfo/var-captured-in-sendable-closure.rs index b415546faeac7..120bbdd7ba902 100644 --- a/src/test/debuginfo/var-captured-in-sendable-closure.rs +++ b/src/test/debuginfo/var-captured-in-sendable-closure.rs @@ -19,7 +19,8 @@ // gdb-command:print constant // gdb-check:$1 = 1 // gdb-command:print a_struct -// gdb-check:$2 = {a = -2, b = 3.5, c = 4} +// gdbg-check:$2 = {a = -2, b = 3.5, c = 4} +// gdbr-check:$2 = var_captured_in_sendable_closure::Struct {a: -2, b: 3.5, c: 4} // gdb-command:print *owned // gdb-check:$3 = 5 // gdb-command:continue diff --git a/src/test/debuginfo/var-captured-in-stack-closure.rs b/src/test/debuginfo/var-captured-in-stack-closure.rs index e60f964dd095e..c795a095b9769 100644 --- a/src/test/debuginfo/var-captured-in-stack-closure.rs +++ b/src/test/debuginfo/var-captured-in-stack-closure.rs @@ -21,9 +21,11 @@ // gdb-command:print constant // gdb-check:$2 = 2 // gdb-command:print a_struct -// gdb-check:$3 = {a = -3, b = 4.5, c = 5} +// gdbg-check:$3 = {a = -3, b = 4.5, c = 5} +// gdbr-check:$3 = var_captured_in_stack_closure::Struct {a: -3, b: 4.5, c: 5} // gdb-command:print *struct_ref -// gdb-check:$4 = {a = -3, b = 4.5, c = 5} +// gdbg-check:$4 = {a = -3, b = 4.5, c = 5} +// gdbr-check:$4 = var_captured_in_stack_closure::Struct {a: -3, b: 4.5, c: 5} // gdb-command:print *owned // gdb-check:$5 = 6 @@ -34,9 +36,11 @@ // gdb-command:print constant // gdb-check:$7 = 2 // gdb-command:print a_struct -// gdb-check:$8 = {a = -3, b = 4.5, c = 5} +// gdbg-check:$8 = {a = -3, b = 4.5, c = 5} +// gdbr-check:$8 = var_captured_in_stack_closure::Struct {a: -3, b: 4.5, c: 5} // gdb-command:print *struct_ref -// gdb-check:$9 = {a = -3, b = 4.5, c = 5} +// gdbg-check:$9 = {a = -3, b = 4.5, c = 5} +// gdbr-check:$9 = var_captured_in_stack_closure::Struct {a: -3, b: 4.5, c: 5} // gdb-command:print *owned // gdb-check:$10 = 6 diff --git a/src/test/debuginfo/vec-slices.rs b/src/test/debuginfo/vec-slices.rs index cdb5bc4ecfb6e..5553f8427e90f 100644 --- a/src/test/debuginfo/vec-slices.rs +++ b/src/test/debuginfo/vec-slices.rs @@ -21,42 +21,57 @@ // gdb-command:print singleton.length // gdb-check:$2 = 1 -// gdb-command:print *((int64_t[1]*)(singleton.data_ptr)) -// gdb-check:$3 = {1} +// gdbg-command:print *((int64_t[1]*)(singleton.data_ptr)) +// gdbr-command:print *(singleton.data_ptr as &[i64; 1]) +// gdbg-check:$3 = {1} +// gdbr-check:$3 = [1] // gdb-command:print multiple.length // gdb-check:$4 = 4 -// gdb-command:print *((int64_t[4]*)(multiple.data_ptr)) -// gdb-check:$5 = {2, 3, 4, 5} +// gdbg-command:print *((int64_t[4]*)(multiple.data_ptr)) +// gdbr-command:print *(multiple.data_ptr as &[i64; 4]) +// gdbg-check:$5 = {2, 3, 4, 5} +// gdbr-check:$5 = [2, 3, 4, 5] // gdb-command:print slice_of_slice.length // gdb-check:$6 = 2 -// gdb-command:print *((int64_t[2]*)(slice_of_slice.data_ptr)) -// gdb-check:$7 = {3, 4} +// gdbg-command:print *((int64_t[2]*)(slice_of_slice.data_ptr)) +// gdbr-command:print *(slice_of_slice.data_ptr as &[i64; 2]) +// gdbg-check:$7 = {3, 4} +// gdbr-check:$7 = [3, 4] // gdb-command:print padded_tuple.length // gdb-check:$8 = 2 // gdb-command:print padded_tuple.data_ptr[0] -// gdb-check:$9 = {__0 = 6, __1 = 7} +// gdbg-check:$9 = {__0 = 6, __1 = 7} +// gdbr-check:$9 = (6, 7) // gdb-command:print padded_tuple.data_ptr[1] -// gdb-check:$10 = {__0 = 8, __1 = 9} +// gdbg-check:$10 = {__0 = 8, __1 = 9} +// gdbr-check:$10 = (8, 9) // gdb-command:print padded_struct.length // gdb-check:$11 = 2 // gdb-command:print padded_struct.data_ptr[0] -// gdb-check:$12 = {x = 10, y = 11, z = 12} +// gdbg-check:$12 = {x = 10, y = 11, z = 12} +// gdbr-check:$12 = vec_slices::AStruct {x: 10, y: 11, z: 12} // gdb-command:print padded_struct.data_ptr[1] -// gdb-check:$13 = {x = 13, y = 14, z = 15} +// gdbg-check:$13 = {x = 13, y = 14, z = 15} +// gdbr-check:$13 = vec_slices::AStruct {x: 13, y: 14, z: 15} -// gdb-command:print 'vec_slices::MUT_VECT_SLICE'.length +// gdbg-command:print 'vec_slices::MUT_VECT_SLICE'.length +// gdbr-command:print MUT_VECT_SLICE.length // gdb-check:$14 = 2 -// gdb-command:print *((int64_t[2]*)('vec_slices::MUT_VECT_SLICE'.data_ptr)) -// gdb-check:$15 = {64, 65} +// gdbg-command:print *((int64_t[2]*)('vec_slices::MUT_VECT_SLICE'.data_ptr)) +// gdbr-command:print *(MUT_VECT_SLICE.data_ptr as &[i64; 2]) +// gdbg-check:$15 = {64, 65} +// gdbr-check:$15 = [64, 65] //gdb-command:print mut_slice.length //gdb-check:$16 = 5 -//gdb-command:print *((int64_t[5]*)(mut_slice.data_ptr)) -//gdb-check:$17 = {1, 2, 3, 4, 5} +//gdbg-command:print *((int64_t[5]*)(mut_slice.data_ptr)) +//gdbr-command:print *(mut_slice.data_ptr as &[i64; 5]) +//gdbg-check:$17 = {1, 2, 3, 4, 5} +//gdbr-check:$17 = [1, 2, 3, 4, 5] // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/vec.rs b/src/test/debuginfo/vec.rs index c9827a02fc759..fbb33b94d9577 100644 --- a/src/test/debuginfo/vec.rs +++ b/src/test/debuginfo/vec.rs @@ -16,9 +16,11 @@ // gdb-command:run // gdb-command:print a -// gdb-check:$1 = {1, 2, 3} +// gdbg-check:$1 = {1, 2, 3} +// gdbr-check:$1 = [1, 2, 3] // gdb-command:print vec::VECT -// gdb-check:$2 = {4, 5, 6} +// gdbg-check:$2 = {4, 5, 6} +// gdbr-check:$2 = [4, 5, 6] // === LLDB TESTS ================================================================================== diff --git a/src/test/run-make/windows-subsystem/Makefile b/src/test/run-make/windows-subsystem/Makefile new file mode 100644 index 0000000000000..34fb5db32f95a --- /dev/null +++ b/src/test/run-make/windows-subsystem/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +all: + $(RUSTC) windows.rs + $(RUSTC) console.rs diff --git a/src/test/run-make/windows-subsystem/console.rs b/src/test/run-make/windows-subsystem/console.rs new file mode 100644 index 0000000000000..3aedb0ecab722 --- /dev/null +++ b/src/test/run-make/windows-subsystem/console.rs @@ -0,0 +1,15 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(windows_subsystem)] +#![windows_subsystem = "console"] + +fn main() {} + diff --git a/src/test/run-make/windows-subsystem/windows.rs b/src/test/run-make/windows-subsystem/windows.rs new file mode 100644 index 0000000000000..5d875a5a1bf1f --- /dev/null +++ b/src/test/run-make/windows-subsystem/windows.rs @@ -0,0 +1,14 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(windows_subsystem)] +#![windows_subsystem = "windows"] + +fn main() {} diff --git a/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs b/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs index 5229d42f1fdd4..6ac0d5ad1a3bc 100644 --- a/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs +++ b/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs @@ -18,10 +18,10 @@ extern crate syntax_pos; extern crate rustc; extern crate rustc_plugin; -use syntax::parse::token::{self, str_to_ident, NtExpr, NtPat}; +use syntax::parse::token::{str_to_ident, NtExpr, NtPat}; use syntax::ast::{Pat}; use syntax::tokenstream::{TokenTree}; -use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager}; +use syntax::ext::base::{ExtCtxt, MacResult, MacEager}; use syntax::ext::build::AstBuilder; use syntax::ext::tt::macro_parser::{MatchedSeq, MatchedNonterminal}; use syntax::ext::tt::macro_parser::{Success, Failure, Error}; @@ -30,35 +30,12 @@ use syntax::ptr::P; use syntax_pos::Span; use rustc_plugin::Registry; -fn expand_mbe_matches(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) +fn expand_mbe_matches(cx: &mut ExtCtxt, _: Span, args: &[TokenTree]) -> Box { let mbe_matcher = quote_matcher!(cx, $matched:expr, $($pat:pat)|+); - - let mac_expr = match TokenTree::parse(cx, &mbe_matcher[..], args) { - Success(map) => { - match (&*map[&str_to_ident("matched")], &*map[&str_to_ident("pat")]) { - (&MatchedNonterminal(NtExpr(ref matched_expr)), - &MatchedSeq(ref pats, seq_sp)) => { - let pats: Vec> = pats.iter().map(|pat_nt| - if let &MatchedNonterminal(NtPat(ref pat)) = &**pat_nt { - pat.clone() - } else { - unreachable!() - } - ).collect(); - let arm = cx.arm(seq_sp, pats, cx.expr_bool(seq_sp, true)); - - quote_expr!(cx, - match $matched_expr { - $arm - _ => false - } - ) - } - _ => unreachable!() - } - } + let map = match TokenTree::parse(cx, &mbe_matcher, args) { + Success(map) => map, Failure(_, tok) => { panic!("expected Success, but got Failure: {}", parse_failure_msg(tok)); } @@ -67,6 +44,34 @@ fn expand_mbe_matches(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) } }; + let matched_nt = match *map[&str_to_ident("matched")] { + MatchedNonterminal(ref nt) => nt.clone(), + _ => unreachable!(), + }; + + let mac_expr = match (&*matched_nt, &*map[&str_to_ident("pat")]) { + (&NtExpr(ref matched_expr), &MatchedSeq(ref pats, seq_sp)) => { + let pats: Vec> = pats.iter().map(|pat_nt| { + match **pat_nt { + MatchedNonterminal(ref nt) => match **nt { + NtPat(ref pat) => pat.clone(), + _ => unreachable!(), + }, + _ => unreachable!(), + } + }).collect(); + let arm = cx.arm(seq_sp, pats, cx.expr_bool(seq_sp, true)); + + quote_expr!(cx, + match $matched_expr { + $arm + _ => false + } + ) + } + _ => unreachable!() + }; + MacEager::expr(mac_expr) } diff --git a/src/test/run-pass/auxiliary/issue-36954.rs b/src/test/run-pass/auxiliary/issue-36954.rs new file mode 100644 index 0000000000000..832ee1d7c1b45 --- /dev/null +++ b/src/test/run-pass/auxiliary/issue-36954.rs @@ -0,0 +1,18 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(const_fn)] +#![crate_type = "lib"] + +const fn foo(i: i32) -> i32 { + i +} + +pub const FOO: i32 = foo(1); diff --git a/src/test/run-pass/issue-36954.rs b/src/test/run-pass/issue-36954.rs new file mode 100644 index 0000000000000..f8330ba99b7ae --- /dev/null +++ b/src/test/run-pass/issue-36954.rs @@ -0,0 +1,17 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:issue-36954.rs + +extern crate issue_36954 as lib; + +fn main() { + let _ = lib::FOO; +} diff --git a/src/test/run-pass/struct-path-associated-type.rs b/src/test/run-pass/struct-path-associated-type.rs index b033ed5c80210..292761dfd005f 100644 --- a/src/test/run-pass/struct-path-associated-type.rs +++ b/src/test/run-pass/struct-path-associated-type.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(more_struct_aliases)] + struct S { a: T, b: U, diff --git a/src/test/run-pass/struct-path-self.rs b/src/test/run-pass/struct-path-self.rs index c7a282c2a2fa0..b569ab62c1bfa 100644 --- a/src/test/run-pass/struct-path-self.rs +++ b/src/test/run-pass/struct-path-self.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![feature(more_struct_aliases)] + use std::ops::Add; struct S { diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 81cb927f26b02..34f3837d8bbb0 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -146,8 +146,14 @@ pub struct Config { // Host triple for the compiler being invoked pub host: String, - // Version of GDB - pub gdb_version: Option, + // Path to / name of the GDB executable + pub gdb: Option, + + // Version of GDB, encoded as ((major * 1000) + minor) * 1000 + patch + pub gdb_version: Option, + + // Whether GDB has native rust support + pub gdb_native_rust: bool, // Version of LLDB pub lldb_version: Option, diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 503a851676925..e57c9949b1c57 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -18,6 +18,8 @@ use common::Config; use common; use util; +use extract_gdb_version; + /// Properties which must be known very early, before actually running /// the test. pub struct EarlyProps { @@ -75,7 +77,7 @@ impl EarlyProps { return true; } - if let Some(ref actual_version) = config.gdb_version { + if let Some(actual_version) = config.gdb_version { if line.contains("min-gdb-version") { let min_version = line.trim() .split(' ') @@ -83,7 +85,7 @@ impl EarlyProps { .expect("Malformed GDB version directive"); // Ignore if actual version is smaller the minimum required // version - gdb_version_to_int(actual_version) < gdb_version_to_int(min_version) + actual_version < extract_gdb_version(min_version).unwrap() } else { false } @@ -464,23 +466,6 @@ pub fn parse_name_value_directive(line: &str, directive: &str) -> Option } } -pub fn gdb_version_to_int(version_string: &str) -> isize { - let error_string = format!("Encountered GDB version string with unexpected format: {}", - version_string); - let error_string = error_string; - - let components: Vec<&str> = version_string.trim().split('.').collect(); - - if components.len() != 2 { - panic!("{}", error_string); - } - - let major: isize = components[0].parse().ok().expect(&error_string); - let minor: isize = components[1].parse().ok().expect(&error_string); - - return major * 1000 + minor; -} - pub fn lldb_version_to_int(version_string: &str) -> isize { let error_string = format!("Encountered LLDB version string with unexpected format: {}", version_string); diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 2dc7cdbf93502..806363679d174 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -12,6 +12,7 @@ #![feature(box_syntax)] #![feature(rustc_private)] +#![feature(static_in_const)] #![feature(test)] #![feature(libc)] @@ -35,6 +36,7 @@ use std::ffi::OsString; use std::fs; use std::io; use std::path::{Path, PathBuf}; +use std::process::Command; use getopts::{optopt, optflag, reqopt}; use common::Config; use common::{Pretty, DebugInfoGdb, DebugInfoLldb, Mode}; @@ -98,7 +100,7 @@ pub fn parse_config(args: Vec ) -> Config { optopt("", "logfile", "file to log test execution to", "FILE"), optopt("", "target", "the target to build for", "TARGET"), optopt("", "host", "the host to build for", "HOST"), - optopt("", "gdb-version", "the version of GDB used", "VERSION STRING"), + optopt("", "gdb", "path to GDB to use for GDB debuginfo tests", "PATH"), optopt("", "lldb-version", "the version of LLDB used", "VERSION STRING"), optopt("", "llvm-version", "the version of LLVM used", "VERSION STRING"), optopt("", "android-cross-path", "Android NDK standalone path", "PATH"), @@ -149,6 +151,8 @@ pub fn parse_config(args: Vec ) -> Config { } } + let (gdb, gdb_version, gdb_native_rust) = analyze_gdb(matches.opt_str("gdb")); + Config { compile_lib_path: make_absolute(opt_path(matches, "compile-lib-path")), run_lib_path: make_absolute(opt_path(matches, "run-lib-path")), @@ -171,7 +175,9 @@ pub fn parse_config(args: Vec ) -> Config { target_rustcflags: matches.opt_str("target-rustcflags"), target: opt_str2(matches.opt_str("target")), host: opt_str2(matches.opt_str("host")), - gdb_version: extract_gdb_version(matches.opt_str("gdb-version")), + gdb: gdb, + gdb_version: gdb_version, + gdb_native_rust: gdb_native_rust, lldb_version: extract_lldb_version(matches.opt_str("lldb-version")), llvm_version: matches.opt_str("llvm-version"), android_cross_path: opt_path(matches, "android-cross-path"), @@ -470,44 +476,96 @@ pub fn make_test_closure(config: &Config, testpaths: &TestPaths) -> test::TestFn })) } -fn extract_gdb_version(full_version_line: Option) -> Option { - match full_version_line { - Some(ref full_version_line) - if !full_version_line.trim().is_empty() => { - let full_version_line = full_version_line.trim(); +/// Returns (Path to GDB, GDB Version, GDB has Rust Support) +fn analyze_gdb(gdb: Option) -> (Option, Option, bool) { + #[cfg(not(windows))] + const GDB_FALLBACK: &str = "gdb"; + #[cfg(windows)] + const GDB_FALLBACK: &str = "gdb.exe"; - // used to be a regex "(^|[^0-9])([0-9]\.[0-9]+)" - for (pos, c) in full_version_line.char_indices() { - if !c.is_digit(10) { - continue - } - if pos + 2 >= full_version_line.len() { - continue - } - if full_version_line[pos + 1..].chars().next().unwrap() != '.' { - continue - } - if !full_version_line[pos + 2..].chars().next().unwrap().is_digit(10) { - continue - } - if pos > 0 && full_version_line[..pos].chars().next_back() - .unwrap().is_digit(10) { - continue - } - let mut end = pos + 3; - while end < full_version_line.len() && - full_version_line[end..].chars().next() - .unwrap().is_digit(10) { - end += 1; - } - return Some(full_version_line[pos..end].to_owned()); - } - println!("Could not extract GDB version from line '{}'", - full_version_line); - None - }, - _ => None + const MIN_GDB_WITH_RUST: u32 = 7011010; + + let gdb = match gdb { + None => GDB_FALLBACK, + Some(ref s) if s.is_empty() => GDB_FALLBACK, // may be empty if configure found no gdb + Some(ref s) => s, + }; + + let version_line = Command::new(gdb).arg("--version").output().map(|output| { + String::from_utf8_lossy(&output.stdout).lines().next().unwrap().to_string() + }).ok(); + + let version = match version_line { + Some(line) => extract_gdb_version(&line), + None => return (None, None, false), + }; + + let gdb_native_rust = version.map_or(false, |v| v >= MIN_GDB_WITH_RUST); + + return (Some(gdb.to_owned()), version, gdb_native_rust); +} + +fn extract_gdb_version(full_version_line: &str) -> Option { + let full_version_line = full_version_line.trim(); + + // GDB versions look like this: "major.minor.patch?.yyyymmdd?", with both + // of the ? sections being optional + + // We will parse up to 3 digits for minor and patch, ignoring the date + // We limit major to 1 digit, otherwise, on openSUSE, we parse the openSUSE version + + // don't start parsing in the middle of a number + let mut prev_was_digit = false; + for (pos, c) in full_version_line.char_indices() { + if prev_was_digit || !c.is_digit(10) { + prev_was_digit = c.is_digit(10); + continue + } + + prev_was_digit = true; + + let line = &full_version_line[pos..]; + + let next_split = match line.find(|c: char| !c.is_digit(10)) { + Some(idx) => idx, + None => continue, // no minor version + }; + + if line.as_bytes()[next_split] != b'.' { + continue; // no minor version + } + + let major = &line[..next_split]; + let line = &line[next_split + 1..]; + + let (minor, patch) = match line.find(|c: char| !c.is_digit(10)) { + Some(idx) => if line.as_bytes()[idx] == b'.' { + let patch = &line[idx + 1..]; + + let patch_len = patch.find(|c: char| !c.is_digit(10)).unwrap_or(patch.len()); + let patch = &patch[..patch_len]; + let patch = if patch_len > 3 || patch_len == 0 { None } else { Some(patch) }; + + (&line[..idx], patch) + } else { + (&line[..idx], None) + }, + None => (line, None), + }; + + if major.len() != 1 || minor.is_empty() { + continue; + } + + let major: u32 = major.parse().unwrap(); + let minor: u32 = minor.parse().unwrap(); + let patch: u32 = patch.unwrap_or("0").parse().unwrap(); + + return Some(((major * 1000) + minor) * 1000 + patch); } + + println!("Could not extract GDB version from line '{}'", full_version_line); + None } fn extract_lldb_version(full_version_line: Option) -> Option { @@ -553,3 +611,44 @@ fn extract_lldb_version(full_version_line: Option) -> Option { fn is_blacklisted_lldb_version(version: &str) -> bool { version == "350" } + +#[test] +fn test_extract_gdb_version() { + macro_rules! test { ($($expectation:tt: $input:tt,)*) => {{$( + assert_eq!(extract_gdb_version($input), Some($expectation)); + )*}}} + + test! { + 7000001: "GNU gdb (GDB) CentOS (7.0.1-45.el5.centos)", + + 7002000: "GNU gdb (GDB) Red Hat Enterprise Linux (7.2-90.el6)", + + 7004000: "GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2.1) 7.4-2012.04", + 7004001: "GNU gdb (GDB) 7.4.1-debian", + + 7006001: "GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-80.el7", + + 7007001: "GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1", + 7007001: "GNU gdb (Debian 7.7.1+dfsg-5) 7.7.1", + 7007001: "GNU gdb (GDB) Fedora 7.7.1-21.fc20", + + 7008000: "GNU gdb (GDB; openSUSE 13.2) 7.8", + 7009001: "GNU gdb (GDB) Fedora 7.9.1-20.fc22", + 7010001: "GNU gdb (GDB) Fedora 7.10.1-31.fc23", + + 7011000: "GNU gdb (Ubuntu 7.11-0ubuntu1) 7.11", + 7011001: "GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.04) 7.11.1", + 7011001: "GNU gdb (Debian 7.11.1-2) 7.11.1", + 7011001: "GNU gdb (GDB) Fedora 7.11.1-86.fc24", + 7011001: "GNU gdb (GDB; openSUSE Leap 42.1) 7.11.1", + 7011001: "GNU gdb (GDB; openSUSE Tumbleweed) 7.11.1", + + 7011090: "7.11.90", + 7011090: "GNU gdb (Ubuntu 7.11.90.20161005-0ubuntu1) 7.11.90.20161005-git", + + 7012000: "7.12", + 7012000: "GNU gdb (GDB) 7.12", + 7012000: "GNU gdb (GDB) 7.12.20161027-git", + 7012050: "GNU gdb (GDB) 7.12.50.20161027-git", + } +} diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 03c05f919b79e..2b53a53293636 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -32,6 +32,8 @@ use std::path::{Path, PathBuf}; use std::process::{Command, Output, ExitStatus}; use std::str; +use extract_gdb_version; + pub fn run(config: Config, testpaths: &TestPaths) { match &*config.target { @@ -44,6 +46,10 @@ pub fn run(config: Config, testpaths: &TestPaths) { _=> { } } + if config.mode == DebugInfoGdb && config.gdb.is_none() { + panic!("gdb not available but debuginfo gdb debuginfo test requested"); + } + if config.verbose { // We're going to be dumping a lot of info. Start on a new line. print!("\n\n"); @@ -430,11 +436,23 @@ actual:\n\ } fn run_debuginfo_gdb_test_no_opt(&self) { + let prefixes = if self.config.gdb_native_rust { + // GDB with Rust + static PREFIXES: &'static [&'static str] = &["gdb", "gdbr"]; + println!("NOTE: compiletest thinks it is using GDB with native rust support"); + PREFIXES + } else { + // Generic GDB + static PREFIXES: &'static [&'static str] = &["gdb", "gdbg"]; + println!("NOTE: compiletest thinks it is using GDB without native rust support"); + PREFIXES + }; + let DebuggerCommands { commands, check_lines, breakpoint_lines - } = self.parse_debugger_commands("gdb"); + } = self.parse_debugger_commands(prefixes); let mut cmds = commands.join("\n"); // compile test file (it should have 'compile-flags:-g' in the header) @@ -586,19 +604,18 @@ actual:\n\ script_str.push_str("show version\n"); match self.config.gdb_version { - Some(ref version) => { + Some(version) => { println!("NOTE: compiletest thinks it is using GDB version {}", version); - if header::gdb_version_to_int(version) > - header::gdb_version_to_int("7.4") { - // Add the directory containing the pretty printers to - // GDB's script auto loading safe path - script_str.push_str( - &format!("add-auto-load-safe-path {}\n", - rust_pp_module_abs_path.replace(r"\", r"\\")) - ); - } + if version > extract_gdb_version("7.4").unwrap() { + // Add the directory containing the pretty printers to + // GDB's script auto loading safe path + script_str.push_str( + &format!("add-auto-load-safe-path {}\n", + rust_pp_module_abs_path.replace(r"\", r"\\")) + ); + } } _ => { println!("NOTE: compiletest does not know which version of \ @@ -633,11 +650,6 @@ actual:\n\ debug!("script_str = {}", script_str); self.dump_output_file(&script_str, "debugger.script"); - // run debugger script with gdb - fn debugger() -> &'static str { - if cfg!(windows) {"gdb.exe"} else {"gdb"} - } - let debugger_script = self.make_out_name("debugger.script"); // FIXME (#9639): This needs to handle non-utf8 paths @@ -648,7 +660,7 @@ actual:\n\ format!("-command={}", debugger_script.to_str().unwrap())]; let proc_args = ProcArgs { - prog: debugger().to_owned(), + prog: self.config.gdb.as_ref().unwrap().to_owned(), args: debugger_opts, }; @@ -731,7 +743,7 @@ actual:\n\ check_lines, breakpoint_lines, .. - } = self.parse_debugger_commands("lldb"); + } = self.parse_debugger_commands(&["lldb"]); // Write debugger script: // We don't want to hang when calling `quit` while the process is still running @@ -826,9 +838,11 @@ actual:\n\ } } - fn parse_debugger_commands(&self, debugger_prefix: &str) -> DebuggerCommands { - let command_directive = format!("{}-command", debugger_prefix); - let check_directive = format!("{}-check", debugger_prefix); + fn parse_debugger_commands(&self, debugger_prefixes: &[&str]) -> DebuggerCommands { + let directives = debugger_prefixes.iter().map(|prefix| ( + format!("{}-command", prefix), + format!("{}-check", prefix), + )).collect::>(); let mut breakpoint_lines = vec![]; let mut commands = vec![]; @@ -842,17 +856,19 @@ actual:\n\ breakpoint_lines.push(counter); } - header::parse_name_value_directive( - &line, - &command_directive).map(|cmd| { - commands.push(cmd) - }); - - header::parse_name_value_directive( - &line, - &check_directive).map(|cmd| { - check_lines.push(cmd) - }); + for &(ref command_directive, ref check_directive) in &directives { + header::parse_name_value_directive( + &line, + &command_directive).map(|cmd| { + commands.push(cmd) + }); + + header::parse_name_value_directive( + &line, + &check_directive).map(|cmd| { + check_lines.push(cmd) + }); + } } Err(e) => { self.fatal(&format!("Error while parsing debugger commands: {}", e)) diff --git a/x.py b/x.py new file mode 100755 index 0000000000000..54148b0d2b29d --- /dev/null +++ b/x.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python +# Copyright 2016 The Rust Project Developers. See the COPYRIGHT +# file at the top-level directory of this distribution and at +# http://rust-lang.org/COPYRIGHT. +# +# Licensed under the Apache License, Version 2.0 or the MIT license +# , at your +# option. This file may not be copied, modified, or distributed +# except according to those terms. + +import sys +import os +dir = os.path.dirname(__file__) +sys.path.append(os.path.abspath(os.path.join(dir, "src", "bootstrap"))) + +import bootstrap + +bootstrap.main()