]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #45283 - alexcrichton:used-mut-nodes, r=arielb1
authorbors <bors@rust-lang.org>
Mon, 16 Oct 2017 03:02:05 +0000 (03:02 +0000)
committerbors <bors@rust-lang.org>
Mon, 16 Oct 2017 03:02:05 +0000 (03:02 +0000)
rustc: Remove `used_mut_nodes` from `TyCtxt`

This updates the borrowck query to return a result, and this result is then used
to incrementally check for unused mutable nodes given sets of all the used
mutable nodes.

Closes #42384

99 files changed:
config.toml.example
src/Cargo.lock
src/bootstrap/Cargo.toml
src/bootstrap/README.md
src/bootstrap/bin/rustc.rs
src/bootstrap/bin/rustdoc.rs
src/bootstrap/builder.rs
src/bootstrap/cc_detect.rs
src/bootstrap/check.rs
src/bootstrap/config.rs
src/bootstrap/lib.rs
src/bootstrap/native.rs
src/bootstrap/tool.rs
src/build_helper/lib.rs
src/ci/docker/cross2/Dockerfile
src/ci/docker/cross2/build-solaris-toolchain.sh
src/doc/unstable-book/src/language-features/non-ascii-idents.md
src/liballoc_jemalloc/Cargo.toml
src/liballoc_jemalloc/build.rs
src/libprofiler_builtins/Cargo.toml
src/librustc/hir/lowering.rs
src/librustc/ty/maps/plumbing.rs
src/librustc_back/target/mod.rs
src/librustc_back/target/x86_64_unknown_linux_gnux32.rs [new file with mode: 0644]
src/librustc_borrowck/borrowck/mod.rs
src/librustc_borrowck/diagnostics.rs
src/librustc_borrowck/lib.rs
src/librustc_driver/lib.rs
src/librustc_llvm/Cargo.toml
src/librustc_mir/build/matches/mod.rs
src/librustc_mir/diagnostics.rs
src/librustc_mir/util/borrowck_errors.rs
src/librustc_passes/ast_validation.rs
src/librustc_resolve/diagnostics.rs
src/librustc_save_analysis/sig.rs
src/librustc_trans/Cargo.toml
src/librustc_trans/back/lto.rs
src/librustc_trans/back/write.rs
src/librustc_typeck/check/callee.rs
src/librustc_typeck/check/mod.rs
src/librustdoc/Cargo.toml
src/librustdoc/html/layout.rs
src/librustdoc/html/render.rs
src/librustdoc/html/static/rustdoc.css
src/librustdoc/lib.rs
src/librustdoc/markdown.rs
src/librustdoc/test.rs
src/libstd/Cargo.toml
src/libstd/build.rs
src/libstd/collections/hash/table.rs
src/libstd/net/tcp.rs
src/libstd/process.rs
src/libstd/sys/unix/net.rs
src/libsyntax/ast.rs
src/libsyntax/feature_gate.rs
src/libsyntax/fold.rs
src/libsyntax/parse/parser.rs
src/libsyntax/parse/token.rs
src/libsyntax/print/pprust.rs
src/libsyntax/visit.rs
src/libsyntax_pos/symbol.rs
src/rustc/compiler_builtins_shim/Cargo.toml
src/rustllvm/PassWrapper.cpp
src/test/compile-fail/borrowck/borrowck-match-already-borrowed.rs [new file with mode: 0644]
src/test/compile-fail/dyn-trait-compatibility.rs [new file with mode: 0644]
src/test/compile-fail/feature-gate-dyn-trait.rs [new file with mode: 0644]
src/test/compile-fail/method-call-err-msg.rs [deleted file]
src/test/compile-fail/trait-bounds-not-on-struct.rs
src/test/parse-fail/trait-object-bad-parens.rs
src/test/run-make/archive-duplicate-names/Makefile
src/test/run-make/compiler-rt-works-on-mingw/Makefile
src/test/run-make/invalid-library/Makefile
src/test/run-make/issue-19371/foo.rs
src/test/run-make/issue-22131/Makefile
src/test/run-make/rustdoc-output-path/Makefile
src/test/run-make/staticlib-blank-lib/Makefile
src/test/run-make/tools.mk
src/test/run-pass/auxiliary/thin-lto-inlines-aux.rs [deleted file]
src/test/run-pass/dyn-trait.rs [new file with mode: 0644]
src/test/run-pass/thin-lto-inlines.rs [deleted file]
src/test/run-pass/thin-lto-inlines2.rs [deleted file]
src/test/run-pass/thinlto/auxiliary/dylib.rs [new file with mode: 0644]
src/test/run-pass/thinlto/auxiliary/thin-lto-inlines-aux.rs [new file with mode: 0644]
src/test/run-pass/thinlto/dylib-works.rs [new file with mode: 0644]
src/test/run-pass/thinlto/thin-lto-inlines.rs [new file with mode: 0644]
src/test/run-pass/thinlto/thin-lto-inlines2.rs [new file with mode: 0644]
src/test/ui/issue-44406.stderr
src/test/ui/method-call-err-msg.rs [new file with mode: 0644]
src/test/ui/method-call-err-msg.stderr [new file with mode: 0644]
src/test/ui/span/missing-unit-argument.rs
src/test/ui/span/missing-unit-argument.stderr
src/tools/build-manifest/src/main.rs
src/tools/clippy
src/tools/compiletest/src/common.rs
src/tools/compiletest/src/errors.rs
src/tools/compiletest/src/main.rs
src/tools/compiletest/src/runtest.rs
src/tools/rustfmt
src/tools/toolstate.toml

index a2f64e6b70588e99175034cb2cd3171553fa5dd7..f50543e18a764845d76fab7ef6eb990d850f1fb1 100644 (file)
 # =============================================================================
 [target.x86_64-unknown-linux-gnu]
 
-# C compiler to be used to compiler C code and link Rust code. Note that the
+# C compiler to be used to compiler C code. Note that the
 # default value is platform specific, and if not specified it may also depend on
 # what platform is crossing to what platform.
 #cc = "cc"
 # This is only used for host targets.
 #cxx = "c++"
 
+# Archiver to be used to assemble static libraries compiled from C/C++ code.
+# Note: an absolute path should be used, otherwise LLVM build will break.
+#ar = "ar"
+
+# Linker to be used to link Rust code. Note that the
+# default value is platform specific, and if not specified it may also depend on
+# what platform is crossing to what platform.
+#linker = "cc"
+
 # Path to the `llvm-config` binary of the installation of a custom LLVM to link
 # against. Note that if this is specifed we don't compile LLVM at all for this
 # target.
index 3c3223fcade1d32c05eb80694dd4dd7420efe1a7..328ce353e2a139351cf0c4ab75b55c0b9dc0eaa0 100644 (file)
@@ -42,7 +42,7 @@ dependencies = [
  "alloc 0.0.0",
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
- "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
  "libc 0.0.0",
 ]
@@ -99,7 +99,7 @@ name = "backtrace-sys"
 version = "0.1.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -136,7 +136,7 @@ name = "bootstrap"
 version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
- "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "cmake 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)",
  "filetime 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.15 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -246,7 +246,7 @@ version = "0.1.0"
 
 [[package]]
 name = "cc"
-version = "1.0.0"
+version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -275,7 +275,7 @@ name = "cmake"
 version = "0.1.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -290,7 +290,7 @@ dependencies = [
 name = "compiler_builtins"
 version = "0.0.0"
 dependencies = [
- "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
 ]
 
@@ -407,7 +407,7 @@ name = "curl-sys"
 version = "0.3.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "libz-sys 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-sys 0.9.19 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -833,7 +833,7 @@ name = "libgit2-sys"
 version = "0.6.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "cmake 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)",
  "curl-sys 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -860,7 +860,7 @@ name = "libz-sys"
 version = "1.0.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -880,7 +880,7 @@ name = "lzma-sys"
 version = "0.1.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "filetime 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -968,7 +968,7 @@ name = "miniz-sys"
 version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1104,7 +1104,7 @@ name = "openssl-sys"
 version = "0.9.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1208,7 +1208,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 name = "profiler_builtins"
 version = "0.0.0"
 dependencies = [
- "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "core 0.0.0",
 ]
 
@@ -1623,7 +1623,7 @@ version = "0.0.0"
 dependencies = [
  "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "build_helper 0.1.0",
- "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_cratesio_shim 0.0.0",
 ]
 
