]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #42370 - mbrubeck:docs, r=frewsxcv
authorMark Simulacrum <mark.simulacrum@gmail.com>
Fri, 2 Jun 2017 15:10:48 +0000 (09:10 -0600)
committerGitHub <noreply@github.com>
Fri, 2 Jun 2017 15:10:48 +0000 (09:10 -0600)
Add [[T]] -> [T] examples to SliceConcatExt docs

None

58 files changed:
.gitignore
.travis.yml
src/Cargo.lock
src/bootstrap/Cargo.toml
src/bootstrap/check.rs
src/bootstrap/compile.rs
src/bootstrap/lib.rs
src/bootstrap/native.rs
src/bootstrap/util.rs
src/ci/docker/run.sh
src/ci/init_repo.sh
src/ci/run.sh
src/ci/shared.sh
src/doc/unstable-book/src/SUMMARY.md
src/doc/unstable-book/src/library-features/slice-rotate.md [new file with mode: 0644]
src/liballoc_jemalloc/Cargo.toml
src/libcollections/benches/lib.rs
src/libcollections/benches/slice.rs
src/libcollections/lib.rs
src/libcollections/slice.rs
src/libcollections/tests/lib.rs
src/libcollections/tests/slice.rs
src/libcollections/tests/vec_deque.rs
src/libcompiler_builtins/Cargo.toml
src/libcore/intrinsics.rs
src/libcore/iter/mod.rs
src/libcore/iter/range.rs
src/libcore/slice/mod.rs
src/libcore/slice/rotate.rs [new file with mode: 0644]
src/libcore/tests/iter.rs
src/libcore/tests/lib.rs
src/libcore/tests/slice.rs
src/libflate/Cargo.toml
src/librustc/dep_graph/README.md
src/librustc/ich/fingerprint.rs
src/librustc_llvm/Cargo.toml
src/librustc_trans/Cargo.toml
src/librustc_trans/back/link.rs
src/librustc_trans/back/msvc/arch.rs [deleted file]
src/librustc_trans/back/msvc/mod.rs [deleted file]
src/librustc_trans/back/msvc/registry.rs [deleted file]
src/librustc_trans/context.rs
src/librustc_trans/intrinsic.rs
src/librustc_trans/lib.rs
src/librustc_typeck/check/intrinsic.rs
src/librustdoc/Cargo.toml
src/librustdoc/clean/mod.rs
src/librustdoc/html/format.rs
src/libstd/Cargo.toml
src/libstd/thread/mod.rs
src/libsyntax/parse/parser.rs
src/test/codegen/prefetch.rs [new file with mode: 0644]
src/test/parse-fail/removed-syntax-extern-const.rs
src/tools/compiletest/src/common.rs
src/tools/compiletest/src/main.rs
src/tools/rust-installer
src/tools/tidy/src/features.rs
src/tools/tidy/src/main.rs

index d82e279e012d8d22b452832a46a014436151c9b1..ff839c34df1a7d323301568c4629f43eb84afd59 100644 (file)
@@ -101,3 +101,4 @@ version.ml
 version.texi
 .cargo
 !src/vendor/**
+/src/target/
index 190cb3380a18c633870f6c4d0f7baf677bf3d09a..9ef759b3f80ae6e7e88f5e94e5bc5b712812b106 100644 (file)
@@ -1,4 +1,4 @@
-language: minimal
+language: generic
 sudo: required
 dist: trusty
 services:
@@ -152,20 +152,21 @@ before_script:
       echo "#### Disk usage before running script:";
       df -h;
       du . | sort -nr | head -n100
-
-script:
   - >
       if [ "$ALLOW_PR" = "" ] && [ "$TRAVIS_BRANCH" != "auto" ]; then
-          echo skipping, not a full build
+          export RUN_SCRIPT="echo 'skipping, not a full build'";
       else
-          stamp src/ci/init_repo.sh . "$HOME/rustsrc" &&
+          RUN_SCRIPT="stamp src/ci/init_repo.sh . $HOME/rustsrc";
           if [ "$TRAVIS_OS_NAME" = "osx" ]; then
-              stamp src/ci/run.sh;
+              export RUN_SCRIPT="$RUN_SCRIPT && stamp src/ci/run.sh";
           else
-              stamp src/ci/docker/run.sh $IMAGE;
+              export RUN_SCRIPT="$RUN_SCRIPT && stamp src/ci/docker/run.sh $IMAGE";
           fi
       fi
 
+script:
+  - sh -x -c "$RUN_SCRIPT"
+
 after_success:
   - >
       echo "#### Build successful; Disk usage after running script:";
index d55dd919bdf28cf9446672dc69b69bd9205990ef..cc2da1a02dc9fe66c4be7eba1b6b90c5573ff454 100644 (file)
@@ -44,7 +44,7 @@ version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
  "core 0.0.0",
- "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.0.0",
 ]
 
@@ -84,7 +84,7 @@ name = "backtrace-sys"
 version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -110,7 +110,7 @@ dependencies = [
  "build_helper 0.1.0",
  "cmake 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
  "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -178,7 +178,7 @@ dependencies = [
  "serde_ignored 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "tar 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -202,7 +202,7 @@ dependencies = [
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "tar 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -239,7 +239,7 @@ name = "cmake"
 version = "0.1.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -257,7 +257,7 @@ version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
  "core 0.0.0",
- "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -308,7 +308,7 @@ name = "curl-sys"
 version = "0.3.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "libz-sys 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-sys 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -411,7 +411,7 @@ name = "flate"
 version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
- "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -444,7 +444,7 @@ dependencies = [
 
 [[package]]
 name = "gcc"
-version = "0.3.46"
+version = "0.3.50"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -540,7 +540,7 @@ dependencies = [
  "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "tar 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "xz2 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -605,7 +605,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cmake 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
  "curl-sys 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "libz-sys 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -630,7 +630,7 @@ name = "libz-sys"
 version = "1.0.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -650,7 +650,7 @@ version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -697,7 +697,7 @@ name = "miniz-sys"
 version = "0.1.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -830,7 +830,7 @@ name = "openssl-sys"
 version = "0.9.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1248,7 +1248,7 @@ name = "rustc_llvm"
 version = "0.0.0"
 dependencies = [
  "build_helper 0.1.0",
- "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_bitflags 0.0.0",
 ]
 
@@ -1375,6 +1375,7 @@ name = "rustc_trans"
 version = "0.0.0"
 dependencies = [
  "flate 0.0.0",
+ "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
@@ -1425,7 +1426,7 @@ dependencies = [
  "arena 0.0.0",
  "build_helper 0.1.0",
  "env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "pulldown-cmark 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
@@ -1577,7 +1578,7 @@ dependencies = [
  "collections 0.0.0",
  "compiler_builtins 0.0.0",
  "core 0.0.0",
- "gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.0.0",
  "panic_abort 0.0.0",
  "panic_unwind 0.0.0",
@@ -1744,7 +1745,7 @@ dependencies = [
 
 [[package]]
 name = "tar"
-version = "0.4.12"
+version = "0.4.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2042,7 +2043,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)" = "36df0166e856739905cd3d7e0b210fe818592211a008862599845e012d8d304c"
 "checksum foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3e4056b9bd47f8ac5ba12be771f77a0dae796d1bbaaf5fd0b9c2d38b69b8a29d"
 "checksum fs2 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "34edaee07555859dc13ca387e6ae05686bb4d0364c95d649b6dab959511f4baf"
-"checksum gcc 0.3.46 (registry+https://github.com/rust-lang/crates.io-index)" = "181e3cebba1d663bd92eb90e2da787e10597e027eb00de8d742b260a7850948f"
+"checksum gcc 0.3.50 (registry+https://github.com/rust-lang/crates.io-index)" = "5f837c392f2ea61cb1576eac188653df828c861b7137d74ea4a5caa89621f9e6"
 "checksum gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0912515a8ff24ba900422ecda800b52f4016a56251922d397c576bf92c690518"
 "checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685"
 "checksum git2 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9de9df4358c17e448a778d90cd0272e1dab5eae30244502333fa2001c4e24357"
@@ -2128,7 +2129,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum syntex_pos 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "13ad4762fe52abc9f4008e85c4fb1b1fe3aa91ccb99ff4826a439c7c598e1047"
 "checksum syntex_syntax 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)" = "76a302e717e348aa372ff577791c3832395650073b8d8432f8b3cb170b34afde"
 "checksum syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6e0e4dbae163dd98989464c23dd503161b338790640e11537686f2ef0f25c791"
-"checksum tar 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "ab0ef9ead2fe0aa9e18475a96a207bfd5143f4124779ef7429503a8665416ce8"
+"checksum tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "281285b717926caa919ad905ef89c63d75805c7d89437fb873100925a53f2b1b"
 "checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6"
 "checksum term 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d168af3930b369cfe245132550579d47dfd873d69470755a19c2c6568dbbd989"
 "checksum term_size 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "07b6c1ac5b3fffd75073276bca1ceed01f67a28537097a2a9539e116e50fb21a"
index cc560e0172e3a3fa63a6e92e2bc873b028d49633..8842dce0257dd064f53544446176d4f1cf54e1e8 100644 (file)
@@ -36,5 +36,5 @@ num_cpus = "1.0"
 toml = "0.1"
 getopts = "0.2"
 rustc-serialize = "0.3"
-gcc = "0.3.46"
+gcc = "0.3.50"
 libc = "0.2"
index d24bb074cd374d13bb50ad7cc8ce670f090e65c6..d51e3102d8ad044a151d2954fc2b98a06e239aaa 100644 (file)
@@ -124,6 +124,7 @@ pub fn cargo(build: &Build, stage: u32, host: &str) {
 /// otherwise just implements a few lint-like checks that are specific to the
 /// compiler itself.
 pub fn tidy(build: &Build, host: &str) {
+    let _folder = build.fold_output(|| "tidy");
     println!("tidy check ({})", host);
     let compiler = Compiler::new(0, host);
     let mut cmd = build.tool_cmd(&compiler, "tidy");
@@ -131,6 +132,9 @@ pub fn tidy(build: &Build, host: &str) {
     if !build.config.vendor {
         cmd.arg("--no-vendor");
     }
+    if build.config.quiet_tests {
+        cmd.arg("--quiet");
+    }
     build.run(&mut cmd);
 }
 
@@ -148,6 +152,7 @@ pub fn compiletest(build: &Build,
                    target: &str,
                    mode: &str,
                    suite: &str) {
+    let _folder = build.fold_output(|| format!("test_{}", suite));
     println!("Check compiletest suite={} mode={} ({} -> {})",
              suite, mode, compiler.host, target);
     let mut cmd = Command::new(build.tool(&Compiler::new(0, compiler.host),
@@ -278,6 +283,8 @@ pub fn compiletest(build: &Build,
         cmd.arg("--android-cross-path").arg("");
     }
 
+    build.ci_env.force_coloring_in_ci(&mut cmd);
+
     let _time = util::timeit();
     build.run(&mut cmd);
 }
@@ -292,6 +299,7 @@ pub fn docs(build: &Build, compiler: &Compiler) {
     // tests for all files that end in `*.md`
     let mut stack = vec![build.src.join("src/doc")];
     let _time = util::timeit();
+    let _folder = build.fold_output(|| "test_docs");
 
     while let Some(p) = stack.pop() {
         if p.is_dir() {
@@ -325,6 +333,7 @@ pub fn docs(build: &Build, compiler: &Compiler) {
 /// generate a markdown file from the error indexes of the code base which is
 /// then passed to `rustdoc --test`.
 pub fn error_index(build: &Build, compiler: &Compiler) {
+    let _folder = build.fold_output(|| "test_error_index");
     println!("Testing error-index stage{}", compiler.stage);
 
     let dir = testdir(build, compiler.host);
@@ -349,13 +358,14 @@ fn markdown_test(build: &Build, compiler: &Compiler, markdown: &Path) {
     cmd.arg(markdown);
     cmd.env("RUSTC_BOOTSTRAP", "1");
 
-    let mut test_args = build.flags.cmd.test_args().join(" ");
-    if build.config.quiet_tests {
-        test_args.push_str(" --quiet");
-    }
+    let test_args = build.flags.cmd.test_args().join(" ");
     cmd.arg("--test-args").arg(test_args);
 
-    build.run(&mut cmd);
+    if build.config.quiet_tests {
+        build.run_quiet(&mut cmd);
+    } else {
+        build.run(&mut cmd);
+    }
 }
 
 /// Run all unit tests plus documentation tests for an entire crate DAG defined
@@ -384,6 +394,9 @@ pub fn krate(build: &Build,
         }
         _ => panic!("can only test libraries"),
     };
+    let _folder = build.fold_output(|| {
+        format!("{}_stage{}-{}", test_kind.subcommand(), compiler.stage, name)
+    });
     println!("{} {} stage{} ({} -> {})", test_kind, name, compiler.stage,
              compiler.host, target);
 
index 114948f0cf278dd240cb39ebf53322812e2ea7ba..9946c93913fe7292fd502c6d2e726831a6af3e5c 100644 (file)
@@ -41,6 +41,7 @@ pub fn std(build: &Build, target: &str, compiler: &Compiler) {
     let libdir = build.sysroot_libdir(compiler, target);
     t!(fs::create_dir_all(&libdir));
 
+    let _folder = build.fold_output(|| format!("stage{}-std", compiler.stage));
     println!("Building stage{} std artifacts ({} -> {})", compiler.stage,
              compiler.host, target);
 
@@ -192,6 +193,7 @@ pub fn build_startup_objects(build: &Build, for_compiler: &Compiler, target: &st
 /// the build using the `compiler` targeting the `target` architecture. The
 /// artifacts created will also be linked into the sysroot directory.
 pub fn test(build: &Build, target: &str, compiler: &Compiler) {
+    let _folder = build.fold_output(|| format!("stage{}-test", compiler.stage));
     println!("Building stage{} test artifacts ({} -> {})", compiler.stage,
              compiler.host, target);
     let out_dir = build.cargo_out(compiler, Mode::Libtest, target);
@@ -228,6 +230,7 @@ pub fn test_link(build: &Build,
 /// the `compiler` targeting the `target` architecture. The artifacts
 /// created will also be linked into the sysroot directory.
 pub fn rustc(build: &Build, target: &str, compiler: &Compiler) {
+    let _folder = build.fold_output(|| format!("stage{}-rustc", compiler.stage));
     println!("Building stage{} compiler artifacts ({} -> {})",
              compiler.stage, compiler.host, target);
 
@@ -435,6 +438,7 @@ pub fn maybe_clean_tools(build: &Build, stage: u32, target: &str, mode: Mode) {
 /// This will build the specified tool with the specified `host` compiler in
 /// `stage` into the normal cargo output directory.
 pub fn tool(build: &Build, stage: u32, target: &str, tool: &str) {
+    let _folder = build.fold_output(|| format!("stage{}-{}", stage, tool));
     println!("Building stage{} tool {} ({})", stage, tool, target);
 
     let compiler = Compiler::new(stage, &build.config.build);
index 665b9ee49c02d5597ed3261be23f344007c7da65..01235fe30bd65a5f886e0e71540b6bd5a788a274 100644 (file)
@@ -90,7 +90,7 @@
 
 use build_helper::{run_silent, run_suppressed, output, mtime};
 
-use util::{exe, libdir, add_lib_path};
+use util::{exe, libdir, add_lib_path, OutputFolder, CiEnv};
 
 mod cc;
 mod channel;
@@ -179,6 +179,7 @@ pub struct Build {
     crates: HashMap<String, Crate>,
     is_sudo: bool,
     src_is_git: bool,
+    ci_env: CiEnv,
 }
 
 #[derive(Debug)]
@@ -272,6 +273,7 @@ pub fn new(flags: Flags, config: Config) -> Build {
             lldb_python_dir: None,
             is_sudo: is_sudo,
             src_is_git: src_is_git,
+            ci_env: CiEnv::current(),
         }
     }
 
@@ -507,6 +509,9 @@ fn cargo(&self,
         if self.config.vendor || self.is_sudo {
             cargo.arg("--frozen");
         }
+
+        self.ci_env.force_coloring_in_ci(&mut cargo);
+
         return cargo
     }
 
@@ -1011,6 +1016,19 @@ fn unstable_features(&self) -> bool {
             "nightly" | _ => true,
         }
     }
+
+    /// Fold the output of the commands after this method into a group. The fold
+    /// ends when the returned object is dropped. Folding can only be used in
+    /// the Travis CI environment.
+    pub fn fold_output<D, F>(&self, name: F) -> Option<OutputFolder>
+        where D: Into<String>, F: FnOnce() -> D
+    {
+        if self.ci_env == CiEnv::Travis {
+            Some(OutputFolder::new(name().into()))
+        } else {
+            None
+        }
+    }
 }
 
 impl<'a> Compiler<'a> {
index 6cb1d1fc4bf05b47c14c968bd56f16e7da135faf..ce1f63b4233e229261ac4c7088792959abe06709 100644 (file)
@@ -63,6 +63,7 @@ pub fn llvm(build: &Build, target: &str) {
         drop(fs::remove_dir_all(&out_dir));
     }
 
+    let _folder = build.fold_output(|| "llvm");
     println!("Building LLVM for {}", target);
     let _time = util::timeit();
     t!(fs::create_dir_all(&out_dir));
@@ -218,6 +219,7 @@ pub fn test_helpers(build: &Build, target: &str) {
         return
     }
 
+    let _folder = build.fold_output(|| "build_test_helpers");
     println!("Building test helpers");
     t!(fs::create_dir_all(&dst));
     let mut cfg = gcc::Config::new();
index e01c06b10fcd63097de8a14f8b5e2b0f525bccb3..61bd85e76c59882b9967746f8bbba3a76ec9382e 100644 (file)
 use std::env;
 use std::ffi::OsString;
 use std::fs;
-use std::io;
+use std::io::{self, Write};
 use std::path::{Path, PathBuf};
 use std::process::Command;
-use std::time::Instant;
+use std::time::{SystemTime, Instant};
 
 use filetime::{self, FileTime};
 
@@ -324,3 +324,102 @@ fn to_u16s<S: AsRef<OsStr>>(s: S) -> io::Result<Vec<u16>> {
         }
     }
 }
+
+/// An RAII structure that indicates all output until this instance is dropped
+/// is part of the same group.
+///
+/// On Travis CI, these output will be folded by default, together with the
+/// elapsed time in this block. This reduces noise from unnecessary logs,
+/// allowing developers to quickly identify the error.
+///
+/// Travis CI supports folding by printing `travis_fold:start:<name>` and
+/// `travis_fold:end:<name>` around the block. Time elapsed is recognized
+/// similarly with `travis_time:[start|end]:<name>`. These are undocumented, but
+/// can easily be deduced from source code of the [Travis build commands].
+///
+/// [Travis build commands]:
+/// https://github.com/travis-ci/travis-build/blob/f603c0089/lib/travis/build/templates/header.sh
+pub struct OutputFolder {
+    name: String,
+    start_time: SystemTime, // we need SystemTime to get the UNIX timestamp.
+}
+
+impl OutputFolder {
+    /// Creates a new output folder with the given group name.
+    pub fn new(name: String) -> OutputFolder {
+        // "\r" moves the cursor to the beginning of the line, and "\x1b[0K" is
+        // the ANSI escape code to clear from the cursor to end of line.
+        // Travis seems to have trouble when _not_ using "\r\x1b[0K", that will
+        // randomly put lines to the top of the webpage.
+        print!("travis_fold:start:{0}\r\x1b[0Ktravis_time:start:{0}\r\x1b[0K", name);
+        OutputFolder {
+            name,
+            start_time: SystemTime::now(),
+        }
+    }
+}
+
+impl Drop for OutputFolder {
+    fn drop(&mut self) {
+        use std::time::*;
+        use std::u64;
+
+        fn to_nanos(duration: Result<Duration, SystemTimeError>) -> u64 {
+            match duration {
+                Ok(d) => d.as_secs() * 1_000_000_000 + d.subsec_nanos() as u64,
+                Err(_) => u64::MAX,
+            }
+        }
+
+        let end_time = SystemTime::now();
+        let duration = end_time.duration_since(self.start_time);
+        let start = self.start_time.duration_since(UNIX_EPOCH);
+        let finish = end_time.duration_since(UNIX_EPOCH);
+        println!(
+            "travis_fold:end:{0}\r\x1b[0K\n\
+                travis_time:end:{0}:start={1},finish={2},duration={3}\r\x1b[0K",
+            self.name,
+            to_nanos(start),
+            to_nanos(finish),
+            to_nanos(duration)
+        );
+        io::stdout().flush().unwrap();
+    }
+}
+
+/// The CI environment rustbuild is running in. This mainly affects how the logs
+/// are printed.
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+pub enum CiEnv {
+    /// Not a CI environment.
+    None,
+    /// The Travis CI environment, for Linux (including Docker) and macOS builds.
+    Travis,
+    /// The AppVeyor environment, for Windows builds.
+    AppVeyor,
+}
+
+impl CiEnv {
+    /// Obtains the current CI environment.
+    pub fn current() -> CiEnv {
+        if env::var("TRAVIS").ok().map_or(false, |e| &*e == "true") {
+            CiEnv::Travis
+        } else if env::var("APPVEYOR").ok().map_or(false, |e| &*e == "True") {
+            CiEnv::AppVeyor
+        } else {
+            CiEnv::None
+        }
+    }
+
+    /// If in a CI environment, forces the command to run with colors.
+    pub fn force_coloring_in_ci(self, cmd: &mut Command) {
+        if self != CiEnv::None {
+            // Due to use of stamp/docker, the output stream of rustbuild is not
+            // a TTY in CI, so coloring is by-default turned off.
+            // The explicit `TERM=xterm` environment is needed for
+            // `--color always` to actually work. This env var was lost when
+            // compiling through the Makefile. Very strange.
+            cmd.env("TERM", "xterm").args(&["--color", "always"]);
+        }
+    }
+}
\ No newline at end of file
index bb9a860574dd2f175245cd6e8e97fc911d8787c7..a9b1167b6faf7460eb19e2b374c551cc6218c076 100755 (executable)
@@ -21,6 +21,9 @@ root_dir="`dirname $src_dir`"
 
 source "$ci_dir/shared.sh"
 
+travis_fold start build_docker
+travis_time_start
+
 if [ -f "$docker_dir/$image/Dockerfile" ]; then
     retry docker \
       build \
@@ -44,6 +47,9 @@ else
     exit 1
 fi
 
+travis_fold end build_docker
+travis_time_finish
+
 objdir=$root_dir/obj
 
 mkdir -p $HOME/.cargo
@@ -72,6 +78,7 @@ exec docker \
   --env DEPLOY=$DEPLOY \
   --env DEPLOY_ALT=$DEPLOY_ALT \
   --env LOCAL_USER_ID=`id -u` \
+  --env TRAVIS=${TRAVIS-false} \
   --volume "$HOME/.cargo:/cargo" \
   --volume "$HOME/rustsrc:$HOME/rustsrc" \
   --privileged \
index 0a17bd3b5710f6430a2817704b7bbfdc51f95dfd..282da009eac35c3f3e29c88b1e4e70c7c2ae1214 100755 (executable)
@@ -13,11 +13,11 @@ set -o errexit
 set -o pipefail
 set -o nounset
 
-set -o xtrace
-
 ci_dir=$(cd $(dirname $0) && pwd)
 . "$ci_dir/shared.sh"
 
+travis_fold start init_repo
+
 REPO_DIR="$1"
 CACHE_DIR="$2"
 
@@ -38,6 +38,7 @@ fi
 
 # Wipe the cache if it's not valid, or mark it as invalid while we update it
 if [ ! -f "$cache_valid_file" ]; then
+    echo "Invalid cache, wiping ($cache_valid_file missing)"
     rm -rf "$CACHE_DIR"
     mkdir "$CACHE_DIR"
 else
@@ -54,10 +55,14 @@ else
         rm -rf "$CACHE_DIR"
         mkdir "$CACHE_DIR"
     else
+        echo "Valid cache ($cache_valid_file exists)"
         rm "$cache_valid_file"
     fi
 fi
 
+travis_fold start update_cache
+travis_time_start
+
 # Update the cache (a pristine copy of the rust source master)
 if [ ! -d "$cache_src_dir/.git" ]; then
     retry sh -c "rm -rf $cache_src_dir && mkdir -p $cache_src_dir && \
@@ -69,8 +74,15 @@ retry sh -c "cd $cache_src_dir && \
     git submodule deinit -f . && git submodule sync && git submodule update --init"
 
 # Cache was updated without errors, mark it as valid
+echo "Refreshed cache (touch $cache_valid_file)"
 touch "$cache_valid_file"
 
+travis_fold end update_cache
+travis_time_finish
+
+travis_fold start update_submodules
+travis_time_start
+
 # Update the submodules of the repo we're in, using the pristine repo as
 # a cache for any object files
 # No, `git submodule foreach` won't work:
@@ -94,3 +106,8 @@ for module in $modules; do
     retry sh -c "git submodule deinit -f $module && \
         git submodule update --init --reference $cache_src_dir/$module $module"
 done
+
+travis_fold end update_submodules
+travis_time_finish
+
+travis_fold end init_repo
index c6510120b47ae7ec3fb500d71df5db6ba5dc52ff..08f5939ef7908406e25cb0beeb1f4681fb9d06ea 100755 (executable)
@@ -58,8 +58,17 @@ else
   fi
 fi
 
+travis_fold start configure
+travis_time_start
 $SRC/configure $RUST_CONFIGURE_ARGS
+travis_fold end configure
+travis_time_finish
+
+travis_fold start make-prepare
+travis_time_start
 retry make prepare
+travis_fold end make-prepare
+travis_time_finish
 
 if [ "$TRAVIS_OS_NAME" = "osx" ]; then
     ncpus=$(sysctl -n hw.ncpu)
@@ -67,12 +76,21 @@ else
     ncpus=$(grep processor /proc/cpuinfo | wc -l)
 fi
 
-set -x
-
 if [ ! -z "$SCRIPT" ]; then
   sh -x -c "$SCRIPT"
 else
-  make -j $ncpus tidy
-  make -j $ncpus
-  make $RUST_CHECK_TARGET -j $ncpus
+  do_make() {
+    travis_fold start "make-$1"
+    travis_time_start
+    echo "make -j $ncpus $1"
+    make -j $ncpus "$1"
+    local retval=$?
+    travis_fold end "make-$1"
+    travis_time_finish
+    return $retval
+  }
+
+  do_make tidy
+  do_make all
+  do_make "$RUST_CHECK_TARGET"
 fi
index f2e13fc73ae4778930fcd635a8c85f21a9e91d7a..4a08683e3ee86511f505d16a88f00b39d3a2fe5d 100644 (file)
@@ -30,3 +30,37 @@ function retry {
     }
   done
 }
+
+if ! declare -F travis_fold; then
+  if [ "${TRAVIS-false}" = 'true' ]; then
+    # This is a trimmed down copy of
+    # https://github.com/travis-ci/travis-build/blob/master/lib/travis/build/templates/header.sh
+    travis_fold() {
+      echo -en "travis_fold:$1:$2\r\033[0K"
+    }
+    travis_time_start() {
+      travis_timer_id=$(printf %08x $(( RANDOM * RANDOM )))
+      travis_start_time=$(travis_nanoseconds)
+      echo -en "travis_time:start:$travis_timer_id\r\033[0K"
+    }
+    travis_time_finish() {
+      travis_end_time=$(travis_nanoseconds)
+      local duration=$(($travis_end_time-$travis_start_time))
+      local msg="travis_time:end:$travis_timer_id"
+      echo -en "\n$msg:start=$travis_start_time,finish=$travis_end_time,duration=$duration\r\033[0K"
+    }
+    if [ $(uname) = 'Darwin' ]; then
+      travis_nanoseconds() {
+        date -u '+%s000000000'
+      }
+    else
+      travis_nanoseconds() {
+        date -u '+%s%N'
+      }
+    fi
+  else
+    travis_fold() { return 0; }
+    travis_time_start() { return 0; }
+    travis_time_finish() { return 0; }
+  fi
+fi
index 28bbcf734f8173de25288f84048483e1c41df57c..2b3ef338fad5860605a9b04b64a9e607e242136b 100644 (file)
     - [sip_hash_13](library-features/sip-hash-13.md)
     - [slice_concat_ext](library-features/slice-concat-ext.md)
     - [slice_get_slice](library-features/slice-get-slice.md)
+    - [slice_rotate](library-features/slice-rotate.md)
     - [slice_rsplit](library-features/slice-rsplit.md)
     - [sort_internals](library-features/sort-internals.md)
     - [sort_unstable](library-features/sort-unstable.md)
diff --git a/src/doc/unstable-book/src/library-features/slice-rotate.md b/src/doc/unstable-book/src/library-features/slice-rotate.md
new file mode 100644 (file)
index 0000000..77fd598
--- /dev/null
@@ -0,0 +1,7 @@
+# `slice_rotate`
+
+The tracking issue for this feature is: [#41891]
+
+[#41891]: https://github.com/rust-lang/rust/issues/41891
+
+------------------------
index 01393be9949ae2f9cdc5a2c7b4e5a8b3e6a1a3cb..49e5baad74dda4322d93ee395ba63a3999fa3f00 100644 (file)
@@ -17,7 +17,7 @@ libc = { path = "../rustc/libc_shim" }
 
 [build-dependencies]
 build_helper = { path = "../build_helper" }
-gcc = "0.3.27"
+gcc = "0.3.50"
 
 [features]
 debug = []
index 9f356e4b57912af410b56fcb4f4b7903a4c27c88..958020d0b0e0c33e3b70b803f187fc204c0f84bb 100644 (file)
@@ -13,6 +13,7 @@
 #![feature(i128_type)]
 #![feature(rand)]
 #![feature(repr_simd)]
+#![feature(slice_rotate)]
 #![feature(sort_unstable)]
 #![feature(test)]
 
index 0079f2d01036cf76d5fa956a75ce7acdb0ec127f..aa5a438b35e62341e5611755f233b1b12c7c830e 100644 (file)
@@ -195,6 +195,11 @@ fn gen_random(len: usize) -> Vec<u64> {
     rng.gen_iter::<u64>().take(len).collect()
 }
 
+fn gen_random_bytes(len: usize) -> Vec<u8> {
+    let mut rng = thread_rng();
+    rng.gen_iter::<u8>().take(len).collect()
+}
+
 fn gen_mostly_ascending(len: usize) -> Vec<u64> {
     let mut rng = thread_rng();
     let mut v = gen_ascending(len);
@@ -315,3 +320,39 @@ fn $name(b: &mut Bencher) {
 reverse!(reverse_u128, u128, |x| x as u128);
 #[repr(simd)] struct F64x4(f64, f64, f64, f64);
 reverse!(reverse_simd_f64x4, F64x4, |x| { let x = x as f64; F64x4(x,x,x,x) });
+
+macro_rules! rotate {
+    ($name:ident, $gen:expr, $len:expr, $mid:expr) => {
+        #[bench]
+        fn $name(b: &mut Bencher) {
+            let size = mem::size_of_val(&$gen(1)[0]);
+            let mut v = $gen($len * 8 / size);
+            b.iter(|| black_box(&mut v).rotate(($mid*8+size-1)/size));
+            b.bytes = (v.len() * size) as u64;
+        }
+    }
+}
+
+rotate!(rotate_tiny_by1, gen_random, 16, 1);
+rotate!(rotate_tiny_half, gen_random, 16, 16/2);
+rotate!(rotate_tiny_half_plus_one, gen_random, 16, 16/2+1);
+
+rotate!(rotate_medium_by1, gen_random, 9158, 1);
+rotate!(rotate_medium_by727_u64, gen_random, 9158, 727);
+rotate!(rotate_medium_by727_bytes, gen_random_bytes, 9158, 727);
+rotate!(rotate_medium_by727_strings, gen_strings, 9158, 727);
+rotate!(rotate_medium_half, gen_random, 9158, 9158/2);
+rotate!(rotate_medium_half_plus_one, gen_random, 9158, 9158/2+1);
+
+// Intended to use more RAM than the machine has cache
+rotate!(rotate_huge_by1, gen_random, 5*1024*1024, 1);
+rotate!(rotate_huge_by9199_u64, gen_random, 5*1024*1024, 9199);
+rotate!(rotate_huge_by9199_bytes, gen_random_bytes, 5*1024*1024, 9199);
+rotate!(rotate_huge_by9199_strings, gen_strings, 5*1024*1024, 9199);
+rotate!(rotate_huge_by9199_big, gen_big_random, 5*1024*1024, 9199);
+rotate!(rotate_huge_by1234577_u64, gen_random, 5*1024*1024, 1234577);
+rotate!(rotate_huge_by1234577_bytes, gen_random_bytes, 5*1024*1024, 1234577);
+rotate!(rotate_huge_by1234577_strings, gen_strings, 5*1024*1024, 1234577);
+rotate!(rotate_huge_by1234577_big, gen_big_random, 5*1024*1024, 1234577);
+rotate!(rotate_huge_half, gen_random, 5*1024*1024, 5*1024*1024/2);
+rotate!(rotate_huge_half_plus_one, gen_random, 5*1024*1024, 5*1024*1024/2+1);
index 72ff6575ca13725bc230059c04b0a6645119ae9e..34626326c221ce533c452920960f12f1604dec5d 100644 (file)
@@ -55,6 +55,7 @@
 #![feature(shared)]
 #![feature(slice_get_slice)]
 #![feature(slice_patterns)]
+#![cfg_attr(not(test), feature(slice_rotate))]
 #![feature(slice_rsplit)]
 #![cfg_attr(not(test), feature(sort_unstable))]
 #![feature(specialization)]
index 15efd122909ffcb10d617db4b49dca6705bf7f3d..97d6687c79b5749aaa3d69e5d0d64a373cb0f133 100644 (file)
@@ -1347,6 +1347,61 @@ pub fn sort_unstable_by_key<B, F>(&mut self, f: F)
         core_slice::SliceExt::sort_unstable_by_key(self, f);
     }
 
+    /// Permutes the slice in-place such that `self[mid..]` moves to the
+    /// beginning of the slice while `self[..mid]` moves to the end of the
+    /// slice.  Equivalently, rotates the slice `mid` places to the left
+    /// or `k = self.len() - mid` places to the right.
+    ///
+    /// This is a "k-rotation", a permutation in which item `i` moves to
+    /// position `i + k`, modulo the length of the slice.  See _Elements
+    /// of Programming_ [§10.4][eop].
+    ///
+    /// Rotation by `mid` and rotation by `k` are inverse operations.
+    ///
+    /// [eop]: https://books.google.com/books?id=CO9ULZGINlsC&pg=PA178&q=k-rotation
+    ///
+    /// # Panics
+    ///
+    /// This function will panic if `mid` is greater than the length of the
+    /// slice.  (Note that `mid == self.len()` does _not_ panic; it's a nop
+    /// rotation with `k == 0`, the inverse of a rotation with `mid == 0`.)
+    ///
+    /// # Complexity
+    ///
+    /// Takes linear (in `self.len()`) time.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(slice_rotate)]
+    ///
+    /// let mut a = [1, 2, 3, 4, 5, 6, 7];
+    /// let mid = 2;
+    /// a.rotate(mid);
+    /// assert_eq!(&a, &[3, 4, 5, 6, 7, 1, 2]);
+    /// let k = a.len() - mid;
+    /// a.rotate(k);
+    /// assert_eq!(&a, &[1, 2, 3, 4, 5, 6, 7]);
+    ///
+    /// use std::ops::Range;
+    /// fn slide<T>(slice: &mut [T], range: Range<usize>, to: usize) {
+    ///     if to < range.start {
+    ///         slice[to..range.end].rotate(range.start-to);
+    ///     } else if to > range.end {
+    ///         slice[range.start..to].rotate(range.end-range.start);
+    ///     }
+    /// }
+    /// let mut v: Vec<_> = (0..10).collect();
+    /// slide(&mut v, 1..4, 7);
+    /// assert_eq!(&v, &[0, 4, 5, 6, 1, 2, 3, 7, 8, 9]);
+    /// slide(&mut v, 6..8, 1);
+    /// assert_eq!(&v, &[0, 3, 7, 4, 5, 6, 1, 2, 8, 9]);
+    /// ```
+    #[unstable(feature = "slice_rotate", issue = "41891")]
+    pub fn rotate(&mut self, mid: usize) {
+        core_slice::SliceExt::rotate(self, mid);
+    }
+
     /// Copies the elements from `src` into `self`.
     ///
     /// The length of `src` must be the same as `self`.
index cda8c6d59987efc42e652802aaa7f82e1f9ceee7..8af8786994e407ba321a207805b7182d5debaddf 100644 (file)
 #![feature(collections)]
 #![feature(const_fn)]
 #![feature(exact_size_is_empty)]
+#![feature(iterator_step_by)]
 #![feature(pattern)]
 #![feature(placement_in_syntax)]
 #![feature(rand)]
+#![feature(slice_rotate)]
 #![feature(splice)]
-#![feature(step_by)]
 #![feature(str_escape)]
 #![feature(test)]
 #![feature(unboxed_closures)]
index 1708f98b7ee47c2ab40ff0807fec183e09de2eea..7fa65a2144e9b47d1f3f093c04fa980bc6bf5596 100644 (file)
@@ -466,6 +466,41 @@ fn test_sort_stability() {
     }
 }
 
+#[test]
+fn test_rotate() {
+    let expected: Vec<_> = (0..13).collect();
+    let mut v = Vec::new();
+
+    // no-ops
+    v.clone_from(&expected);
+    v.rotate(0);
+    assert_eq!(v, expected);
+    v.rotate(expected.len());
+    assert_eq!(v, expected);
+    let mut zst_array = [(), (), ()];
+    zst_array.rotate(2);
+
+    // happy path
+    v = (5..13).chain(0..5).collect();
+    v.rotate(8);
+    assert_eq!(v, expected);
+
+    let expected: Vec<_> = (0..1000).collect();
+
+    // small rotations in large slice, uses ptr::copy
+    v = (2..1000).chain(0..2).collect();
+    v.rotate(998);
+    assert_eq!(v, expected);
+    v = (998..1000).chain(0..998).collect();
+    v.rotate(2);
+    assert_eq!(v, expected);
+
+    // non-small prime rotation, has a few rounds of swapping
+    v = (389..1000).chain(0..389).collect();
+    v.rotate(1000-389);
+    assert_eq!(v, expected);
+}
+
 #[test]
 fn test_concat() {
     let v: [Vec<i32>; 0] = [];
index f2935c05d4f7a90ac3112b0481fdac7057562652..a992351653d7b996e2f2100c57f5c8c1c4ee82a1 100644 (file)
@@ -510,7 +510,8 @@ fn test_from_iter() {
     let u: Vec<_> = deq.iter().cloned().collect();
     assert_eq!(u, v);
 
-    let seq = (0..).step_by(2).take(256);
+    // FIXME #27741: Remove `.skip(0)` when Range::step_by is fully removed
+    let seq = (0..).skip(0).step_by(2).take(256);
     let deq: VecDeque<_> = seq.collect();
     for (i, &x) in deq.iter().enumerate() {
         assert_eq!(2 * i, x);
index 3f844b3f09e3a28648d4c3b76b30e3a9cb1f3c59..2c9cee5e7a0937cf3644a712095f375b212fa8dd 100644 (file)
@@ -16,4 +16,4 @@ core = { path = "../libcore" }
 
 [build-dependencies]
 build_helper = { path = "../build_helper" }
-gcc = "0.3.27"
+gcc = "0.3.50"
index 9f1870e56d38af2d504c0fbfc64913163078a58a..3566bbdebc2b6b1a2b2d31d18fed33827cb00936 100644 (file)
     pub fn atomic_umax_rel<T>(dst: *mut T, src: T) -> T;
     pub fn atomic_umax_acqrel<T>(dst: *mut T, src: T) -> T;
     pub fn atomic_umax_relaxed<T>(dst: *mut T, src: T) -> T;
+
+    /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction
+    /// if supported; otherwise, it is a noop.
+    /// Prefetches have no effect on the behavior of the program but can change its performance
+    /// characteristics.
+    ///
+    /// The `locality` argument must be a constant integer and is a temporal locality specifier
+    /// ranging from (0) - no locality, to (3) - extremely local keep in cache
+    #[cfg(not(stage0))]
+    pub fn prefetch_read_data<T>(data: *const T, locality: i32);
+    /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction
+    /// if supported; otherwise, it is a noop.
+    /// Prefetches have no effect on the behavior of the program but can change its performance
+    /// characteristics.
+    ///
+    /// The `locality` argument must be a constant integer and is a temporal locality specifier
+    /// ranging from (0) - no locality, to (3) - extremely local keep in cache
+    #[cfg(not(stage0))]
+    pub fn prefetch_write_data<T>(data: *const T, locality: i32);
+    /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction
+    /// if supported; otherwise, it is a noop.
+    /// Prefetches have no effect on the behavior of the program but can change its performance
+    /// characteristics.
+    ///
+    /// The `locality` argument must be a constant integer and is a temporal locality specifier
+    /// ranging from (0) - no locality, to (3) - extremely local keep in cache
+    #[cfg(not(stage0))]
+    pub fn prefetch_read_instruction<T>(data: *const T, locality: i32);
+    /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction
+    /// if supported; otherwise, it is a noop.
+    /// Prefetches have no effect on the behavior of the program but can change its performance
+    /// characteristics.
+    ///
+    /// The `locality` argument must be a constant integer and is a temporal locality specifier
+    /// ranging from (0) - no locality, to (3) - extremely local keep in cache
+    #[cfg(not(stage0))]
+    pub fn prefetch_write_instruction<T>(data: *const T, locality: i32);
 }
 
+// Empty bootstrap implementations for stage0 compilation
+#[cfg(stage0)]
+pub fn prefetch_read_data<T>(_data: *const T, _locality: i32) { /* EMPTY */ }
+#[cfg(stage0)]
+pub fn prefetch_write_data<T>(_data: *const T, _locality: i32) { /* EMPTY */ }
+#[cfg(stage0)]
+pub fn prefetch_read_instruction<T>(_data: *const T, _locality: i32) { /* EMPTY */ }
+#[cfg(stage0)]
+pub fn prefetch_write_instruction<T>(_data: *const T, _locality: i32) { /* EMPTY */ }
+
 extern "rust-intrinsic" {
 
     pub fn atomic_fence();
index 07aed65f7a05709b9725529e27b977c1b91e3aef..34563c88d0ad13b0b6685c01c736371a728644e1 100644 (file)
 pub use self::range::Step;
 #[unstable(feature = "step_by", reason = "recent addition",
            issue = "27741")]