@@ -1755,7 +1755,7 @@ name = "rustc_trans"
 version = "0.0.0"
 dependencies = [
  "bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
  "jobserver 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1824,7 +1824,7 @@ name = "rustdoc"
 version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
- "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "html-diff 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1994,7 +1994,6 @@ dependencies = [
  "alloc_jemalloc 0.0.0",
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
- "cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "collections 0.0.0",
  "compiler_builtins 0.0.0",
  "core 0.0.0",
@@ -2485,7 +2484,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
 "checksum bitflags 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f5cde24d1b2e2216a726368b2363a273739c91f4e3eb4e0dd12d672d396ad989"
 "checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32"
-"checksum cc 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7db2f146208d7e0fbee761b09cd65a7f51ccc38705d4e7262dad4d73b12a76b1"
+"checksum cc 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2c674f0870e3dbd4105184ea035acb1c32c8ae69939c9e228d2b11bbfe29efad"
 "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
 "checksum clap 2.26.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3451e409013178663435d6f15fdb212f14ee4424a3d74f979d081d0a66b6f1f2"
 "checksum cmake 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "357c07e7a1fc95732793c1edb5901e1a1f305cfcf63a90eb12dbd22bdb6b789d"
index 3f1d03b187203d220a7fc26bc312460b121ceee9..bbbbf0e1915555c419039a827eb1703a8c267c4e 100644 (file)
@@ -34,7 +34,7 @@ cmake = "0.1.23"
 filetime = "0.1"
 num_cpus = "1.0"
 getopts = "0.2"
-cc = "1.0"
+cc = "1.0.1"
 libc = "0.2"
 serde = "1.0.8"
 serde_derive = "1.0.8"
index ebacc62b0fdda6d76c01fe999646ddca6b533496..6eb074605fc1493e70919edf5e94a728c3be3aef 100644 (file)
@@ -126,7 +126,7 @@ install a nightly, presumably using `rustup`. You will then want to
 configure your directory to use this build, like so:
 
 ```
-# configure to use local rust instead of downloding a beta.
+# configure to use local rust instead of downloading a beta.
 # `--local-rust-root` is optional here. If elided, we will
 # use whatever rustc we find on your PATH.
 > configure --enable-rustbuild --local-rust-root=~/.cargo/ --enable-local-rebuild
index e91acb21dac992c122eb3cfb4954b52bd56043ae..aeeda85e924ef1657825aa28993741867561f2c6 100644 (file)
@@ -120,10 +120,9 @@ fn main() {
             cmd.arg("-L").arg(&root);
         }
 
-        // Pass down extra flags, commonly used to configure `-Clinker` when
-        // cross compiling.
-        if let Ok(s) = env::var("RUSTC_FLAGS") {
-            cmd.args(&s.split(" ").filter(|s| !s.is_empty()).collect::<Vec<_>>());
+        // Override linker if necessary.
+        if let Ok(target_linker) = env::var("RUSTC_TARGET_LINKER") {
+            cmd.arg(format!("-Clinker={}", target_linker));
         }
 
         // Pass down incremental directory, if any.
@@ -252,6 +251,11 @@ fn main() {
         if env::var_os("RUSTC_FORCE_UNSTABLE").is_some() {
             cmd.arg("-Z").arg("force-unstable-if-unmarked");
         }
+    } else {
+        // Override linker if necessary.
+        if let Ok(host_linker) = env::var("RUSTC_HOST_LINKER") {
+            cmd.arg(format!("-Clinker={}", host_linker));
+        }
     }
 
     let color = match env::var("RUSTC_COLOR") {
index d18512b257d6aa9fcc08c037520a310dca995f7c..4e975adc9721cdef87aac309521056c7816ba39c 100644 (file)
@@ -47,6 +47,9 @@ fn main() {
     if env::var_os("RUSTC_FORCE_UNSTABLE").is_some() {
         cmd.arg("-Z").arg("force-unstable-if-unmarked");
     }
+    if let Some(linker) = env::var_os("RUSTC_TARGET_LINKER") {
+        cmd.arg("--linker").arg(linker).arg("-Z").arg("unstable-options");
+    }
 
     // Bootstrap's Cargo-command builder sets this variable to the current Rust version; let's pick
     // it up so we can make rustdoc print this into the docs
index 1d63e112ca6fb357e9286bcef175cdb065dcbeae..6480b5a619c03c48d51138fc394229ebfb2b9bc2 100644 (file)
@@ -413,13 +413,15 @@ pub fn rustdoc(&self, host: Interned<String>) -> PathBuf {
     pub fn rustdoc_cmd(&self, host: Interned<String>) -> Command {
         let mut cmd = Command::new(&self.out.join("bootstrap/debug/rustdoc"));
         let compiler = self.compiler(self.top_stage, host);
-        cmd
-            .env("RUSTC_STAGE", compiler.stage.to_string())
-            .env("RUSTC_SYSROOT", self.sysroot(compiler))
-            .env("RUSTC_LIBDIR", self.sysroot_libdir(compiler, self.build.build))
-            .env("CFG_RELEASE_CHANNEL", &self.build.config.channel)
-            .env("RUSTDOC_REAL", self.rustdoc(host))
-            .env("RUSTDOC_CRATE_VERSION", self.build.rust_version());
+        cmd.env("RUSTC_STAGE", compiler.stage.to_string())
+           .env("RUSTC_SYSROOT", self.sysroot(compiler))
+           .env("RUSTC_LIBDIR", self.sysroot_libdir(compiler, self.build.build))
+           .env("CFG_RELEASE_CHANNEL", &self.build.config.channel)
+           .env("RUSTDOC_REAL", self.rustdoc(host))
+           .env("RUSTDOC_CRATE_VERSION", self.build.rust_version());
+        if let Some(linker) = self.build.linker(host) {
+            cmd.env("RUSTC_TARGET_LINKER", linker);
+        }
         cmd
     }
 
@@ -482,8 +484,14 @@ pub fn cargo(&self,
              } else {
                  PathBuf::from("/path/to/nowhere/rustdoc/not/required")
              })
-             .env("TEST_MIRI", self.config.test_miri.to_string())
-             .env("RUSTC_FLAGS", self.rustc_flags(target).join(" "));
+             .env("TEST_MIRI", self.config.test_miri.to_string());
+
+        if let Some(host_linker) = self.build.linker(compiler.host) {
+            cargo.env("RUSTC_HOST_LINKER", host_linker);
+        }
+        if let Some(target_linker) = self.build.linker(target) {
+            cargo.env("RUSTC_TARGET_LINKER", target_linker);
+        }
 
         if mode != Mode::Tool {
             // Tools don't get debuginfo right now, e.g. cargo and rls don't
@@ -557,17 +565,35 @@ pub fn cargo(&self,
 
         cargo.env("RUSTC_VERBOSE", format!("{}", self.verbosity));
 
-        // Specify some various options for build scripts used throughout
-        // the build.
+        // Throughout the build Cargo can execute a number of build scripts
+        // compiling C/C++ code and we need to pass compilers, archivers, flags, etc
+        // obtained previously to those build scripts.
+        // Build scripts use either the `cc` crate or `configure/make` so we pass
+        // the options through environment variables that are fetched and understood by both.
         //
         // FIXME: the guard against msvc shouldn't need to be here
         if !target.contains("msvc") {
-            cargo.env(format!("CC_{}", target), self.cc(target))
-                 .env(format!("AR_{}", target), self.ar(target).unwrap()) // only msvc is None
-                 .env(format!("CFLAGS_{}", target), self.cflags(target).join(" "));
+            let cc = self.cc(target);
+            cargo.env(format!("CC_{}", target), cc)
+                 .env("CC", cc);
+
+            let cflags = self.cflags(target).join(" ");
+            cargo.env(format!("CFLAGS_{}", target), cflags.clone())
+                 .env("CFLAGS", cflags.clone());
+
+            if let Some(ar) = self.ar(target) {
+                let ranlib = format!("{} s", ar.display());
+                cargo.env(format!("AR_{}", target), ar)
+                     .env("AR", ar)
+                     .env(format!("RANLIB_{}", target), ranlib.clone())
+                     .env("RANLIB", ranlib);
+            }
 
             if let Ok(cxx) = self.cxx(target) {
-                 cargo.env(format!("CXX_{}", target), cxx);
+                cargo.env(format!("CXX_{}", target), cxx)
+                     .env("CXX", cxx)
+                     .env(format!("CXXFLAGS_{}", target), cflags.clone())
+                     .env("CXXFLAGS", cflags);
             }
         }
 
index 08df65c7611821bce454586aa9f72a6244df3b39..6e3e3c920291d00e51738f284ce8498e699bb8d5 100644 (file)
 //! ever be probed for. Instead the compilers found here will be used for
 //! everything.
 
+use std::collections::HashSet;
+use std::{env, iter};
+use std::path::{Path, PathBuf};
 use std::process::Command;
-use std::iter;
 
-use build_helper::{cc2ar, output};
+use build_helper::output;
 use cc;
 
 use Build;
 use config::Target;
 use cache::Interned;
 
+// The `cc` crate doesn't provide a way to obtain a path to the detected archiver,
+// so use some simplified logic here. First we respect the environment variable `AR`, then
+// try to infer the archiver path from the C compiler path.
+// In the future this logic should be replaced by calling into the `cc` crate.
+fn cc2ar(cc: &Path, target: &str) -> Option<PathBuf> {
+    if let Some(ar) = env::var_os("AR") {
+        Some(PathBuf::from(ar))
+    } else if target.contains("msvc") {
+        None
+    } else if target.contains("musl") {
+        Some(PathBuf::from("ar"))
+    } else if target.contains("openbsd") {
+        Some(PathBuf::from("ar"))
+    } else {
+        let parent = cc.parent().unwrap();
+        let file = cc.file_name().unwrap().to_str().unwrap();
+        for suffix in &["gcc", "cc", "clang"] {
+            if let Some(idx) = file.rfind(suffix) {
+                let mut file = file[..idx].to_owned();
+                file.push_str("ar");
+                return Some(parent.join(&file));
+            }
+        }
+        Some(parent.join(file))
+    }
+}
+
 pub fn find(build: &mut Build) {
     // For all targets we're going to need a C compiler for building some shims
     // and such as well as for being a linker for Rust code.
-    for target in build.targets.iter().chain(&build.hosts).cloned().chain(iter::once(build.build)) {
+    let targets = build.targets.iter().chain(&build.hosts).cloned().chain(iter::once(build.build))
+                               .collect::<HashSet<_>>();
+    for target in targets.into_iter() {
         let mut cfg = cc::Build::new();
         cfg.cargo_metadata(false).opt_level(0).warnings(false).debug(false)
            .target(&target).host(&build.build);
@@ -57,16 +88,23 @@ pub fn find(build: &mut Build) {
         }
 
         let compiler = cfg.get_compiler();
-        let ar = cc2ar(compiler.path(), &target);
+        let ar = if let ar @ Some(..) = config.and_then(|c| c.ar.clone()) {
+            ar
+        } else {
+            cc2ar(compiler.path(), &target)
+        };
+
         build.verbose(&format!("CC_{} = {:?}", &target, compiler.path()));
-        if let Some(ref ar) = ar {
+        build.cc.insert(target, compiler);
+        if let Some(ar) = ar {
             build.verbose(&format!("AR_{} = {:?}", &target, ar));
+            build.ar.insert(target, ar);
         }
-        build.cc.insert(target, (compiler, ar));
     }
 
     // For all host triples we need to find a C++ compiler as well
-    for host in build.hosts.iter().cloned().chain(iter::once(build.build)) {
+    let hosts = build.hosts.iter().cloned().chain(iter::once(build.build)).collect::<HashSet<_>>();
+    for host in hosts.into_iter() {
         let mut cfg = cc::Build::new();
         cfg.cargo_metadata(false).opt_level(0).warnings(false).debug(false).cpp(true)
            .target(&host).host(&build.build);
index 06edbd8e9eec3999067a49504c79f5cc6041a48a..d9ee63eef8cdd95ceb2b35fd1ca1d672c1c57431 100644 (file)
@@ -364,6 +364,7 @@ fn run(self, builder: &Builder) {
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub struct Clippy {
+    stage: u32,
     host: Interned<String>,
 }
 
@@ -378,6 +379,7 @@ fn should_run(run: ShouldRun) -> ShouldRun {
 
     fn make_run(run: RunConfig) {
         run.builder.ensure(Clippy {
+            stage: run.builder.top_stage,
             host: run.target,
         });
     }
@@ -385,10 +387,11 @@ fn make_run(run: RunConfig) {
     /// Runs `cargo test` for clippy.
     fn run(self, builder: &Builder) {
         let build = builder.build;
+        let stage = self.stage;
         let host = self.host;
-        let compiler = builder.compiler(1, host);
+        let compiler = builder.compiler(stage, host);
 
-        let _clippy = builder.ensure(tool::Clippy { compiler, target: self.host });
+        let clippy = builder.ensure(tool::Clippy { compiler, target: self.host });
         let mut cargo = builder.cargo(compiler, Mode::Tool, host, "test");
         cargo.arg("--manifest-path").arg(build.src.join("src/tools/clippy/Cargo.toml"));
 
@@ -396,6 +399,8 @@ fn run(self, builder: &Builder) {
         cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");
         // clippy tests need to know about the stage sysroot
         cargo.env("SYSROOT", builder.sysroot(compiler));
+        // clippy tests need to find the driver
+        cargo.env("CLIPPY_DRIVER_PATH", clippy);
 
         builder.add_rustc_lib_path(compiler, &mut cargo);
 
@@ -742,12 +747,14 @@ fn run(self, builder: &Builder) {
             flags.push("-g".to_string());
         }
 
-        let mut hostflags = build.rustc_flags(compiler.host);
-        hostflags.extend(flags.clone());
+        if let Some(linker) = build.linker(target) {
+            cmd.arg("--linker").arg(linker);
+        }
+
+        let hostflags = flags.clone();
         cmd.arg("--host-rustcflags").arg(hostflags.join(" "));
 
-        let mut targetflags = build.rustc_flags(target);
-        targetflags.extend(flags);
+        let mut targetflags = flags.clone();
         targetflags.push(format!("-Lnative={}",
                                  build.test_helpers_out(target).display()));
         cmd.arg("--target-rustcflags").arg(targetflags.join(" "));
@@ -801,6 +808,9 @@ fn run(self, builder: &Builder) {
                 .arg("--cflags").arg(build.cflags(target).join(" "))
                 .arg("--llvm-components").arg(llvm_components.trim())
                 .arg("--llvm-cxxflags").arg(llvm_cxxflags.trim());
+                if let Some(ar) = build.ar(target) {
+                    cmd.arg("--ar").arg(ar);
+                }
             }
         }
         if suite == "run-make" && !build.config.llvm_enabled {
@@ -826,7 +836,7 @@ fn run(self, builder: &Builder) {
         // Note that if we encounter `PATH` we make sure to append to our own `PATH`
         // rather than stomp over it.
         if target.contains("msvc") {
-            for &(ref k, ref v) in build.cc[&target].0.env() {
+            for &(ref k, ref v) in build.cc[&target].env() {
                 if k != "PATH" {
                     cmd.env(k, v);
                 }
index 5fb5eb3b7f1a586167014bed3e68c5a404f6fde3..69e0f58f1cd068f8639cb4737bdf6ae73461cd79 100644 (file)
@@ -143,6 +143,8 @@ pub struct Target {
     pub jemalloc: Option<PathBuf>,
     pub cc: Option<PathBuf>,
     pub cxx: Option<PathBuf>,
+    pub ar: Option<PathBuf>,
+    pub linker: Option<PathBuf>,
     pub ndk: Option<PathBuf>,
     pub crt_static: Option<bool>,
     pub musl_root: Option<PathBuf>,
@@ -282,6 +284,8 @@ struct TomlTarget {
     jemalloc: Option<String>,
     cc: Option<String>,
     cxx: Option<String>,
+    ar: Option<String>,
+    linker: Option<String>,
     android_ndk: Option<String>,
     crt_static: Option<bool>,
     musl_root: Option<String>,
@@ -484,8 +488,10 @@ pub fn parse(args: &[String]) -> Config {
                 if let Some(ref s) = cfg.android_ndk {
                     target.ndk = Some(env::current_dir().unwrap().join(s));
                 }
-                target.cxx = cfg.cxx.clone().map(PathBuf::from);
                 target.cc = cfg.cc.clone().map(PathBuf::from);
+                target.cxx = cfg.cxx.clone().map(PathBuf::from);
+                target.ar = cfg.ar.clone().map(PathBuf::from);
+                target.linker = cfg.linker.clone().map(PathBuf::from);
                 target.crt_static = cfg.crt_static.clone();
                 target.musl_root = cfg.musl_root.clone().map(PathBuf::from);
                 target.qemu_rootfs = cfg.qemu_rootfs.clone().map(PathBuf::from);
index 2d721f455785a0fa8152365b26411173917e7c3e..6ac919d3fbdda544922e5cf1ef678d9e75e53991 100644 (file)
@@ -240,10 +240,11 @@ pub struct Build {
     lldb_python_dir: Option<String>,
 
     // Runtime state filled in later on
-    // target -> (cc, ar)
-    cc: HashMap<Interned<String>, (cc::Tool, Option<PathBuf>)>,
-    // host -> (cc, ar)
+    // C/C++ compilers and archiver for all targets
+    cc: HashMap<Interned<String>, cc::Tool>,
     cxx: HashMap<Interned<String>, cc::Tool>,
+    ar: HashMap<Interned<String>, PathBuf>,
+    // Misc
     crates: HashMap<Interned<String>, Crate>,
     is_sudo: bool,
     ci_env: CiEnv,
@@ -324,6 +325,7 @@ pub fn new(config: Config) -> Build {
             rls_info,
             cc: HashMap::new(),
             cxx: HashMap::new(),
+            ar: HashMap::new(),
             crates: HashMap::new(),
             lldb_version: None,
             lldb_python_dir: None,
@@ -612,7 +614,7 @@ fn jobs(&self) -> u32 {
 
     /// Returns the path to the C compiler for the target specified.
     fn cc(&self, target: Interned<String>) -> &Path {
-        self.cc[&target].0.path()
+        self.cc[&target].path()
     }
 
     /// Returns a list of flags to pass to the C compiler for the target
@@ -620,7 +622,7 @@ fn cc(&self, target: Interned<String>) -> &Path {
     fn cflags(&self, target: Interned<String>) -> Vec<String> {
         // Filter out -O and /O (the optimization flags) that we picked up from
         // cc-rs because the build scripts will determine that for themselves.
-        let mut base = self.cc[&target].0.args().iter()
+        let mut base = self.cc[&target].args().iter()
                            .map(|s| s.to_string_lossy().into_owned())
                            .filter(|s| !s.starts_with("-O") && !s.starts_with("/O"))
                            .collect::<Vec<_>>();
@@ -644,7 +646,7 @@ fn cflags(&self, target: Interned<String>) -> Vec<String> {
 
     /// Returns the path to the `ar` archive utility for the target specified.
     fn ar(&self, target: Interned<String>) -> Option<&Path> {
-        self.cc[&target].1.as_ref().map(|p| &**p)
+        self.ar.get(&target).map(|p| &**p)
     }
 
     /// Returns the path to the C++ compiler for the target specified.
@@ -657,21 +659,17 @@ fn cxx(&self, target: Interned<String>) -> Result<&Path, String> {
         }
     }
 
-    /// Returns flags to pass to the compiler to generate code for `target`.
-    fn rustc_flags(&self, target: Interned<String>) -> Vec<String> {
-        // New flags should be added here with great caution!
-        //
-        // It's quite unfortunate to **require** flags to generate code for a
-        // target, so it should only be passed here if absolutely necessary!
-        // Most default configuration should be done through target specs rather
-        // than an entry here.
-
-        let mut base = Vec::new();
-        if target != self.config.build && !target.contains("msvc") &&
-            !target.contains("emscripten") {
-            base.push(format!("-Clinker={}", self.cc(target).display()));
+    /// Returns the path to the linker for the given target if it needs to be overriden.
+    fn linker(&self, target: Interned<String>) -> Option<&Path> {
+        if let Some(linker) = self.config.target_config.get(&target)
+                                                       .and_then(|c| c.linker.as_ref()) {
+            Some(linker)
+        } else if target != self.config.build &&
+                  !target.contains("msvc") && !target.contains("emscripten") {
+            Some(self.cc(target))
+        } else {
+            None
         }
-        base
     }
 
     /// Returns if this target should statically link the C runtime, if specified
index 2c8e5004041da3480cdd8ae0e32bb0e60dda45a7..941ea96bbec23c8b327acf9a6a3471a11c6c21fe 100644 (file)
@@ -227,6 +227,13 @@ fn run(self, builder: &Builder) {
             cfg.build_arg("-j").build_arg(build.jobs().to_string());
             cfg.define("CMAKE_C_FLAGS", build.cflags(target).join(" "));
             cfg.define("CMAKE_CXX_FLAGS", build.cflags(target).join(" "));
+            if let Some(ar) = build.ar(target) {
+                if ar.is_absolute() {
+                    // LLVM build breaks if `CMAKE_AR` is a relative path, for some reason it
+                    // tries to resolve this path in the LLVM build directory.
+                    cfg.define("CMAKE_AR", sanitize_cc(ar));
+                }
+            }
         };
 
         configure_compilers(&mut cfg);
index a05e58e6a22706a0ba355df8d3f716ffeb1ac9f6..662c56d728dfe9f0d7b34aa80adf77a4b456e9a9 100644 (file)
@@ -387,7 +387,7 @@ pub struct Clippy {
 
 impl Step for Clippy {
     type Output = PathBuf;
-    const DEFAULT: bool = false;
+    const DEFAULT: bool = true;
     const ONLY_HOSTS: bool = true;
 
     fn should_run(run: ShouldRun) -> ShouldRun {
@@ -411,7 +411,7 @@ fn run(self, builder: &Builder) -> PathBuf {
         builder.ensure(ToolBuild {
             compiler: self.compiler,
             target: self.target,
-            tool: "clippy",
+            tool: "clippy-driver",
             mode: Mode::Librustc,
             path: "src/tools/clippy",
             expectation: builder.build.config.toolstate.clippy.passes(ToolState::Compiling),
@@ -561,7 +561,7 @@ fn prepare_tool_cmd(&self, compiler: Compiler, cmd: &mut Command) {
         if compiler.host.contains("msvc") {
             let curpaths = env::var_os("PATH").unwrap_or_default();
             let curpaths = env::split_paths(&curpaths).collect::<Vec<_>>();
-            for &(ref k, ref v) in self.cc[&compiler.host].0.env() {
+            for &(ref k, ref v) in self.cc[&compiler.host].env() {
                 if k != "PATH" {
                     continue
                 }
index e81dab70b43e702112b119cad19951ece97c02e2..97723e260f6cb4404aa04618a546f474db70b024 100644 (file)
@@ -138,27 +138,6 @@ pub fn gnu_target(target: &str) -> String {
     }
 }
 
-pub fn cc2ar(cc: &Path, target: &str) -> Option<PathBuf> {
-    if target.contains("msvc") {
-        None
-    } else if target.contains("musl") {
-        Some(PathBuf::from("ar"))
-    } else if target.contains("openbsd") {
-        Some(PathBuf::from("ar"))
-    } else {
-        let parent = cc.parent().unwrap();
-        let file = cc.file_name().unwrap().to_str().unwrap();
-        for suffix in &["gcc", "cc", "clang"] {
-            if let Some(idx) = file.rfind(suffix) {
-                let mut file = file[..idx].to_owned();
-                file.push_str("ar");
-                return Some(parent.join(&file));
-            }
-        }
-        Some(parent.join(file))
-    }
-}
-
 pub fn make(host: &str) -> PathBuf {
     if host.contains("bitrig") || host.contains("dragonfly") ||
         host.contains("freebsd") || host.contains("netbsd") ||
index f5fc06767ce9035af26504e6575060a5334a372f..cc260382f494628102f7c2f59bc7f8f56ea5f4fc 100644 (file)
@@ -5,6 +5,7 @@ RUN sh /scripts/cross-apt-packages.sh
 
 RUN apt-get build-dep -y clang llvm && apt-get install -y --no-install-recommends \
   build-essential \
+  gcc-multilib \
   libedit-dev \
   libgmp-dev \
   libisl-dev \
@@ -36,17 +37,18 @@ ENV \
     AR_aarch64_unknown_fuchsia=aarch64-unknown-fuchsia-ar \
     CC_aarch64_unknown_fuchsia=aarch64-unknown-fuchsia-clang \
     CXX_aarch64_unknown_fuchsia=aarch64-unknown-fuchsia-clang++ \
-    AR_sparcv9_sun_solaris=sparcv9-sun-solaris2.11-ar \
-    CC_sparcv9_sun_solaris=sparcv9-sun-solaris2.11-gcc \
-    CXX_sparcv9_sun_solaris=sparcv9-sun-solaris2.11-g++ \
-    AR_x86_64_sun_solaris=x86_64-sun-solaris2.11-ar \
-    CC_x86_64_sun_solaris=x86_64-sun-solaris2.11-gcc \
-    CXX_x86_64_sun_solaris=x86_64-sun-solaris2.11-g++
+    AR_sparcv9_sun_solaris=sparcv9-sun-solaris2.10-ar \
+    CC_sparcv9_sun_solaris=sparcv9-sun-solaris2.10-gcc \
+    CXX_sparcv9_sun_solaris=sparcv9-sun-solaris2.10-g++ \
+    AR_x86_64_sun_solaris=x86_64-sun-solaris2.10-ar \
+    CC_x86_64_sun_solaris=x86_64-sun-solaris2.10-gcc \
+    CXX_x86_64_sun_solaris=x86_64-sun-solaris2.10-g++
 
 ENV TARGETS=x86_64-unknown-fuchsia
 ENV TARGETS=$TARGETS,aarch64-unknown-fuchsia
 ENV TARGETS=$TARGETS,sparcv9-sun-solaris
 ENV TARGETS=$TARGETS,x86_64-sun-solaris
+ENV TARGETS=$TARGETS,x86_64-unknown-linux-gnux32
 
 ENV RUST_CONFIGURE_ARGS --target=$TARGETS --enable-extended
 ENV SCRIPT python2.7 ../x.py dist --target $TARGETS
index ae84cc62b608638e5df4eeddc0d3cc88ea283e7c..935cbe5d61b58eff77992c5df1cee66d300425c8 100755 (executable)
@@ -25,7 +25,7 @@ cd binutils
 curl https://ftp.gnu.org/gnu/binutils/binutils-$BINUTILS.tar.xz | tar xJf -
 mkdir binutils-build
 cd binutils-build
-hide_output ../binutils-$BINUTILS/configure --target=$ARCH-sun-solaris2.11
+hide_output ../binutils-$BINUTILS/configure --target=$ARCH-sun-solaris2.10
 hide_output make -j10
 hide_output make install
 
@@ -58,13 +58,17 @@ for deb in *$APT_ARCH.deb; do
   dpkg -x $deb .
 done
 
-mkdir                  /usr/local/$ARCH-sun-solaris2.11/usr
-mv usr/include         /usr/local/$ARCH-sun-solaris2.11/usr/include
-mv usr/lib/$LIB_ARCH/* /usr/local/$ARCH-sun-solaris2.11/lib
-mv     lib/$LIB_ARCH/* /usr/local/$ARCH-sun-solaris2.11/lib
+# Strip Solaris 11 functions that are optionally used by libbacktrace.
+# This is for Solaris 10 compatibility.
+$ARCH-sun-solaris2.10-strip -N dl_iterate_phdr -N strnlen lib/$LIB_ARCH/libc.so
 
-ln -s /usr/local/$ARCH-sun-solaris2.11/usr/include /usr/local/$ARCH-sun-solaris2.11/sys-include
-ln -s /usr/local/$ARCH-sun-solaris2.11/usr/include /usr/local/$ARCH-sun-solaris2.11/include
+mkdir                  /usr/local/$ARCH-sun-solaris2.10/usr
+mv usr/include         /usr/local/$ARCH-sun-solaris2.10/usr/include
+mv usr/lib/$LIB_ARCH/* /usr/local/$ARCH-sun-solaris2.10/lib
+mv     lib/$LIB_ARCH/* /usr/local/$ARCH-sun-solaris2.10/lib
+
+ln -s /usr/local/$ARCH-sun-solaris2.10/usr/include /usr/local/$ARCH-sun-solaris2.10/sys-include
+ln -s /usr/local/$ARCH-sun-solaris2.10/usr/include /usr/local/$ARCH-sun-solaris2.10/include
 
 cd ..
 rm -rf solaris
@@ -80,7 +84,7 @@ mkdir ../gcc-build
 cd ../gcc-build
 hide_output ../gcc-$GCC/configure \
   --enable-languages=c,c++        \
-  --target=$ARCH-sun-solaris2.11  \
+  --target=$ARCH-sun-solaris2.10  \
   --with-gnu-as                   \
   --with-gnu-ld                   \
   --disable-multilib              \
@@ -94,7 +98,7 @@ hide_output ../gcc-$GCC/configure \
   --disable-libsanitizer          \
   --disable-libquadmath-support   \
   --disable-lto                   \
-  --with-sysroot=/usr/local/$ARCH-sun-solaris2.11
+  --with-sysroot=/usr/local/$ARCH-sun-solaris2.10
 
 hide_output make -j10
 hide_output make install
index d5600c58fd9a657fff7c7e8c4c992335a2b4f666..efb5495fe26acf32334ddd188aaa9db53c644a0b 100644 (file)
@@ -15,4 +15,34 @@ The `non_ascii_idents` feature adds support for non-ASCII identifiers.
 
 const Îµ: f64 = 0.00001f64;
 const Î : f64 = 3.14f64;
-```
\ No newline at end of file
+```
+
+## Changes to the language reference
+
+> **<sup>Lexer:<sup>**  
+> IDENTIFIER :  
+> &nbsp;&nbsp; &nbsp;&nbsp; XID_start XID_continue<sup>\*</sup>  
+> &nbsp;&nbsp; | `_` XID_continue<sup>+</sup>  
+
+An identifier is any nonempty Unicode string of the following form:
+
+Either
+
+   * The first character has property [`XID_start`]
+   * The remaining characters have property [`XID_continue`]
+
+Or
+
+   * The first character is `_`
+   * The identifier is more than one character, `_` alone is not an identifier
+   * The remaining characters have property [`XID_continue`]
+
+that does _not_ occur in the set of [strict keywords].
+
+> **Note**: [`XID_start`] and [`XID_continue`] as character properties cover the
+> character ranges used to form the more familiar C and Java language-family
+> identifiers.
+
+[`XID_start`]:  http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3AXID_Start%3A%5D&abb=on&g=&i=
+[`XID_continue`]: http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3AXID_Continue%3A%5D&abb=on&g=&i=
+[strict keywords]: ../reference/keywords.html#strict-keywords
index 4042c4d2d4e02de3d31687758246ea9c7c26fea7..6d7d83dd99388aa10145a78c4b7b663dd38af802 100644 (file)
@@ -19,7 +19,7 @@ libc = { path = "../rustc/libc_shim" }
 
 [build-dependencies]
 build_helper = { path = "../build_helper" }
-cc = "1.0"
+cc = "1.0.1"
 
 [features]
 debug = []
index 7dd85ddcc796595c521fd145439bb1d0afa158f6..65e035d4ffdef39bde2246c1fb80d36dd31806f3 100644 (file)
@@ -63,15 +63,6 @@ fn main() {
         _ => return,
     };
 
-    let compiler = cc::Build::new().get_compiler();
-    // only msvc returns None for ar so unwrap is okay
-    let ar = build_helper::cc2ar(compiler.path(), &target).unwrap();
-    let cflags = compiler.args()
-        .iter()
-        .map(|s| s.to_str().unwrap())
-        .collect::<Vec<_>>()
-        .join(" ");
-
     let mut cmd = Command::new("sh");
     cmd.arg(native.src_dir.join("configure")
                           .to_str()
@@ -79,8 +70,6 @@ fn main() {
                           .replace("C:\\", "/c/")
                           .replace("\\", "/"))
        .current_dir(&native.out_dir)
-       .env("CC", compiler.path())
-       .env("EXTRA_CFLAGS", cflags.clone())
        // jemalloc generates Makefile deps using GCC's "-MM" flag. This means
        // that GCC will run the preprocessor, and only the preprocessor, over
        // jemalloc's source files. If we don't specify CPPFLAGS, then at least
@@ -89,9 +78,7 @@ fn main() {
        // passed to GCC, and then GCC won't define the
        // "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4" macro that jemalloc needs to
        // select an atomic operation implementation.
-       .env("CPPFLAGS", cflags.clone())
-       .env("AR", &ar)
-       .env("RANLIB", format!("{} s", ar.display()));
+       .env("CPPFLAGS", env::var_os("CFLAGS").unwrap_or_default());
 
     if target.contains("ios") {
         cmd.arg("--disable-tls");
index eb31f5730d191f5c8b2d7ff0aaa710fae3aced89..04f456917b95703b5eebe33a62e81baa864a36d7 100644 (file)
@@ -15,4 +15,4 @@ doc = false
 core = { path = "../libcore" }
 
 [build-dependencies]
-cc = "1.0"
+cc = "1.0.1"
index 64a2ba1fa6f246fc951fb429b4d8188c8834d777..54aecb4b00f826580f8d0e683ec2d1e80c7d4650 100644 (file)
@@ -705,7 +705,7 @@ fn lower_ty(&mut self, t: &Ty) -> P<hir::Ty> {
                 let expr = self.lower_body(None, |this| this.lower_expr(expr));
                 hir::TyTypeof(expr)
             }
-            TyKind::TraitObject(ref bounds) => {
+            TyKind::TraitObject(ref bounds, ..) => {
                 let mut lifetime_bound = None;
                 let bounds = bounds.iter().filter_map(|bound| {
                     match *bound {
index 3f215303ccbeeade0af0793f4dc80253b34b814d..d6eaf6d1bc48fef0eee6daabc1b93134e8ca146d 100644 (file)
@@ -344,6 +344,52 @@ fn try_get_with(tcx: TyCtxt<'a, $tcx, 'lcx>,
                 }
             }
 
+            /// Ensure that either this query has all green inputs or been executed.
+            /// Executing query::ensure(D) is considered a read of the dep-node D.
+            ///
+            /// This function is particularly useful when executing passes for their
+            /// side-effects -- e.g., in order to report errors for erroneous programs.
+            ///
+            /// Note: The optimization is only available during incr. comp.
+            pub fn ensure(tcx: TyCtxt<'a, $tcx, 'lcx>, key: $K) -> () {
+                let dep_node = Self::to_dep_node(tcx, &key);
+
+                // Ensuring an "input" or anonymous query makes no sense
+                assert!(!dep_node.kind.is_anon());
+                assert!(!dep_node.kind.is_input());
+                use dep_graph::DepNodeColor;
+                match tcx.dep_graph.node_color(&dep_node) {
+                    Some(DepNodeColor::Green(dep_node_index)) => {
+                        tcx.dep_graph.read_index(dep_node_index);
+                    }
+                    Some(DepNodeColor::Red) => {
+                        // A DepNodeColor::Red DepNode means that this query was executed
+                        // before. We can not call `dep_graph.read()` here as we don't have
+                        // the DepNodeIndex. Instead, We call the query again to issue the
+                        // appropriate `dep_graph.read()` call. The performance cost this
+                        // introduces should be negligible as we'll immediately hit the
+                        // in-memory cache.
+                        let _ = tcx.$name(key);
+                    }
+                    None => {
+                        // Huh
+                        if !tcx.dep_graph.is_fully_enabled() {
+                            let _ = tcx.$name(key);
+                            return;
+                        }
+                        match tcx.dep_graph.try_mark_green(tcx, &dep_node) {
+                            Some(dep_node_index) => {
+                                debug_assert!(tcx.dep_graph.is_green(dep_node_index));
+                                tcx.dep_graph.read_index(dep_node_index);
+                            }
+                            None => {
+                                let _ = tcx.$name(key);
+                            }
+                        }
+                    }
+                }
+            }
+
             fn compute_result(tcx: TyCtxt<'a, $tcx, 'lcx>, key: $K) -> $V {
                 let provider = tcx.maps.providers[key.map_crate()].$name;
                 provider(tcx.global_tcx(), key)
index 79f8ce7883121fe185b2ebf5f8bc2253385a1da7..a56d067815819c9df04f2f814917a2c9caf00af3 100644 (file)
@@ -135,6 +135,7 @@ fn $module() {
 
 supported_targets! {
     ("x86_64-unknown-linux-gnu", x86_64_unknown_linux_gnu),
+    ("x86_64-unknown-linux-gnux32", x86_64_unknown_linux_gnux32),
     ("i686-unknown-linux-gnu", i686_unknown_linux_gnu),
     ("i586-unknown-linux-gnu", i586_unknown_linux_gnu),
     ("mips-unknown-linux-gnu", mips_unknown_linux_gnu),
diff --git a/src/librustc_back/target/x86_64_unknown_linux_gnux32.rs b/src/librustc_back/target/x86_64_unknown_linux_gnux32.rs
new file mode 100644 (file)
index 0000000..7038203
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use LinkerFlavor;
+use target::{Target, TargetResult};
+
+pub fn target() -> TargetResult {
+    let mut base = super::linux_base::opts();
+    base.cpu = "x86-64".to_string();
+    base.max_atomic_width = Some(64);
+    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-mx32".to_string());
+    base.stack_probes = true;
+    base.has_elf_tls = false;
+
+    Ok(Target {
+        llvm_target: "x86_64-unknown-linux-gnux32".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "32".to_string(),
+        target_c_int_width: "32".to_string(),
+        data_layout: "e-m:e-p:32:32-i64:64-f80:128-n8:16:32:64-S128".to_string(),
+        arch: "x86_64".to_string(),
+        target_os: "linux".to_string(),
+        target_env: "gnu".to_string(),
+        target_vendor: "unknown".to_string(),
+        linker_flavor: LinkerFlavor::Gcc,
+        options: base,
+    })
+}
index a324219020bf3e41cd6f5c6e0edc6fa3ae5d5529..d29250ac57cfbeb10e9450046ab28aaf852912fd 100644 (file)
@@ -645,11 +645,12 @@ pub fn report_use_of_moved_value(&self,
                 let partial = moved_lp.depth() > lp.depth();
                 let msg = if !has_fork && partial { "partially " }
                           else if has_fork && !has_common { "collaterally "}
-                          else { "" };
-                let mut err = struct_span_err!(
-                    self.tcx.sess, use_span, E0382,
-                    "{} of {}moved value: `{}`",
-                    verb, msg, nl);
+                else { "" };
+                let mut err = self.cannot_act_on_moved_value(use_span,
+                                                             verb,
+                                                             msg,
+                                                             &format!("{}", nl),
+                                                             Origin::Ast);
                 let need_note = match lp.ty.sty {
                     ty::TypeVariants::TyClosure(id, _) => {
                         let node_id = self.tcx.hir.as_local_node_id(id).unwrap();
@@ -729,10 +730,10 @@ pub fn report_partial_reinitialization_of_uninitialized_structure(
             &self,
             span: Span,
             lp: &LoanPath<'tcx>) {
-        span_err!(
-            self.tcx.sess, span, E0383,
-            "partial reinitialization of uninitialized structure `{}`",
-            self.loan_path_to_string(lp));
+        self.cannot_partially_reinit_an_uninit_struct(span,
+                                                      &self.loan_path_to_string(lp),
+                                                      Origin::Ast)
+            .emit();
     }
 
     pub fn report_reassigned_immutable_variable(&self,
@@ -807,8 +808,7 @@ fn report_bckerr(&self, err: &BckError<'tcx>) {
                         db
                     }
                     BorrowViolation(euv::ClosureCapture(_)) => {
-                        struct_span_err!(self.tcx.sess, error_span, E0595,
-                                         "closure cannot assign to {}", descr)
+                        self.closure_cannot_assign_to_borrowed(error_span, &descr, Origin::Ast)
                     }
                     BorrowViolation(euv::OverloadedOperator) |
                     BorrowViolation(euv::AddrOf) |
@@ -817,8 +817,7 @@ fn report_bckerr(&self, err: &BckError<'tcx>) {
                     BorrowViolation(euv::AutoUnsafe) |
                     BorrowViolation(euv::ForLoop) |
                     BorrowViolation(euv::MatchDiscriminant) => {
-                        struct_span_err!(self.tcx.sess, error_span, E0596,
-                                         "cannot borrow {} as mutable", descr)
+                        self.cannot_borrow_path_as_mutable(error_span, &descr, Origin::Ast)
                     }
                     BorrowViolation(euv::ClosureInvocation) => {
                         span_bug!(err.span,
@@ -900,21 +899,12 @@ fn report_bckerr(&self, err: &BckError<'tcx>) {
 
                 if let Some((yield_span, _)) = maybe_borrow_across_yield {
                     debug!("err_out_of_scope: opt_yield_span = {:?}", yield_span);
-                    struct_span_err!(self.tcx.sess,
-                                     error_span,
-                                     E0626,
-                                     "borrow may still be in use when generator yields")
-                        .span_label(yield_span, "possible yield occurs here")
+                    self.cannot_borrow_across_generator_yield(error_span, yield_span, Origin::Ast)
                         .emit();
                     return;
                 }
 
-                let mut db = struct_span_err!(self.tcx.sess,
-                                              error_span,
-                                              E0597,
-                                              "{} does not live long enough",
-                                              msg);
-
+                let mut db = self.path_does_not_live_long_enough(error_span, &msg, Origin::Ast);
                 let (value_kind, value_msg) = match err.cmt.cat {
                     mc::Categorization::Rvalue(..) =>
                         ("temporary value", "temporary value created here"),
@@ -1023,11 +1013,7 @@ fn report_bckerr(&self, err: &BckError<'tcx>) {
             }
             err_borrowed_pointer_too_short(loan_scope, ptr_scope) => {
                 let descr = self.cmt_to_path_or_string(&err.cmt);
-                let mut db = struct_span_err!(self.tcx.sess, error_span, E0598,
-                                              "lifetime of {} is too short to guarantee \
-                                               its contents can be safely reborrowed",
-                                              descr);
-
+                let mut db = self.lifetime_too_short_for_reborrow(error_span, &descr, Origin::Ast);
                 let descr = match opt_loan_path(&err.cmt) {
                     Some(lp) => {
                         format!("`{}`", self.loan_path_to_string(&lp))
@@ -1099,12 +1085,8 @@ pub fn report_aliasability_violation(&self,
         let blame = cmt.immutability_blame();
         let mut err = match blame {
             Some(ImmutabilityBlame::ClosureEnv(id)) => {
-                let mut err = struct_span_err!(
-                    self.tcx.sess, span, E0387,
-                    "{} in a captured outer variable in an `Fn` closure", prefix);
-
                 // FIXME: the distinction between these 2 messages looks wrong.
-                let help = if let BorrowViolation(euv::ClosureCapture(_)) = kind {
+                let help_msg = if let BorrowViolation(euv::ClosureCapture(_)) = kind {
                     // The aliasability violation with closure captures can
                     // happen for nested closures, so we know the enclosing
                     // closure incorrectly accepts an `Fn` while it needs to
@@ -1115,15 +1097,15 @@ pub fn report_aliasability_violation(&self,
                     "consider changing this closure to take self by mutable reference"
                 };
                 let node_id = self.tcx.hir.def_index_to_node_id(id);
-                err.span_help(self.tcx.hir.span(node_id), help);
-                err
+                let help_span = self.tcx.hir.span(node_id);
+                self.cannot_act_on_capture_in_sharable_fn(span,
+                                                          prefix,
+                                                          (help_span, help_msg),
+                                                          Origin::Ast)
             }
             _ =>  {
-                let mut err = struct_span_err!(
-                    self.tcx.sess, span, E0389,
-                    "{} in a `&` reference", prefix);
-                err.span_label(span, "assignment into an immutable reference");
-                err
+                self.cannot_assign_into_immutable_reference(span, prefix,
+                                                            Origin::Ast)
             }
         };
         self.note_immutability_blame(&mut err, blame);
@@ -1275,17 +1257,10 @@ fn report_out_of_scope_escaping_closure_capture(&self,
                 Err(_) => format!("move |<args>| <body>")
             };
 
-        struct_span_err!(self.tcx.sess, err.span, E0373,
-                         "closure may outlive the current function, \
-                          but it borrows {}, \
-                          which is owned by the current function",
-                         cmt_path_or_string)
-            .span_label(capture_span,
-                       format!("{} is borrowed here",
-                                cmt_path_or_string))
-            .span_label(err.span,
-                       format!("may outlive borrowed value {}",
-                                cmt_path_or_string))
+        self.cannot_capture_in_long_lived_closure(err.span,
+                                                  &cmt_path_or_string,
+                                                  capture_span,
+                                                  Origin::Ast)
             .span_suggestion(err.span,
                              &format!("to force the closure to take ownership of {} \
                                        (and any other referenced variables), \
index 031dbcb1ebb91c2a0198476898eb072b3a04c5ae..3fea01443be4b9d34fa31d68024bdea9ed4037dd 100644 (file)
@@ -9,472 +9,3 @@
 // except according to those terms.
 
 #![allow(non_snake_case)]
-
-register_long_diagnostics! {
-
-E0373: r##"
-This error occurs when an attempt is made to use data captured by a closure,
-when that data may no longer exist. It's most commonly seen when attempting to
-return a closure:
-
-```compile_fail,E0373
-fn foo() -> Box<Fn(u32) -> u32> {
-    let x = 0u32;
-    Box::new(|y| x + y)
-}
-```
-
-Notice that `x` is stack-allocated by `foo()`. By default, Rust captures
-closed-over data by reference. This means that once `foo()` returns, `x` no
-longer exists. An attempt to access `x` within the closure would thus be
-unsafe.
-
-Another situation where this might be encountered is when spawning threads:
-
-```compile_fail,E0373
-fn foo() {
-    let x = 0u32;
-    let y = 1u32;
-
-    let thr = std::thread::spawn(|| {
-        x + y
-    });
-}
-```
-
-Since our new thread runs in parallel, the stack frame containing `x` and `y`
-may well have disappeared by the time we try to use them. Even if we call
-`thr.join()` within foo (which blocks until `thr` has completed, ensuring the
-stack frame won't disappear), we will not succeed: the compiler cannot prove
-that this behaviour is safe, and so won't let us do it.
-
-The solution to this problem is usually to switch to using a `move` closure.
-This approach moves (or copies, where possible) data into the closure, rather
-than taking references to it. For example:
-
-```
-fn foo() -> Box<Fn(u32) -> u32> {
-    let x = 0u32;
-    Box::new(move |y| x + y)
-}
-```
-
-Now that the closure has its own copy of the data, there's no need to worry
-about safety.
-"##,
-
-E0382: r##"
-This error occurs when an attempt is made to use a variable after its contents
-have been moved elsewhere. For example:
-
-```compile_fail,E0382
-struct MyStruct { s: u32 }
-
-fn main() {
-    let mut x = MyStruct{ s: 5u32 };
-    let y = x;
-    x.s = 6;
-    println!("{}", x.s);
-}
-```
-
-Since `MyStruct` is a type that is not marked `Copy`, the data gets moved out
-of `x` when we set `y`. This is fundamental to Rust's ownership system: outside
-of workarounds like `Rc`, a value cannot be owned by more than one variable.
-
-If we own the type, the easiest way to address this problem is to implement
-`Copy` and `Clone` on it, as shown below. This allows `y` to copy the
-information in `x`, while leaving the original version owned by `x`. Subsequent
-changes to `x` will not be reflected when accessing `y`.
-
-```
-#[derive(Copy, Clone)]
-struct MyStruct { s: u32 }
-
-fn main() {
-    let mut x = MyStruct{ s: 5u32 };
-    let y = x;
-    x.s = 6;
-    println!("{}", x.s);
-}
-```
-
-Alternatively, if we don't control the struct's definition, or mutable shared
-ownership is truly required, we can use `Rc` and `RefCell`:
-
-```
-use std::cell::RefCell;
-use std::rc::Rc;
-
-struct MyStruct { s: u32 }
-
-fn main() {
-    let mut x = Rc::new(RefCell::new(MyStruct{ s: 5u32 }));
-    let y = x.clone();
-    x.borrow_mut().s = 6;
-    println!("{}", x.borrow().s);
-}
-```
-
-With this approach, x and y share ownership of the data via the `Rc` (reference
-count type). `RefCell` essentially performs runtime borrow checking: ensuring
-that at most one writer or multiple readers can access the data at any one time.
-
-If you wish to learn more about ownership in Rust, start with the chapter in the
-Book:
-
-https://doc.rust-lang.org/book/first-edition/ownership.html
-"##,
-
-E0383: r##"
-This error occurs when an attempt is made to partially reinitialize a
-structure that is currently uninitialized.
-
-For example, this can happen when a drop has taken place:
-
-```compile_fail,E0383
-struct Foo {
-    a: u32,
-}
-impl Drop for Foo {
-    fn drop(&mut self) { /* ... */ }
-}
-
-let mut x = Foo { a: 1 };
-drop(x); // `x` is now uninitialized
-x.a = 2; // error, partial reinitialization of uninitialized structure `t`
-```
-
-This error can be fixed by fully reinitializing the structure in question:
-
-```
-struct Foo {
-    a: u32,
-}
-impl Drop for Foo {
-    fn drop(&mut self) { /* ... */ }
-}
-
-let mut x = Foo { a: 1 };
-drop(x);
-x = Foo { a: 2 };
-```
-"##,
-
-/*E0386: r##"
-This error occurs when an attempt is made to mutate the target of a mutable
-reference stored inside an immutable container.
-
-For example, this can happen when storing a `&mut` inside an immutable `Box`:
-
-```compile_fail,E0386
-let mut x: i64 = 1;
-let y: Box<_> = Box::new(&mut x);
-**y = 2; // error, cannot assign to data in an immutable container
-```
-
-This error can be fixed by making the container mutable:
-
-```
-let mut x: i64 = 1;
-let mut y: Box<_> = Box::new(&mut x);
-**y = 2;
-```
-
-It can also be fixed by using a type with interior mutability, such as `Cell`
-or `RefCell`:
-
-```
-use std::cell::Cell;
-
-let x: i64 = 1;
-let y: Box<Cell<_>> = Box::new(Cell::new(x));
-y.set(2);
-```
-"##,*/
-
-E0387: r##"
-This error occurs when an attempt is made to mutate or mutably reference data
-that a closure has captured immutably. Examples of this error are shown below:
-
-```compile_fail,E0387
-// Accepts a function or a closure that captures its environment immutably.
-// Closures passed to foo will not be able to mutate their closed-over state.
-fn foo<F: Fn()>(f: F) { }
-
-// Attempts to mutate closed-over data. Error message reads:
-// `cannot assign to data in a captured outer variable...`
-fn mutable() {
-    let mut x = 0u32;
-    foo(|| x = 2);
-}
-
-// Attempts to take a mutable reference to closed-over data.  Error message
-// reads: `cannot borrow data mutably in a captured outer variable...`
-fn mut_addr() {
-    let mut x = 0u32;
-    foo(|| { let y = &mut x; });
-}
-```
-
-The problem here is that foo is defined as accepting a parameter of type `Fn`.
-Closures passed into foo will thus be inferred to be of type `Fn`, meaning that
-they capture their context immutably.
-
-If the definition of `foo` is under your control, the simplest solution is to
-capture the data mutably. This can be done by defining `foo` to take FnMut
-rather than Fn:
-
-```
-fn foo<F: FnMut()>(f: F) { }
-```
-
-Alternatively, we can consider using the `Cell` and `RefCell` types to achieve
-interior mutability through a shared reference. Our example's `mutable`
-function could be redefined as below:
-
-```
-use std::cell::Cell;
-
-fn foo<F: Fn()>(f: F) { }
-
-fn mutable() {
-    let x = Cell::new(0u32);
-    foo(|| x.set(2));
-}
-```
-
-You can read more about cell types in the API documentation:
-
-https://doc.rust-lang.org/std/cell/
-"##,
-
-E0388: r##"
-E0388 was removed and is no longer issued.
-"##,
-
-E0389: r##"
-An attempt was made to mutate data using a non-mutable reference. This
-commonly occurs when attempting to assign to a non-mutable reference of a
-mutable reference (`&(&mut T)`).
-
-Example of erroneous code:
-
-```compile_fail,E0389
-struct FancyNum {
-    num: u8,
-}
-
-fn main() {
-    let mut fancy = FancyNum{ num: 5 };
-    let fancy_ref = &(&mut fancy);
-    fancy_ref.num = 6; // error: cannot assign to data in a `&` reference
-    println!("{}", fancy_ref.num);
-}
-```
-
-Here, `&mut fancy` is mutable, but `&(&mut fancy)` is not. Creating an
-immutable reference to a value borrows it immutably. There can be multiple
-references of type `&(&mut T)` that point to the same value, so they must be
-immutable to prevent multiple mutable references to the same value.
-
-To fix this, either remove the outer reference:
-
-```
-struct FancyNum {
-    num: u8,
-}
-
-fn main() {
-    let mut fancy = FancyNum{ num: 5 };
-
-    let fancy_ref = &mut fancy;
-    // `fancy_ref` is now &mut FancyNum, rather than &(&mut FancyNum)
-
-    fancy_ref.num = 6; // No error!
-
-    println!("{}", fancy_ref.num);
-}
-```
-
-Or make the outer reference mutable:
-
-```
-struct FancyNum {
-    num: u8
-}
-
-fn main() {
-    let mut fancy = FancyNum{ num: 5 };
-
-    let fancy_ref = &mut (&mut fancy);
-    // `fancy_ref` is now &mut(&mut FancyNum), rather than &(&mut FancyNum)
-
-    fancy_ref.num = 6; // No error!
-
-    println!("{}", fancy_ref.num);
-}
-```
-"##,
-
-E0595: r##"
-Closures cannot mutate immutable captured variables.
-
-Erroneous code example:
-
-```compile_fail,E0595
-let x = 3; // error: closure cannot assign to immutable local variable `x`
-let mut c = || { x += 1 };
-```
-
-Make the variable binding mutable:
-
-```
-let mut x = 3; // ok!
-let mut c = || { x += 1 };
-```
-"##,
-
-E0596: r##"
-This error occurs because you tried to mutably borrow a non-mutable variable.
-
-Example of erroneous code:
-
-```compile_fail,E0596
-let x = 1;
-let y = &mut x; // error: cannot borrow mutably
-```
-
-In here, `x` isn't mutable, so when we try to mutably borrow it in `y`, it
-fails. To fix this error, you need to make `x` mutable:
-
-```
-let mut x = 1;
-let y = &mut x; // ok!
-```
-"##,
-
-E0597: r##"
-This error occurs because a borrow was made inside a variable which has a
-greater lifetime than the borrowed one.
-
-Example of erroneous code:
-
-```compile_fail,E0597
-struct Foo<'a> {
-    x: Option<&'a u32>,
-}
-
-let mut x = Foo { x: None };
-let y = 0;
-x.x = Some(&y); // error: `y` does not live long enough
-```
-
-In here, `x` is created before `y` and therefore has a greater lifetime. Always
-keep in mind that values in a scope are dropped in the opposite order they are
-created. So to fix the previous example, just make the `y` lifetime greater than
-the `x`'s one:
-
-```
-struct Foo<'a> {
-    x: Option<&'a u32>,
-}
-
-let y = 0;
-let mut x = Foo { x: None };
-x.x = Some(&y);
-```
-"##,
-
-E0626: r##"
-This error occurs because a borrow in a generator persists across a
-yield point.
-
-```compile_fail,E0626
-# #![feature(generators, generator_trait)]
-# use std::ops::Generator;
-let mut b = || {
-    let a = &String::new(); // <-- This borrow...
-    yield (); // ...is still in scope here, when the yield occurs.
-    println!("{}", a);
-};
-b.resume();
-```
-
-At present, it is not permitted to have a yield that occurs while a
-borrow is still in scope. To resolve this error, the borrow must
-either be "contained" to a smaller scope that does not overlap the
-yield or else eliminated in another way. So, for example, we might
-resolve the previous example by removing the borrow and just storing
-the integer by value:
-
-```
-# #![feature(generators, generator_trait)]
-# use std::ops::Generator;
-let mut b = || {
-    let a = 3;
-    yield ();
-    println!("{}", a);
-};
-b.resume();
-```
-
-This is a very simple case, of course. In more complex cases, we may
-wish to have more than one reference to the value that was borrowed --
-in those cases, something like the `Rc` or `Arc` types may be useful.
-
-This error also frequently arises with iteration:
-
-```compile_fail,E0626
-# #![feature(generators, generator_trait)]
-# use std::ops::Generator;
-let mut b = || {
-  let v = vec![1,2,3];
-  for &x in &v { // <-- borrow of `v` is still in scope...
-    yield x; // ...when this yield occurs.
-  }
-};
-b.resume();
-```
-
-Such cases can sometimes be resolved by iterating "by value" (or using
-`into_iter()`) to avoid borrowing:
-
-```
-# #![feature(generators, generator_trait)]
-# use std::ops::Generator;
-let mut b = || {
-  let v = vec![1,2,3];
-  for x in v { // <-- Take ownership of the values instead!
-    yield x; // <-- Now yield is OK.
-  }
-};
-b.resume();
-```
-
-If taking ownership is not an option, using indices can work too:
-
-```
-# #![feature(generators, generator_trait)]
-# use std::ops::Generator;
-let mut b = || {
-  let v = vec![1,2,3];
-  let len = v.len(); // (*)
-  for i in 0..len {
-    let x = v[i]; // (*)
-    yield x; // <-- Now yield is OK.
-  }
-};
-b.resume();
-
-// (*) -- Unfortunately, these temporaries are currently required.
-// See <https://github.com/rust-lang/rust/issues/43122>.
-```
-"##,
-
-}
-
-register_diagnostics! {
-//    E0385, // {} in an aliasable location
-    E0598, // lifetime of {} is too short to guarantee its contents can be...
-}
index 0a39dc1d8b5a2c6709e00b0177765c737693db4c..78aacd49f807dafafc8ae37f7f29db8ed6e81e27 100644 (file)
 #![allow(non_camel_case_types)]
 
 #![feature(quote)]
-#![feature(rustc_diagnostic_macros)]
 
 #[macro_use] extern crate log;
-#[macro_use] extern crate syntax;
+extern crate syntax;
 extern crate syntax_pos;
 extern crate rustc_errors as errors;
 extern crate rustc_back;
 pub use borrowck::check_crate;
 pub use borrowck::build_borrowck_dataflow_data_for_fn;
 
-// NB: This module needs to be declared first so diagnostics are
-// registered before they are used.
-mod diagnostics;
-
 mod borrowck;
 
 pub mod graphviz;
 
 pub use borrowck::provide;
-
-__build_diagnostic_array! { librustc_borrowck, DIAGNOSTICS }
index cd21060aff652ad343a08bb35fa22c1dc31d2d87..3514302c6c8f3e49ea18c1e6aa700450944b15e1 100644 (file)
@@ -1259,7 +1259,6 @@ pub fn diagnostics_registry() -> errors::registry::Registry {
     let mut all_errors = Vec::new();
     all_errors.extend_from_slice(&rustc::DIAGNOSTICS);
     all_errors.extend_from_slice(&rustc_typeck::DIAGNOSTICS);
-    all_errors.extend_from_slice(&rustc_borrowck::DIAGNOSTICS);
     all_errors.extend_from_slice(&rustc_resolve::DIAGNOSTICS);
     all_errors.extend_from_slice(&rustc_privacy::DIAGNOSTICS);
     #[cfg(feature="llvm")]
index de5add56b761d1afb44d9b478c06044211a874f1..a9566c4bcacd7e791d2ac470632e4c46714b7bdb 100644 (file)
@@ -18,4 +18,4 @@ rustc_cratesio_shim = { path = "../librustc_cratesio_shim" }
 
 [build-dependencies]
 build_helper = { path = "../build_helper" }
-cc = "1.0"
+cc = "1.0.1"
index f04dede6e4005d55271442a332a63be99522dba7..56c926eaa615343ee7737abda5f9ac668871c62f 100644 (file)
@@ -21,7 +21,7 @@
 use rustc::hir;
 use hair::*;
 use syntax::ast::{Name, NodeId};
-use syntax_pos::Span;
+use syntax_pos::{DUMMY_SP, Span};
 
 // helper functions, broken out by category:
 mod simplify;
@@ -398,10 +398,12 @@ fn match_candidates<'pat>(&mut self,
             candidates.iter().take_while(|c| c.match_pairs.is_empty()).count();
         debug!("match_candidates: {:?} candidates fully matched", fully_matched);
         let mut unmatched_candidates = candidates.split_off(fully_matched);
-        for candidate in candidates {
+        for (index, candidate) in candidates.into_iter().enumerate() {
             // If so, apply any bindings, test the guard (if any), and
             // branch to the arm.
-            if let Some(b) = self.bind_and_guard_matched_candidate(block, arm_blocks, candidate) {
+            let is_last = index == fully_matched - 1;
+            if let Some(b) = self.bind_and_guard_matched_candidate(block, arm_blocks,
+                                                                   candidate, is_last) {
                 block = b;
             } else {
                 // if None is returned, then any remaining candidates
@@ -664,7 +666,8 @@ fn test_candidates<'pat>(&mut self,
     fn bind_and_guard_matched_candidate<'pat>(&mut self,
                                               mut block: BasicBlock,
                                               arm_blocks: &mut ArmBlocks,
-                                              candidate: Candidate<'pat, 'tcx>)
+                                              candidate: Candidate<'pat, 'tcx>,
+                                              is_last_arm: bool)
                                               -> Option<BasicBlock> {
         debug!("bind_and_guard_matched_candidate(block={:?}, candidate={:?})",
                block, candidate);
@@ -685,10 +688,26 @@ fn bind_and_guard_matched_candidate<'pat>(&mut self,
             self.cfg.terminate(block, source_info,
                                TerminatorKind::if_(self.hir.tcx(), cond, arm_block, otherwise));
             Some(otherwise)
+        } else if !is_last_arm {
+            // Add always true guard in case of more than one arm
+            // it creates false edges and allow MIR borrowck detects errors
+            // FIXME(#45184) -- permit "false edges"
+            let source_info = self.source_info(candidate.span);
+            let true_expr = Expr {
+                temp_lifetime: None,
+                ty: self.hir.tcx().types.bool,
+                span: DUMMY_SP,
+                kind: ExprKind::Literal{literal: self.hir.true_literal()},
+            };
+            let cond = unpack!(block = self.as_local_operand(block, true_expr));
+            let otherwise = self.cfg.start_new_block();
+            self.cfg.terminate(block, source_info,
+                               TerminatorKind::if_(self.hir.tcx(), cond, arm_block, otherwise));
+            Some(otherwise)
         } else {
             let source_info = self.source_info(candidate.span);
             self.cfg.terminate(block, source_info,
-                               TerminatorKind::Goto { target: arm_block });
+                               TerminatorKind::Goto { target: arm_block  });
             None
         }
     }
index 645af0bff64deb09c5875a051098d538fe465cb6..98c5345c69d35fbc25c6d8d6260bd693e5d422eb 100644 (file)
@@ -229,6 +229,57 @@ fn main() {
 See also https://doc.rust-lang.org/book/first-edition/unsafe.html
 "##,
 
+E0373: r##"
+This error occurs when an attempt is made to use data captured by a closure,
+when that data may no longer exist. It's most commonly seen when attempting to
+return a closure:
+
+```compile_fail,E0373
+fn foo() -> Box<Fn(u32) -> u32> {
+    let x = 0u32;
+    Box::new(|y| x + y)
+}
+```
+
+Notice that `x` is stack-allocated by `foo()`. By default, Rust captures
+closed-over data by reference. This means that once `foo()` returns, `x` no
+longer exists. An attempt to access `x` within the closure would thus be
+unsafe.
+
+Another situation where this might be encountered is when spawning threads:
+
+```compile_fail,E0373
+fn foo() {
+    let x = 0u32;
+    let y = 1u32;
+
+    let thr = std::thread::spawn(|| {
+        x + y
+    });
+}
+```
+
+Since our new thread runs in parallel, the stack frame containing `x` and `y`
+may well have disappeared by the time we try to use them. Even if we call
+`thr.join()` within foo (which blocks until `thr` has completed, ensuring the
+stack frame won't disappear), we will not succeed: the compiler cannot prove
+that this behaviour is safe, and so won't let us do it.
+
+The solution to this problem is usually to switch to using a `move` closure.
+This approach moves (or copies, where possible) data into the closure, rather
+than taking references to it. For example:
+
+```
+fn foo() -> Box<Fn(u32) -> u32> {
+    let x = 0u32;
+    Box::new(move |y| x + y)
+}
+```
+
+Now that the closure has its own copy of the data, there's no need to worry
+about safety.
+"##,
+
 E0381: r##"
 It is not allowed to use or capture an uninitialized variable. For example:
 
@@ -250,6 +301,104 @@ fn main() {
 ```
 "##,
 
+E0382: r##"
+This error occurs when an attempt is made to use a variable after its contents
+have been moved elsewhere. For example:
+
+```compile_fail,E0382
+struct MyStruct { s: u32 }
+
+fn main() {
+    let mut x = MyStruct{ s: 5u32 };
+    let y = x;
+    x.s = 6;
+    println!("{}", x.s);
+}
+```
+
+Since `MyStruct` is a type that is not marked `Copy`, the data gets moved out
+of `x` when we set `y`. This is fundamental to Rust's ownership system: outside
+of workarounds like `Rc`, a value cannot be owned by more than one variable.
+
+If we own the type, the easiest way to address this problem is to implement
+`Copy` and `Clone` on it, as shown below. This allows `y` to copy the
+information in `x`, while leaving the original version owned by `x`. Subsequent
+changes to `x` will not be reflected when accessing `y`.
+
+```
+#[derive(Copy, Clone)]
+struct MyStruct { s: u32 }
+
+fn main() {
+    let mut x = MyStruct{ s: 5u32 };
+    let y = x;
+    x.s = 6;
+    println!("{}", x.s);
+}
+```
+
+Alternatively, if we don't control the struct's definition, or mutable shared
+ownership is truly required, we can use `Rc` and `RefCell`:
+
+```
+use std::cell::RefCell;
+use std::rc::Rc;
+
+struct MyStruct { s: u32 }
+
+fn main() {
+    let mut x = Rc::new(RefCell::new(MyStruct{ s: 5u32 }));
+    let y = x.clone();
+    x.borrow_mut().s = 6;
+    println!("{}", x.borrow().s);
+}
+```
+
+With this approach, x and y share ownership of the data via the `Rc` (reference
+count type). `RefCell` essentially performs runtime borrow checking: ensuring
+that at most one writer or multiple readers can access the data at any one time.
+
+If you wish to learn more about ownership in Rust, start with the chapter in the
+Book:
+
+https://doc.rust-lang.org/book/first-edition/ownership.html
+"##,
+
+E0383: r##"
+This error occurs when an attempt is made to partially reinitialize a
+structure that is currently uninitialized.
+
+For example, this can happen when a drop has taken place:
+
+```compile_fail,E0383
+struct Foo {
+    a: u32,
+}
+impl Drop for Foo {
+    fn drop(&mut self) { /* ... */ }
+}
+
+let mut x = Foo { a: 1 };
+drop(x); // `x` is now uninitialized
+x.a = 2; // error, partial reinitialization of uninitialized structure `t`
+```
+
+This error can be fixed by fully reinitializing the structure in question:
+
+```
+struct Foo {
+    a: u32,
+}
+impl Drop for Foo {
+    fn drop(&mut self) { /* ... */ }
+}
+
+let mut x = Foo { a: 1 };
+drop(x);
+x = Foo { a: 2 };
+```
+"##,
+
 E0384: r##"
 This error occurs when an attempt is made to reassign an immutable variable.
 For example:
@@ -272,6 +421,161 @@ fn main() {
 ```
 "##,
 
+/*E0386: r##"
+This error occurs when an attempt is made to mutate the target of a mutable
+reference stored inside an immutable container.
+
+For example, this can happen when storing a `&mut` inside an immutable `Box`:
+
+```compile_fail,E0386
+let mut x: i64 = 1;
+let y: Box<_> = Box::new(&mut x);
+**y = 2; // error, cannot assign to data in an immutable container
+```
+
+This error can be fixed by making the container mutable:
+
+```
+let mut x: i64 = 1;
+let mut y: Box<_> = Box::new(&mut x);
+**y = 2;
+```
+
+It can also be fixed by using a type with interior mutability, such as `Cell`
+or `RefCell`:
+
+```
+use std::cell::Cell;
+
+let x: i64 = 1;
+let y: Box<Cell<_>> = Box::new(Cell::new(x));
+y.set(2);
+```
+"##,*/
+
+E0387: r##"
+This error occurs when an attempt is made to mutate or mutably reference data
+that a closure has captured immutably. Examples of this error are shown below:
+
+```compile_fail,E0387
+// Accepts a function or a closure that captures its environment immutably.
+// Closures passed to foo will not be able to mutate their closed-over state.
+fn foo<F: Fn()>(f: F) { }
+
+// Attempts to mutate closed-over data. Error message reads:
+// `cannot assign to data in a captured outer variable...`
+fn mutable() {
+    let mut x = 0u32;
+    foo(|| x = 2);
+}
+
+// Attempts to take a mutable reference to closed-over data.  Error message
+// reads: `cannot borrow data mutably in a captured outer variable...`
+fn mut_addr() {
+    let mut x = 0u32;
+    foo(|| { let y = &mut x; });
+}
+```
+
+The problem here is that foo is defined as accepting a parameter of type `Fn`.
+Closures passed into foo will thus be inferred to be of type `Fn`, meaning that
+they capture their context immutably.
+
+If the definition of `foo` is under your control, the simplest solution is to
+capture the data mutably. This can be done by defining `foo` to take FnMut
+rather than Fn:
+
+```
+fn foo<F: FnMut()>(f: F) { }
+```
+
+Alternatively, we can consider using the `Cell` and `RefCell` types to achieve
+interior mutability through a shared reference. Our example's `mutable`
+function could be redefined as below:
+
+```
+use std::cell::Cell;
+
+fn foo<F: Fn()>(f: F) { }
+
+fn mutable() {
+    let x = Cell::new(0u32);
+    foo(|| x.set(2));
+}
+```
+
+You can read more about cell types in the API documentation:
+
+https://doc.rust-lang.org/std/cell/
+"##,
+
+E0388: r##"
+E0388 was removed and is no longer issued.
+"##,
+
+E0389: r##"
+An attempt was made to mutate data using a non-mutable reference. This
+commonly occurs when attempting to assign to a non-mutable reference of a
+mutable reference (`&(&mut T)`).
+
+Example of erroneous code:
+
+```compile_fail,E0389
+struct FancyNum {
+    num: u8,
+}
+
+fn main() {
+    let mut fancy = FancyNum{ num: 5 };
+    let fancy_ref = &(&mut fancy);
+    fancy_ref.num = 6; // error: cannot assign to data in a `&` reference
+    println!("{}", fancy_ref.num);
+}
+```
+
+Here, `&mut fancy` is mutable, but `&(&mut fancy)` is not. Creating an
+immutable reference to a value borrows it immutably. There can be multiple
+references of type `&(&mut T)` that point to the same value, so they must be
+immutable to prevent multiple mutable references to the same value.
+
+To fix this, either remove the outer reference:
+
+```
+struct FancyNum {
+    num: u8,
+}
+
+fn main() {
+    let mut fancy = FancyNum{ num: 5 };
+
+    let fancy_ref = &mut fancy;
+    // `fancy_ref` is now &mut FancyNum, rather than &(&mut FancyNum)
+
+    fancy_ref.num = 6; // No error!
+
+    println!("{}", fancy_ref.num);
+}
+```
+
+Or make the outer reference mutable:
+
+```
+struct FancyNum {
+    num: u8
+}
+
+fn main() {
+    let mut fancy = FancyNum{ num: 5 };
+
+    let fancy_ref = &mut (&mut fancy);
+    // `fancy_ref` is now &mut(&mut FancyNum), rather than &(&mut FancyNum)
+
+    fancy_ref.num = 6; // No error!
+
+    println!("{}", fancy_ref.num);
+}
+```
+"##,
 
 E0394: r##"
 A static was referred to by value by another static.
@@ -1265,12 +1569,169 @@ fn main() {
 ```
 "##,
 
+E0595: r##"
+Closures cannot mutate immutable captured variables.
+
+Erroneous code example:
+
+```compile_fail,E0595
+let x = 3; // error: closure cannot assign to immutable local variable `x`
+let mut c = || { x += 1 };
+```
+
+Make the variable binding mutable:
+
+```
+let mut x = 3; // ok!
+let mut c = || { x += 1 };
+```
+"##,
+
+E0596: r##"
+This error occurs because you tried to mutably borrow a non-mutable variable.
+
+Example of erroneous code:
+
+```compile_fail,E0596
+let x = 1;
+let y = &mut x; // error: cannot borrow mutably
+```
+
+In here, `x` isn't mutable, so when we try to mutably borrow it in `y`, it
+fails. To fix this error, you need to make `x` mutable:
+
+```
+let mut x = 1;
+let y = &mut x; // ok!
+```
+"##,
+
+E0597: r##"
+This error occurs because a borrow was made inside a variable which has a
+greater lifetime than the borrowed one.
+
+Example of erroneous code:
+
+```compile_fail,E0597
+struct Foo<'a> {
+    x: Option<&'a u32>,
+}
+
+let mut x = Foo { x: None };
+let y = 0;
+x.x = Some(&y); // error: `y` does not live long enough
+```
+
+In here, `x` is created before `y` and therefore has a greater lifetime. Always
+keep in mind that values in a scope are dropped in the opposite order they are
+created. So to fix the previous example, just make the `y` lifetime greater than
+the `x`'s one:
+
+```
+struct Foo<'a> {
+    x: Option<&'a u32>,
+}
+
+let y = 0;
+let mut x = Foo { x: None };
+x.x = Some(&y);
+```
+"##,
+
+E0626: r##"
+This error occurs because a borrow in a generator persists across a
+yield point.
+
+```compile_fail,E0626
+# #![feature(generators, generator_trait)]
+# use std::ops::Generator;
+let mut b = || {
+    let a = &String::new(); // <-- This borrow...
+    yield (); // ...is still in scope here, when the yield occurs.
+    println!("{}", a);
+};
+b.resume();
+```
+
+At present, it is not permitted to have a yield that occurs while a
+borrow is still in scope. To resolve this error, the borrow must
+either be "contained" to a smaller scope that does not overlap the
+yield or else eliminated in another way. So, for example, we might
+resolve the previous example by removing the borrow and just storing
+the integer by value:
+
+```
+# #![feature(generators, generator_trait)]
+# use std::ops::Generator;
+let mut b = || {
+    let a = 3;
+    yield ();
+    println!("{}", a);
+};
+b.resume();
+```
+
+This is a very simple case, of course. In more complex cases, we may
+wish to have more than one reference to the value that was borrowed --
+in those cases, something like the `Rc` or `Arc` types may be useful.
+
+This error also frequently arises with iteration:
+
+```compile_fail,E0626
+# #![feature(generators, generator_trait)]
+# use std::ops::Generator;
+let mut b = || {
+  let v = vec![1,2,3];
+  for &x in &v { // <-- borrow of `v` is still in scope...
+    yield x; // ...when this yield occurs.
+  }
+};
+b.resume();
+```
+
+Such cases can sometimes be resolved by iterating "by value" (or using
+`into_iter()`) to avoid borrowing:
+
+```
+# #![feature(generators, generator_trait)]
+# use std::ops::Generator;
+let mut b = || {
+  let v = vec![1,2,3];
+  for x in v { // <-- Take ownership of the values instead!
+    yield x; // <-- Now yield is OK.
+  }
+};
+b.resume();
+```
+
+If taking ownership is not an option, using indices can work too:
+
+```
+# #![feature(generators, generator_trait)]
+# use std::ops::Generator;
+let mut b = || {
+  let v = vec![1,2,3];
+  let len = v.len(); // (*)
+  for i in 0..len {
+    let x = v[i]; // (*)
+    yield x; // <-- Now yield is OK.
+  }
+};
+b.resume();
+
+// (*) -- Unfortunately, these temporaries are currently required.
+// See <https://github.com/rust-lang/rust/issues/43122>.
+```
+"##,
+
 }
 
 register_diagnostics! {
+//    E0385, // {} in an aliasable location
     E0493, // destructors cannot be evaluated at compile-time
     E0524, // two closures require unique access to `..` at the same time
     E0526, // shuffle indices are not constant
     E0594, // cannot assign to {}
+    E0598, // lifetime of {} is too short to guarantee its contents can be...
     E0625, // thread-local statics cannot be accessed at compile-time
 }
index 37d53ca829e8562220d4922707517dc2c2a32a6b..216f6e4457096d28d6c51590c46840d579a57f36 100644 (file)
@@ -294,6 +294,139 @@ fn cannot_move_out_of_interior_of_drop(&self,
         err.span_label(move_from_span, "cannot move out of here");
         err
     }