+#[rustc_deprecated(since = "1.19.0",
+                   reason = "replaced by `iter::StepBy`")]
+#[allow(deprecated)]
 pub use self::range::StepBy as DeprecatedStepBy;
 
 #[stable(feature = "rust1", since = "1.0.0")]
index c0313333ea9ee41d604afcbc133968fc6606e3b6..9aea4477fb7fc604027231739c7045074b1aebeb 100644 (file)
@@ -252,6 +252,9 @@ fn steps_between_by_one(start: &Self, end: &Self) -> Option<usize> {
 #[derive(Clone, Debug)]
 #[unstable(feature = "step_by", reason = "recent addition",
            issue = "27741")]
+#[rustc_deprecated(since = "1.19.0",
+                   reason = "replaced by `iter::StepBy`")]
+#[allow(deprecated)]
 pub struct StepBy<A, R> {
     step_by: A,
     range: R,
@@ -272,6 +275,9 @@ impl<A: Step> ops::RangeFrom<A> {
     /// ```
     #[unstable(feature = "step_by", reason = "recent addition",
                issue = "27741")]
+    #[rustc_deprecated(since = "1.19.0",
+                       reason = "replaced by `Iterator::step_by`")]
+    #[allow(deprecated)]
     pub fn step_by(self, by: A) -> StepBy<A, Self> {
         StepBy {
             step_by: by,
@@ -297,6 +303,9 @@ impl<A: Step> ops::Range<A> {
     /// ```
     #[unstable(feature = "step_by", reason = "recent addition",
                issue = "27741")]
+    #[rustc_deprecated(since = "1.19.0",
+                       reason = "replaced by `Iterator::step_by`")]
+    #[allow(deprecated)]
     pub fn step_by(self, by: A) -> StepBy<A, Self> {
         StepBy {
             step_by: by,
@@ -321,6 +330,9 @@ impl<A: Step> ops::RangeInclusive<A> {
     /// ```
     #[unstable(feature = "step_by", reason = "recent addition",
                issue = "27741")]
+    #[rustc_deprecated(since = "1.19.0",
+                       reason = "replaced by `Iterator::step_by`")]
+    #[allow(deprecated)]
     pub fn step_by(self, by: A) -> StepBy<A, Self> {
         StepBy {
             step_by: by,
@@ -331,6 +343,7 @@ pub fn step_by(self, by: A) -> StepBy<A, Self> {
 
 #[unstable(feature = "step_by", reason = "recent addition",
            issue = "27741")]
+#[allow(deprecated)]
 impl<A> Iterator for StepBy<A, ops::RangeFrom<A>> where
     A: Clone,
     for<'a> &'a A: Add<&'a A, Output = A>
@@ -351,11 +364,13 @@ fn size_hint(&self) -> (usize, Option<usize>) {
 }
 
 #[unstable(feature = "fused", issue = "35602")]
+#[allow(deprecated)]
 impl<A> FusedIterator for StepBy<A, ops::RangeFrom<A>>
     where A: Clone, for<'a> &'a A: Add<&'a A, Output = A> {}
 
 #[unstable(feature = "step_by", reason = "recent addition",
            issue = "27741")]