+
+    fn cannot_act_on_moved_value(&self,
+                                 use_span: Span,
+                                 verb: &str,
+                                 optional_adverb_for_moved: &str,
+                                 moved_path: &str,
+                                 o: Origin)
+                                 -> DiagnosticBuilder
+    {
+        let err = struct_span_err!(self, use_span, E0382,
+                                   "{} of {}moved value: `{}`{OGN}",
+                                   verb, optional_adverb_for_moved, moved_path, OGN=o);
+        err
+    }
+
+    fn cannot_partially_reinit_an_uninit_struct(&self,
+                                                span: Span,
+                                                uninit_path: &str,
+                                                o: Origin)
+                                                -> DiagnosticBuilder
+    {
+        let err = struct_span_err!(self,
+                                   span,
+                                   E0383,
+                                   "partial reinitialization of uninitialized structure `{}`{OGN}",
+                                   uninit_path, OGN=o);
+        err
+    }
+
+    fn closure_cannot_assign_to_borrowed(&self,
+                                         span: Span,
+                                         descr: &str,
+                                         o: Origin)
+                                         -> DiagnosticBuilder
+    {
+        let err = struct_span_err!(self, span, E0595, "closure cannot assign to {}{OGN}",
+                                   descr, OGN=o);
+        err
+    }
+
+    fn cannot_borrow_path_as_mutable(&self,
+                                     span: Span,
+                                     path: &str,
+                                     o: Origin)
+                                     -> DiagnosticBuilder
+    {
+        let err = struct_span_err!(self, span, E0596, "cannot borrow {} as mutable{OGN}",
+                                   path, OGN=o);
+        err
+    }
+
+    fn cannot_borrow_across_generator_yield(&self,
+                                            span: Span,
+                                            yield_span: Span,
+                                            o: Origin)
+                                            -> DiagnosticBuilder
+    {
+        let mut err = struct_span_err!(self,
+                                       span,
+                                       E0626,
+                                       "borrow may still be in use when generator yields{OGN}",
+                                       OGN=o);
+        err.span_label(yield_span, "possible yield occurs here");
+        err
+    }
+
+    fn path_does_not_live_long_enough(&self,
+                                      span: Span,
+                                      path: &str,
+                                      o: Origin)
+                                      -> DiagnosticBuilder
+    {
+        let err = struct_span_err!(self, span, E0597, "{} does not live long enough{OGN}",
+                                   path, OGN=o);
+        err
+    }
+
+    fn lifetime_too_short_for_reborrow(&self,
+                                       span: Span,
+                                       path: &str,
+                                       o: Origin)
+                                       -> DiagnosticBuilder
+    {
+        let err = struct_span_err!(self, span, E0598,
+                                   "lifetime of {} is too short to guarantee \
+                                    its contents can be safely reborrowed{OGN}",
+                                   path, OGN=o);
+        err
+    }
+
+    fn cannot_act_on_capture_in_sharable_fn(&self,
+                                            span: Span,
+                                            bad_thing: &str,
+                                            help: (Span, &str),
+                                            o: Origin)
+                                            -> DiagnosticBuilder
+    {
+        let (help_span, help_msg) = help;
+        let mut err = struct_span_err!(self, span, E0387,
+                                       "{} in a captured outer variable in an `Fn` closure{OGN}",
+                                       bad_thing, OGN=o);
+        err.span_help(help_span, help_msg);
+        err
+    }
+
+    fn cannot_assign_into_immutable_reference(&self,
+                                              span: Span,
+                                              bad_thing: &str,
+                                              o: Origin)
+                                              -> DiagnosticBuilder
+    {
+        let mut err = struct_span_err!(self, span, E0389, "{} in a `&` reference{OGN}",
+                                       bad_thing, OGN=o);
+        err.span_label(span, "assignment into an immutable reference");
+        err
+    }
+
+    fn cannot_capture_in_long_lived_closure(&self,
+                                            closure_span: Span,
+                                            borrowed_path: &str,
+                                            capture_span: Span,
+                                            o: Origin)
+                                            -> DiagnosticBuilder
+    {
+        let mut err = struct_span_err!(self, closure_span, E0373,
+                                       "closure may outlive the current function, \
+                                        but it borrows {}, \
+                                        which is owned by the current function{OGN}",
+                                       borrowed_path, OGN=o);
+        err.span_label(capture_span, format!("{} is borrowed here", borrowed_path))
+            .span_label(closure_span, format!("may outlive borrowed value {}", borrowed_path));
+        err
+    }
 }
 
 impl<'b, 'tcx, 'gcx> BorrowckErrors for TyCtxt<'b, 'tcx, 'gcx> {
index efb5b0318099822877662560b6fe457ecbd971f6..14e33378969aaa8cd25d1f091917fe7e1740acb2 100644 (file)
@@ -152,7 +152,7 @@ fn visit_ty(&mut self, ty: &'a Ty) {
                     err.emit();
                 });
             }