+#[allow(deprecated)]
 impl<A: Step + Clone> Iterator for StepBy<A, ops::Range<A>> {
     type Item = A;
 
@@ -393,11 +408,13 @@ fn size_hint(&self) -> (usize, Option<usize>) {
 }
 
 #[unstable(feature = "fused", issue = "35602")]
+#[allow(deprecated)]
 impl<A: Step + Clone> FusedIterator for StepBy<A, ops::Range<A>> {}
 
 #[unstable(feature = "inclusive_range",
            reason = "recently added, follows RFC",
            issue = "28237")]
+#[allow(deprecated)]
 impl<A: Step + Clone> Iterator for StepBy<A, ops::RangeInclusive<A>> {
     type Item = A;
 
@@ -437,6 +454,7 @@ fn size_hint(&self) -> (usize, Option<usize>) {
 }
 
 #[unstable(feature = "fused", issue = "35602")]
+#[allow(deprecated)]
 impl<A: Step + Clone> FusedIterator for StepBy<A, ops::RangeInclusive<A>> {}
 
 macro_rules! range_exact_iter_impl {
index cef3682fd94d74859a69f0207b2796555520154a..b13e19c0306947e2c893d77adc066d838dc83950 100644 (file)
@@ -51,6 +51,7 @@
 use marker::{Copy, Send, Sync, Sized, self};
 use iter_private::TrustedRandomAccess;
 
+mod rotate;
 mod sort;
 
 #[repr(C)]
@@ -202,6 +203,9 @@ unsafe fn get_unchecked_mut<I>(&mut self, index: I) -> &mut I::Output
     #[stable(feature = "core", since = "1.6.0")]
     fn ends_with(&self, needle: &[Self::Item]) -> bool where Self::Item: PartialEq;
 
+    #[unstable(feature = "slice_rotate", issue = "41891")]
+    fn rotate(&mut self, mid: usize);
+
     #[stable(feature = "clone_from_slice", since = "1.7.0")]
     fn clone_from_slice(&mut self, src: &[Self::Item]) where Self::Item: Clone;
 
@@ -635,6 +639,16 @@ fn binary_search<Q: ?Sized>(&self, x: &Q) -> Result<usize, usize>
         self.binary_search_by(|p| p.borrow().cmp(x))
     }
 
+    fn rotate(&mut self, mid: usize) {
+        assert!(mid <= self.len());
+        let k = self.len() - mid;
+
+        unsafe {
+            let p = self.as_mut_ptr();
+            rotate::ptr_rotate(mid, p.offset(mid as isize), k);
+        }
+    }
+
     #[inline]
     fn clone_from_slice(&mut self, src: &[T]) where T: Clone {
         assert!(self.len() == src.len(),
diff --git a/src/libcore/slice/rotate.rs b/src/libcore/slice/rotate.rs
new file mode 100644 (file)
index 0000000..3b9ae56
--- /dev/null
@@ -0,0 +1,112 @@
+// Copyright 2012-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 cmp;
+use mem;
+use ptr;
+
+/// Rotation is much faster if it has access to a little bit of memory. This
+/// union provides a RawVec-like interface, but to a fixed-size stack buffer.
+#[allow(unions_with_drop_fields)]
+union RawArray<T> {
+    /// Ensure this is appropriately aligned for T, and is big
+    /// enough for two elements even if T is enormous.
+    typed: [T; 2],
+    /// For normally-sized types, especially things like u8, having more
+    /// than 2 in the buffer is necessary for usefulness, so pad it out
+    /// enough to be helpful, but not so big as to risk overflow.
+    _extra: [usize; 32],
+}
+
+impl<T> RawArray<T> {
+    fn new() -> Self {
+        unsafe { mem::uninitialized() }
+    }
+    fn ptr(&self) -> *mut T {
+        unsafe { &self.typed as *const T as *mut T }
+    }
+    fn cap() -> usize {
+        if mem::size_of::<T>() == 0 {
+            usize::max_value()
+        } else {
+            mem::size_of::<Self>() / mem::size_of::<T>()
+        }
+    }
+}
+
+/// Rotates the range `[mid-left, mid+right)` such that the element at `mid`
+/// becomes the first element.  Equivalently, rotates the range `left`
+/// elements to the left or `right` elements to the right.
+///
+/// # Safety
+///
+/// The specified range must be valid for reading and writing.
+/// The type `T` must have non-zero size.
+///
+/// # Algorithm
+///
+/// For longer rotations, swap the left-most `delta = min(left, right)`
+/// elements with the right-most `delta` elements.  LLVM vectorizes this,
+/// which is profitable as we only reach this step for a "large enough"
+/// rotation.  Doing this puts `delta` elements on the larger side into the
+/// correct position, leaving a smaller rotate problem.  Demonstration:
+///
+/// ```text
+/// [ 6 7 8 9 10 11 12 13 . 1 2 3 4 5 ]
+/// 1 2 3 4 5 [ 11 12 13 . 6 7 8 9 10 ]
+/// 1 2 3 4 5 [ 8 9 10 . 6 7 ] 11 12 13
+/// 1 2 3 4 5 6 7 [ 10 . 8 9 ] 11 12 13
+/// 1 2 3 4 5 6 7 [ 9 . 8 ] 10 11 12 13
+/// 1 2 3 4 5 6 7 8 [ . ] 9 10 11 12 13
+/// ```
+///
+/// Once the rotation is small enough, copy some elements into a stack
+/// buffer, `memmove` the others, and move the ones back from the buffer.
+pub unsafe fn ptr_rotate<T>(mut left: usize, mid: *mut T, mut right: usize) {
+    loop {
+        let delta = cmp::min(left, right);
+        if delta <= RawArray::<T>::cap() {
+            break;
+        }
+
+        ptr_swap_n(
+            mid.offset(-(left as isize)),
+            mid.offset((right-delta) as isize),
+            delta);
+
+        if left <= right {
+            right -= delta;
+        } else {
+            left -= delta;
+        }
+    }
+
+    let rawarray = RawArray::new();
+    let buf = rawarray.ptr();
+
+    let dim = mid.offset(-(left as isize)).offset(right as isize);
+    if left <= right {
+        ptr::copy_nonoverlapping(mid.offset(-(left as isize)), buf, left);
+        ptr::copy(mid, mid.offset(-(left as isize)), right);
+        ptr::copy_nonoverlapping(buf, dim, left);
+    }
+    else {
+        ptr::copy_nonoverlapping(mid, buf, right);
+        ptr::copy(mid.offset(-(left as isize)), dim, left);
+        ptr::copy_nonoverlapping(buf, mid.offset(-(left as isize)), right);
+    }
+}
+
+unsafe fn ptr_swap_n<T>(a: *mut T, b: *mut T, n: usize) {
+    for i in 0..n {
+        // These are nonoverlapping, so use mem::swap instead of ptr::swap
+        mem::swap(&mut *a.offset(i as isize), &mut *b.offset(i as isize));
+    }
+}
index 44d5936c63edd5c6d6e0b256a4401dc3e50a3824..4f9951cd1539931c06dfad7d0e0fb64fb9f51a53 100644 (file)
 use core::{i8, i16, isize};
 use core::usize;
 
+// FIXME #27741: This is here to simplify calling Iterator::step_by. Remove
+// once Range::step_by is completely gone (not just deprecated).
+trait IterEx: Sized {
+    fn iter_step_by(self, n: usize) -> StepBy<Self>;
+}
+impl<I:Iterator> IterEx for I {
+    fn iter_step_by(self, n: usize) -> StepBy<Self> { self.step_by(n) }
+}
+
 #[test]
 fn test_lt() {
     let empty: [isize; 0] = [];
@@ -67,7 +76,7 @@ fn test_multi_iter() {
 
 #[test]
 fn test_counter_from_iter() {
-    let it = (0..).step_by(5).take(10);
+    let it = (0..).iter_step_by(5).take(10);
     let xs: Vec<isize> = FromIterator::from_iter(it);
     assert_eq!(xs, [0, 5, 10, 15, 20, 25, 30, 35, 40, 45]);
 }
@@ -85,7 +94,7 @@ fn test_iterator_chain() {
     }
     assert_eq!(i, expected.len());
 
-    let ys = (30..).step_by(10).take(4);
+    let ys = (30..).iter_step_by(10).take(4);
     let it = xs.iter().cloned().chain(ys);
     let mut i = 0;
     for x in it {
@@ -147,15 +156,13 @@ fn test_iterator_chain_find() {
 #[test]
 fn test_iterator_step_by() {
     // Identity
-    // Replace with (0..).step_by(1) after Range::step_by gets removed
-    let mut it = Iterator::step_by((0..), 1).take(3);
+    let mut it = (0..).iter_step_by(1).take(3);
     assert_eq!(it.next(), Some(0));
     assert_eq!(it.next(), Some(1));
     assert_eq!(it.next(), Some(2));
     assert_eq!(it.next(), None);
 
-    // Replace with (0..).step_by(3) after Range::step_by gets removed
-    let mut it = Iterator::step_by((0..), 3).take(4);
+    let mut it = (0..).iter_step_by(3).take(4);
     assert_eq!(it.next(), Some(0));
     assert_eq!(it.next(), Some(3));
     assert_eq!(it.next(), Some(6));
@@ -166,8 +173,7 @@ fn test_iterator_step_by() {
 #[test]
 #[should_panic]
 fn test_iterator_step_by_zero() {
-    // Replace with (0..).step_by(0) after Range::step_by gets removed
-    let mut it = Iterator::step_by((0..), 0);
+    let mut it = (0..).iter_step_by(0);
     it.next();
 }
 
@@ -246,7 +252,7 @@ fn test(self) -> bool { true }
 
 #[test]
 fn test_filter_map() {
-    let it = (0..).step_by(1).take(10)
+    let it = (0..).iter_step_by(1).take(10)
         .filter_map(|x| if x % 2 == 0 { Some(x*x) } else { None });
     assert_eq!(it.collect::<Vec<usize>>(), [0*0, 2*2, 4*4, 6*6, 8*8]);
 }
@@ -648,7 +654,7 @@ fn add(old: &mut isize, new: &usize) -> Option<f64> {
 fn test_iterator_flat_map() {
     let xs = [0, 3, 6];
     let ys = [0, 1, 2, 3, 4, 5, 6, 7, 8];
-    let it = xs.iter().flat_map(|&x| (x..).step_by(1).take(3));
+    let it = xs.iter().flat_map(|&x| (x..).iter_step_by(1).take(3));
     let mut i = 0;
     for x in it {
         assert_eq!(x, ys[i]);
@@ -674,13 +680,13 @@ fn test_inspect() {
 #[test]
 fn test_cycle() {
     let cycle_len = 3;
-    let it = (0..).step_by(1).take(cycle_len).cycle();
+    let it = (0..).iter_step_by(1).take(cycle_len).cycle();
     assert_eq!(it.size_hint(), (usize::MAX, None));
     for (i, x) in it.take(100).enumerate() {
         assert_eq!(i % cycle_len, x);
     }
 
-    let mut it = (0..).step_by(1).take(0).cycle();
+    let mut it = (0..).iter_step_by(1).take(0).cycle();
     assert_eq!(it.size_hint(), (0, Some(0)));
     assert_eq!(it.next(), None);
 }
@@ -759,7 +765,7 @@ fn test_iterator_min() {
 
 #[test]
 fn test_iterator_size_hint() {
-    let c = (0..).step_by(1);
+    let c = (0..).iter_step_by(1);
     let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
     let v2 = &[10, 11, 12];
     let vi = v.iter();
@@ -1081,6 +1087,8 @@ fn test_range() {
 
 #[test]
 fn test_range_step() {
+    #![allow(deprecated)]
+
     assert_eq!((0..20).step_by(5).collect::<Vec<isize>>(), [0, 5, 10, 15]);
     assert_eq!((20..0).step_by(-5).collect::<Vec<isize>>(), [20, 15, 10, 5]);
     assert_eq!((20..0).step_by(-6).collect::<Vec<isize>>(), [20, 14, 8, 2]);
index e9f62dfbaed76c140bd866b11d5babea9c205884..505e51fa80b333b651eb10c089b1378272620dc0 100644 (file)
@@ -30,6 +30,7 @@
 #![feature(raw)]
 #![feature(sip_hash_13)]
 #![feature(slice_patterns)]
+#![feature(slice_rotate)]
 #![feature(sort_internals)]
 #![feature(sort_unstable)]
 #![feature(specialization)]
index 15047204e50d609699e5df8bcee730d9aa37ee6c..e5d6b53b570628b688e8e623a0b6052f5dab1f0d 100644 (file)
@@ -238,6 +238,22 @@ fn test_find_rfind() {
     assert_eq!(v.iter().rfind(|&&x| x <= 3), Some(&3));
 }
 
+#[test]
+fn test_rotate() {
+    const N: usize = 600;
+    let a: &mut [_] = &mut [0; N];
+    for i in 0..N {
+        a[i] = i;
+    }
+
+    a.rotate(42);
+    let k = N - 42;
+
+    for i in 0..N {
+        assert_eq!(a[(i+k)%N], i);
+    }
+}
+
 #[test]
 fn sort_unstable() {
     let mut v = [0; 600];
index 5423da9c81c02880c991871943c00b6442751fe6..e5c611460f73897ee3986277a60f9f8dd43974e5 100644 (file)
@@ -11,4 +11,4 @@ crate-type = ["dylib"]
 
 [build-dependencies]
 build_helper = { path = "../build_helper" }
-gcc = "0.3.27"
+gcc = "0.3.50"
index daed41f04700d95afb4d145db71344329495b5f8..72715cf6bc74d6e65a49ee5812f5bbcc760e9c5f 100644 (file)
@@ -254,7 +254,7 @@ and `...` are whatever edges the `/* compute value */` closure creates.
 In particular, using the memoize helper is much better than writing
 the obvious code yourself:
 
-```
+```rust
 if let Some(result) = map.get(key) {
     return result;
 }
index a947f6aeff709af0ebc9ec71a47658cc2988e084..8308c756c0532f1ecaddea56bc018e671a857ff2 100644 (file)
@@ -8,12 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use rustc_serialize::{Encodable, Decodable, Encoder, Decoder};
 use rustc_data_structures::stable_hasher;
 use std::mem;
 use std::slice;
 
-#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Clone, Copy)]
+#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Clone, Copy, RustcEncodable, RustcDecodable)]
 pub struct Fingerprint(u64, u64);
 
 impl Fingerprint {
@@ -37,23 +36,6 @@ pub fn to_hex(&self) -> String {
     }
 }
 
-impl Encodable for Fingerprint {
-    #[inline]
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        s.emit_u64(self.0.to_le())?;
-        s.emit_u64(self.1.to_le())
-    }
-}
-
-impl Decodable for Fingerprint {
-    #[inline]
-    fn decode<D: Decoder>(d: &mut D) -> Result<Fingerprint, D::Error> {
-        let _0 = u64::from_le(d.read_u64()?);
-        let _1 = u64::from_le(d.read_u64()?);
-        Ok(Fingerprint(_0, _1))
-    }
-}
-
 impl ::std::fmt::Display for Fingerprint {
     fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
         write!(formatter, "{:x}-{:x}", self.0, self.1)
index f97daa22ff6624c26487dfe8b9a5e1d1a1c43fb0..f2eea014dd3020244ec026004bd96dc780ff69b1 100644 (file)
@@ -17,4 +17,4 @@ rustc_bitflags = { path = "../librustc_bitflags" }
 
 [build-dependencies]
 build_helper = { path = "../build_helper" }
-gcc = "0.3.27"
+gcc = "0.3.50"
index 4ccc85257f3c990ba313df23fa87a9de43476721..7355b399360a30485c08670cb4b88d0b3edb3352 100644 (file)
@@ -25,3 +25,6 @@ rustc_platform_intrinsics = { path = "../librustc_platform_intrinsics" }
 serialize = { path = "../libserialize" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
+
+[target."cfg(windows)".dependencies]
+gcc = "0.3.50"
index e40267238801cb791e63a600821b493aa769e84b..ee92a4b4a2dfeaf170998eabe3dd56fb523de8b1 100644 (file)
@@ -12,7 +12,6 @@
 use super::linker::Linker;
 use super::rpath::RPathConfig;
 use super::rpath;
-use super::msvc;
 use metadata::METADATA_FILENAME;
 use rustc::session::config::{self, NoDebugInfo, OutputFilenames, Input, OutputType};
 use rustc::session::filesearch;
@@ -142,20 +141,41 @@ pub fn build_link_meta(incremental_hashes_map: &IncrementalHashesMap) -> LinkMet
     return r;
 }
 
-// The third parameter is for an extra path to add to PATH for MSVC
-// cross linkers for host toolchain DLL dependencies
-pub fn get_linker(sess: &Session) -> (String, Command, Option<PathBuf>) {
+// The third parameter is for an env vars, used to set up the path for MSVC
+// to find its DLLs
+pub fn get_linker(sess: &Session) -> (String, Command, Vec<(OsString, OsString)>) {
     if let Some(ref linker) = sess.opts.cg.linker {
-        (linker.clone(), Command::new(linker), None)
+        (linker.clone(), Command::new(linker), vec![])
     } else if sess.target.target.options.is_like_msvc {
-        let (cmd, host) = msvc::link_exe_cmd(sess);
-        ("link.exe".to_string(), cmd, host)
+        let (cmd, envs) = msvc_link_exe_cmd(sess);
+        ("link.exe".to_string(), cmd, envs)
     } else {
         (sess.target.target.options.linker.clone(),
-         Command::new(&sess.target.target.options.linker), None)
+         Command::new(&sess.target.target.options.linker), vec![])
     }
 }
 
+#[cfg(windows)]
+pub fn msvc_link_exe_cmd(sess: &Session) -> (Command, Vec<(OsString, OsString)>) {
+    use gcc::windows_registry;
+
+    let target = &sess.opts.target_triple;
+    let tool = windows_registry::find_tool(target, "link.exe");
+
+    if let Some(tool) = tool {
+        let envs = tool.env().to_vec();
+        (tool.to_command(), envs)
+    } else {
+        debug!("Failed to locate linker.");
+        (Command::new("link.exe"), vec![])
+    }
+}
+
+#[cfg(not(windows))]
+pub fn msvc_link_exe_cmd(_sess: &Session) -> (Command, Vec<(OsString, OsString)>) {
+    (Command::new("link.exe"), vec![])
+}
+
 pub fn get_ar_prog(sess: &Session) -> String {
     sess.opts.cg.ar.clone().unwrap_or_else(|| {
         sess.target.target.options.ar.clone()
@@ -706,8 +726,9 @@ fn link_natively(sess: &Session,
     let flavor = sess.linker_flavor();
 
     // The invocations of cc share some flags across platforms
-    let (pname, mut cmd, extra) = get_linker(sess);
-    cmd.env("PATH", command_path(sess, extra));
+    let (pname, mut cmd, envs) = get_linker(sess);
+    // This will set PATH on MSVC
+    cmd.envs(envs);
 
     let root = sess.target_filesearch(PathKind::Native).get_lib_path();
     if let Some(args) = sess.target.target.options.pre_link_args.get(&flavor) {
diff --git a/src/librustc_trans/back/msvc/arch.rs b/src/librustc_trans/back/msvc/arch.rs
deleted file mode 100644 (file)
index c10312a..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-// 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.
-
-#![allow(non_camel_case_types, non_snake_case)]
-
-use libc::c_void;
-use std::mem;
-
-type DWORD = u32;
-type WORD = u16;
-type LPVOID = *mut c_void;
-type DWORD_PTR = usize;
-
-const PROCESSOR_ARCHITECTURE_INTEL: WORD = 0;
-const PROCESSOR_ARCHITECTURE_AMD64: WORD = 9;
-
-#[repr(C)]
-struct SYSTEM_INFO {
-    wProcessorArchitecture: WORD,
-    _wReserved: WORD,
-    _dwPageSize: DWORD,
-    _lpMinimumApplicationAddress: LPVOID,
-    _lpMaximumApplicationAddress: LPVOID,
-    _dwActiveProcessorMask: DWORD_PTR,
-    _dwNumberOfProcessors: DWORD,
-    _dwProcessorType: DWORD,
-    _dwAllocationGranularity: DWORD,
-    _wProcessorLevel: WORD,
-    _wProcessorRevision: WORD,
-}
-
-extern "system" {
-    fn GetNativeSystemInfo(lpSystemInfo: *mut SYSTEM_INFO);
-}
-
-pub enum Arch {
-    X86,
-    Amd64,
-}
-
-pub fn host_arch() -> Option<Arch> {
-    let mut info = unsafe { mem::zeroed() };
-    unsafe { GetNativeSystemInfo(&mut info) };
-    match info.wProcessorArchitecture {
-        PROCESSOR_ARCHITECTURE_INTEL => Some(Arch::X86),
-        PROCESSOR_ARCHITECTURE_AMD64 => Some(Arch::Amd64),
-        _ => None,
-    }
-}
diff --git a/src/librustc_trans/back/msvc/mod.rs b/src/librustc_trans/back/msvc/mod.rs
deleted file mode 100644 (file)
index 9764888..0000000
+++ /dev/null
@@ -1,305 +0,0 @@
-// 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.
-
-//! MSVC-specific logic for linkers and such.
-//!
-//! This module contains a cross-platform interface but has a blank unix
-//! implementation. The Windows implementation builds on top of Windows native
-//! libraries (reading registry keys), so it otherwise wouldn't link on unix.
-//!
-//! Note that we don't have much special logic for finding the system linker on
-//! any other platforms, so it may seem a little odd to single out MSVC to have
-//! a good deal of code just to find the linker. Unlike Unix systems, however,
-//! the MSVC linker is not in the system PATH by default. It also additionally
-//! needs a few environment variables or command line flags to be able to link
-//! against system libraries.
-//!
-//! In order to have a nice smooth experience on Windows, the logic in this file
-//! is here to find the MSVC linker and set it up in the default configuration
-//! one would need to set up anyway. This means that the Rust compiler can be
-//! run not only in the developer shells of MSVC but also the standard cmd.exe
-//! shell or MSYS shells.
-//!
-//! As a high-level note, all logic in this module for looking up various
-//! paths/files is based on Microsoft's logic in their vcvars bat files, but
-//! comments can also be found below leading through the various code paths.
-
-// A simple macro to make this option mess easier to read
-#[cfg(windows)]
-macro_rules! otry {
-    ($expr:expr) => (match $expr {
-        Some(val) => val,
-        None => return None,
-    })
-}
-
-#[cfg(windows)]
-mod registry;
-#[cfg(windows)]
-mod arch;
-
-#[cfg(windows)]
-mod platform {
-    use std::env;
-    use std::ffi::OsString;
-    use std::fs;
-    use std::path::{Path, PathBuf};
-    use std::process::Command;
-    use rustc::session::Session;
-    use super::arch::{host_arch, Arch};
-    use super::registry::LOCAL_MACHINE;
-
-    // First we need to figure out whether the environment is already correctly
-    // configured by vcvars. We do this by looking at the environment variable
-    // `VCINSTALLDIR` which is always set by vcvars, and unlikely to be set
-    // otherwise. If it is defined, then we find `link.exe` in `PATH and trust
-    // that everything else is configured correctly.
-    //
-    // If `VCINSTALLDIR` wasn't defined (or we couldn't find the linker where
-    // it claimed it should be), then we resort to finding everything
-    // ourselves. First we find where the latest version of MSVC is installed
-    // and what version it is. Then based on the version we find the
-    // appropriate SDKs.
-    //
-    // If despite our best efforts we are still unable to find MSVC then we
-    // just blindly call `link.exe` and hope for the best.
-    //
-    // This code only supports VC 11 through 15. For versions older than that
-    // the user will need to manually execute the appropriate vcvars bat file
-    // and it should hopefully work.
-    //
-    // The second member of the tuple we return is the directory for the host
-    // linker toolchain, which is necessary when using the cross linkers.
-    pub fn link_exe_cmd(sess: &Session) -> (Command, Option<PathBuf>) {
-        let arch = &sess.target.target.arch;
-        env::var_os("VCINSTALLDIR").and_then(|_| {
-            debug!("Detected that vcvars was already run.");
-            let path = otry!(env::var_os("PATH"));
-            // Mingw has its own link which is not the link we want so we
-            // look for `cl.exe` too as a precaution.
-            env::split_paths(&path).find(|path| {
-                path.join("cl.exe").is_file()
-                    && path.join("link.exe").is_file()
-            }).map(|path| {
-                (Command::new(path.join("link.exe")), None)
-            })
-        }).or_else(|| {
-            None.or_else(|| {
-                find_msvc_latest(arch, "15.0")
-            }).or_else(|| {
-                find_msvc_latest(arch, "14.0")
-            }).or_else(|| {
-                find_msvc_12(arch)
-            }).or_else(|| {
-                find_msvc_11(arch)
-            }).map(|(cmd, path)| (cmd, Some(path)))
-        }).unwrap_or_else(|| {
-            debug!("Failed to locate linker.");
-            (Command::new("link.exe"), None)
-        })
-    }
-
-    // For MSVC 14 or newer we need to find the Universal CRT as well as either
-    // the Windows 10 SDK or Windows 8.1 SDK.
-    fn find_msvc_latest(arch: &str, ver: &str) -> Option<(Command, PathBuf)> {
-        let vcdir = otry!(get_vc_dir(ver));
-        let (mut cmd, host) = otry!(get_linker(&vcdir, arch));
-        let sub = otry!(lib_subdir(arch));
-        let ucrt = otry!(get_ucrt_dir());
-        debug!("Found Universal CRT {:?}", ucrt);
-        add_lib(&mut cmd, &ucrt.join("ucrt").join(sub));
-        if let Some(dir) = get_sdk10_dir() {
-            debug!("Found Win10 SDK {:?}", dir);
-            add_lib(&mut cmd, &dir.join("um").join(sub));
-        } else if let Some(dir) = get_sdk81_dir() {
-            debug!("Found Win8.1 SDK {:?}", dir);
-            add_lib(&mut cmd, &dir.join("um").join(sub));
-        } else {
-            return None
-        }
-        Some((cmd, host))
-    }
-
-    // For MSVC 12 we need to find the Windows 8.1 SDK.
-    fn find_msvc_12(arch: &str) -> Option<(Command, PathBuf)> {
-        let vcdir = otry!(get_vc_dir("12.0"));
-        let (mut cmd, host) = otry!(get_linker(&vcdir, arch));
-        let sub = otry!(lib_subdir(arch));
-        let sdk81 = otry!(get_sdk81_dir());
-        debug!("Found Win8.1 SDK {:?}", sdk81);
-        add_lib(&mut cmd, &sdk81.join("um").join(sub));
-        Some((cmd, host))
-    }
-
-    // For MSVC 11 we need to find the Windows 8 SDK.
-    fn find_msvc_11(arch: &str) -> Option<(Command, PathBuf)> {
-        let vcdir = otry!(get_vc_dir("11.0"));
-        let (mut cmd, host) = otry!(get_linker(&vcdir, arch));
-        let sub = otry!(lib_subdir(arch));
-        let sdk8 = otry!(get_sdk8_dir());
-        debug!("Found Win8 SDK {:?}", sdk8);
-        add_lib(&mut cmd, &sdk8.join("um").join(sub));
-        Some((cmd, host))
-    }
-
-    // A convenience function to append library paths.
-    fn add_lib(cmd: &mut Command, lib: &Path) {
-        let mut arg: OsString = "/LIBPATH:".into();
-        arg.push(lib);
-        cmd.arg(arg);
-    }
-
-    // Given a possible MSVC installation directory, we look for the linker and
-    // then add the MSVC library path.
-    fn get_linker(path: &Path, arch: &str) -> Option<(Command, PathBuf)> {
-        debug!("Looking for linker in {:?}", path);
-        bin_subdir(arch).into_iter().map(|(sub, host)| {
-            (path.join("bin").join(sub).join("link.exe"),
-             path.join("bin").join(host))
-        }).filter(|&(ref path, _)| {
-            path.is_file()
-        }).map(|(path, host)| {
-            (Command::new(path), host)
-        }).filter_map(|(mut cmd, host)| {
-            let sub = otry!(vc_lib_subdir(arch));
-            add_lib(&mut cmd, &path.join("lib").join(sub));
-            Some((cmd, host))
-        }).next()
-    }
-
-    // To find MSVC we look in a specific registry key for the version we are
-    // trying to find.
-    fn get_vc_dir(ver: &str) -> Option<PathBuf> {
-        let key = otry!(LOCAL_MACHINE
-            .open(r"SOFTWARE\Microsoft\VisualStudio\SxS\VC7".as_ref()).ok());
-        let path = otry!(key.query_str(ver).ok());
-        Some(path.into())
-    }
-
-    // To find the Universal CRT we look in a specific registry key for where
-    // all the Universal CRTs are located and then sort them asciibetically to
-    // find the newest version. While this sort of sorting isn't ideal,  it is
-    // what vcvars does so that's good enough for us.
-    fn get_ucrt_dir() -> Option<PathBuf> {
-        let key = otry!(LOCAL_MACHINE
-            .open(r"SOFTWARE\Microsoft\Windows Kits\Installed Roots".as_ref()).ok());
-        let root = otry!(key.query_str("KitsRoot10").ok());
-        let readdir = otry!(fs::read_dir(Path::new(&root).join("lib")).ok());
-        readdir.filter_map(|dir| {
-            dir.ok()
-        }).map(|dir| {
-            dir.path()
-        }).filter(|dir| {
-            dir.components().last().and_then(|c| {
-                c.as_os_str().to_str()
-            }).map(|c| {
-                c.starts_with("10.") && dir.join("ucrt").is_dir()
-            }).unwrap_or(false)
-        }).max()
-    }
-
-    // Vcvars finds the correct version of the Windows 10 SDK by looking
-    // for the include `um\Windows.h` because sometimes a given version will
-    // only have UCRT bits without the rest of the SDK. Since we only care about
-    // libraries and not includes, we instead look for `um\x64\kernel32.lib`.
-    // Since the 32-bit and 64-bit libraries are always installed together we
-    // only need to bother checking x64, making this code a tiny bit simpler.
-    // Like we do for the Universal CRT, we sort the possibilities
-    // asciibetically to find the newest one as that is what vcvars does.
-    fn get_sdk10_dir() -> Option<PathBuf> {
-        let key = otry!(LOCAL_MACHINE
-            .open(r"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v10.0".as_ref()).ok());
-        let root = otry!(key.query_str("InstallationFolder").ok());
-        let readdir = otry!(fs::read_dir(Path::new(&root).join("lib")).ok());
-        let mut dirs: Vec<_> = readdir.filter_map(|dir| dir.ok())
-            .map(|dir| dir.path()).collect();
-        dirs.sort();
-        dirs.into_iter().rev().filter(|dir| {
-            dir.join("um").join("x64").join("kernel32.lib").is_file()
-        }).next()
-    }
-
-    // Interestingly there are several subdirectories, `win7` `win8` and
-    // `winv6.3`. Vcvars seems to only care about `winv6.3` though, so the same
-    // applies to us. Note that if we were targetting kernel mode drivers
-    // instead of user mode applications, we would care.
-    fn get_sdk81_dir() -> Option<PathBuf> {
-        let key = otry!(LOCAL_MACHINE
-            .open(r"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v8.1".as_ref()).ok());
-        let root = otry!(key.query_str("InstallationFolder").ok());
-        Some(Path::new(&root).join("lib").join("winv6.3"))
-    }
-
-    fn get_sdk8_dir() -> Option<PathBuf> {
-        let key = otry!(LOCAL_MACHINE
-            .open(r"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v8.0".as_ref()).ok());
-        let root = otry!(key.query_str("InstallationFolder").ok());
-        Some(Path::new(&root).join("lib").join("win8"))
-    }
-
-    // When choosing the linker toolchain to use, we have to choose the one
-    // which matches the host architecture. Otherwise we end up in situations
-    // where someone on 32-bit Windows is trying to cross compile to 64-bit and
-    // it tries to invoke the native 64-bit linker which won't work.
-    //
-    // For the return value of this function, the first member of the tuple is
-    // the folder of the linker we will be invoking, while the second member
-    // is the folder of the host toolchain for that linker which is essential
-    // when using a cross linker. We return a Vec since on x64 there are often
-    // two linkers that can target the architecture we desire. The 64-bit host
-    // linker is preferred, and hence first, due to 64-bit allowing it more
-    // address space to work with and potentially being faster.
-    //
-    // FIXME - Figure out what happens when the host architecture is arm.
-    fn bin_subdir(arch: &str) -> Vec<(&'static str, &'static str)> {
-        match (arch, host_arch()) {
-            ("x86", Some(Arch::X86)) => vec![("", "")],
-            ("x86", Some(Arch::Amd64)) => vec![("amd64_x86", "amd64"), ("", "")],
-            ("x86_64", Some(Arch::X86)) => vec![("x86_amd64", "")],
-            ("x86_64", Some(Arch::Amd64)) => vec![("amd64", "amd64"), ("x86_amd64", "")],
-            ("arm", Some(Arch::X86)) => vec![("x86_arm", "")],
-            ("arm", Some(Arch::Amd64)) => vec![("amd64_arm", "amd64"), ("x86_arm", "")],
-            _ => vec![],
-        }
-    }
-
-    fn lib_subdir(arch: &str) -> Option<&'static str> {
-        match arch {
-            "x86" => Some("x86"),
-            "x86_64" => Some("x64"),
-            "arm" => Some("arm"),
-            _ => None,
-        }
-    }
-
-    // MSVC's x86 libraries are not in a subfolder
-    fn vc_lib_subdir(arch: &str) -> Option<&'static str> {
-        match arch {
-            "x86" => Some(""),
-            "x86_64" => Some("amd64"),
-            "arm" => Some("arm"),
-            _ => None,
-        }
-    }
-}
-
-// If we're not on Windows, then there's no registry to search through and MSVC
-// wouldn't be able to run, so we just call `link.exe` and hope for the best.
-#[cfg(not(windows))]
-mod platform {
-    use std::path::PathBuf;
-    use std::process::Command;
-    use rustc::session::Session;
-    pub fn link_exe_cmd(_sess: &Session) -> (Command, Option<PathBuf>) {
-        (Command::new("link.exe"), None)
-    }
-}
-
-pub use self::platform::*;
diff --git a/src/librustc_trans/back/msvc/registry.rs b/src/librustc_trans/back/msvc/registry.rs
deleted file mode 100644 (file)
index 8242f53..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-// 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.
-
-use std::io;
-use std::ffi::{OsString, OsStr};
-use std::os::windows::prelude::*;
-use std::ptr;
-use libc::c_long;
-
-pub type DWORD = u32;
-type LPCWSTR = *const u16;
-type LONG = c_long;
-type LPDWORD = *mut DWORD;
-type LPBYTE = *mut u8;
-
-
-const HKEY_LOCAL_MACHINE: HKEY = 0x80000002 as HKEY;
-const KEY_WOW64_32KEY: REGSAM = 0x0200;
-const KEY_READ: REGSAM = (STANDARD_RIGTS_READ | KEY_QUERY_VALUE |
-                          KEY_ENUMERATE_SUB_KEYS | KEY_NOTIFY) & !SYNCHRONIZE;
-const STANDARD_RIGTS_READ: REGSAM = READ_CONTROL;
-const READ_CONTROL: REGSAM = 0x00020000;
-const KEY_QUERY_VALUE: REGSAM = 0x0001;
-const KEY_ENUMERATE_SUB_KEYS: REGSAM = 0x0008;
-const KEY_NOTIFY: REGSAM = 0x0010;
-const SYNCHRONIZE: REGSAM = 0x00100000;
-const REG_SZ: DWORD = 1;
-const ERROR_SUCCESS: i32 = 0;
-
-pub enum __HKEY__ {}
-pub type HKEY = *mut __HKEY__;
-pub type PHKEY = *mut HKEY;
-pub type REGSAM = DWORD;
-
-#[link(name = "advapi32")]
-extern "system" {
-    fn RegOpenKeyExW(hKey: HKEY,
-                     lpSubKey: LPCWSTR,
-                     ulOptions: DWORD,
-                     samDesired: REGSAM,
-                     phkResult: PHKEY) -> LONG;
-    fn RegQueryValueExW(hKey: HKEY,
-                        lpValueName: LPCWSTR,
-                        lpReserved: LPDWORD,
-                        lpType: LPDWORD,
-                        lpData: LPBYTE,
-                        lpcbData: LPDWORD) -> LONG;
-    fn RegCloseKey(hKey: HKEY) -> LONG;
-}
-
-pub struct RegistryKey(Repr);
-
-struct OwnedKey(HKEY);
-
-enum Repr {
-    Const(HKEY),
-    Owned(OwnedKey),
-}
-
-unsafe impl Sync for RegistryKey {}
-unsafe impl Send for RegistryKey {}
-
-pub static LOCAL_MACHINE: RegistryKey = RegistryKey(Repr::Const(HKEY_LOCAL_MACHINE));
-
-impl RegistryKey {
-    fn raw(&self) -> HKEY {
-        match self.0 {
-            Repr::Const(val) => val,
-            Repr::Owned(ref val) => val.0,
-        }
-    }
-
-    pub fn open(&self, key: &OsStr) -> io::Result<RegistryKey> {
-        let key = key.encode_wide().chain(Some(0)).collect::<Vec<_>>();
-        let mut ret = ptr::null_mut();
-        let err = unsafe {
-            RegOpenKeyExW(self.raw(), key.as_ptr(), 0,
-                          KEY_READ | KEY_WOW64_32KEY, &mut ret)
-        };
-        if err == ERROR_SUCCESS {
-            Ok(RegistryKey(Repr::Owned(OwnedKey(ret))))
-        } else {
-            Err(io::Error::from_raw_os_error(err as i32))
-        }
-    }
-
-    pub fn query_str(&self, name: &str) -> io::Result<OsString> {
-        let name: &OsStr = name.as_ref();
-        let name = name.encode_wide().chain(Some(0)).collect::<Vec<_>>();
-        let mut len = 0;
-        let mut kind = 0;
-        unsafe {
-            let err = RegQueryValueExW(self.raw(), name.as_ptr(), ptr::null_mut(),
-                                       &mut kind, ptr::null_mut(), &mut len);
-            if err != ERROR_SUCCESS {
-                return Err(io::Error::from_raw_os_error(err as i32))
-            }
-            if kind != REG_SZ {
-                return Err(io::Error::new(io::ErrorKind::Other,
-                                          "registry key wasn't a string"))
-            }
-
-            // The length here is the length in bytes, but we're using wide
-            // characters so we need to be sure to halve it for the capacity
-            // passed in.
-            let mut v = Vec::with_capacity(len as usize / 2);
-            let err = RegQueryValueExW(self.raw(), name.as_ptr(), ptr::null_mut(),
-                                       ptr::null_mut(), v.as_mut_ptr() as *mut _,
-                                       &mut len);
-            if err != ERROR_SUCCESS {
-                return Err(io::Error::from_raw_os_error(err as i32))
-            }
-            v.set_len(len as usize / 2);
-
-            // Some registry keys may have a terminating nul character, but
-            // we're not interested in that, so chop it off if it's there.
-            if v[v.len() - 1] == 0 {
-                v.pop();
-            }
-            Ok(OsString::from_wide(&v))
-        }
-    }
-}
-
-impl Drop for OwnedKey {
-    fn drop(&mut self) {
-        unsafe { RegCloseKey(self.0); }
-    }
-}
index c3b16c2d07d0733ddc43b0c403ab7dc426a38455..0413b0ea5c81ccdd00ce045caeb321807daab706 100644 (file)
@@ -942,6 +942,7 @@ macro_rules! mk_struct {
     ifn!("llvm.x86.seh.recoverfp", fn(i8p, i8p) -> i8p);
 
     ifn!("llvm.assume", fn(i1) -> void);
+    ifn!("llvm.prefetch", fn(i8p, t_i32, t_i32, t_i32) -> void);
 
     if ccx.sess().opts.debuginfo != NoDebugInfo {
         ifn!("llvm.dbg.declare", fn(Type::metadata(ccx), Type::metadata(ccx)) -> void);
index 54e20f590c6718350bd22c1b4326402202f4cc63..f2e6aa3ef00b1b038fcc709c1619923574ade2d8 100644 (file)
@@ -255,7 +255,18 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bcx: &Builder<'a, 'tcx>,
             }
             C_nil(ccx)
         },
-
+        "prefetch_read_data" | "prefetch_write_data" |
+        "prefetch_read_instruction" | "prefetch_write_instruction" => {
+            let expect = ccx.get_intrinsic(&("llvm.prefetch"));
+            let (rw, cache_type) = match name {
+                "prefetch_read_data" => (0, 1),
+                "prefetch_write_data" => (1, 1),
+                "prefetch_read_instruction" => (0, 0),
+                "prefetch_write_instruction" => (1, 0),
+                _ => bug!()
+            };
+            bcx.call(expect, &[llargs[0], C_i32(ccx, rw), llargs[1], C_i32(ccx, cache_type)], None)
+        },
         "ctlz" | "cttz" | "ctpop" | "bswap" |
         "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" |
         "overflowing_add" | "overflowing_sub" | "overflowing_mul" |
index c111a3983e7ea272e0b7c0c9957e2d906776f775..71fb2e5fb202a232302192bd475e4d68096a6b7b 100644 (file)
@@ -35,6 +35,7 @@
 #![feature(slice_patterns)]
 #![feature(unicode)]
 #![feature(conservative_impl_trait)]
+#![feature(command_envs)]
 
 #![cfg_attr(stage0, unstable(feature = "rustc_private", issue = "27812"))]
 #![cfg_attr(stage0, feature(rustc_private))]
@@ -62,6 +63,8 @@
 extern crate syntax_pos;
 extern crate rustc_errors as errors;
 extern crate serialize;
+#[cfg(windows)]
+extern crate gcc; // Used to locate MSVC, not gcc :)
 
 pub use base::trans_crate;
 pub use back::symbol_names::provide;
@@ -77,8 +80,7 @@ pub mod back {
     pub(crate) mod symbol_export;
     pub(crate) mod symbol_names;
     pub mod write;
-    mod msvc;
-    mod rpath;
+    pub mod rpath;
 }
 
 mod diagnostics;
index 60067e6a6ec0238e9c8da62e73ec9f60ed71e31c..daf202cd7973150c7895a375e59f2bd47a6a8213 100644 (file)
@@ -133,6 +133,14 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                   ],
                tcx.mk_nil())
             }
+            "prefetch_read_data" | "prefetch_write_data" |
+            "prefetch_read_instruction" | "prefetch_write_instruction" => {
+                (1, vec![tcx.mk_ptr(ty::TypeAndMut {
+                          ty: param(0),
+                          mutbl: hir::MutImmutable
+                         }), tcx.types.i32],
+                    tcx.mk_nil())
+            }
             "drop_in_place" => {
                 (1, vec![tcx.mk_mut_ptr(param(0))], tcx.mk_nil())
             }
index 0e8a6606ae79f387aca5d2d7941e2225a98e75af..68f03d32e83cf267237be23ea61b8ad83f5077dd 100644 (file)
@@ -30,4 +30,4 @@ pulldown-cmark = { version = "0.0.14", default-features = false }
 
 [build-dependencies]
 build_helper = { path = "../build_helper" }
-gcc = "0.3.27"
+gcc = "0.3.50"
index 9464ac83870d92ba946be207c0970467281ebc7d..25e55ff36e7c63ed4697c6f532f445aa5652b022 100644 (file)
@@ -1506,8 +1506,8 @@ pub enum Type {
     /// extern "ABI" fn
     BareFunction(Box<BareFunctionDecl>),
     Tuple(Vec<Type>),
-    Vector(Box<Type>),
-    FixedVector(Box<Type>, String),
+    Slice(Box<Type>),
+    Array(Box<Type>, usize),
     Never,
     Unique(Box<Type>),
     RawPointer(Mutability, Box<Type>),
@@ -1573,10 +1573,8 @@ impl Type {
     pub fn primitive_type(&self) -> Option<PrimitiveType> {
         match *self {
             Primitive(p) | BorrowedRef { type_: box Primitive(p), ..} => Some(p),
-            Vector(..) | BorrowedRef{ type_: box Vector(..), ..  } => Some(PrimitiveType::Slice),
-            FixedVector(..) | BorrowedRef { type_: box FixedVector(..), .. } => {
-                Some(PrimitiveType::Array)
-            }
+            Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice),
+            Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array),
             Tuple(..) => Some(PrimitiveType::Tuple),
             RawPointer(..) => Some(PrimitiveType::RawPointer),
             _ => None,
@@ -1717,11 +1715,11 @@ fn clean(&self, cx: &DocContext) -> Type {
                 BorrowedRef {lifetime: lifetime, mutability: m.mutbl.clean(cx),
                              type_: box m.ty.clean(cx)}
             }
-            TySlice(ref ty) => Vector(box ty.clean(cx)),
+            TySlice(ref ty) => Slice(box ty.clean(cx)),
             TyArray(ref ty, length) => {
                 use rustc::middle::const_val::eval_length;
                 let n = eval_length(cx.tcx, length, "array length").unwrap();
-                FixedVector(box ty.clean(cx), n.to_string())
+                Array(box ty.clean(cx), n)
             },
             TyTup(ref tys) => Tuple(tys.clean(cx)),
             TyPath(hir::QPath::Resolved(None, ref path)) => {
@@ -1832,9 +1830,8 @@ fn clean(&self, cx: &DocContext) -> Type {
             ty::TyUint(uint_ty) => Primitive(uint_ty.into()),
             ty::TyFloat(float_ty) => Primitive(float_ty.into()),
             ty::TyStr => Primitive(PrimitiveType::Str),
-            ty::TySlice(ty) => Vector(box ty.clean(cx)),
-            ty::TyArray(ty, i) => FixedVector(box ty.clean(cx),
-                                              format!("{}", i)),
+            ty::TySlice(ty) => Slice(box ty.clean(cx)),
+            ty::TyArray(ty, n) => Array(box ty.clean(cx), n),
             ty::TyRawPtr(mt) => RawPointer(mt.mutbl.clean(cx), box mt.ty.clean(cx)),
             ty::TyRef(r, mt) => BorrowedRef {
                 lifetime: r.clean(cx),
index 6111ea073dd1906b92e102615026e5210cda3a9c..86660c28f80ad848aea2e827034790259ed3d104 100644 (file)
@@ -25,7 +25,6 @@
 use clean::{self, PrimitiveType};
 use core::DocAccessLevels;
 use html::item_type::ItemType;
-use html::escape::Escape;
 use html::render;
 use html::render::{cache, CURRENT_LOCATION_KEY};
 
@@ -643,21 +642,15 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool) -> fmt:
                 }
             }
         }
-        clean::Vector(ref t) => {
+        clean::Slice(ref t) => {
             primitive_link(f, PrimitiveType::Slice, "[")?;
             fmt::Display::fmt(t, f)?;
             primitive_link(f, PrimitiveType::Slice, "]")
         }
-        clean::FixedVector(ref t, ref s) => {
+        clean::Array(ref t, n) => {
             primitive_link(f, PrimitiveType::Array, "[")?;
             fmt::Display::fmt(t, f)?;
-            if f.alternate() {
-                primitive_link(f, PrimitiveType::Array,
-                               &format!("; {}]", s))
-            } else {
-                primitive_link(f, PrimitiveType::Array,
-                               &format!("; {}]", Escape(s)))
-            }
+            primitive_link(f, PrimitiveType::Array, &format!("; {}]", n))
         }
         clean::Never => f.write_str("!"),
         clean::RawPointer(m, ref t) => {
@@ -685,7 +678,7 @@ fn fmt_type(t: &clean::Type, f: &mut fmt::Formatter, use_absolute: bool) -> fmt:
             };
             let m = MutableSpace(mutability);
             match **ty {
-                clean::Vector(ref bt) => { // BorrowedRef{ ... Vector(T) } is &[T]
+                clean::Slice(ref bt) => { // BorrowedRef{ ... Slice(T) } is &[T]
                     match **bt {
                         clean::Generic(_) => {
                             if f.alternate() {
index 717892be2abad5f4eb4bf9855527453d81a5228e..e17918506fe5aa62868b1028a28fe4e648facb3c 100644 (file)
@@ -35,7 +35,7 @@ rustc_tsan = { path = "../librustc_tsan" }
 
 [build-dependencies]
 build_helper = { path = "../build_helper" }
-gcc = "0.3.27"
+gcc = "0.3.50"
 
 [features]
 backtrace = []
index d0e3b00d75fac43fdf2ad5f869e0f1add11be067..64c31c2a681cf2a259006caf7a14822f4a342c9b 100644 (file)
@@ -1094,11 +1094,12 @@ fn join(&mut self) -> Result<T> {
 
 /// An owned permission to join on a thread (block on its termination).
 ///
-/// A `JoinHandle` *detaches* the child thread when it is dropped.
+/// A `JoinHandle` *detaches* the associated thread when it is dropped, which
+/// means that there is no longer any handle to thread and no way to `join`
+/// on it.
 ///
 /// Due to platform restrictions, it is not possible to [`Clone`] this
-/// handle: the ability to join a child thread is a uniquely-owned
-/// permission.
+/// handle: the ability to join a thread is a uniquely-owned permission.
 ///
 /// This `struct` is created by the [`thread::spawn`] function and the
 /// [`thread::Builder::spawn`] method.
@@ -1127,6 +1128,30 @@ fn join(&mut self) -> Result<T> {
 /// }).unwrap();
 /// ```
 ///
+/// Child being detached and outliving its parent:
+///
+/// ```no_run
+/// use std::thread;
+/// use std::time::Duration;
+///
+/// let original_thread = thread::spawn(|| {
+///     let _detached_thread = thread::spawn(|| {
+///         // Here we sleep to make sure that the first thread returns before.
+///         thread::sleep(Duration::from_millis(10));
+///         // This will be called, even though the JoinHandle is dropped.
+///         println!("♫ Still alive ♫");
+///     });
+/// });
+///
+/// let _ = original_thread.join();
+/// println!("Original thread is joined.");
+///
+/// // We make sure that the new thread has time to run, before the main
+/// // thread returns.
+///
+/// thread::sleep(Duration::from_millis(1000));
+/// ```
+///
 /// [`Clone`]: ../../std/clone/trait.Clone.html
 /// [`thread::spawn`]: fn.spawn.html
 /// [`thread::Builder::spawn`]: struct.Builder.html#method.spawn
index 936a2e8b2e1be93ae0c9596d8da869a95e91e233..d9cb2b4ab7db072bcdb45252758adbd280a665d5 100644 (file)
@@ -5985,6 +5985,10 @@ fn parse_foreign_item(&mut self) -> PResult<'a, Option<ForeignItem>> {
             return Ok(Some(self.parse_item_foreign_fn(visibility, lo, attrs)?));
         }
 
+        if self.check_keyword(keywords::Const) {
+            return Err(self.span_fatal(self.span, "extern items cannot be `const`"));
+        }
+
         // FIXME #5668: this will occur for a macro invocation:
         match self.parse_macro_use_or_failure(attrs, true, false, lo, visibility)? {
             Some(item) => {
diff --git a/src/test/codegen/prefetch.rs b/src/test/codegen/prefetch.rs
new file mode 100644 (file)
index 0000000..9ca2f01
--- /dev/null
@@ -0,0 +1,75 @@
+// 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: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+#![feature(core_intrinsics)]
+
+use std::intrinsics::{prefetch_read_data, prefetch_write_data,
+                      prefetch_read_instruction, prefetch_write_instruction};
+
+#[no_mangle]
+pub fn check_prefetch_read_data(data: &[i8]) {
+    unsafe {
+        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 0, i32 0, i32 1)
+        prefetch_read_data(data.as_ptr(), 0);
+        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 0, i32 1, i32 1)
+        prefetch_read_data(data.as_ptr(), 1);
+        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 0, i32 2, i32 1)
+        prefetch_read_data(data.as_ptr(), 2);
+        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 0, i32 3, i32 1)
+        prefetch_read_data(data.as_ptr(), 3);
+    }
+}
+
+#[no_mangle]
+pub fn check_prefetch_write_data(data: &[i8]) {
+    unsafe {
+        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 1, i32 0, i32 1)
+        prefetch_write_data(data.as_ptr(), 0);
+        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 1, i32 1, i32 1)
+        prefetch_write_data(data.as_ptr(), 1);
+        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 1, i32 2, i32 1)
+        prefetch_write_data(data.as_ptr(), 2);
+        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 1, i32 3, i32 1)
+        prefetch_write_data(data.as_ptr(), 3);
+    }
+}
+
+#[no_mangle]
+pub fn check_prefetch_read_instruction(data: &[i8]) {
+    unsafe {
+        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 0, i32 0, i32 0)
+        prefetch_read_instruction(data.as_ptr(), 0);
+        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 0, i32 1, i32 0)
+        prefetch_read_instruction(data.as_ptr(), 1);
+        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 0, i32 2, i32 0)
+        prefetch_read_instruction(data.as_ptr(), 2);
+        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 0, i32 3, i32 0)
+        prefetch_read_instruction(data.as_ptr(), 3);
+    }
+}
+
+#[no_mangle]
+pub fn check_prefetch_write_instruction(data: &[i8]) {
+    unsafe {
+        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 1, i32 0, i32 0)
+        prefetch_write_instruction(data.as_ptr(), 0);
+        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 1, i32 1, i32 0)
+        prefetch_write_instruction(data.as_ptr(), 1);
+        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 1, i32 2, i32 0)
+        prefetch_write_instruction(data.as_ptr(), 2);
+        // CHECK: call void @llvm.prefetch(i8* %{{.*}}, i32 1, i32 3, i32 0)
+        prefetch_write_instruction(data.as_ptr(), 3);
+    }
+}
+
+
index e632af6c83b1d4f7950fd66e5d38da658321053d..27688867de378b471fcf12a633ee3d08580c862f 100644 (file)
@@ -12,5 +12,5 @@
 
 extern {
     const i: isize;
-    //~^ ERROR expected one of `fn`, `pub`, `static`, or `}`, found `const`
+    //~^ ERROR extern items cannot be `const`
 }
index df41e786be58fc120b37709717e79e2eedc543df..92f6f36d69d99538cd1c8fd248d99b65a3c6cddd 100644 (file)
@@ -13,6 +13,8 @@
 use std::str::FromStr;
 use std::path::PathBuf;
 
+use test::ColorConfig;
+
 #[derive(Clone, Copy, PartialEq, Debug)]
 pub enum Mode {
     CompileFail,
@@ -185,6 +187,9 @@ pub struct Config {
     // Print one character per test instead of one line
     pub quiet: bool,
 
+    // Whether to use colors in test.
+    pub color: ColorConfig,
+
     // where to find the remote test client process, if we're using it
     pub remote_test_client: Option<PathBuf>,
 
index 6fc7f9f07ac174c407a235adc4e173aea6bf8476..1bb0b765f9f1c8dc6fa4031b11f1242e1d185387 100644 (file)
@@ -37,7 +37,7 @@
 use getopts::{optopt, optflag, reqopt};
 use common::Config;
 use common::{Pretty, DebugInfoGdb, DebugInfoLldb, Mode};
-use test::TestPaths;
+use test::{TestPaths, ColorConfig};
 use util::logv;
 
 use self::header::EarlyProps;
@@ -90,6 +90,7 @@ pub fn parse_config(args: Vec<String> ) -> Config {
           optopt("", "target-rustcflags", "flags to pass to rustc for target", "FLAGS"),
           optflag("", "verbose", "run tests verbosely, showing all output"),
           optflag("", "quiet", "print one character per test instead of one line"),
+          optopt("", "color", "coloring: auto, always, never", "WHEN"),
           optopt("", "logfile", "file to log test execution to", "FILE"),
           optopt("", "target", "the target to build for", "TARGET"),
           optopt("", "host", "the host to build for", "HOST"),
@@ -147,6 +148,13 @@ fn make_absolute(path: PathBuf) -> PathBuf {
 
     let (gdb, gdb_version, gdb_native_rust) = analyze_gdb(matches.opt_str("gdb"));
 
+    let color = match matches.opt_str("color").as_ref().map(|x| &**x) {
+        Some("auto") | None => ColorConfig::AutoColor,
+        Some("always") => ColorConfig::AlwaysColor,
+        Some("never") => ColorConfig::NeverColor,
+        Some(x) => panic!("argument for --color must be auto, always, or never, but found `{}`", x),
+    };
+
     Config {
         compile_lib_path: make_absolute(opt_path(matches, "compile-lib-path")),
         run_lib_path: make_absolute(opt_path(matches, "run-lib-path")),
@@ -185,6 +193,7 @@ fn make_absolute(path: PathBuf) -> PathBuf {
         lldb_python_dir: matches.opt_str("lldb-python-dir"),
         verbose: matches.opt_present("verbose"),
         quiet: matches.opt_present("quiet"),
+        color: color,
         remote_test_client: matches.opt_str("remote-test-client").map(PathBuf::from),
 
         cc: matches.opt_str("cc").unwrap(),
@@ -332,7 +341,7 @@ pub fn test_opts(config: &Config) -> test::TestOpts {
             Ok(val) => &val != "0",
             Err(_) => false
         },
-        color: test::AutoColor,
+        color: config.color,
         test_threads: None,
         skip: vec![],
         list: false,
index 8707ceaf040f6d87b67a002de16a8d2bc4db7a41..b4ff403041f17957f735ad750c3241a3a428b9b7 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 8707ceaf040f6d87b67a002de16a8d2bc4db7a41
+Subproject commit b4ff403041f17957f735ad750c3241a3a428b9b7
index 791b8d77e0b907f635782f1d7b33dec9ec09ae83..e34821e3584c5809953ea732b3e51350924be01d 100644 (file)
@@ -49,7 +49,7 @@ pub struct Feature {
     pub has_gate_test: bool,
 }
 
-pub fn check(path: &Path, bad: &mut bool) {
+pub fn check(path: &Path, bad: &mut bool, quiet: bool) {
     let mut features = collect_lang_features(path);
     assert!(!features.is_empty());
 
@@ -134,6 +134,10 @@ pub fn check(path: &Path, bad: &mut bool) {
     if *bad {
         return;
     }
+    if quiet {
+        println!("* {} features", features.len());
+        return;
+    }
 
     let mut lines = Vec::new();
     for (name, feature) in features.iter() {
index 6b666fa809f7a8cbfeb1d099ff25289eaed5834f..23a31131f7a6ca6aaa1a7aa24d4c9474ce1ace4e 100644 (file)
@@ -57,11 +57,12 @@ fn main() {
     let args: Vec<String> = env::args().skip(1).collect();
 
     let mut bad = false;
+    let quiet = args.iter().any(|s| *s == "--quiet");
     bins::check(&path, &mut bad);
     style::check(&path, &mut bad);
     errors::check(&path, &mut bad);
     cargo::check(&path, &mut bad);
-    features::check(&path, &mut bad);
+    features::check(&path, &mut bad, quiet);
     pal::check(&path, &mut bad);
     unstable_book::check(&path, &mut bad);
     if !args.iter().any(|s| *s == "--no-vendor") {