-            TyKind::TraitObject(ref bounds) => {
+            TyKind::TraitObject(ref bounds, ..) => {
                 let mut any_lifetime_bounds = false;
                 for bound in bounds {
                     if let RegionTyParamBound(ref lifetime) = *bound {
index 9193ac0fcd66e3fe4cee952cd201b8c731b5dacf..564626ac39885328089f8be721805ed6e8045981 100644 (file)
@@ -43,7 +43,7 @@ struct Foo<U=(), T=U> {
 "##,
 
 E0154: r##"
-## Note: this error code is no longer emitted by the compiler.
+#### Note: this error code is no longer emitted by the compiler.
 
 Imports (`use` statements) are not allowed after non-item statements, such as
 variable declarations and expression statements.
@@ -79,7 +79,7 @@ fn f() {
 "##,
 
 E0251: r##"
-## Note: this error code is no longer emitted by the compiler.
+#### Note: this error code is no longer emitted by the compiler.
 
 Two items of the same name cannot be imported without rebinding one of the
 items under a new local name.
@@ -268,7 +268,7 @@ fn main() {
 "##,
 
 E0256: r##"
-## Note: this error code is no longer emitted by the compiler.
+#### Note: this error code is no longer emitted by the compiler.
 
 You can't import a type or module when the name of the item being imported is
 the same as another type or submodule defined in the module.
index c7e00245d63502b6b883ac079f79ff9cbfe1c636..47e5ad6c0108834a427f7d8e6331c4cd73229c2f 100644 (file)
@@ -288,7 +288,7 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext) ->
                     })
                 }
             }
-            ast::TyKind::TraitObject(ref bounds) => {
+            ast::TyKind::TraitObject(ref bounds, ..) => {
                 // FIXME recurse into bounds
                 let nested = pprust::bounds_to_string(bounds);
                 Ok(text_sig(nested))
index 482350d04b5a72e539aa21c615900f9ee0cb843d..5b7879ea58ee7e88de2b444d2f112c8c34811f27 100644 (file)
@@ -32,4 +32,4 @@ syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
 
 [target."cfg(windows)".dependencies]
-cc = "1.0"
+cc = "1.0.1"
index 8f75b891a302c9dd765c4ee7d4a64fc8051d2822..01d3d656dfe19677600d6e9fd2f419de4af0934e 100644 (file)
@@ -130,6 +130,7 @@ pub fn run(cgcx: &CodegenContext,
         .filter_map(symbol_filter)
         .collect::<Vec<CString>>();
     timeline.record("whitelist");
+    info!("{} symbols to preserve in this crate", symbol_white_list.len());
 
     // If we're performing LTO for the entire crate graph, then for each of our
     // upstream dependencies, find the corresponding rlib and load the bitcode
@@ -437,7 +438,24 @@ fn run_pass_manager(cgcx: &CodegenContext,
         assert!(!pass.is_null());
         llvm::LLVMRustAddPass(pm, pass);
 
-        with_llvm_pmb(llmod, config, &mut |b| {
+        // When optimizing for LTO we don't actually pass in `-O0`, but we force
+        // it to always happen at least with `-O1`.
+        //
+        // With ThinLTO we mess around a lot with symbol visibility in a way
+        // that will actually cause linking failures if we optimize at O0 which
+        // notable is lacking in dead code elimination. To ensure we at least
+        // get some optimizations and correctly link we forcibly switch to `-O1`
+        // to get dead code elimination.
+        //
+        // Note that in general this shouldn't matter too much as you typically
+        // only turn on ThinLTO when you're compiling with optimizations
+        // otherwise.
+        let opt_level = config.opt_level.unwrap_or(llvm::CodeGenOptLevel::None);
+        let opt_level = match opt_level {
+            llvm::CodeGenOptLevel::None => llvm::CodeGenOptLevel::Less,
+            level => level,
+        };
+        with_llvm_pmb(llmod, config, opt_level, &mut |b| {
             if thin {
                 if !llvm::LLVMRustPassManagerBuilderPopulateThinLTOPassManager(b, pm) {
                     panic!("this version of LLVM does not support ThinLTO");
index 9d914243ec6e21958ade8281a7592ccd2be82d25..f7e0ad029afafd8a87717553e4340db00c35c38a 100644 (file)
@@ -217,7 +217,7 @@ pub struct ModuleConfig {
     passes: Vec<String>,
     /// Some(level) to optimize at a certain level, or None to run
     /// absolutely no optimizations (used for the metadata module).
-    opt_level: Option<llvm::CodeGenOptLevel>,
+    pub opt_level: Option<llvm::CodeGenOptLevel>,
 
     /// Some(level) to optimize binary size, or None to not affect program size.
     opt_size: Option<llvm::CodeGenOptSize>,
@@ -507,7 +507,8 @@ unsafe fn optimize(cgcx: &CodegenContext,
         if !config.no_prepopulate_passes {
             llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod);
             llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod);
-            with_llvm_pmb(llmod, &config, &mut |b| {
+            let opt_level = config.opt_level.unwrap_or(llvm::CodeGenOptLevel::None);
+            with_llvm_pmb(llmod, &config, opt_level, &mut |b| {
                 llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(b, fpm);
                 llvm::LLVMPassManagerBuilderPopulateModulePassManager(b, mpm);
             })
@@ -1842,16 +1843,17 @@ pub fn run_assembler(sess: &Session, outputs: &OutputFilenames) {
 
 pub unsafe fn with_llvm_pmb(llmod: ModuleRef,
                             config: &ModuleConfig,
+                            opt_level: llvm::CodeGenOptLevel,
                             f: &mut FnMut(llvm::PassManagerBuilderRef)) {
     // Create the PassManagerBuilder for LLVM. We configure it with
     // reasonable defaults and prepare it to actually populate the pass
     // manager.
     let builder = llvm::LLVMPassManagerBuilderCreate();
-    let opt_level = config.opt_level.unwrap_or(llvm::CodeGenOptLevel::None);
     let opt_size = config.opt_size.unwrap_or(llvm::CodeGenOptSizeNone);
     let inline_threshold = config.inline_threshold;
 
-    llvm::LLVMRustConfigurePassManagerBuilder(builder, opt_level,
+    llvm::LLVMRustConfigurePassManagerBuilder(builder,
+                                              opt_level,
                                               config.merge_functions,
                                               config.vectorize_slp,
                                               config.vectorize_loop);
index 7461df8bda509b1d66ed57cfc68ce0065ccb983f..91ce4511a31cb3fe386a403ac4096db1ac56f9b5 100644 (file)
@@ -271,6 +271,7 @@ fn confirm_builtin_call(&self,
                                             fn_sig.output(),
                                             fn_sig.inputs());
         self.check_argument_types(call_expr.span,
+                                  call_expr.span,
                                   fn_sig.inputs(),
                                   &expected_arg_tys[..],
                                   arg_exprs,
@@ -298,6 +299,7 @@ fn confirm_deferred_closure_call(&self,
                                                                fn_sig.inputs());
 
         self.check_argument_types(call_expr.span,
+                                  call_expr.span,
                                   fn_sig.inputs(),
                                   &expected_arg_tys,
                                   arg_exprs,
@@ -315,6 +317,7 @@ fn confirm_overloaded_call(&self,
                                method_callee: MethodCallee<'tcx>)
                                -> Ty<'tcx> {
         let output_type = self.check_method_argument_types(call_expr.span,
+                                                           call_expr.span,
                                                            Ok(method_callee),
                                                            arg_exprs,
                                                            TupleArgumentsFlag::TupleArguments,
index 9c6a4abfbd7c0295c0d77fdf239537bf931bd519..6e263bdb1ad80281d4a9cddf1b91417f64c9087a 100644 (file)
@@ -728,7 +728,7 @@ fn typeck_item_bodies<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum
     debug_assert!(crate_num == LOCAL_CRATE);
     Ok(tcx.sess.track_errors(|| {
         for body_owner_def_id in tcx.body_owners() {
-            tcx.typeck_tables_of(body_owner_def_id);
+            ty::maps::queries::typeck_tables_of::ensure(tcx, body_owner_def_id);
         }
     })?)
 }
@@ -2352,6 +2352,7 @@ fn try_overloaded_lvalue_op(&self,
 
     fn check_method_argument_types(&self,
                                    sp: Span,
+                                   expr_sp: Span,
                                    method: Result<MethodCallee<'tcx>, ()>,
                                    args_no_rcvr: &'gcx [hir::Expr],
                                    tuple_arguments: TupleArgumentsFlag,
@@ -2371,7 +2372,7 @@ fn check_method_argument_types(&self,
                 TupleArguments => vec![self.tcx.intern_tup(&err_inputs[..], false)],
             };
 
-            self.check_argument_types(sp, &err_inputs[..], &[], args_no_rcvr,
+            self.check_argument_types(sp, expr_sp, &err_inputs[..], &[], args_no_rcvr,
                                       false, tuple_arguments, None);
             return self.tcx.types.err;
         }
@@ -2384,7 +2385,7 @@ fn check_method_argument_types(&self,
             method.sig.output(),
             &method.sig.inputs()[1..]
         );
-        self.check_argument_types(sp, &method.sig.inputs()[1..], &expected_arg_tys[..],
+        self.check_argument_types(sp, expr_sp, &method.sig.inputs()[1..], &expected_arg_tys[..],
                                   args_no_rcvr, method.sig.variadic, tuple_arguments,
                                   self.tcx.hir.span_if_local(method.def_id));
         method.sig.output()
@@ -2394,6 +2395,7 @@ fn check_method_argument_types(&self,
     /// method calls and overloaded operators.
     fn check_argument_types(&self,
                             sp: Span,
+                            expr_sp: Span,
                             fn_inputs: &[Ty<'tcx>],
                             expected_arg_tys: &[Ty<'tcx>],
                             args: &'gcx [hir::Expr],
@@ -2434,9 +2436,15 @@ fn check_argument_types(&self,
             sp
         };
 
-        fn parameter_count_error<'tcx>(sess: &Session, sp: Span, expected_count: usize,
-                                       arg_count: usize, error_code: &str, variadic: bool,
-                                       def_span: Option<Span>, sugg_unit: bool) {
+        fn parameter_count_error<'tcx>(sess: &Session,
+                                       sp: Span,
+                                       expr_sp: Span,
+                                       expected_count: usize,
+                                       arg_count: usize,
+                                       error_code: &str,
+                                       variadic: bool,
+                                       def_span: Option<Span>,
+                                       sugg_unit: bool) {
             let mut err = sess.struct_span_err_with_code(sp,
                 &format!("this function takes {}{} parameter{} but {} parameter{} supplied",
                     if variadic {"at least "} else {""},
@@ -2450,12 +2458,12 @@ fn parameter_count_error<'tcx>(sess: &Session, sp: Span, expected_count: usize,
                 err.span_label(def_s, "defined here");
             }
             if sugg_unit {
-                let sugg_span = sp.end_point();
+                let sugg_span = expr_sp.end_point();
                 // remove closing `)` from the span
                 let sugg_span = sugg_span.with_hi(sugg_span.lo());
                 err.span_suggestion(
                     sugg_span,
-                    "expected the unit value `()`. You can create one with a pair of parenthesis",
+                    "expected the unit value `()`; create it with empty parentheses",
                     String::from("()"));
             } else {
                 err.span_label(sp, format!("expected {}{} parameter{}",
@@ -2470,7 +2478,7 @@ fn parameter_count_error<'tcx>(sess: &Session, sp: Span, expected_count: usize,
             let tuple_type = self.structurally_resolved_type(sp, fn_inputs[0]);
             match tuple_type.sty {
                 ty::TyTuple(arg_types, _) if arg_types.len() != args.len() => {
-                    parameter_count_error(tcx.sess, sp_args, arg_types.len(), args.len(),
+                    parameter_count_error(tcx.sess, sp_args, expr_sp, arg_types.len(), args.len(),
                                           "E0057", false, def_span, false);
                     expected_arg_tys = &[];
                     self.err_args(args.len())
@@ -2499,7 +2507,7 @@ fn parameter_count_error<'tcx>(sess: &Session, sp: Span, expected_count: usize,
             if supplied_arg_count >= expected_arg_count {
                 fn_inputs.to_vec()
             } else {
-                parameter_count_error(tcx.sess, sp_args, expected_arg_count,
+                parameter_count_error(tcx.sess, sp_args, expr_sp, expected_arg_count,
                                       supplied_arg_count, "E0060", true, def_span, false);
                 expected_arg_tys = &[];
                 self.err_args(supplied_arg_count)
@@ -2513,7 +2521,7 @@ fn parameter_count_error<'tcx>(sess: &Session, sp: Span, expected_count: usize,
             } else {
                 false
             };
-            parameter_count_error(tcx.sess, sp_args, expected_arg_count,
+            parameter_count_error(tcx.sess, sp_args, expr_sp, expected_arg_count,
                                   supplied_arg_count, "E0061", false, def_span, sugg_unit);
             expected_arg_tys = &[];
             self.err_args(supplied_arg_count)
@@ -2866,7 +2874,9 @@ fn check_method_call(&self,
         };
 
         // Call the generic checker.
-        self.check_method_argument_types(span, method,
+        self.check_method_argument_types(span,
+                                         expr.span,
+                                         method,
                                          &args[1..],
                                          DontTupleArguments,
                                          expected)
index b295b414a035b1be6de36a55363f8cfc397debe0..e168222058f9a32b290d1424ede8c3cb376051a3 100644 (file)
@@ -18,4 +18,4 @@ html-diff = "0.0.4"
 
 [build-dependencies]
 build_helper = { path = "../build_helper" }
-cc = "1.0"
+cc = "1.0.1"
index d08a7bde71c73ae874480f87ccd8bb57145d5e33..873d978b9cb84b960cb58f47b099e32aafa884c8 100644 (file)
@@ -97,9 +97,9 @@ pub fn render<T: fmt::Display, S: fmt::Display>(
                     <dd>Show this help dialog</dd>
                     <dt>S</dt>
                     <dd>Focus the search field</dd>
-                    <dt>&larrb;</dt>
+                    <dt>↑</dt>
                     <dd>Move up in search results</dd>
-                    <dt>&rarrb;</dt>
+                    <dt>↓</dt>
                     <dd>Move down in search results</dd>
                     <dt>&#9166;</dt>
                     <dd>Go to active search result</dd>
index 967a19e0e968fb103a3d4e783b4a025a32d44667..3c789cb3a15939d3c50afa7d35356b8418e6c31f 100644 (file)
@@ -125,6 +125,21 @@ pub struct SharedContext {
     /// Warnings for the user if rendering would differ using different markdown
     /// parsers.
     pub markdown_warnings: RefCell<Vec<(Span, String, Vec<html_diff::Difference>)>>,
+    /// The directories that have already been created in this doc run. Used to reduce the number
+    /// of spurious `create_dir_all` calls.
+    pub created_dirs: RefCell<FxHashSet<PathBuf>>,
+}
+
+impl SharedContext {
+    fn ensure_dir(&self, dst: &Path) -> io::Result<()> {
+        let mut dirs = self.created_dirs.borrow_mut();
+        if !dirs.contains(dst) {
+            fs::create_dir_all(dst)?;
+            dirs.insert(dst.to_path_buf());
+        }
+
+        Ok(())
+    }
 }
 
 /// Indicates where an external crate can be found.
@@ -463,6 +478,7 @@ pub fn run(mut krate: clean::Crate,
         },
         css_file_extension: css_file_extension.clone(),
         markdown_warnings: RefCell::new(vec![]),
+        created_dirs: RefCell::new(FxHashSet()),
     };
 
     // If user passed in `--playground-url` arg, we fill in crate name here
@@ -794,7 +810,6 @@ fn write_shared(cx: &Context,
     // Write out the shared files. Note that these are shared among all rustdoc
     // docs placed in the output directory, so this needs to be a synchronized
     // operation with respect to all other rustdocs running around.
-    try_err!(fs::create_dir_all(&cx.dst), &cx.dst);
     let _lock = flock::Lock::panicking_new(&cx.dst.join(".lock"), true, true, true);
 
     // Add all the static files. These may already exist, but we just
@@ -1518,8 +1533,8 @@ fn item<F>(&mut self, item: clean::Item, mut f: F) -> Result<(), Error> where
                 this.render_item(&mut buf, &item, false).unwrap();
                 // buf will be empty if the module is stripped and there is no redirect for it
                 if !buf.is_empty() {
+                    try_err!(this.shared.ensure_dir(&this.dst), &this.dst);
                     let joint_dst = this.dst.join("index.html");
-                    try_err!(fs::create_dir_all(&this.dst), &this.dst);
                     let mut dst = try_err!(File::create(&joint_dst), &joint_dst);
                     try_err!(dst.write_all(&buf), &joint_dst);
                 }
@@ -1553,8 +1568,8 @@ fn item<F>(&mut self, item: clean::Item, mut f: F) -> Result<(), Error> where
                 let name = item.name.as_ref().unwrap();
                 let item_type = item.type_();
                 let file_name = &item_path(item_type, name);
+                try_err!(self.shared.ensure_dir(&self.dst), &self.dst);
                 let joint_dst = self.dst.join(file_name);
-                try_err!(fs::create_dir_all(&self.dst), &self.dst);
                 let mut dst = try_err!(File::create(&joint_dst), &joint_dst);
                 try_err!(dst.write_all(&buf), &joint_dst);
 
@@ -1562,9 +1577,10 @@ fn item<F>(&mut self, item: clean::Item, mut f: F) -> Result<(), Error> where
                 // URL for the page.
                 let redir_name = format!("{}.{}.html", name, item_type.name_space());
                 let redir_dst = self.dst.join(redir_name);
-                if let Ok(mut redirect_out) = OpenOptions::new().create_new(true)
+                if let Ok(redirect_out) = OpenOptions::new().create_new(true)
                                                                 .write(true)
                                                                 .open(&redir_dst) {
+                    let mut redirect_out = BufWriter::new(redirect_out);
                     try_err!(layout::redirect(&mut redirect_out, file_name), &redir_dst);
                 }
 
@@ -1574,7 +1590,8 @@ fn item<F>(&mut self, item: clean::Item, mut f: F) -> Result<(), Error> where
                 if item_type == ItemType::Macro {
                     let redir_name = format!("{}.{}!.html", item_type, name);
                     let redir_dst = self.dst.join(redir_name);
-                    let mut redirect_out = try_err!(File::create(&redir_dst), &redir_dst);
+                    let redirect_out = try_err!(File::create(&redir_dst), &redir_dst);
+                    let mut redirect_out = BufWriter::new(redirect_out);
                     try_err!(layout::redirect(&mut redirect_out, file_name), &redir_dst);
                 }
             }
index 9e2798f1cf71abd0faff9dae5d6a9f5d1d1fa120..a132223a051017a90956060d345a6487da152ae7 100644 (file)
@@ -831,6 +831,10 @@ span.since {
        .toggle-wrapper {
                height: 1.5em;
        }
+
+       #search {
+               margin-left: 0;
+       }
 }
 
 @media print {
index f8bf00ad73fcca1fb9fc417e80978d6a47e1e619..890e1169c05918e1ea8a9024fe11acd39602cebe 100644 (file)
@@ -246,6 +246,9 @@ pub fn opts() -> Vec<RustcOptGroup> {
         unstable("crate-version", |o| {
             o.optopt("", "crate-version", "crate version to print into documentation", "VERSION")
         }),
+        unstable("linker", |o| {
+            o.optopt("", "linker", "linker used for building executable test code", "PATH")
+        }),
     ]
 }
 
@@ -357,15 +360,16 @@ pub fn main_args(args: &[String]) -> isize {
     let playground_url = matches.opt_str("playground-url");
     let maybe_sysroot = matches.opt_str("sysroot").map(PathBuf::from);
     let display_warnings = matches.opt_present("display-warnings");
+    let linker = matches.opt_str("linker");
 
     match (should_test, markdown_input) {
         (true, true) => {
             return markdown::test(input, cfgs, libs, externs, test_args, maybe_sysroot, render_type,
-                                  display_warnings)
+                                  display_warnings, linker)
         }
         (true, false) => {
             return test::run(input, cfgs, libs, externs, test_args, crate_name, maybe_sysroot,
-                             render_type, display_warnings)
+                             render_type, display_warnings, linker)
         }
         (false, true) => return markdown::render(input,
                                                  output.unwrap_or(PathBuf::from("doc")),
index 484285e91f6e9093564c7b85b06f1fa1d3a225c1..fe6bd985bb6181fc5c65f8eaf22a2746d7458fbe 100644 (file)
@@ -142,7 +142,7 @@ pub fn render(input: &str, mut output: PathBuf, matches: &getopts::Matches,
 /// Run any tests/code examples in the markdown file `input`.
 pub fn test(input: &str, cfgs: Vec<String>, libs: SearchPaths, externs: Externs,
             mut test_args: Vec<String>, maybe_sysroot: Option<PathBuf>,
-            render_type: RenderType, display_warnings: bool) -> isize {
+            render_type: RenderType, display_warnings: bool, linker: Option<String>) -> isize {
     let input_str = match load_string(input) {
         Ok(s) => s,
         Err(LoadStringError::ReadFail) => return 1,
@@ -154,7 +154,7 @@ pub fn test(input: &str, cfgs: Vec<String>, libs: SearchPaths, externs: Externs,
     let mut collector = Collector::new(input.to_string(), cfgs, libs, externs,
                                        true, opts, maybe_sysroot, None,
                                        Some(input.to_owned()),
-                                       render_type);
+                                       render_type, linker);
     if render_type == RenderType::Pulldown {
         old_find_testable_code(&input_str, &mut collector, DUMMY_SP);
         find_testable_code(&input_str, &mut collector, DUMMY_SP);
index 09565dd7664c2f98872634231a5dbca9f867b679..8b2c8d2da395a1f87074507b17e8cb2118d04e49 100644 (file)
@@ -61,7 +61,8 @@ pub fn run(input: &str,
            crate_name: Option<String>,
            maybe_sysroot: Option<PathBuf>,
            render_type: RenderType,
-           display_warnings: bool)
+           display_warnings: bool,
+           linker: Option<String>)
            -> isize {
     let input_path = PathBuf::from(input);
     let input = config::Input::File(input_path.clone());
@@ -121,7 +122,8 @@ pub fn run(input: &str,
                                        maybe_sysroot,
                                        Some(codemap),
                                        None,
-                                       render_type);
+                                       render_type,
+                                       linker);
 
     {
         let map = hir::map::map_crate(&sess, &*cstore, &mut hir_forest, &defs);
@@ -180,7 +182,8 @@ fn run_test(test: &str, cratename: &str, filename: &str, cfgs: Vec<String>, libs
             externs: Externs,
             should_panic: bool, no_run: bool, as_test_harness: bool,
             compile_fail: bool, mut error_codes: Vec<String>, opts: &TestOptions,
-            maybe_sysroot: Option<PathBuf>) {
+            maybe_sysroot: Option<PathBuf>,
+            linker: Option<String>) {
     // the test harness wants its own `main` & top level functions, so
     // never wrap the test in `fn main() { ... }`
     let test = make_test(test, Some(cratename), as_test_harness, opts);
@@ -201,6 +204,7 @@ fn run_test(test: &str, cratename: &str, filename: &str, cfgs: Vec<String>, libs
         externs,
         cg: config::CodegenOptions {
             prefer_dynamic: true,
+            linker,
             .. config::basic_codegen_options()
         },
         test: as_test_harness,
@@ -407,13 +411,33 @@ pub struct Collector {
     pub tests: Vec<testing::TestDescAndFn>,
     // to be removed when hoedown will be definitely gone
     pub old_tests: HashMap<String, Vec<String>>,
+
+    // The name of the test displayed to the user, separated by `::`.
+    //
+    // In tests from Rust source, this is the path to the item
+    // e.g. `["std", "vec", "Vec", "push"]`.
+    //
+    // In tests from a markdown file, this is the titles of all headers (h1~h6)
+    // of the sections that contain the code block, e.g. if the markdown file is
+    // written as:
+    //
+    // ``````markdown
+    // # Title
+    //
+    // ## Subtitle
+    //
+    // ```rust
+    // assert!(true);
+    // ```
+    // ``````
+    //
+    // the `names` vector of that test will be `["Title", "Subtitle"]`.
     names: Vec<String>,
+
     cfgs: Vec<String>,
     libs: SearchPaths,
     externs: Externs,
-    cnt: usize,
     use_headers: bool,
-    current_header: Option<String>,
     cratename: String,
     opts: TestOptions,
     maybe_sysroot: Option<PathBuf>,
@@ -422,13 +446,14 @@ pub struct Collector {
     filename: Option<String>,
     // to be removed when hoedown will be removed as well
     pub render_type: RenderType,
+    linker: Option<String>,
 }
 
 impl Collector {
     pub fn new(cratename: String, cfgs: Vec<String>, libs: SearchPaths, externs: Externs,
                use_headers: bool, opts: TestOptions, maybe_sysroot: Option<PathBuf>,
                codemap: Option<Rc<CodeMap>>, filename: Option<String>,
-               render_type: RenderType) -> Collector {
+               render_type: RenderType, linker: Option<String>) -> Collector {
         Collector {
             tests: Vec::new(),
             old_tests: HashMap::new(),
@@ -436,9 +461,7 @@ pub fn new(cratename: String, cfgs: Vec<String>, libs: SearchPaths, externs: Ext
             cfgs,
             libs,
             externs,
-            cnt: 0,
             use_headers,
-            current_header: None,
             cratename,
             opts,
             maybe_sysroot,
@@ -446,32 +469,17 @@ pub fn new(cratename: String, cfgs: Vec<String>, libs: SearchPaths, externs: Ext
             codemap,
             filename,
             render_type,
+            linker,
         }
     }
 
     fn generate_name(&self, line: usize, filename: &str) -> String {
-        if self.use_headers {
-            if let Some(ref header) = self.current_header {
-                format!("{} - {} (line {})", filename, header, line)
-            } else {
-                format!("{} - (line {})", filename, line)
-            }
-        } else {
-            format!("{} - {} (line {})", filename, self.names.join("::"), line)
-        }
+        format!("{} - {} (line {})", filename, self.names.join("::"), line)
     }
 
     // to be removed once hoedown is gone
     fn generate_name_beginning(&self, filename: &str) -> String {
-        if self.use_headers {
-            if let Some(ref header) = self.current_header {
-                format!("{} - {} (line", filename, header)
-            } else {
-                format!("{} - (line", filename)
-            }
-        } else {
-            format!("{} - {} (line", filename, self.names.join("::"))
-        }
+        format!("{} - {} (line", filename, self.names.join("::"))
     }
 
     pub fn add_old_test(&mut self, test: String, filename: String) {
@@ -508,6 +516,7 @@ pub fn add_test(&mut self, test: String,
         let cratename = self.cratename.to_string();
         let opts = self.opts.clone();
         let maybe_sysroot = self.maybe_sysroot.clone();
+        let linker = self.linker.clone();
         debug!("Creating test {}: {}", name, test);
         self.tests.push(testing::TestDescAndFn {
             desc: testing::TestDesc {
@@ -536,7 +545,8 @@ pub fn add_test(&mut self, test: String,
                                  compile_fail,
                                  error_codes,
                                  &opts,
-                                 maybe_sysroot)
+                                 maybe_sysroot,
+                                 linker)
                     })
                 } {
                     Ok(()) => (),
@@ -579,7 +589,7 @@ pub fn get_filename(&self) -> String {
     }
 
     pub fn register_header(&mut self, name: &str, level: u32) {
-        if self.use_headers && level == 1 {
+        if self.use_headers {
             // we use these headings as test names, so it's good if
             // they're valid identifiers.
             let name = name.chars().enumerate().map(|(i, c)| {
@@ -591,9 +601,28 @@ pub fn register_header(&mut self, name: &str, level: u32) {
                     }
                 }).collect::<String>();
 
-            // new header => reset count.
-            self.cnt = 0;
-            self.current_header = Some(name);
+            // Here we try to efficiently assemble the header titles into the
+            // test name in the form of `h1::h2::h3::h4::h5::h6`.
+            //
+            // Suppose originally `self.names` contains `[h1, h2, h3]`...
+            let level = level as usize;
+            if level <= self.names.len() {
+                // ... Consider `level == 2`. All headers in the lower levels
+                // are irrelevant in this new level. So we should reset
+                // `self.names` to contain headers until <h2>, and replace that
+                // slot with the new name: `[h1, name]`.
+                self.names.truncate(level);
+                self.names[level - 1] = name;
+            } else {
+                // ... On the other hand, consider `level == 5`. This means we
+                // need to extend `self.names` to contain five headers. We fill
+                // in the missing level (<h4>) with `_`. Thus `self.names` will
+                // become `[h1, h2, h3, "_", name]`.
+                if level - 1 > self.names.len() {
+                    self.names.resize(level - 1, "_".to_owned());
+                }
+                self.names.push(name);
+            }
         }
     }
 }
@@ -624,7 +653,6 @@ fn visit_testable<F: FnOnce(&mut Self)>(&mut self,
         attrs.collapse_doc_comments();
         attrs.unindent_doc_comments();
         if let Some(doc) = attrs.doc_value() {
-            self.collector.cnt = 0;
             if self.collector.render_type == RenderType::Pulldown {
                 markdown::old_find_testable_code(doc, self.collector,
                                                  attrs.span.unwrap_or(DUMMY_SP));
index fb276448ffac4d126c10f9c55e3802e411868aa2..866c0038a7fd9b5b501456c3987d2a216cfc5748 100644 (file)
@@ -36,7 +36,6 @@ rustc_tsan = { path = "../librustc_tsan" }
 
 [build-dependencies]
 build_helper = { path = "../build_helper" }
-cc = "1.0"
 
 [features]
 backtrace = []
index 7ca762c801a814a0e5186f2be6171a565d82c60e..0e6214ea04fc0a20a939fae3b739f44b2b6913a4 100644 (file)
@@ -11,7 +11,6 @@
 #![deny(warnings)]
 
 extern crate build_helper;
-extern crate cc;
 
 use std::env;
 use std::process::Command;
@@ -77,12 +76,6 @@ fn main() {
 fn build_libbacktrace(host: &str, target: &str) -> Result<(), ()> {
     let native = native_lib_boilerplate("libbacktrace", "libbacktrace", "backtrace", ".libs")?;
 
-    let compiler = cc::Build::new().get_compiler();
-    // only msvc returns None for ar so unwrap is okay
-    let ar = build_helper::cc2ar(compiler.path(), target).unwrap();
-    let mut cflags = compiler.args().iter().map(|s| s.to_str().unwrap())
-                             .collect::<Vec<_>>().join(" ");
-    cflags.push_str(" -fvisibility=hidden");
     run(Command::new("sh")
                 .current_dir(&native.out_dir)
                 .arg(native.src_dir.join("configure").to_str().unwrap()
@@ -94,10 +87,7 @@ fn build_libbacktrace(host: &str, target: &str) -> Result<(), ()> {
                 .arg("--disable-host-shared")
                 .arg(format!("--host={}", build_helper::gnu_target(target)))
                 .arg(format!("--build={}", build_helper::gnu_target(host)))
-                .env("CC", compiler.path())
-                .env("AR", &ar)
-                .env("RANLIB", format!("{} s", ar.display()))
-                .env("CFLAGS", cflags),
+                .env("CFLAGS", env::var("CFLAGS").unwrap_or_default() + " -fvisibility=hidden"),
         BuildExpectation::None);
 
     run(Command::new(build_helper::make(host))
index 93929637e2f1e247eb73c4d2958fddc1fc578aab..7e623a0af17c3c1bab2db1c7948cb2b5f3974aad 100644 (file)
@@ -717,26 +717,25 @@ fn calculate_offsets(hashes_size: usize,
     (pairs_offset, end_of_pairs, oflo)
 }
 
-// Returns a tuple of (minimum required malloc alignment, hash_offset,
+// Returns a tuple of (minimum required malloc alignment,
 // array_size), from the start of a mallocated array.
 fn calculate_allocation(hash_size: usize,
                         hash_align: usize,
                         pairs_size: usize,
                         pairs_align: usize)
-                        -> (usize, usize, usize, bool) {
-    let hash_offset = 0;
+                        -> (usize, usize, bool) {
     let (_, end_of_pairs, oflo) = calculate_offsets(hash_size, pairs_size, pairs_align);
 
     let align = cmp::max(hash_align, pairs_align);
 
-    (align, hash_offset, end_of_pairs, oflo)
+    (align, end_of_pairs, oflo)
 }
 
 #[test]
 fn test_offset_calculation() {
-    assert_eq!(calculate_allocation(128, 8, 16, 8), (8, 0, 144, false));
-    assert_eq!(calculate_allocation(3, 1, 2, 1), (1, 0, 5, false));
-    assert_eq!(calculate_allocation(6, 2, 12, 4), (4, 0, 20, false));
+    assert_eq!(calculate_allocation(128, 8, 16, 8), (8, 144, false));
+    assert_eq!(calculate_allocation(3, 1, 2, 1), (1, 5, false));
+    assert_eq!(calculate_allocation(6, 2, 12, 4), (4, 20, false));
     assert_eq!(calculate_offsets(128, 15, 4), (128, 143, false));
     assert_eq!(calculate_offsets(3, 2, 4), (4, 6, false));
     assert_eq!(calculate_offsets(6, 12, 4), (8, 20, false));
@@ -768,10 +767,10 @@ unsafe fn new_uninitialized(capacity: usize) -> RawTable<K, V> {
         // This is great in theory, but in practice getting the alignment
         // right is a little subtle. Therefore, calculating offsets has been
         // factored out into a different function.
-        let (alignment, hash_offset, size, oflo) = calculate_allocation(hashes_size,
-                                                                        align_of::<HashUint>(),
-                                                                        pairs_size,
-                                                                        align_of::<(K, V)>());
+        let (alignment, size, oflo) = calculate_allocation(hashes_size,
+                                                           align_of::<HashUint>(),
+                                                           pairs_size,
+                                                           align_of::<(K, V)>());
         assert!(!oflo, "capacity overflow");
 
         // One check for overflow that covers calculation and rounding of size.
@@ -784,7 +783,7 @@ unsafe fn new_uninitialized(capacity: usize) -> RawTable<K, V> {
         let buffer = Heap.alloc(Layout::from_size_align(size, alignment).unwrap())
             .unwrap_or_else(|e| Heap.oom(e));
 
-        let hashes = buffer.offset(hash_offset as isize) as *mut HashUint;
+        let hashes = buffer as *mut HashUint;
 
         RawTable {
             capacity_mask: capacity.wrapping_sub(1),
@@ -1157,6 +1156,7 @@ fn clone(&self) -> RawTable<K, V> {
             }
 
             new_ht.size = self.size();
+            new_ht.set_tag(self.tag());
 
             new_ht
         }
@@ -1183,10 +1183,10 @@ fn drop(&mut self) {
 
         let hashes_size = self.capacity() * size_of::<HashUint>();
         let pairs_size = self.capacity() * size_of::<(K, V)>();
-        let (align, _, size, oflo) = calculate_allocation(hashes_size,
-                                                          align_of::<HashUint>(),
-                                                          pairs_size,
-                                                          align_of::<(K, V)>());
+        let (align, size, oflo) = calculate_allocation(hashes_size,
+                                                       align_of::<HashUint>(),
+                                                       pairs_size,
+                                                       align_of::<(K, V)>());
 
         debug_assert!(!oflo, "should be impossible");
 
index b904641a336ba1bcf6e75a2e3101a4cbd35a880f..4656cc5a7a78137aec9eb51c5c5eeab96083b4d2 100644 (file)
@@ -1579,6 +1579,21 @@ fn connect_timeout_unroutable() {
                 "bad error: {} {:?}", e, e.kind());
     }
 
+    #[test]
+    fn connect_timeout_unbound() {
+        // bind and drop a socket to track down a "probably unassigned" port
+        let socket = TcpListener::bind("127.0.0.1:0").unwrap();
+        let addr = socket.local_addr().unwrap();
+        drop(socket);
+
+        let timeout = Duration::from_secs(1);
+        let e = TcpStream::connect_timeout(&addr, timeout).unwrap_err();
+        assert!(e.kind() == io::ErrorKind::ConnectionRefused ||
+                e.kind() == io::ErrorKind::TimedOut ||
+                e.kind() == io::ErrorKind::Other,
+                "bad error: {} {:?}", e, e.kind());
+    }
+
     #[test]
     fn connect_timeout_valid() {
         let listener = TcpListener::bind("127.0.0.1:0").unwrap();
index 7d8ce4154fbfc073b5a187d433ae4085c0840337..f448cffd3725c30ae6709205aa1f87976cbf710a 100644 (file)
@@ -702,6 +702,15 @@ fn as_inner_mut(&mut self) -> &mut imp::Command { &mut self.inner }
 }
 
 /// The output of a finished process.
+///
+/// This is returned in a Result by either the [`output`] method of a
+/// [`Command`], or the [`wait_with_output`] method of a [`Child`]
+/// process.
+///
+/// [`Command`]: struct.Command.html
+/// [`Child`]: struct.Child.html
+/// [`output`]: struct.Command.html#method.output
+/// [`wait_with_output`]: struct.Child.html#method.wait_with_output
 #[derive(PartialEq, Eq, Clone)]
 #[stable(feature = "process", since = "1.0.0")]
 pub struct Output {
index c8019d1c768c5d7bdd34a9564baa139f54adf203..e775f857f2b40a84b8df717f9ed6d30649a02b3c 100644 (file)
@@ -176,11 +176,16 @@ pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Resul
                 }
                 0 => {}
                 _ => {
-                    if pollfd.revents & libc::POLLOUT == 0 {
-                        if let Some(e) = self.take_error()? {
-                            return Err(e);
-                        }
+                    // linux returns POLLOUT|POLLERR|POLLHUP for refused connections (!), so look
+                    // for POLLHUP rather than read readiness
+                    if pollfd.revents & libc::POLLHUP != 0 {
+                        let e = self.take_error()?
+                            .unwrap_or_else(|| {
+                                io::Error::new(io::ErrorKind::Other, "no error set after POLLHUP")
+                            });
+                        return Err(e);
                     }
+
                     return Ok(());
                 }
             }
index 021f96aff8caf94ec84038a8dc999f02df86f61f..f445def9e0335182dbed2e0118e0a8f288098706 100644 (file)
@@ -1419,7 +1419,7 @@ pub enum TyKind {
     Path(Option<QSelf>, Path),
     /// A trait object type `Bound1 + Bound2 + Bound3`
     /// where `Bound` is a trait or a lifetime.
-    TraitObject(TyParamBounds),
+    TraitObject(TyParamBounds, TraitObjectSyntax),
     /// An `impl Bound1 + Bound2 + Bound3` type
     /// where `Bound` is a trait or a lifetime.
     ImplTrait(TyParamBounds),
@@ -1438,6 +1438,13 @@ pub enum TyKind {
     Err,
 }
 
+/// Syntax used to declare a trait object.
+#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum TraitObjectSyntax {
+    Dyn,
+    None,
+}
+
 /// Inline assembly dialect.
 ///
 /// E.g. `"intel"` as in `asm!("mov eax, 2" : "={eax}"(result) : : : "intel")``
index a2f29181a20d3ec5f423ddfb7f2efe173f16bd52..9060a613bc132d87f03f2300483046420bc62511 100644 (file)
@@ -398,6 +398,9 @@ pub fn new() -> Features {
 
     // Default match binding modes (RFC 2005)
     (active, match_default_bindings, "1.22.0", Some(42640)),
+
+    // Trait object syntax with `dyn` prefix
+    (active, dyn_trait, "1.22.0", Some(44662)),
 );
 
 declare_features! (
@@ -1417,6 +1420,10 @@ fn visit_ty(&mut self, ty: &'a ast::Ty) {
                 gate_feature_post!(&self, never_type, ty.span,
                                    "The `!` type is experimental");
             },
+            ast::TyKind::TraitObject(_, ast::TraitObjectSyntax::Dyn) => {
+                gate_feature_post!(&self, dyn_trait, ty.span,
+                                   "`dyn Trait` syntax is unstable");
+            }
             _ => {}
         }
         visit::walk_ty(self, ty)
index 03c47b71d02d717c223ec953233e6b8a309e6a8c..d7d491db71f05bfb449c7d5d21436a2da42de7be 100644 (file)
@@ -400,8 +400,8 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
             TyKind::Typeof(expr) => {
                 TyKind::Typeof(fld.fold_expr(expr))
             }
-            TyKind::TraitObject(bounds) => {
-                TyKind::TraitObject(bounds.move_map(|b| fld.fold_ty_param_bound(b)))
+            TyKind::TraitObject(bounds, syntax) => {
+                TyKind::TraitObject(bounds.move_map(|b| fld.fold_ty_param_bound(b)), syntax)
             }
             TyKind::ImplTrait(bounds) => {
                 TyKind::ImplTrait(bounds.move_map(|b| fld.fold_ty_param_bound(b)))
index 04e6cdcfe5820fe0197f73b0c46d8c5dbe8b8996..bd400ef6dd6dab9ecdbb0fd960171bc9c13ec94a 100644 (file)
@@ -33,7 +33,7 @@
 use ast::{VariantData, StructField};
 use ast::StrStyle;
 use ast::SelfKind;
-use ast::{TraitItem, TraitRef};
+use ast::{TraitItem, TraitRef, TraitObjectSyntax};
 use ast::{Ty, TyKind, TypeBinding, TyParam, TyParamBounds};
 use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
 use ast::{Visibility, WhereClause};
@@ -364,6 +364,13 @@ fn is_ident_or_underscore(t: &token::Token) -> bool {
     t.is_ident() || *t == token::Underscore
 }
 
+// Returns true if `IDENT t` can start a type - `IDENT::a::b`, `IDENT<u8, u8>`,
+// `IDENT<<u8 as Trait>::AssocTy>`, `IDENT(u8, u8) -> u8`.
+fn can_continue_type_after_ident(t: &token::Token) -> bool {
+    t == &token::ModSep || t == &token::Lt ||
+    t == &token::BinOp(token::Shl) || t == &token::OpenDelim(token::Paren)
+}
+
 /// Information about the path to a module.
 pub struct ModulePath {
     pub name: String,
@@ -1428,7 +1435,7 @@ fn parse_ty_common(&mut self, allow_plus: bool) -> PResult<'a, P<Ty>> {
                     TyKind::Path(None, ref path) if maybe_bounds => {
                         self.parse_remaining_bounds(Vec::new(), path.clone(), lo, true)?
                     }
-                    TyKind::TraitObject(ref bounds)
+                    TyKind::TraitObject(ref bounds, TraitObjectSyntax::None)
                             if maybe_bounds && bounds.len() == 1 && !trailing_plus => {
                         let path = match bounds[0] {
                             TraitTyParamBound(ref pt, ..) => pt.trait_ref.path.clone(),
@@ -1472,27 +1479,6 @@ fn parse_ty_common(&mut self, allow_plus: bool) -> PResult<'a, P<Ty>> {
         } else if self.eat(&token::Underscore) {
             // A type to be inferred `_`
             TyKind::Infer
-        } else if self.eat_lt() {
-            // Qualified path
-            let (qself, path) = self.parse_qpath(PathStyle::Type)?;
-            TyKind::Path(Some(qself), path)
-        } else if self.token.is_path_start() {
-            // Simple path
-            let path = self.parse_path(PathStyle::Type)?;
-            if self.eat(&token::Not) {
-                // Macro invocation in type position
-                let (_, tts) = self.expect_delimited_token_tree()?;
-                TyKind::Mac(respan(lo.to(self.span), Mac_ { path: path, tts: tts }))
-            } else {
-                // Just a type path or bound list (trait object type) starting with a trait.
-                //   `Type`
-                //   `Trait1 + Trait2 + 'a`
-                if allow_plus && self.check(&token::BinOp(token::Plus)) {
-                    self.parse_remaining_bounds(Vec::new(), path, lo, true)?
-                } else {
-                    TyKind::Path(None, path)
-                }
-            }
         } else if self.token_is_bare_fn_keyword() {
             // Function pointer type
             self.parse_ty_bare_fn(Vec::new())?
@@ -1512,10 +1498,37 @@ fn parse_ty_common(&mut self, allow_plus: bool) -> PResult<'a, P<Ty>> {
         } else if self.eat_keyword(keywords::Impl) {
             // FIXME: figure out priority of `+` in `impl Trait1 + Trait2` (#34511).
             TyKind::ImplTrait(self.parse_ty_param_bounds()?)
+        } else if self.check_keyword(keywords::Dyn) &&
+                  self.look_ahead(1, |t| t.can_begin_bound() && !can_continue_type_after_ident(t)) {
+            // FIXME: figure out priority of `+` in `dyn Trait1 + Trait2` (#34511).
+            self.bump(); // `dyn`
+            TyKind::TraitObject(self.parse_ty_param_bounds()?, TraitObjectSyntax::Dyn)
         } else if self.check(&token::Question) ||
-                  self.check_lifetime() && self.look_ahead(1, |t| t == &token::BinOp(token::Plus)){
+                  self.check_lifetime() && self.look_ahead(1, |t| t == &token::BinOp(token::Plus)) {
             // Bound list (trait object type)
-            TyKind::TraitObject(self.parse_ty_param_bounds_common(allow_plus)?)
+            TyKind::TraitObject(self.parse_ty_param_bounds_common(allow_plus)?,
+                                TraitObjectSyntax::None)
+        } else if self.eat_lt() {
+            // Qualified path
+            let (qself, path) = self.parse_qpath(PathStyle::Type)?;
+            TyKind::Path(Some(qself), path)
+        } else if self.token.is_path_start() {
+            // Simple path
+            let path = self.parse_path(PathStyle::Type)?;
+            if self.eat(&token::Not) {
+                // Macro invocation in type position
+                let (_, tts) = self.expect_delimited_token_tree()?;
+                TyKind::Mac(respan(lo.to(self.span), Mac_ { path: path, tts: tts }))
+            } else {
+                // Just a type path or bound list (trait object type) starting with a trait.
+                //   `Type`
+                //   `Trait1 + Trait2 + 'a`
+                if allow_plus && self.check(&token::BinOp(token::Plus)) {
+                    self.parse_remaining_bounds(Vec::new(), path, lo, true)?
+                } else {
+                    TyKind::Path(None, path)
+                }
+            }
         } else {
             let msg = format!("expected type, found {}", self.this_token_descr());
             return Err(self.fatal(&msg));
@@ -1538,7 +1551,7 @@ fn parse_remaining_bounds(&mut self, lifetime_defs: Vec<LifetimeDef>, path: ast:
             self.bump(); // `+`
             bounds.append(&mut self.parse_ty_param_bounds()?);
         }
-        Ok(TyKind::TraitObject(bounds))
+        Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None))
     }
 
     fn maybe_recover_from_bad_type_plus(&mut self, allow_plus: bool, ty: &Ty) -> PResult<'a, ()> {
@@ -4256,6 +4269,7 @@ fn warn_dotdoteq(&self, span: Span) {
     fn parse_ty_param_bounds_common(&mut self, allow_plus: bool) -> PResult<'a, TyParamBounds> {
         let mut bounds = Vec::new();
         loop {
+            // This needs to be syncronized with `Token::can_begin_bound`.
             let is_bound_start = self.check_path() || self.check_lifetime() ||
                                  self.check(&token::Question) ||
                                  self.check_keyword(keywords::For) ||
index 4888654fac9d0ed09c9454ee6f23b92731757b40..20db87cfc82d9849367418a197ed876691136aa0 100644 (file)
@@ -258,6 +258,12 @@ pub fn can_begin_type(&self) -> bool {
         }
     }
 
+    /// Returns `true` if the token can appear at the start of a generic bound.
+    pub fn can_begin_bound(&self) -> bool {
+        self.is_path_start() || self.is_lifetime() || self.is_keyword(keywords::For) ||
+        self == &Question || self == &OpenDelim(Paren)
+    }
+
     /// Returns `true` if the token is any literal
     pub fn is_lit(&self) -> bool {
         match *self {
index 959dd4ef30f29853506d4288199b5a14c0e44b0d..02f871c58c73cfb7065d05f8f34c98d16b656fbf 100644 (file)
@@ -1049,8 +1049,9 @@ pub fn print_type(&mut self, ty: &ast::Ty) -> io::Result<()> {
             ast::TyKind::Path(Some(ref qself), ref path) => {
                 self.print_qpath(path, qself, false)?
             }
-            ast::TyKind::TraitObject(ref bounds) => {
-                self.print_bounds("", &bounds[..])?;
+            ast::TyKind::TraitObject(ref bounds, syntax) => {
+                let prefix = if syntax == ast::TraitObjectSyntax::Dyn { "dyn " } else { "" };
+                self.print_bounds(prefix, &bounds[..])?;
             }
             ast::TyKind::ImplTrait(ref bounds) => {
                 self.print_bounds("impl ", &bounds[..])?;
index 05077d42a0bedb6886ee60069cc03490f6513c26..521c6030eba2cc06d064e78ec08a475631638e69 100644 (file)
@@ -348,7 +348,7 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) {
             visitor.visit_ty(ty);
             visitor.visit_expr(expression)
         }
-        TyKind::TraitObject(ref bounds) |
+        TyKind::TraitObject(ref bounds, ..) |
         TyKind::ImplTrait(ref bounds) => {
             walk_list!(visitor, visit_ty_param_bound, bounds);
         }
index 4d3db15ef29dbd8fead00742db3303c032284af2..872fc031cfb1a8a0fe980b86a5f6e34857884de9 100644 (file)
@@ -309,10 +309,11 @@ fn fresh() -> Self {
     (54, Yield,          "yield")
 
     // Weak keywords, have special meaning only in specific contexts.
-    (55, Default,        "default")
-    (56, StaticLifetime, "'static")
-    (57, Union,          "union")
-    (58, Catch,          "catch")
+    (55, Catch,          "catch")
+    (56, Default,        "default")
+    (57, Dyn,            "dyn")
+    (58, StaticLifetime, "'static")
+    (59, Union,          "union")
 }
 
 // If an interner exists in TLS, return it. Otherwise, prepare a fresh one.
index 886e239246d2558f4dfffdc3f8378740029a58a0..608e5f5f36d02eb3b6d5ae7eaa8e8a77077beb7f 100644 (file)
@@ -30,7 +30,7 @@ doctest = false
 core = { path = "../../libcore" }
 
 [build-dependencies]
-cc = "1.0"
+cc = "1.0.1"
 
 [features]
 c = []
index e37f048dd4757c2779efb02a0dc3974592418921..1287b94159a57f23ff80fbe32b395a946f250d9c 100644 (file)
@@ -901,9 +901,7 @@ addPreservedGUID(const ModuleSummaryIndex &Index,
       }
     }
 
-    GlobalValueSummary *GVSummary = Summary.get();
-    if (isa<FunctionSummary>(GVSummary)) {
-      FunctionSummary *FS = cast<FunctionSummary>(GVSummary);
+    if (auto *FS = dyn_cast<FunctionSummary>(Summary.get())) {
       for (auto &Call: FS->calls()) {
         if (Call.first.isGUID()) {
           addPreservedGUID(Index, Preserved, Call.first.getGUID());
@@ -916,6 +914,10 @@ addPreservedGUID(const ModuleSummaryIndex &Index,
         addPreservedGUID(Index, Preserved, GUID);
       }
     }
+    if (auto *AS = dyn_cast<AliasSummary>(Summary.get())) {
+      auto GUID = AS->getAliasee().getOriginalName();
+      addPreservedGUID(Index, Preserved, GUID);
+    }
   }
 }
 
@@ -963,12 +965,13 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules,
   // combined index
   //
   // This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp`
-  computeDeadSymbols(Ret->Index, Ret->GUIDPreservedSymbols);
+  auto DeadSymbols = computeDeadSymbols(Ret->Index, Ret->GUIDPreservedSymbols);
   ComputeCrossModuleImport(
     Ret->Index,
     Ret->ModuleToDefinedGVSummaries,
     Ret->ImportLists,
-    Ret->ExportLists
+    Ret->ExportLists,
+    &DeadSymbols
   );
 
   // Resolve LinkOnce/Weak symbols, this has to be computed early be cause it
diff --git a/src/test/compile-fail/borrowck/borrowck-match-already-borrowed.rs b/src/test/compile-fail/borrowck/borrowck-match-already-borrowed.rs
new file mode 100644 (file)
index 0000000..1d21f40
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// revisions: ast mir
+//[mir]compile-flags: -Z emit-end-regions -Z borrowck-mir
+
+fn main() {
+    let mut x = 1;
+    let _x = &mut x;
+    let _ = match x {
+        x => x + 1, //[ast]~ ERROR E0503
+                    //[mir]~^ ERROR (Mir) [E0503]
+                    //[mir]~| ERROR (Ast) [E0503]
+        y => y + 2, //[ast]~ ERROR [E0503]
+                    //[mir]~^ ERROR (Mir) [E0503]
+                    //[mir]~| ERROR (Ast) [E0503]
+    };
+}
diff --git a/src/test/compile-fail/dyn-trait-compatibility.rs b/src/test/compile-fail/dyn-trait-compatibility.rs
new file mode 100644 (file)
index 0000000..a7cfda5
--- /dev/null
@@ -0,0 +1,29 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+type A0 = dyn;
+//~^ ERROR cannot find type `dyn` in this scope
+type A1 = dyn::dyn;
+//~^ ERROR Use of undeclared type or module `dyn`
+type A2 = dyn<dyn, dyn>;
+//~^ ERROR cannot find type `dyn` in this scope
+//~| ERROR cannot find type `dyn` in this scope
+//~| ERROR cannot find type `dyn` in this scope
+type A3 = dyn<<dyn as dyn>::dyn>;
+//~^ ERROR cannot find type `dyn` in this scope
+//~| ERROR cannot find type `dyn` in this scope
+//~| ERROR Use of undeclared type or module `dyn`
+type A4 = dyn(dyn, dyn) -> dyn;
+//~^ ERROR cannot find type `dyn` in this scope
+//~| ERROR cannot find type `dyn` in this scope
+//~| ERROR cannot find type `dyn` in this scope
+//~| ERROR cannot find type `dyn` in this scope
+
+fn main() {}
diff --git a/src/test/compile-fail/feature-gate-dyn-trait.rs b/src/test/compile-fail/feature-gate-dyn-trait.rs
new file mode 100644 (file)
index 0000000..4b3803d
--- /dev/null
@@ -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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Trait {}
+type A = Box<dyn Trait>; //~ ERROR `dyn Trait` syntax is unstable
+
+fn main() {}
diff --git a/src/test/compile-fail/method-call-err-msg.rs b/src/test/compile-fail/method-call-err-msg.rs
deleted file mode 100644 (file)
index 14fa74d..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Test that parameter cardinality or missing method error gets span exactly.
-
-pub struct Foo;
-impl Foo {
-    fn zero(self) -> Foo { self }
-    //~^ NOTE defined here
-    fn one(self, _: isize) -> Foo { self }
-    //~^ NOTE defined here
-    fn two(self, _: isize, _: isize) -> Foo { self }
-    //~^ NOTE defined here
-}
-
-fn main() {
-    let x = Foo;
-    x.zero(0)   //~ ERROR this function takes 0 parameters but 1 parameter was supplied
-     //~^ NOTE expected 0 parameters
-     .one()     //~ ERROR this function takes 1 parameter but 0 parameters were supplied
-     //~^ NOTE expected 1 parameter
-     .two(0);   //~ ERROR this function takes 2 parameters but 1 parameter was supplied
-     //~^ NOTE expected 2 parameters
-
-    let y = Foo;
-    y.zero()
-     .take()    //~ ERROR no method named `take` found for type `Foo` in the current scope
-     //~^ NOTE the method `take` exists but the following trait bounds were not satisfied
-     //~| NOTE the following traits define an item `take`, perhaps you need to implement one of them
-     .one(0);
-}
index cabe0fd48edf99d0124ef40e19b45060f8ec4cf0..6cd439167314bd9ba4f684f4538b26b1bb8b45b5 100644 (file)
@@ -8,9 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(dyn_trait)]
 
 struct Foo;
 
 fn foo(_x: Box<Foo + Send>) { } //~ ERROR expected trait, found struct `Foo`
 
+type A<T> = Box<dyn Vec<T>>; //~ ERROR expected trait, found struct `Vec`
+
 fn main() { }
index a44c0c3f32fef0b46b8d3f4e8b6f697cb9abd6ca..3e8c140eb197d154c9f7af6f02ef97d908e7d7fa 100644 (file)
@@ -17,4 +17,6 @@ fn main() {
     //~^ ERROR expected a path on the left-hand side of `+`, not `( Copy + Copy)`
     let _: Box<(Copy +) + Copy>;
     //~^ ERROR expected a path on the left-hand side of `+`, not `( Copy)`
+    let _: Box<(dyn Copy) + Copy>;
+    //~^ ERROR expected a path on the left-hand side of `+`, not `(dyn  Copy)`
 }
index 5202e6dea541ee396c97d99c249d7cbce84fccca..93711c41d79f82cc8a906f761a74b76828a18adf 100644 (file)
@@ -5,7 +5,7 @@ all:
        mkdir $(TMPDIR)/b
        $(call COMPILE_OBJ,$(TMPDIR)/a/foo.o,foo.c)
        $(call COMPILE_OBJ,$(TMPDIR)/b/foo.o,bar.c)
-       ar crus $(TMPDIR)/libfoo.a $(TMPDIR)/a/foo.o $(TMPDIR)/b/foo.o
+       $(AR) crus $(TMPDIR)/libfoo.a $(TMPDIR)/a/foo.o $(TMPDIR)/b/foo.o
        $(RUSTC) foo.rs
        $(RUSTC) bar.rs
        $(call RUN,bar)
index 4ec54f73e67a5927ae02447ecbdec1ec201315b5..06d1bb6698ece6ba07aa4379cd2ad0ce9f22238c 100644 (file)
@@ -3,8 +3,8 @@
 ifneq (,$(findstring MINGW,$(UNAME)))
 ifndef IS_MSVC
 all:
-       g++ foo.cpp -c -o $(TMPDIR)/foo.o
-       ar crus $(TMPDIR)/libfoo.a $(TMPDIR)/foo.o
+       $(CXX) foo.cpp -c -o $(TMPDIR)/foo.o
+       $(AR) crus $(TMPDIR)/libfoo.a $(TMPDIR)/foo.o
        $(RUSTC) foo.rs -lfoo -lstdc++
        $(call RUN,foo)
 else
index 0dbe655b77dfd9c91ff5104b3e6fe81f80106281..5c9cc9935099f55efecea3971289169f27b926c0 100644 (file)
@@ -2,5 +2,5 @@
 
 all:
        touch $(TMPDIR)/rust.metadata.bin
-       ar crus $(TMPDIR)/libfoo-ffffffff-1.0.rlib $(TMPDIR)/rust.metadata.bin
+       $(AR) crus $(TMPDIR)/libfoo-ffffffff-1.0.rlib $(TMPDIR)/rust.metadata.bin
        $(RUSTC) foo.rs 2>&1 | grep "can't find crate for"
index 461df49b468f94dca3cfc47f0ced18404da9b32a..4db027aaeef7150632f058e02da47e7a29f6dc87 100644 (file)
@@ -18,7 +18,6 @@
 extern crate rustc_trans;
 extern crate syntax;
 
-use rustc::dep_graph::DepGraph;
 use rustc::session::{build_session, Session};
 use rustc::session::config::{basic_options, build_configuration, Input,
                              OutputType, OutputTypes};
@@ -56,6 +55,9 @@ fn basic_sess(sysroot: PathBuf) -> (Session, Rc<CStore>) {
     let mut opts = basic_options();
     opts.output_types = OutputTypes::new(&[(OutputType::Exe, None)]);
     opts.maybe_sysroot = Some(sysroot);
+    if let Ok(linker) = std::env::var("RUSTC_LINKER") {
+        opts.cg.linker = Some(linker);
+    }
 
     let descriptions = Registry::new(&rustc::DIAGNOSTICS);
     let cstore = Rc::new(CStore::new(Box::new(rustc_trans::LlvmMetadataLoader)));
@@ -67,8 +69,7 @@ fn basic_sess(sysroot: PathBuf) -> (Session, Rc<CStore>) {
 
 fn compile(code: String, output: PathBuf, sysroot: PathBuf) {
     let (sess, cstore) = basic_sess(sysroot);
-    let cfg = build_configuration(&sess, HashSet::new());
     let control = CompileController::basic();
     let input = Input::Str { name: anon_src(), input: code };
-    compile_input(&sess, &cstore, &input, &None, &Some(output), None, &control);
+    let _ = compile_input(&sess, &cstore, &input, &None, &Some(output), None, &control);
 }
index 64af91b487b322f82e913337175eca6a3091de75..cb4f14627334876917a6702826dea3271fe1ce70 100644 (file)
@@ -2,6 +2,6 @@
 
 all: foo.rs
        $(RUSTC) --cfg 'feature="bar"' --crate-type lib foo.rs
-       $(HOST_RPATH_ENV) '$(RUSTDOC)' --test --cfg 'feature="bar"' \
+       $(RUSTDOC) --test --cfg 'feature="bar"' \
                -L $(TMPDIR) foo.rs |\
                grep -q 'foo.rs - foo (line 11) ... ok'
index 4e570718a62f987ffcf9b812550b0b759ca88735..8ce1c699526cd1b9e4c49aa2627bf5650e95b63f 100644 (file)
@@ -1,4 +1,4 @@
 -include ../tools.mk
 
 all:
-       $(HOST_RPATH_ENV) '$(RUSTDOC)' -o "$(TMPDIR)/foo/bar/doc" foo.rs
+       $(RUSTDOC) -o "$(TMPDIR)/foo/bar/doc" foo.rs
index 5878eec66bad492d902d5e3e01c55d6bb40a4b5c..92a278825c242941a41b2af7eaf1e620d22c7ce3 100644 (file)
@@ -1,6 +1,6 @@
 -include ../tools.mk
 
 all:
-       ar crus $(TMPDIR)/libfoo.a foo.rs
-       ar d $(TMPDIR)/libfoo.a foo.rs
+       $(AR) crus $(TMPDIR)/libfoo.a foo.rs
+       $(AR) d $(TMPDIR)/libfoo.a foo.rs
        $(RUSTC) foo.rs
index 27f235d54d46bc74567b6b9020d5303ce2ebe8d7..c5d5626bf7269f41f03ab4836edbab937da21e4b 100644 (file)
@@ -7,7 +7,13 @@ TARGET_RPATH_ENV = \
 
 RUSTC_ORIGINAL := $(RUSTC)
 BARE_RUSTC := $(HOST_RPATH_ENV) '$(RUSTC)'
+BARE_RUSTDOC := $(HOST_RPATH_ENV) '$(RUSTDOC)'
 RUSTC := $(BARE_RUSTC) --out-dir $(TMPDIR) -L $(TMPDIR) $(RUSTFLAGS)
+RUSTDOC := $(BARE_RUSTDOC)
+ifdef RUSTC_LINKER
+RUSTC := $(RUSTC) -Clinker=$(RUSTC_LINKER)
+RUSTDOC := $(RUSTDOC) --linker $(RUSTC_LINKER) -Z unstable-options
+endif
 #CC := $(CC) -L $(TMPDIR)
 HTMLDOCCK := $(PYTHON) $(S)/src/etc/htmldocck.py
 
@@ -102,13 +108,13 @@ REMOVE_DYLIBS     = rm $(TMPDIR)/$(call DYLIB_GLOB,$(1))
 REMOVE_RLIBS      = rm $(TMPDIR)/$(call RLIB_GLOB,$(1))
 
 %.a: %.o
-       ar crus $@ $<
+       $(AR) crus $@ $<
 ifdef IS_MSVC
 %.lib: lib%.o
        $(MSVC_LIB) -out:`cygpath -w $@` $<
 else
 %.lib: lib%.o
-       ar crus $@ $<
+       $(AR) crus $@ $<
 endif
 %.dylib: %.o
        $(CC) -dynamiclib -Wl,-dylib -o $@ $<
diff --git a/src/test/run-pass/auxiliary/thin-lto-inlines-aux.rs b/src/test/run-pass/auxiliary/thin-lto-inlines-aux.rs
deleted file mode 100644 (file)
index ccbb0e7..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// no-prefer-dynamic
-
-#![crate_type = "rlib"]
-
-pub fn bar() -> u32 {
-    3
-}
diff --git a/src/test/run-pass/dyn-trait.rs b/src/test/run-pass/dyn-trait.rs
new file mode 100644 (file)
index 0000000..9193085
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(dyn_trait)]
+
+use std::fmt::Display;
+
+static BYTE: u8 = 33;
+
+fn main() {
+    let x: &(dyn 'static + Display) = &BYTE;
+    let y: Box<dyn Display + 'static> = Box::new(BYTE);
+    let xstr = format!("{}", x);
+    let ystr = format!("{}", y);
+    assert_eq!(xstr, "33");
+    assert_eq!(ystr, "33");
+}
diff --git a/src/test/run-pass/thin-lto-inlines.rs b/src/test/run-pass/thin-lto-inlines.rs
deleted file mode 100644 (file)
index 3135a68..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-flags: -Z thinlto -C codegen-units=8 -O
-// min-llvm-version 4.0
-// ignore-emscripten
-
-// We want to assert here that ThinLTO will inline across codegen units. There's
-// not really a great way to do that in general so we sort of hack around it by
-// praying two functions go into separate codegen units and then assuming that
-// if inlining *doesn't* happen the first byte of the functions will differ.
-
-pub fn foo() -> u32 {
-    bar::bar()
-}
-
-mod bar {
-    pub fn bar() -> u32 {
-        3
-    }
-}
-
-fn main() {
-    println!("{} {}", foo(), bar::bar());
-
-    unsafe {
-        let foo = foo as usize as *const u8;
-        let bar = bar::bar as usize as *const u8;
-
-        assert_eq!(*foo, *bar);
-    }
-}
diff --git a/src/test/run-pass/thin-lto-inlines2.rs b/src/test/run-pass/thin-lto-inlines2.rs
deleted file mode 100644 (file)
index ed899d2..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-flags: -Z thinlto -C codegen-units=8 -O -C lto
-// aux-build:thin-lto-inlines-aux.rs
-// min-llvm-version 4.0
-// no-prefer-dynamic
-// ignore-emscripten
-
-// We want to assert here that ThinLTO will inline across codegen units. There's
-// not really a great way to do that in general so we sort of hack around it by
-// praying two functions go into separate codegen units and then assuming that
-// if inlining *doesn't* happen the first byte of the functions will differ.
-
-extern crate thin_lto_inlines_aux as bar;
-
-pub fn foo() -> u32 {
-    bar::bar()
-}
-
-fn main() {
-    println!("{} {}", foo(), bar::bar());
-
-    unsafe {
-        let foo = foo as usize as *const u8;
-        let bar = bar::bar as usize as *const u8;
-
-        assert_eq!(*foo, *bar);
-    }
-}
-
diff --git a/src/test/run-pass/thinlto/auxiliary/dylib.rs b/src/test/run-pass/thinlto/auxiliary/dylib.rs
new file mode 100644 (file)
index 0000000..cdb3f49
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -Z thinlto -C codegen-units=8
+
+#[inline]
+pub fn foo(b: u8) {
+    b.to_string();
+}
diff --git a/src/test/run-pass/thinlto/auxiliary/thin-lto-inlines-aux.rs b/src/test/run-pass/thinlto/auxiliary/thin-lto-inlines-aux.rs
new file mode 100644 (file)
index 0000000..ccbb0e7
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// no-prefer-dynamic
+
+#![crate_type = "rlib"]
+
+pub fn bar() -> u32 {
+    3
+}
diff --git a/src/test/run-pass/thinlto/dylib-works.rs b/src/test/run-pass/thinlto/dylib-works.rs
new file mode 100644 (file)
index 0000000..3f54519
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:dylib.rs
+// min-llvm-version 4.0
+
+extern crate dylib;
+
+fn main() {
+    dylib::foo(1);
+}
diff --git a/src/test/run-pass/thinlto/thin-lto-inlines.rs b/src/test/run-pass/thinlto/thin-lto-inlines.rs
new file mode 100644 (file)
index 0000000..3135a68
--- /dev/null
@@ -0,0 +1,39 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -Z thinlto -C codegen-units=8 -O
+// min-llvm-version 4.0
+// ignore-emscripten
+
+// We want to assert here that ThinLTO will inline across codegen units. There's
+// not really a great way to do that in general so we sort of hack around it by
+// praying two functions go into separate codegen units and then assuming that
+// if inlining *doesn't* happen the first byte of the functions will differ.
+
+pub fn foo() -> u32 {
+    bar::bar()
+}
+
+mod bar {
+    pub fn bar() -> u32 {
+        3
+    }
+}
+
+fn main() {
+    println!("{} {}", foo(), bar::bar());
+
+    unsafe {
+        let foo = foo as usize as *const u8;
+        let bar = bar::bar as usize as *const u8;
+
+        assert_eq!(*foo, *bar);
+    }
+}
diff --git a/src/test/run-pass/thinlto/thin-lto-inlines2.rs b/src/test/run-pass/thinlto/thin-lto-inlines2.rs
new file mode 100644 (file)
index 0000000..ed899d2
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -Z thinlto -C codegen-units=8 -O -C lto
+// aux-build:thin-lto-inlines-aux.rs
+// min-llvm-version 4.0
+// no-prefer-dynamic
+// ignore-emscripten
+
+// We want to assert here that ThinLTO will inline across codegen units. There's
+// not really a great way to do that in general so we sort of hack around it by
+// praying two functions go into separate codegen units and then assuming that
+// if inlining *doesn't* happen the first byte of the functions will differ.
+
+extern crate thin_lto_inlines_aux as bar;
+
+pub fn foo() -> u32 {
+    bar::bar()
+}
+
+fn main() {
+    println!("{} {}", foo(), bar::bar());
+
+    unsafe {
+        let foo = foo as usize as *const u8;
+        let bar = bar::bar as usize as *const u8;
+
+        assert_eq!(*foo, *bar);
+    }
+}
+
index e07face24bab7b0c4acfd1dfd4e8693e64e5a208..9beae91540abfd09a1ebdd8e6d68c2b72e8b2c69 100644 (file)
@@ -13,11 +13,11 @@ error: expected type, found keyword `true`
 18 |     foo!(true);
    |          ^^^^ expecting a type here because of type ascription
 
-error: expected one of `!`, `&&`, `&`, `(`, `*`, `.`, `;`, `<`, `?`, `[`, `_`, `extern`, `fn`, `for`, `impl`, `unsafe`, `}`, an operator, or lifetime, found `true`
+error: expected one of `!`, `&&`, `&`, `(`, `*`, `.`, `;`, `<`, `?`, `[`, `_`, `dyn`, `extern`, `fn`, `for`, `impl`, `unsafe`, `}`, an operator, or lifetime, found `true`
   --> $DIR/issue-44406.rs:18:10
    |
 13 |         bar(baz: $rest)
-   |                 - expected one of 19 possible tokens here
+   |                 - expected one of 20 possible tokens here
 ...
 18 |     foo!(true);
    |          ^^^^ unexpected token
diff --git a/src/test/ui/method-call-err-msg.rs b/src/test/ui/method-call-err-msg.rs
new file mode 100644 (file)
index 0000000..14fa74d
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that parameter cardinality or missing method error gets span exactly.
+
+pub struct Foo;
+impl Foo {
+    fn zero(self) -> Foo { self }
+    //~^ NOTE defined here
+    fn one(self, _: isize) -> Foo { self }
+    //~^ NOTE defined here
+    fn two(self, _: isize, _: isize) -> Foo { self }
+    //~^ NOTE defined here
+}
+
+fn main() {
+    let x = Foo;
+    x.zero(0)   //~ ERROR this function takes 0 parameters but 1 parameter was supplied
+     //~^ NOTE expected 0 parameters
+     .one()     //~ ERROR this function takes 1 parameter but 0 parameters were supplied
+     //~^ NOTE expected 1 parameter
+     .two(0);   //~ ERROR this function takes 2 parameters but 1 parameter was supplied
+     //~^ NOTE expected 2 parameters
+
+    let y = Foo;
+    y.zero()
+     .take()    //~ ERROR no method named `take` found for type `Foo` in the current scope
+     //~^ NOTE the method `take` exists but the following trait bounds were not satisfied
+     //~| NOTE the following traits define an item `take`, perhaps you need to implement one of them
+     .one(0);
+}
diff --git a/src/test/ui/method-call-err-msg.stderr b/src/test/ui/method-call-err-msg.stderr
new file mode 100644 (file)
index 0000000..c39c62d
--- /dev/null
@@ -0,0 +1,44 @@
+error[E0061]: this function takes 0 parameters but 1 parameter was supplied
+  --> $DIR/method-call-err-msg.rs:25:12
+   |
+15 |     fn zero(self) -> Foo { self }
+   |     ----------------------------- defined here
+...
+25 |     x.zero(0)   //~ ERROR this function takes 0 parameters but 1 parameter was supplied
+   |            ^ expected 0 parameters
+
+error[E0061]: this function takes 1 parameter but 0 parameters were supplied
+  --> $DIR/method-call-err-msg.rs:27:7
+   |
+17 |     fn one(self, _: isize) -> Foo { self }
+   |     -------------------------------------- defined here
+...
+27 |      .one()     //~ ERROR this function takes 1 parameter but 0 parameters were supplied
+   |       ^^^ expected 1 parameter
+
+error[E0061]: this function takes 2 parameters but 1 parameter was supplied
+  --> $DIR/method-call-err-msg.rs:29:11
+   |
+19 |     fn two(self, _: isize, _: isize) -> Foo { self }
+   |     ------------------------------------------------ defined here
+...
+29 |      .two(0);   //~ ERROR this function takes 2 parameters but 1 parameter was supplied
+   |           ^ expected 2 parameters
+
+error[E0599]: no method named `take` found for type `Foo` in the current scope
+  --> $DIR/method-call-err-msg.rs:34:7
+   |
+34 |      .take()    //~ ERROR no method named `take` found for type `Foo` in the current scope
+   |       ^^^^
+   |
+   = note: the method `take` exists but the following trait bounds were not satisfied:
+           `&mut Foo : std::iter::Iterator`
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following traits define an item `take`, perhaps you need to implement one of them:
+           candidate #1: `std::collections::hash::Recover`
+           candidate #2: `std::io::Read`
+           candidate #3: `std::iter::Iterator`
+           candidate #4: `alloc::btree::Recover`
+
+error: aborting due to 4 previous errors
+
index 2cdab5bedc49ab1c7ca0034f61fcede41d574e5e..ba1a999121cc57cae44b3bbe61cac232284de43e 100644 (file)
 fn foo(():(), ():()) {}
 fn bar(():()) {}
 
+struct S;
+impl S {
+    fn baz(self, (): ()) { }
+    fn generic<T>(self, _: T) { }
+}
+
 fn main() {
     let _: Result<(), String> = Ok();
     foo();
     foo(());
     bar();
+    S.baz();
+    S.generic::<()>();
 }
index e508a30d1826ca801ce4591798aa4f2e01c6c76c..af558d0ab8335913a77cb936de546e2cb67dfe28 100644 (file)
@@ -1,45 +1,73 @@
 error[E0061]: this function takes 1 parameter but 0 parameters were supplied
-  --> $DIR/missing-unit-argument.rs:15:33
+  --> $DIR/missing-unit-argument.rs:21:33
    |
-15 |     let _: Result<(), String> = Ok();
+21 |     let _: Result<(), String> = Ok();
    |                                 ^^^^
    |
-help: expected the unit value `()`. You can create one with a pair of parenthesis
+help: expected the unit value `()`; create it with empty parentheses
    |
-15 |     let _: Result<(), String> = Ok(());
+21 |     let _: Result<(), String> = Ok(());
    |                                    ^^
 
 error[E0061]: this function takes 2 parameters but 0 parameters were supplied
-  --> $DIR/missing-unit-argument.rs:16:5
+  --> $DIR/missing-unit-argument.rs:22:5
    |
 11 | fn foo(():(), ():()) {}
    | ----------------------- defined here
 ...
-16 |     foo();
+22 |     foo();
    |     ^^^^^ expected 2 parameters
 
 error[E0061]: this function takes 2 parameters but 1 parameter was supplied
-  --> $DIR/missing-unit-argument.rs:17:9
+  --> $DIR/missing-unit-argument.rs:23:9
    |
 11 | fn foo(():(), ():()) {}
    | ----------------------- defined here
 ...
-17 |     foo(());
+23 |     foo(());
    |         ^^ expected 2 parameters
 
 error[E0061]: this function takes 1 parameter but 0 parameters were supplied
-  --> $DIR/missing-unit-argument.rs:18:5
+  --> $DIR/missing-unit-argument.rs:24:5
    |
 12 | fn bar(():()) {}
    | ---------------- defined here
 ...
-18 |     bar();
+24 |     bar();
    |     ^^^^^
    |
-help: expected the unit value `()`. You can create one with a pair of parenthesis
+help: expected the unit value `()`; create it with empty parentheses
    |
-18 |     bar(());
+24 |     bar(());
    |         ^^
 
-error: aborting due to 4 previous errors
+error[E0061]: this function takes 1 parameter but 0 parameters were supplied
+  --> $DIR/missing-unit-argument.rs:25:7
+   |
+16 |     fn baz(self, (): ()) { }
+   |     ------------------------ defined here
+...
+25 |     S.baz();
+   |       ^^^
+   |
+help: expected the unit value `()`; create it with empty parentheses
+   |
+25 |     S.baz(());
+   |           ^^
+
+error[E0061]: this function takes 1 parameter but 0 parameters were supplied
+  --> $DIR/missing-unit-argument.rs:26:7
+   |
+17 |     fn generic<T>(self, _: T) { }
+   |     ----------------------------- defined here
+...
+26 |     S.generic::<()>();
+   |       ^^^^^^^
+   |
+help: expected the unit value `()`; create it with empty parentheses
+   |
+26 |     S.generic::<()>(());
+   |                     ^^
+
+error: aborting due to 6 previous errors
 
index daeac35a0170a03afa59498ff13af869e03faa19..8c1b130b116520dcc28f5b6121b5214600274f79 100644 (file)
@@ -95,6 +95,7 @@
     "x86_64-unknown-freebsd",
     "x86_64-unknown-fuchsia",
     "x86_64-unknown-linux-gnu",
+    "x86_64-unknown-linux-gnux32",
     "x86_64-unknown-linux-musl",
     "x86_64-unknown-netbsd",
     "x86_64-unknown-redox",
index 25444585592f5da648edd5317fcdd21f2db8bb64..b62b1b68edcdf23a70cb12f31403c80e97f13634 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 25444585592f5da648edd5317fcdd21f2db8bb64
+Subproject commit b62b1b68edcdf23a70cb12f31403c80e97f13634
index cee7e52c7f3c63f23edce8c7bde77322cc90ab26..aa98f818f40405a241e03ce3db37c7eb574546c3 100644 (file)
@@ -201,6 +201,8 @@ pub struct Config {
     pub cc: String,
     pub cxx: String,
     pub cflags: String,
+    pub ar: String,
+    pub linker: Option<String>,
     pub llvm_components: String,
     pub llvm_cxxflags: String,
     pub nodejs: Option<String>,
index b7fb3670165d6d928e5c1adaa2953edbdd320fcb..251dd4d5edb4e672782c1322598be7e4579bd855 100644 (file)
@@ -45,7 +45,7 @@ fn from_str(s: &str) -> Result<Self, Self::Err> {
 impl fmt::Display for ErrorKind {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
-            ErrorKind::Help => write!(f, "help"),
+            ErrorKind::Help => write!(f, "help message"),
             ErrorKind::Error => write!(f, "error"),
             ErrorKind::Note => write!(f, "note"),
             ErrorKind::Suggestion => write!(f, "suggestion"),
index 306497da9e3f9df5d2cd67b7f1502ae97c6050b1..1701c8a3e43eec5194cac204527bad1590e6e694 100644 (file)
@@ -102,6 +102,8 @@ pub fn parse_config(args: Vec<String> ) -> Config {
         .reqopt("", "cc", "path to a C compiler", "PATH")
         .reqopt("", "cxx", "path to a C++ compiler", "PATH")
         .reqopt("", "cflags", "flags for the C compiler", "FLAGS")
+        .optopt("", "ar", "path to an archiver", "PATH")
+        .optopt("", "linker", "path to a linker", "PATH")
         .reqopt("", "llvm-components", "list of LLVM components built in", "LIST")
         .reqopt("", "llvm-cxxflags", "C++ flags for LLVM", "FLAGS")
         .optopt("", "nodejs", "the name of nodejs", "PATH")
@@ -198,6 +200,8 @@ fn make_absolute(path: PathBuf) -> PathBuf {
         cc: matches.opt_str("cc").unwrap(),
         cxx: matches.opt_str("cxx").unwrap(),
         cflags: matches.opt_str("cflags").unwrap(),
+        ar: matches.opt_str("ar").unwrap_or("ar".into()),
+        linker: matches.opt_str("linker"),
         llvm_components: matches.opt_str("llvm-components").unwrap(),
         llvm_cxxflags: matches.opt_str("llvm-cxxflags").unwrap(),
         nodejs: matches.opt_str("nodejs"),
@@ -234,6 +238,8 @@ pub fn log_config(config: &Config) {
     logv(c, format!("adb_test_dir: {:?}", config.adb_test_dir));
     logv(c, format!("adb_device_status: {}",
                     config.adb_device_status));
+    logv(c, format!("ar: {}", config.ar));
+    logv(c, format!("linker: {:?}", config.linker));
     logv(c, format!("verbose: {}", config.verbose));
     logv(c, format!("quiet: {}", config.quiet));
     logv(c, "\n".to_string());
index af9061ab367719908c4e832b7ef42d71db2d0db2..d61077643f1fe435c36b318f6cf097e7e1100d3d 100644 (file)
@@ -1041,7 +1041,7 @@ fn check_expected_errors(&self,
                 None => {
                     if self.is_unexpected_compiler_message(actual_error, expect_help, expect_note) {
                         self.error(
-                            &format!("{}:{}: unexpected {:?}: '{}'",
+                            &format!("{}:{}: unexpected {}: '{}'",
                                      file_name,
                                      actual_error.line_num,
                                      actual_error.kind.as_ref()
@@ -1155,6 +1155,9 @@ fn document(&self, out_dir: &Path) -> ProcRes {
             .arg("-o").arg(out_dir)
             .arg(&self.testpaths.file)
             .args(&self.props.compile_flags);
+        if let Some(ref linker) = self.config.linker {
+            rustdoc.arg("--linker").arg(linker).arg("-Z").arg("unstable-options");
+        }
 
         self.compose_and_run_compiler(rustdoc, None)
     }
@@ -1441,6 +1444,9 @@ fn make_compile_args(&self, input_file: &Path, output_file: TargetLocation) -> C
         } else {
             rustc.args(self.split_maybe_args(&self.config.target_rustcflags));
         }
+        if let Some(ref linker) = self.config.linker {
+            rustc.arg(format!("-Clinker={}", linker));
+        }
 
         rustc.args(&self.props.compile_flags);
 
@@ -2101,6 +2107,10 @@ fn run_rmake_test(&self) {
            .env("LLVM_COMPONENTS", &self.config.llvm_components)
            .env("LLVM_CXXFLAGS", &self.config.llvm_cxxflags);
 
+        if let Some(ref linker) = self.config.linker {
+            cmd.env("RUSTC_LINKER", linker);
+        }
+
         // We don't want RUSTFLAGS set from the outside to interfere with
         // compiler flags set in the test cases:
         cmd.env_remove("RUSTFLAGS");
@@ -2123,7 +2133,8 @@ fn run_rmake_test(&self) {
                .env("CXX", &self.config.cxx);
         } else {
             cmd.env("CC", format!("{} {}", self.config.cc, self.config.cflags))
-               .env("CXX", format!("{} {}", self.config.cxx, self.config.cflags));
+               .env("CXX", format!("{} {}", self.config.cxx, self.config.cflags))
+               .env("AR", &self.config.ar);
 
             if self.config.target.contains("windows") {
                 cmd.env("IS_WINDOWS", "1");
index 22eb5241c0ee5bb7eaf95e270a2b1500e82bf767..16a478368c8dcc0c0ee47372a9f663b23d28b097 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 22eb5241c0ee5bb7eaf95e270a2b1500e82bf767
+Subproject commit 16a478368c8dcc0c0ee47372a9f663b23d28b097
index 1700daa0aff1497351fc17692d84b50f51947f42..b03e4f05641eed1d4d3bb1a0b0d6b5233fad60a2 100644 (file)
@@ -3,7 +3,7 @@
 #
 # There are three states a tool can be in:
 # 1. Broken: The tool doesn't build
-# 2. Building: The tool builds but its tests are failing
+# 2. Compiling: The tool builds but its tests are failing
 # 3. Testing: The tool builds and its tests are passing
 #
 # In the future there will be further states like "Distributing", which
@@ -26,7 +26,7 @@
 miri = "Broken"
 
 # ping @Manishearth @llogiq @mcarton @oli-obk
-clippy = "Broken"
+clippy = "Compiling"
 
 # ping @nrc
 rls = "Testing"