]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #50525 - nnethercote:lit_token, r=michaelwoerister
authorkennytm <kennytm@gmail.com>
Wed, 9 May 2018 09:23:31 +0000 (17:23 +0800)
committerkennytm <kennytm@gmail.com>
Wed, 9 May 2018 09:23:31 +0000 (17:23 +0800)
Optimize string handling in lit_token().

In the common case, the string value in a string literal Token is the
same as the string value in a string literal LitKind. (The exception is
when escapes or \r are involved.) This patch takes advantage of that to
avoid calling str_lit() and re-interning the string in that case. This
speeds up incremental builds for a few of the rustc-benchmarks, the best
by 3%.

Benchmarks that got a speedup of 1% or more:
```
coercions
        avg: -1.1%      min: -3.5%      max: 0.4%
regex-check
        avg: -1.2%      min: -1.5%      max: -0.6%
futures-check
        avg: -0.9%      min: -1.4%      max: -0.3%
futures
        avg: -0.8%      min: -1.3%      max: -0.3%
futures-opt
        avg: -0.7%      min: -1.2%      max: -0.1%
regex
        avg: -0.5%      min: -1.2%      max: -0.1%
regex-opt
        avg: -0.5%      min: -1.1%      max: -0.1%
hyper-check
        avg: -0.7%      min: -1.0%      max: -0.3%
```

80 files changed:
.mailmap
src/Cargo.lock
src/bootstrap/README.md
src/bootstrap/builder.rs
src/bootstrap/flags.rs
src/bootstrap/lib.rs
src/bootstrap/test.rs
src/bootstrap/tool.rs
src/doc/book
src/doc/nomicon
src/doc/reference
src/doc/rust-by-example
src/doc/rustc/src/lints/listing/deny-by-default.md
src/doc/rustc/src/lints/listing/warn-by-default.md
src/liballoc/binary_heap.rs
src/liballoc/boxed.rs
src/libcore/lib.rs
src/libcore/marker.rs
src/libcore/mem.rs
src/libcore/slice/memchr.rs
src/libcore/tests/lib.rs
src/libcore/tests/num/uint_macros.rs
src/libcore/tests/slice.rs
src/libcore/tests/time.rs [new file with mode: 0644]
src/libcore/time.rs
src/libproc_macro/lib.rs
src/librustc/lint/builtin.rs
src/librustc/session/config.rs
src/librustc/ty/layout.rs
src/librustc_lint/builtin.rs
src/librustc_lint/lib.rs
src/librustc_lint/types.rs
src/librustc_lint/unused.rs
src/librustc_mir/interpret/eval_context.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_save_analysis/lib.rs
src/librustc_target/abi/mod.rs
src/librustc_trans/back/write.rs
src/librustc_trans/debuginfo/metadata.rs
src/librustc_trans/mir/place.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/libstd/lib.rs
src/libsyntax/edition.rs
src/libsyntax/feature_gate.rs
src/libsyntax/print/pprust.rs
src/libsyntax_ext/assert.rs
src/stdsimd
src/test/compile-fail/issue-43355.rs
src/test/compile-fail/issue-50471.rs [new file with mode: 0644]
src/test/compile-fail/rfc-2126-extern-absolute-paths/non-existent-1.rs
src/test/compile-fail/rfc-2126-extern-absolute-paths/non-existent-2.rs
src/test/compile-fail/rfc-2126-extern-absolute-paths/non-existent-3.rs
src/test/compile-fail/rfc-2126-extern-absolute-paths/single-segment.rs
src/test/compile-fail/unused-result.rs
src/test/run-make-fulldeps/save-analysis-rfc2126/Makefile
src/test/run-make/cross-lang-lto/Makefile [new file with mode: 0644]
src/test/run-make/cross-lang-lto/lib.rs [new file with mode: 0644]
src/test/run-make/cross-lang-lto/main.rs [new file with mode: 0644]
src/test/run-pass/issue-43355.rs [deleted file]
src/test/run-pass/rfc-2126-extern-absolute-paths/basic.rs
src/test/run-pass/rfc-2126-extern-absolute-paths/test.rs
src/test/rustdoc/auxiliary/mod-stackoverflow.rs [new file with mode: 0644]
src/test/rustdoc/mod-stackoverflow.rs [new file with mode: 0644]
src/test/ui-fulldeps/unnecessary-extern-crate.rs [new file with mode: 0644]
src/test/ui-fulldeps/unnecessary-extern-crate.stderr [new file with mode: 0644]
src/test/ui/const-eval/extern_fat_pointer.rs [new file with mode: 0644]
src/test/ui/fn_must_use.stderr
src/tools/cargo
src/tools/clippy
src/tools/compiletest/src/header.rs
src/tools/compiletest/src/main.rs
src/tools/miri
src/tools/publish_toolstate.py
src/tools/rls
src/tools/rustfmt
src/tools/tidy/src/lib.rs
src/tools/tidy/src/libcoretest.rs [new file with mode: 0644]
src/tools/tidy/src/main.rs

index 3ff9e94ee5410d259b65120b13f7ba0f7ede9784..8f4287a438580315f099fb20566f3723e0e212af 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -51,6 +51,7 @@ Carol Willing <carolcode@willingconsulting.com>
 Chris C Cerami <chrisccerami@users.noreply.github.com> Chris C Cerami <chrisccerami@gmail.com>
 Chris Pressey <cpressey@gmail.com>
 Chris Thorn <chris@thorn.co> Chris Thorn <thorn@thoughtbot.com>
+Chris Vittal <christopher.vittal@gmail.com> Christopher Vittal <christopher.vittal@gmail.com>
 Clark Gaebel <cg.wowus.cg@gmail.com> <cgaebel@mozilla.com>
 Clinton Ryan <clint.ryan3@gmail.com>
 Corey Richardson <corey@octayn.net> Elaine "See More" Nemo <corey@octayn.net>
index a2767bd290d5e882f0ab3ea8622db283b8ce4f8c..21c35458398b7d1e98bc8d7e157225ab55f3aaa7 100644 (file)
@@ -305,11 +305,11 @@ dependencies = [
 
 [[package]]
 name = "clippy"
-version = "0.0.195"
+version = "0.0.197"
 dependencies = [
  "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "clippy-mini-macro-test 0.2.0",
- "clippy_lints 0.0.195",
+ "clippy_lints 0.0.197",
  "compiletest_rs 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "derive-new 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -325,8 +325,9 @@ version = "0.2.0"
 
 [[package]]
 name = "clippy_lints"
-version = "0.0.195"
+version = "0.0.197"
 dependencies = [
+ "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "if_chain 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1630,7 +1631,7 @@ version = "0.127.0"
 dependencies = [
  "cargo 0.28.0",
  "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "clippy_lints 0.0.195",
+ "clippy_lints 0.0.197",
  "env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "json 0.11.13 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1641,7 +1642,7 @@ dependencies = [
  "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "racer 2.0.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rls-analysis 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rls-analysis 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-blacklist 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-data 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-rustc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1656,7 +1657,7 @@ dependencies = [
 
 [[package]]
 name = "rls-analysis"
-version = "0.12.0"
+version = "0.12.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "derive-new 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3144,7 +3145,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "aec3f58d903a7d2a9dc2bf0e41a746f4530e0cab6b615494e058f67a3ef947fb"
 "checksum regex-syntax 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "bd90079345f4a4c3409214734ae220fd773c6f2e8a543d07370c6c1c369cfbfb"
 "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5"
-"checksum rls-analysis 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b339561571efd8d2d4ae1b16eb27f760cad46907d49e9726242844dbbde14e79"
+"checksum rls-analysis 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a41488cf5dc99d6ce383319d2978756567b70d4ed0539eb0d9ce07763e732e46"
 "checksum rls-blacklist 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e4a9cc2545ccb7e05b355bfe047b8039a6ec12270d5f3c996b766b340a50f7d2"
 "checksum rls-data 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bea04462e94b5512a78499837eecb7db182ff082144cd1b4bc32ef5d43de6510"
 "checksum rls-rustc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "885f66b92757420572cbb02e033d4a9558c7413ca9b7ac206f28fd58ffdb44ea"
index 9ff681ac680874b09b35122160f7807025d4b1cc..98c353eb6ec8c3fa967b317693d261948d0ed0b3 100644 (file)
@@ -64,6 +64,10 @@ The script accepts commands, flags, and arguments to determine what to do:
   # execute tests in the standard library in stage0
   ./x.py test --stage 0 src/libstd
 
+  # execute tests in the core and standard library in stage0,
+  # without running doc tests (thus avoid depending on building the compiler)
+  ./x.py test --stage 0 --no-doc src/libcore src/libstd
+
   # execute all doc tests
   ./x.py test src/doc
   ```
index 43387e285657d40232cad569544db0ddf62ffeb7..9c35cb7f506f970a8370bf427a3bf1fe513e02ab 100644 (file)
@@ -25,7 +25,7 @@
 use install;
 use dist;
 use util::{exe, libdir, add_lib_path};
-use {Build, Mode};
+use {Build, Mode, DocTests};
 use cache::{INTERNER, Interned, Cache};
 use check;
 use test;
@@ -591,6 +591,8 @@ pub fn cargo(&self,
                 format!("{} {}", env::var("RUSTFLAGS").unwrap_or_default(), extra_args));
         }
 
+        let want_rustdoc = self.doc_tests != DocTests::No;
+
         // Customize the compiler we're running. Specify the compiler to cargo
         // as our shim and then pass it some various options used to configure
         // how the actual compiler itself is called.
@@ -607,7 +609,7 @@ pub fn cargo(&self,
              .env("RUSTC_LIBDIR", self.rustc_libdir(compiler))
              .env("RUSTC_RPATH", self.config.rust_rpath.to_string())
              .env("RUSTDOC", self.out.join("bootstrap/debug/rustdoc"))
-             .env("RUSTDOC_REAL", if cmd == "doc" || cmd == "test" {
+             .env("RUSTDOC_REAL", if cmd == "doc" || (cmd == "test" && want_rustdoc) {
                  self.rustdoc(compiler.host)
              } else {
                  PathBuf::from("/path/to/nowhere/rustdoc/not/required")
@@ -624,7 +626,7 @@ pub fn cargo(&self,
         if let Some(ref error_format) = self.config.rustc_error_format {
             cargo.env("RUSTC_ERROR_FORMAT", error_format);
         }
-        if cmd != "build" && cmd != "check" {
+        if cmd != "build" && cmd != "check" && want_rustdoc {
             cargo.env("RUSTDOC_LIBDIR", self.rustc_libdir(self.compiler(2, self.config.build)));
         }
 
@@ -1407,4 +1409,39 @@ fn build_with_target_flag() {
             },
         ]);
     }
+
+    #[test]
+    fn test_with_no_doc_stage0() {
+        let mut config = configure(&[], &[]);
+        config.stage = Some(0);
+        config.cmd = Subcommand::Test {
+            paths: vec!["src/libstd".into()],
+            test_args: vec![],
+            rustc_args: vec![],
+            fail_fast: true,
+            doc_tests: DocTests::No,
+        };
+
+        let build = Build::new(config);
+        let mut builder = Builder::new(&build);
+
+        let host = INTERNER.intern_str("A");
+
+        builder.run_step_descriptions(
+            &[StepDescription::from::<test::Crate>()],
+            &["src/libstd".into()],
+        );
+
+        // Ensure we don't build any compiler artifacts.
+        assert!(builder.cache.all::<compile::Rustc>().is_empty());
+        assert_eq!(first(builder.cache.all::<test::Crate>()), &[
+            test::Crate {
+                compiler: Compiler { host, stage: 0 },
+                target: host,
+                mode: Mode::Libstd,
+                test_kind: test::TestKind::Test,
+                krate: INTERNER.intern_str("std"),
+            },
+        ]);
+    }
 }
index 3eb9dca2aa835807fc663e85e88f736e4515087d..5315a3028ffa9c05fa8d3839ff52b223ddad9a4d 100644 (file)
@@ -19,7 +19,7 @@
 
 use getopts::Options;
 
-use Build;
+use {Build, DocTests};
 use config::Config;
 use metadata;
 use builder::Builder;
@@ -62,7 +62,7 @@ pub enum Subcommand {
         test_args: Vec<String>,
         rustc_args: Vec<String>,
         fail_fast: bool,
-        doc_tests: bool,
+        doc_tests: DocTests,
     },
     Bench {
         paths: Vec<PathBuf>,
@@ -171,7 +171,8 @@ pub fn parse(args: &[String]) -> Flags {
                     "extra options to pass the compiler when running tests",
                     "ARGS",
                 );
-                opts.optflag("", "doc", "run doc tests");
+                opts.optflag("", "no-doc", "do not run doc tests");
+                opts.optflag("", "doc", "only run doc tests");
             },
             "bench" => { opts.optmulti("", "test-args", "extra arguments", "ARGS"); },
             "clean" => { opts.optflag("", "all", "clean all build artifacts"); },
@@ -324,7 +325,13 @@ pub fn parse(args: &[String]) -> Flags {
                     test_args: matches.opt_strs("test-args"),
                     rustc_args: matches.opt_strs("rustc-args"),
                     fail_fast: !matches.opt_present("no-fail-fast"),
-                    doc_tests: matches.opt_present("doc"),
+                    doc_tests: if matches.opt_present("doc") {
+                        DocTests::Only
+                    } else if matches.opt_present("no-doc") {
+                        DocTests::No
+                    } else {
+                        DocTests::Yes
+                    }
                 }
             }
             "bench" => {
@@ -411,10 +418,10 @@ pub fn fail_fast(&self) -> bool {
         }
     }
 
-    pub fn doc_tests(&self) -> bool {
+    pub fn doc_tests(&self) -> DocTests {
         match *self {
             Subcommand::Test { doc_tests, .. } => doc_tests,
-            _ => false,
+            _ => DocTests::Yes,
         }
     }
 }
index 0a7f0e5ff4ee25c64116f80a23227dab368bf063..e53fef06786130e03c26611efb51998211c60b76 100644 (file)
@@ -210,6 +210,16 @@ pub struct Compiler {
     host: Interned<String>,
 }
 
+#[derive(PartialEq, Eq, Copy, Clone, Debug)]
+pub enum DocTests {
+    // Default, run normal tests and doc tests.
+    Yes,
+    // Do not run any doc tests.
+    No,
+    // Only run doc tests.
+    Only,
+}
+
 /// Global configuration for the build system.
 ///
 /// This structure transitively contains all configuration for the build system.
@@ -233,7 +243,7 @@ pub struct Build {
     rustfmt_info: channel::GitInfo,
     local_rebuild: bool,
     fail_fast: bool,
-    doc_tests: bool,
+    doc_tests: DocTests,
     verbosity: usize,
 
     // Targets for which to build.
@@ -294,7 +304,7 @@ fn local_path(&self, build: &Build) -> PathBuf {
 ///
 /// These entries currently correspond to the various output directories of the
 /// build system, with each mod generating output in a different directory.
-#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
 pub enum Mode {
     /// Build the standard library, placing output in the "stageN-std" directory.
     Libstd,
index e8c40dfdb0ad2bcfdc877b9a269f26f6aca760e6..650e09feb0e6340d2905bf4854aafbad44c6b084 100644 (file)
 use native;
 use tool::{self, Tool};
 use util::{self, dylib_path, dylib_path_var};
-use Mode;
+use {Mode, DocTests};
 use toolstate::ToolState;
 
 const ADB_TEST_DIR: &str = "/data/tmp/work";
 
 /// The two modes of the test runner; tests or benchmarks.
-#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
+#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, PartialOrd, Ord)]
 pub enum TestKind {
     /// Run `cargo test`
     Test,
@@ -313,6 +313,9 @@ fn run(self, builder: &Builder) {
 
         // Don't build tests dynamically, just a pain to work with
         cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");
+        let dir = testdir(builder, compiler.host);
+        t!(fs::create_dir_all(&dir));
+        cargo.env("RUSTFMT_TEST_DIR", dir);
 
         builder.add_rustc_lib_path(compiler, &mut cargo);
 
@@ -832,7 +835,7 @@ fn run(self, builder: &Builder) {
     host: true
 });
 
-default_test!(RunMake {
+host_test!(RunMake {
     path: "src/test/run-make",
     mode: "run-make",
     suite: "run-make"
@@ -1019,7 +1022,7 @@ fn run(self, builder: &Builder) {
 
             // Only pass correct values for these flags for the `run-make` suite as it
             // requires that a C++ compiler was configured which isn't always the case.
-            if !builder.config.dry_run && suite == "run-make-fulldeps" {
+            if !builder.config.dry_run && mode == "run-make" {
                 let llvm_components = output(Command::new(&llvm_config).arg("--components"));
                 let llvm_cxxflags = output(Command::new(&llvm_config).arg("--cxxflags"));
                 cmd.arg("--cc").arg(builder.cc(target))
@@ -1032,13 +1035,13 @@ fn run(self, builder: &Builder) {
                 }
             }
         }
-        if suite == "run-make-fulldeps" && !builder.config.llvm_enabled {
+        if mode == "run-make" && !builder.config.llvm_enabled {
             builder.info(
                 &format!("Ignoring run-make test suite as they generally don't work without LLVM"));
             return;
         }
 
-        if suite != "run-make-fulldeps" {
+        if mode != "run-make" {
             cmd.arg("--cc").arg("")
                .arg("--cxx").arg("")
                .arg("--cflags").arg("")
@@ -1407,13 +1410,13 @@ fn run(self, builder: &Builder) {
 }
 
 
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
 pub struct Crate {
-    compiler: Compiler,
-    target: Interned<String>,
-    mode: Mode,
-    test_kind: TestKind,
-    krate: Interned<String>,
+    pub compiler: Compiler,
+    pub target: Interned<String>,
+    pub mode: Mode,
+    pub test_kind: TestKind,
+    pub krate: Interned<String>,
 }
 
 impl Step for Crate {
@@ -1519,8 +1522,14 @@ fn run(self, builder: &Builder) {
         if test_kind.subcommand() == "test" && !builder.fail_fast {
             cargo.arg("--no-fail-fast");
         }
-        if builder.doc_tests {
-            cargo.arg("--doc");
+        match builder.doc_tests {
+            DocTests::Only => {
+                cargo.arg("--doc");
+            }
+            DocTests::No => {
+                cargo.args(&["--lib", "--bins", "--examples", "--tests", "--benches"]);
+            }
+            DocTests::Yes => {}
         }
 
         cargo.arg("-p").arg(krate);
index 6c29bd84fe4673b407da036a821a3d3add99d55a..220af6bd6e4af02b7c8df1f64a7f427379b1c1ab 100644 (file)
@@ -10,6 +10,7 @@
 
 use std::fs;
 use std::env;
+use std::iter;
 use std::path::PathBuf;
 use std::process::{Command, exit};
 
@@ -593,7 +594,7 @@ pub fn tool_cmd(&self, tool: Tool) -> Command {
     /// right location to run `compiler`.
     fn prepare_tool_cmd(&self, compiler: Compiler, cmd: &mut Command) {
         let host = &compiler.host;
-        let mut paths: Vec<PathBuf> = vec![
+        let mut lib_paths: Vec<PathBuf> = vec![
             PathBuf::from(&self.sysroot_libdir(compiler, compiler.host)),
             self.cargo_out(compiler, Mode::Tool, *host).join("deps"),
         ];
@@ -610,11 +611,46 @@ fn prepare_tool_cmd(&self, compiler: Compiler, cmd: &mut Command) {
                 }
                 for path in env::split_paths(v) {
                     if !curpaths.contains(&path) {
-                        paths.push(path);
+                        lib_paths.push(path);
                     }
                 }
             }
         }
-        add_lib_path(paths, cmd);
+
+        // Add the llvm/bin directory to PATH since it contains lots of
+        // useful, platform-independent tools
+        if let Some(llvm_bin_path) = self.llvm_bin_path() {
+            if host.contains("windows") {
+                // On Windows, PATH and the dynamic library path are the same,
+                // so we just add the LLVM bin path to lib_path
+                lib_paths.push(llvm_bin_path);
+            } else {
+                let old_path = env::var_os("PATH").unwrap_or_default();
+                let new_path = env::join_paths(iter::once(llvm_bin_path)
+                        .chain(env::split_paths(&old_path)))
+                    .expect("Could not add LLVM bin path to PATH");
+                cmd.env("PATH", new_path);
+            }
+        }
+
+        add_lib_path(lib_paths, cmd);
+    }
+
+    fn llvm_bin_path(&self) -> Option<PathBuf> {
+        if self.config.llvm_enabled && !self.config.dry_run {
+            let llvm_config = self.ensure(native::Llvm {
+                target: self.config.build,
+                emscripten: false,
+            });
+
+            // Add the llvm/bin directory to PATH since it contains lots of
+            // useful, platform-independent tools
+            let llvm_bin_path = llvm_config.parent()
+                .expect("Expected llvm-config to be contained in directory");
+            assert!(llvm_bin_path.is_dir());
+            Some(llvm_bin_path.to_path_buf())
+        } else {
+            None
+        }
     }
 }
index 6237a75790cd2e0ca22961b55f64a83319e73464..f51127530d46b9acbf4747c859da185e771cfcf3 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 6237a75790cd2e0ca22961b55f64a83319e73464
+Subproject commit f51127530d46b9acbf4747c859da185e771cfcf3
index 3c56329d1bd9038e5341f1962bcd8d043312a712..748a5e6742db4a21c4c630a58087f818828e8a0a 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 3c56329d1bd9038e5341f1962bcd8d043312a712
+Subproject commit 748a5e6742db4a21c4c630a58087f818828e8a0a
index 76296346e97c3702974d3398fdb94af9e10111a2..134f419ee62714590b04712fe6072253bc2a7822 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 76296346e97c3702974d3398fdb94af9e10111a2
+Subproject commit 134f419ee62714590b04712fe6072253bc2a7822
index d5ec87eabe5733cc2348c7dada89fc67c086f391..eebda16e4b45f2eed4310cf7b9872cc752278163 160000 (submodule)
@@ -1 +1 @@
-Subproject commit d5ec87eabe5733cc2348c7dada89fc67c086f391
+Subproject commit eebda16e4b45f2eed4310cf7b9872cc752278163
index e7ec6af8be1e3752a89a2a1e5bc0eb8f2e05151f..ef76295f04d587a469fcfa38a2e0fbc4b35478fc 100644 (file)
@@ -239,3 +239,44 @@ error: invalid `crate_type` value
   | ^^^^^^^^^^^^^^^^^^^^
   |
 ```
+
+## incoherent-fundamental-impls
+
+This lint detects potentially-conflicting impls that were erroneously allowed. Some
+example code that triggers this lint:
+
+```rust,ignore
+pub trait Trait1<X> {
+    type Output;
+}
+
+pub trait Trait2<X> {}
+
+pub struct A;
+
+impl<X, T> Trait1<X> for T where T: Trait2<X> {
+    type Output = ();
+}
+
+impl<X> Trait1<Box<X>> for A {
+    type Output = i32;
+}
+```
+
+This will produce:
+
+```text
+error: conflicting implementations of trait `Trait1<std::boxed::Box<_>>` for type `A`: (E0119)
+  --> src/main.rs:13:1
+   |
+9  | impl<X, T> Trait1<X> for T where T: Trait2<X> {
+   | --------------------------------------------- first implementation here
+...
+13 | impl<X> Trait1<Box<X>> for A {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `A`
+   |
+   = note: #[deny(incoherent_fundamental_impls)] on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #46205 <https://github.com/rust-lang/rust/issues/46205>
+   = note: downstream crates may implement trait `Trait2<std::boxed::Box<_>>` for type `A`
+```
index 1171f75caa1fdf69ac32e2c02ee562a85df2f7a4..b49708ff6adcd2e11fb0276eb318904b22ba082c 100644 (file)
@@ -117,47 +117,6 @@ warning: found struct without foreign-function-safe representation annotation in
   |
 ```
 
-## incoherent-fundamental-impls
-
-This lint detects potentially-conflicting impls that were erroneously allowed. Some
-example code that triggers this lint:
-
-```rust
-pub trait Trait1<X> {
-    type Output;
-}
-
-pub trait Trait2<X> {}
-
-pub struct A;
-
-impl<X, T> Trait1<X> for T where T: Trait2<X> {
-    type Output = ();
-}
-
-impl<X> Trait1<Box<X>> for A {
-    type Output = i32;
-}
-```
-
-This will produce:
-
-```text
-warning: conflicting implementations of trait `Trait1<std::boxed::Box<_>>` for type `A`: (E0119)
-  --> src/main.rs:13:1
-   |
-9  | impl<X, T> Trait1<X> for T where T: Trait2<X> {
-   | --------------------------------------------- first implementation here
-...
-13 | impl<X> Trait1<Box<X>> for A {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `A`
-   |
-   = note: #[warn(incoherent_fundamental_impls)] on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #46205 <https://github.com/rust-lang/rust/issues/46205>
-   = note: downstream crates may implement trait `Trait2<std::boxed::Box<_>>` for type `A`
-```
-
 ## late-bound-lifetime-arguments
 
 This lint detects detects generic lifetime arguments in path segments with
index 668b61c51d8bc0f8e3a39e496ecc0c79b2d5ed4e..fcadcb544c431a9e9ede7bc00912ce3123b2533c 100644 (file)
 
 use core::ops::{Deref, DerefMut};
 use core::iter::{FromIterator, FusedIterator};
-use core::mem::{swap, size_of};
+use core::mem::{swap, size_of, ManuallyDrop};
 use core::ptr;
 use core::fmt;
 
@@ -864,8 +864,7 @@ fn better_to_rebuild(len1: usize, len2: usize) -> bool {
 /// position with the value that was originally removed.
 struct Hole<'a, T: 'a> {
     data: &'a mut [T],
-    /// `elt` is always `Some` from new until drop.
-    elt: Option<T>,
+    elt: ManuallyDrop<T>,
     pos: usize,
 }
 
@@ -879,7 +878,7 @@ unsafe fn new(data: &'a mut [T], pos: usize) -> Self {
         let elt = ptr::read(&data[pos]);
         Hole {
             data,
-            elt: Some(elt),
+            elt: ManuallyDrop::new(elt),
             pos,
         }
     }
@@ -892,7 +891,7 @@ fn pos(&self) -> usize {
     /// Returns a reference to the element removed.
     #[inline]
     fn element(&self) -> &T {
-        self.elt.as_ref().unwrap()
+        &self.elt
     }
 
     /// Returns a reference to the element at `index`.
@@ -925,7 +924,7 @@ fn drop(&mut self) {
         // fill the hole again
         unsafe {
             let pos = self.pos;
-            ptr::write(self.data.get_unchecked_mut(pos), self.elt.take().unwrap());
+            ptr::copy_nonoverlapping(&*self.elt, self.data.get_unchecked_mut(pos), 1);
         }
     }
 }
index 1b4f86dcfac1c07174e3efc4c8217b7824435a68..a15673442355125b5eb9e4c71647a3f70e6ce4a9 100644 (file)
@@ -62,7 +62,7 @@
 use core::hash::{Hash, Hasher};
 use core::iter::FusedIterator;
 use core::marker::{Unpin, Unsize};
-use core::mem::{self, Pin};
+use core::mem::{self, PinMut};
 use core::ops::{CoerceUnsized, Deref, DerefMut, Generator, GeneratorState};
 use core::ptr::{self, NonNull, Unique};
 use core::convert::From;
@@ -771,8 +771,8 @@ pub fn new(data: T) -> PinBox<T> {
 #[unstable(feature = "pin", issue = "49150")]
 impl<T: ?Sized> PinBox<T> {
     /// Get a pinned reference to the data in this PinBox.
-    pub fn as_pin<'a>(&'a mut self) -> Pin<'a, T> {
-        unsafe { Pin::new_unchecked(&mut *self.inner) }
+    pub fn as_pin_mut<'a>(&'a mut self) -> PinMut<'a, T> {
+        unsafe { PinMut::new_unchecked(&mut *self.inner) }
     }
 
     /// Get a mutable reference to the data inside this PinBox.
index 04dd42583d406eb468e646e10bfd56dbcf81be8a..54f35d17974fb2412db5e25bdcb802d350ef96e6 100644 (file)
 
 // Since libcore defines many fundamental lang items, all tests live in a
 // separate crate, libcoretest, to avoid bizarre issues.
+//
+// Here we explicitly #[cfg]-out this whole crate when testing. If we don't do
+// this, both the generated test artifact and the linked libtest (which
+// transitively includes libcore) will both define the same set of lang items,
+// and this will cause the E0152 "duplicate lang item found" error. See
+// discussion in #50466 for details.
+//
+// This cfg won't affect doc tests.
+#![cfg(not(test))]
 
 #![stable(feature = "core", since = "1.6.0")]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
index c074adfd570e339adaa765b09080eb750fe4e44c..db5f50a99cadc3471b33d531670cbc2c8f016ddf 100644 (file)
@@ -595,15 +595,15 @@ unsafe impl<T: ?Sized> Freeze for *mut T {}
 unsafe impl<'a, T: ?Sized> Freeze for &'a T {}
 unsafe impl<'a, T: ?Sized> Freeze for &'a mut T {}
 
-/// Types which can be moved out of a `Pin`.
+/// Types which can be moved out of a `PinMut`.
 ///
-/// The `Unpin` trait is used to control the behavior of the [`Pin`] type. If a
+/// The `Unpin` trait is used to control the behavior of the [`PinMut`] type. If a
 /// type implements `Unpin`, it is safe to move a value of that type out of the
-/// `Pin` pointer.
+/// `PinMut` pointer.
 ///
 /// This trait is automatically implemented for almost every type.
 ///
-/// [`Pin`]: ../mem/struct.Pin.html
+/// [`PinMut`]: ../mem/struct.PinMut.html
 #[unstable(feature = "pin", issue = "49150")]
 pub unsafe auto trait Unpin {}
 
index 10efab82ddff586d6c44671388968ecf8e8a318f..6cbe26afae9eb7c879810f05adfd5dbf3a5c25b2 100644 (file)
@@ -1101,53 +1101,56 @@ fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
 /// value implements the `Unpin` trait.
 #[unstable(feature = "pin", issue = "49150")]
 #[fundamental]
-pub struct Pin<'a, T: ?Sized + 'a> {
+pub struct PinMut<'a, T: ?Sized + 'a> {
     inner: &'a mut T,
 }
 
 #[unstable(feature = "pin", issue = "49150")]
-impl<'a, T: ?Sized + Unpin> Pin<'a, T> {
-    /// Construct a new `Pin` around a reference to some data of a type that
+impl<'a, T: ?Sized + Unpin> PinMut<'a, T> {
+    /// Construct a new `PinMut` around a reference to some data of a type that
     /// implements `Unpin`.
     #[unstable(feature = "pin", issue = "49150")]
-    pub fn new(reference: &'a mut T) -> Pin<'a, T> {
-        Pin { inner: reference }
+    pub fn new(reference: &'a mut T) -> PinMut<'a, T> {
+        PinMut { inner: reference }
     }
 }
 
 
 #[unstable(feature = "pin", issue = "49150")]
-impl<'a, T: ?Sized> Pin<'a, T> {
-    /// Construct a new `Pin` around a reference to some data of a type that
+impl<'a, T: ?Sized> PinMut<'a, T> {
+    /// Construct a new `PinMut` around a reference to some data of a type that
     /// may or may not implement `Unpin`.
     ///
     /// This constructor is unsafe because we do not know what will happen with
     /// that data after the reference ends. If you cannot guarantee that the
     /// data will never move again, calling this constructor is invalid.
     #[unstable(feature = "pin", issue = "49150")]
-    pub unsafe fn new_unchecked(reference: &'a mut T) -> Pin<'a, T> {
-        Pin { inner: reference }
+    pub unsafe fn new_unchecked(reference: &'a mut T) -> PinMut<'a, T> {
+        PinMut { inner: reference }
     }
 
-    /// Borrow a Pin for a shorter lifetime than it already has.
+    /// Reborrow a `PinMut` for a shorter lifetime.
+    ///
+    /// For example, `PinMut::get_mut(x.reborrow())` (unsafely) returns a
+    /// short-lived mutable reference reborrowing from `x`.
     #[unstable(feature = "pin", issue = "49150")]
-    pub fn borrow<'b>(this: &'b mut Pin<'a, T>) -> Pin<'b, T> {
-        Pin { inner: this.inner }
+    pub fn reborrow<'b>(&'b mut self) -> PinMut<'b, T> {
+        PinMut { inner: self.inner }
     }
 
-    /// Get a mutable reference to the data inside of this `Pin`.
+    /// Get a mutable reference to the data inside of this `PinMut`.
     ///
     /// This function is unsafe. You must guarantee that you will never move
     /// the data out of the mutable reference you receive when you call this
     /// function.
     #[unstable(feature = "pin", issue = "49150")]
-    pub unsafe fn get_mut<'b>(this: &'b mut Pin<'a, T>) -> &'b mut T {
+    pub unsafe fn get_mut(this: PinMut<'a, T>) -> &'a mut T {
         this.inner
     }
 
     /// Construct a new pin by mapping the interior value.
     ///
-    /// For example, if you  wanted to get a `Pin` of a field of something, you
+    /// For example, if you  wanted to get a `PinMut` of a field of something, you
     /// could use this to get access to that field in one line of code.
     ///
     /// This function is unsafe. You must guarantee that the data you return
@@ -1155,15 +1158,15 @@ pub unsafe fn get_mut<'b>(this: &'b mut Pin<'a, T>) -> &'b mut T {
     /// because it is one of the fields of that value), and also that you do
     /// not move out of the argument you receive to the interior function.
     #[unstable(feature = "pin", issue = "49150")]
-    pub unsafe fn map<'b, U, F>(this: &'b mut Pin<'a, T>, f: F) -> Pin<'b, U> where
+    pub unsafe fn map<U, F>(this: PinMut<'a, T>, f: F) -> PinMut<'a, U> where
         F: FnOnce(&mut T) -> &mut U
     {
-        Pin { inner: f(this.inner) }
+        PinMut { inner: f(this.inner) }
     }
 }
 
 #[unstable(feature = "pin", issue = "49150")]
-impl<'a, T: ?Sized> Deref for Pin<'a, T> {
+impl<'a, T: ?Sized> Deref for PinMut<'a, T> {
     type Target = T;
 
     fn deref(&self) -> &T {
@@ -1172,35 +1175,35 @@ fn deref(&self) -> &T {
 }
 
 #[unstable(feature = "pin", issue = "49150")]
-impl<'a, T: ?Sized + Unpin> DerefMut for Pin<'a, T> {
+impl<'a, T: ?Sized + Unpin> DerefMut for PinMut<'a, T> {
     fn deref_mut(&mut self) -> &mut T {
         self.inner
     }
 }
 
 #[unstable(feature = "pin", issue = "49150")]
-impl<'a, T: fmt::Debug + ?Sized> fmt::Debug for Pin<'a, T> {
+impl<'a, T: fmt::Debug + ?Sized> fmt::Debug for PinMut<'a, T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         fmt::Debug::fmt(&**self, f)
     }
 }
 
 #[unstable(feature = "pin", issue = "49150")]
-impl<'a, T: fmt::Display + ?Sized> fmt::Display for Pin<'a, T> {
+impl<'a, T: fmt::Display + ?Sized> fmt::Display for PinMut<'a, T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         fmt::Display::fmt(&**self, f)
     }
 }
 
 #[unstable(feature = "pin", issue = "49150")]
-impl<'a, T: ?Sized> fmt::Pointer for Pin<'a, T> {
+impl<'a, T: ?Sized> fmt::Pointer for PinMut<'a, T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         fmt::Pointer::fmt(&(&*self.inner as *const T), f)
     }
 }
 
 #[unstable(feature = "pin", issue = "49150")]
-impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Pin<'a, U>> for Pin<'a, T> {}
+impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<PinMut<'a, U>> for PinMut<'a, T> {}
 
 #[unstable(feature = "pin", issue = "49150")]
-unsafe impl<'a, T: ?Sized> Unpin for Pin<'a, T> {}
+unsafe impl<'a, T: ?Sized> Unpin for PinMut<'a, T> {}
index 469404f7f6bb080d7c55209bc89cd6c884ff4597..7b62e7b0620fd4ddd51348f523139004d2a4a0ed 100644 (file)
@@ -135,85 +135,3 @@ pub fn memrchr(x: u8, text: &[u8]) -> Option<usize> {
     // find the byte before the point the body loop stopped
     text[..offset].iter().rposition(|elt| *elt == x)
 }
-
-// test fallback implementations on all platforms
-#[test]
-fn matches_one() {
-    assert_eq!(Some(0), memchr(b'a', b"a"));
-}
-
-#[test]
-fn matches_begin() {
-    assert_eq!(Some(0), memchr(b'a', b"aaaa"));
-}
-
-#[test]
-fn matches_end() {
-    assert_eq!(Some(4), memchr(b'z', b"aaaaz"));
-}
-
-#[test]
-fn matches_nul() {
-    assert_eq!(Some(4), memchr(b'\x00', b"aaaa\x00"));
-}
-
-#[test]
-fn matches_past_nul() {
-    assert_eq!(Some(5), memchr(b'z', b"aaaa\x00z"));
-}
-
-#[test]
-fn no_match_empty() {
-    assert_eq!(None, memchr(b'a', b""));
-}
-
-#[test]
-fn no_match() {
-    assert_eq!(None, memchr(b'a', b"xyz"));
-}
-
-#[test]
-fn matches_one_reversed() {
-    assert_eq!(Some(0), memrchr(b'a', b"a"));
-}
-
-#[test]
-fn matches_begin_reversed() {
-    assert_eq!(Some(3), memrchr(b'a', b"aaaa"));
-}
-
-#[test]
-fn matches_end_reversed() {
-    assert_eq!(Some(0), memrchr(b'z', b"zaaaa"));
-}
-
-#[test]
-fn matches_nul_reversed() {
-    assert_eq!(Some(4), memrchr(b'\x00', b"aaaa\x00"));
-}
-
-#[test]
-fn matches_past_nul_reversed() {
-    assert_eq!(Some(0), memrchr(b'z', b"z\x00aaaa"));
-}
-
-#[test]
-fn no_match_empty_reversed() {
-    assert_eq!(None, memrchr(b'a', b""));
-}
-
-#[test]
-fn no_match_reversed() {
-    assert_eq!(None, memrchr(b'a', b"xyz"));
-}
-
-#[test]
-fn each_alignment_reversed() {
-    let mut data = [1u8; 64];
-    let needle = 2;
-    let pos = 40;
-    data[pos] = needle;
-    for start in 0..16 {
-        assert_eq!(Some(pos - start), memrchr(needle, &data[start..]));
-    }
-}
index f6750c590b33ab97303f7f5b3231bbd7caa334df..5e98e40e0d5e6b42f2e431152dd9bd59f89a3e84 100644 (file)
@@ -46,6 +46,7 @@
 #![feature(reverse_bits)]
 #![feature(inclusive_range_methods)]
 #![feature(iterator_find_map)]
+#![feature(slice_internals)]
 
 extern crate core;
 extern crate test;
@@ -74,4 +75,5 @@
 mod slice;
 mod str;
 mod str_lossy;
+mod time;
 mod tuple;
index ca6906f731047c62e0091c3a3212756cff2b5c23..257f6ea20d4eab7aa12a87ab53874d44bbefc86c 100644 (file)
@@ -98,6 +98,7 @@ fn test_swap_bytes() {
     }
 
     #[test]
+    #[cfg(not(stage0))]
     fn test_reverse_bits() {
         assert_eq!(A.reverse_bits().reverse_bits(), A);
         assert_eq!(B.reverse_bits().reverse_bits(), B);
index 53fdfa0682742454284a2ea9bdea79970d335a6c..c81e5e97cbb7acc5c43927e8d2fae22c14fa2969 100644 (file)
@@ -550,3 +550,89 @@ fn sort_unstable() {
     v.sort_unstable();
     assert!(v == [0xDEADBEEF]);
 }
+
+pub mod memchr {
+    use core::slice::memchr::{memchr, memrchr};
+
+    // test fallback implementations on all platforms
+    #[test]
+    fn matches_one() {
+        assert_eq!(Some(0), memchr(b'a', b"a"));
+    }
+
+    #[test]
+    fn matches_begin() {
+        assert_eq!(Some(0), memchr(b'a', b"aaaa"));
+    }
+
+    #[test]
+    fn matches_end() {
+        assert_eq!(Some(4), memchr(b'z', b"aaaaz"));
+    }
+
+    #[test]
+    fn matches_nul() {
+        assert_eq!(Some(4), memchr(b'\x00', b"aaaa\x00"));
+    }
+
+    #[test]
+    fn matches_past_nul() {
+        assert_eq!(Some(5), memchr(b'z', b"aaaa\x00z"));
+    }
+
+    #[test]
+    fn no_match_empty() {
+        assert_eq!(None, memchr(b'a', b""));
+    }
+
+    #[test]
+    fn no_match() {
+        assert_eq!(None, memchr(b'a', b"xyz"));
+    }
+
+    #[test]
+    fn matches_one_reversed() {
+        assert_eq!(Some(0), memrchr(b'a', b"a"));
+    }
+
+    #[test]
+    fn matches_begin_reversed() {
+        assert_eq!(Some(3), memrchr(b'a', b"aaaa"));
+    }
+
+    #[test]
+    fn matches_end_reversed() {
+        assert_eq!(Some(0), memrchr(b'z', b"zaaaa"));
+    }
+
+    #[test]
+    fn matches_nul_reversed() {
+        assert_eq!(Some(4), memrchr(b'\x00', b"aaaa\x00"));
+    }
+
+    #[test]
+    fn matches_past_nul_reversed() {
+        assert_eq!(Some(0), memrchr(b'z', b"z\x00aaaa"));
+    }
+
+    #[test]
+    fn no_match_empty_reversed() {
+        assert_eq!(None, memrchr(b'a', b""));
+    }
+
+    #[test]
+    fn no_match_reversed() {
+        assert_eq!(None, memrchr(b'a', b"xyz"));
+    }
+
+    #[test]
+    fn each_alignment_reversed() {
+        let mut data = [1u8; 64];
+        let needle = 2;
+        let pos = 40;
+        data[pos] = needle;
+        for start in 0..16 {
+            assert_eq!(Some(pos - start), memrchr(needle, &data[start..]));
+        }
+    }
+}
diff --git a/src/libcore/tests/time.rs b/src/libcore/tests/time.rs
new file mode 100644 (file)
index 0000000..042c523
--- /dev/null
@@ -0,0 +1,124 @@
+// Copyright 2018 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 core::time::Duration;
+
+#[test]
+fn creation() {
+    assert!(Duration::from_secs(1) != Duration::from_secs(0));
+    assert_eq!(Duration::from_secs(1) + Duration::from_secs(2),
+               Duration::from_secs(3));
+    assert_eq!(Duration::from_millis(10) + Duration::from_secs(4),
+               Duration::new(4, 10 * 1_000_000));
+    assert_eq!(Duration::from_millis(4000), Duration::new(4, 0));
+}
+
+#[test]
+fn secs() {
+    assert_eq!(Duration::new(0, 0).as_secs(), 0);
+    assert_eq!(Duration::from_secs(1).as_secs(), 1);
+    assert_eq!(Duration::from_millis(999).as_secs(), 0);
+    assert_eq!(Duration::from_millis(1001).as_secs(), 1);
+}
+
+#[test]
+fn nanos() {
+    assert_eq!(Duration::new(0, 0).subsec_nanos(), 0);
+    assert_eq!(Duration::new(0, 5).subsec_nanos(), 5);
+    assert_eq!(Duration::new(0, 1_000_000_001).subsec_nanos(), 1);
+    assert_eq!(Duration::from_secs(1).subsec_nanos(), 0);
+    assert_eq!(Duration::from_millis(999).subsec_nanos(), 999 * 1_000_000);
+    assert_eq!(Duration::from_millis(1001).subsec_nanos(), 1 * 1_000_000);
+}
+
+#[test]
+fn add() {
+    assert_eq!(Duration::new(0, 0) + Duration::new(0, 1),
+               Duration::new(0, 1));
+    assert_eq!(Duration::new(0, 500_000_000) + Duration::new(0, 500_000_001),
+               Duration::new(1, 1));
+}
+
+#[test]
+fn checked_add() {
+    assert_eq!(Duration::new(0, 0).checked_add(Duration::new(0, 1)),
+               Some(Duration::new(0, 1)));
+    assert_eq!(Duration::new(0, 500_000_000).checked_add(Duration::new(0, 500_000_001)),
+               Some(Duration::new(1, 1)));
+    assert_eq!(Duration::new(1, 0).checked_add(Duration::new(::core::u64::MAX, 0)), None);
+}
+
+#[test]
+fn sub() {
+    assert_eq!(Duration::new(0, 1) - Duration::new(0, 0),
+               Duration::new(0, 1));
+    assert_eq!(Duration::new(0, 500_000_001) - Duration::new(0, 500_000_000),
+               Duration::new(0, 1));
+    assert_eq!(Duration::new(1, 0) - Duration::new(0, 1),
+               Duration::new(0, 999_999_999));
+}
+
+#[test]
+fn checked_sub() {
+    let zero = Duration::new(0, 0);
+    let one_nano = Duration::new(0, 1);
+    let one_sec = Duration::new(1, 0);
+    assert_eq!(one_nano.checked_sub(zero), Some(Duration::new(0, 1)));
+    assert_eq!(one_sec.checked_sub(one_nano),
+               Some(Duration::new(0, 999_999_999)));
+    assert_eq!(zero.checked_sub(one_nano), None);
+    assert_eq!(zero.checked_sub(one_sec), None);
+}
+
+#[test]
+#[should_panic]
+fn sub_bad1() {
+    let _ = Duration::new(0, 0) - Duration::new(0, 1);
+}
+
+#[test]
+#[should_panic]
+fn sub_bad2() {
+    let _ = Duration::new(0, 0) - Duration::new(1, 0);
+}
+
+#[test]
+fn mul() {
+    assert_eq!(Duration::new(0, 1) * 2, Duration::new(0, 2));
+    assert_eq!(Duration::new(1, 1) * 3, Duration::new(3, 3));
+    assert_eq!(Duration::new(0, 500_000_001) * 4, Duration::new(2, 4));
+    assert_eq!(Duration::new(0, 500_000_001) * 4000,
+               Duration::new(2000, 4000));
+}
+
+#[test]
+fn checked_mul() {
+    assert_eq!(Duration::new(0, 1).checked_mul(2), Some(Duration::new(0, 2)));
+    assert_eq!(Duration::new(1, 1).checked_mul(3), Some(Duration::new(3, 3)));
+    assert_eq!(Duration::new(0, 500_000_001).checked_mul(4), Some(Duration::new(2, 4)));
+    assert_eq!(Duration::new(0, 500_000_001).checked_mul(4000),
+               Some(Duration::new(2000, 4000)));
+    assert_eq!(Duration::new(::core::u64::MAX - 1, 0).checked_mul(2), None);
+}
+
+#[test]
+fn div() {
+    assert_eq!(Duration::new(0, 1) / 2, Duration::new(0, 0));
+    assert_eq!(Duration::new(1, 1) / 3, Duration::new(0, 333_333_333));
+    assert_eq!(Duration::new(99, 999_999_000) / 100,
+               Duration::new(0, 999_999_990));
+}
+
+#[test]
+fn checked_div() {
+    assert_eq!(Duration::new(2, 0).checked_div(2), Some(Duration::new(1, 0)));
+    assert_eq!(Duration::new(1, 0).checked_div(2), Some(Duration::new(0, 500_000_000)));
+    assert_eq!(Duration::new(2, 0).checked_div(0), None);
+}
index e22fe450bb1f6562ac0e5f8c3e13fbb4211521d1..8e8b1691c657a3bc0edaa12e336332e82f55a3db 100644 (file)
@@ -481,119 +481,3 @@ fn sum<I: Iterator<Item=&'a Duration>>(iter: I) -> Duration {
         iter.fold(Duration::new(0, 0), |a, b| a + *b)
     }
 }
-
-#[cfg(test)]
-mod tests {
-    use super::Duration;
-
-    #[test]
-    fn creation() {
-        assert!(Duration::from_secs(1) != Duration::from_secs(0));
-        assert_eq!(Duration::from_secs(1) + Duration::from_secs(2),
-                   Duration::from_secs(3));
-        assert_eq!(Duration::from_millis(10) + Duration::from_secs(4),
-                   Duration::new(4, 10 * 1_000_000));
-        assert_eq!(Duration::from_millis(4000), Duration::new(4, 0));
-    }
-
-    #[test]
-    fn secs() {
-        assert_eq!(Duration::new(0, 0).as_secs(), 0);
-        assert_eq!(Duration::from_secs(1).as_secs(), 1);
-        assert_eq!(Duration::from_millis(999).as_secs(), 0);
-        assert_eq!(Duration::from_millis(1001).as_secs(), 1);
-    }
-
-    #[test]
-    fn nanos() {
-        assert_eq!(Duration::new(0, 0).subsec_nanos(), 0);
-        assert_eq!(Duration::new(0, 5).subsec_nanos(), 5);
-        assert_eq!(Duration::new(0, 1_000_000_001).subsec_nanos(), 1);
-        assert_eq!(Duration::from_secs(1).subsec_nanos(), 0);
-        assert_eq!(Duration::from_millis(999).subsec_nanos(), 999 * 1_000_000);
-        assert_eq!(Duration::from_millis(1001).subsec_nanos(), 1 * 1_000_000);
-    }
-
-    #[test]
-    fn add() {
-        assert_eq!(Duration::new(0, 0) + Duration::new(0, 1),
-                   Duration::new(0, 1));
-        assert_eq!(Duration::new(0, 500_000_000) + Duration::new(0, 500_000_001),
-                   Duration::new(1, 1));
-    }
-
-    #[test]
-    fn checked_add() {
-        assert_eq!(Duration::new(0, 0).checked_add(Duration::new(0, 1)),
-                   Some(Duration::new(0, 1)));
-        assert_eq!(Duration::new(0, 500_000_000).checked_add(Duration::new(0, 500_000_001)),
-                   Some(Duration::new(1, 1)));
-        assert_eq!(Duration::new(1, 0).checked_add(Duration::new(::u64::MAX, 0)), None);
-    }
-
-    #[test]
-    fn sub() {
-        assert_eq!(Duration::new(0, 1) - Duration::new(0, 0),
-                   Duration::new(0, 1));
-        assert_eq!(Duration::new(0, 500_000_001) - Duration::new(0, 500_000_000),
-                   Duration::new(0, 1));
-        assert_eq!(Duration::new(1, 0) - Duration::new(0, 1),
-                   Duration::new(0, 999_999_999));
-    }
-
-    #[test]
-    fn checked_sub() {
-        let zero = Duration::new(0, 0);
-        let one_nano = Duration::new(0, 1);
-        let one_sec = Duration::new(1, 0);
-        assert_eq!(one_nano.checked_sub(zero), Some(Duration::new(0, 1)));
-        assert_eq!(one_sec.checked_sub(one_nano),
-                   Some(Duration::new(0, 999_999_999)));
-        assert_eq!(zero.checked_sub(one_nano), None);
-        assert_eq!(zero.checked_sub(one_sec), None);
-    }
-
-    #[test] #[should_panic]
-    fn sub_bad1() {
-        Duration::new(0, 0) - Duration::new(0, 1);
-    }
-
-    #[test] #[should_panic]
-    fn sub_bad2() {
-        Duration::new(0, 0) - Duration::new(1, 0);
-    }
-
-    #[test]
-    fn mul() {
-        assert_eq!(Duration::new(0, 1) * 2, Duration::new(0, 2));
-        assert_eq!(Duration::new(1, 1) * 3, Duration::new(3, 3));
-        assert_eq!(Duration::new(0, 500_000_001) * 4, Duration::new(2, 4));
-        assert_eq!(Duration::new(0, 500_000_001) * 4000,
-                   Duration::new(2000, 4000));
-    }
-
-    #[test]
-    fn checked_mul() {
-        assert_eq!(Duration::new(0, 1).checked_mul(2), Some(Duration::new(0, 2)));
-        assert_eq!(Duration::new(1, 1).checked_mul(3), Some(Duration::new(3, 3)));
-        assert_eq!(Duration::new(0, 500_000_001).checked_mul(4), Some(Duration::new(2, 4)));
-        assert_eq!(Duration::new(0, 500_000_001).checked_mul(4000),
-                   Some(Duration::new(2000, 4000)));
-        assert_eq!(Duration::new(::u64::MAX - 1, 0).checked_mul(2), None);
-    }
-
-    #[test]
-    fn div() {
-        assert_eq!(Duration::new(0, 1) / 2, Duration::new(0, 0));
-        assert_eq!(Duration::new(1, 1) / 3, Duration::new(0, 333_333_333));
-        assert_eq!(Duration::new(99, 999_999_000) / 100,
-                   Duration::new(0, 999_999_990));
-    }
-
-    #[test]
-    fn checked_div() {
-        assert_eq!(Duration::new(2, 0).checked_div(2), Some(Duration::new(1, 0)));
-        assert_eq!(Duration::new(1, 0).checked_div(2), Some(Duration::new(0, 500_000_000)));
-        assert_eq!(Duration::new(2, 0).checked_div(0), None);
-    }
-}
index f51dbc3772f06ee1c3302304fe69f802b653c2e3..8451e5987e908d1a77067729428622723691395d 100644 (file)
 #[derive(Clone)]
 pub struct TokenStream(tokenstream::TokenStream);
 
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl !Send for TokenStream {}
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl !Sync for TokenStream {}
+
 /// Error returned from `TokenStream::from_str`.
 #[stable(feature = "proc_macro_lib", since = "1.15.0")]
 #[derive(Debug)]
@@ -81,6 +86,11 @@ pub struct LexError {
     _inner: (),
 }
 
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl !Send for LexError {}
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl !Sync for LexError {}
+
 impl TokenStream {
     /// Returns an empty `TokenStream`.
     #[unstable(feature = "proc_macro", issue = "38356")]
@@ -231,6 +241,11 @@ pub fn quote_span(span: Span) -> TokenStream {
 #[derive(Copy, Clone)]
 pub struct Span(syntax_pos::Span);
 
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl !Send for Span {}
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl !Sync for Span {}
+
 macro_rules! diagnostic_method {
     ($name:ident, $level:expr) => (
         /// Create a new `Diagnostic` with the given `message` at the span
@@ -363,6 +378,11 @@ pub struct LineColumn {
     pub column: usize
 }
 
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl !Send for LineColumn {}
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl !Sync for LineColumn {}
+
 /// The source file of a given `Span`.
 #[unstable(feature = "proc_macro", issue = "38356")]
 #[derive(Clone)]
@@ -393,7 +413,7 @@ pub fn path(&self) -> &FileName {
 
     /// Returns `true` if this source file is a real source file, and not generated by an external
     /// macro's expansion.
-    # [unstable(feature = "proc_macro", issue = "38356")]
+    #[unstable(feature = "proc_macro", issue = "38356")]
     pub fn is_real(&self) -> bool {
         // This is a hack until intercrate spans are implemented and we can have real source files
         // for spans generated in external macros.
@@ -450,6 +470,11 @@ pub enum TokenTree {
     Literal(Literal),
 }
 
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl !Send for TokenTree {}
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl !Sync for TokenTree {}
+
 impl TokenTree {
     /// Returns the span of this token, accessing the `span` method of each of
     /// the internal tokens.
@@ -546,6 +571,11 @@ pub struct Group {
     span: Span,
 }
 
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl !Send for Group {}
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl !Sync for Group {}
+
 /// Describes how a sequence of token trees is delimited.
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 #[unstable(feature = "proc_macro", issue = "38356")]
@@ -628,6 +658,11 @@ pub struct Op {
     span: Span,
 }
 
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl !Send for Op {}
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl !Sync for Op {}
+
 /// Whether an `Op` is either followed immediately by another `Op` or followed by whitespace.
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 #[unstable(feature = "proc_macro", issue = "38356")]
@@ -694,6 +729,11 @@ pub struct Term {
     span: Span,
 }
 
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl !Send for Term {}
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl !Sync for Term {}
+
 impl Term {
     /// Creates a new `Term` with the given `string` as well as the specified
     /// `span`.
@@ -752,6 +792,11 @@ pub struct Literal {
     span: Span,
 }
 
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl !Send for Literal {}
+#[unstable(feature = "proc_macro", issue = "38356")]
+impl !Sync for Literal {}
+
 macro_rules! suffixed_int_literals {
     ($($name:ident => $kind:ident,)*) => ($(
         /// Creates a new suffixed integer literal with the specified value.
index 109edffcde38a5d3cc9a22804c6b6e3b47ed5d7f..398d7d5704c7fb4be1f0ca15388f30546efe65d1 100644 (file)
@@ -14,7 +14,7 @@
 //! compiler code, rather than using their own custom pass. Those
 //! lints are all available in `rustc_lint::builtin`.
 
-use errors::DiagnosticBuilder;
+use errors::{Applicability, DiagnosticBuilder};
 use lint::{LintPass, LateLintPass, LintArray};
 use session::Session;
 use syntax::codemap::Span;
 
 declare_lint! {
     pub INCOHERENT_FUNDAMENTAL_IMPLS,
-    Warn,
+    Deny,
     "potentially-conflicting impls were erroneously allowed"
 }
 
@@ -341,15 +341,16 @@ pub fn run(self, sess: &Session, db: &mut DiagnosticBuilder) {
         match self {
             BuiltinLintDiagnostics::Normal => (),
             BuiltinLintDiagnostics::BareTraitObject(span, is_global) => {
-                let sugg = match sess.codemap().span_to_snippet(span) {
-                    Ok(ref s) if is_global => format!("dyn ({})", s),
-                    Ok(s) => format!("dyn {}", s),
-                    Err(_) => format!("dyn <type>")
+                let (sugg, app) = match sess.codemap().span_to_snippet(span) {
+                    Ok(ref s) if is_global => (format!("dyn ({})", s),
+                                               Applicability::MachineApplicable),
+                    Ok(s) => (format!("dyn {}", s), Applicability::MachineApplicable),
+                    Err(_) => (format!("dyn <type>"), Applicability::HasPlaceholders)
                 };
-                db.span_suggestion(span, "use `dyn`", sugg);
+                db.span_suggestion_with_applicability(span, "use `dyn`", sugg, app);
             }
             BuiltinLintDiagnostics::AbsPathWithModule(span) => {
-                let sugg = match sess.codemap().span_to_snippet(span) {
+                let (sugg, app) = match sess.codemap().span_to_snippet(span) {
                     Ok(ref s) => {
                         // FIXME(Manishearth) ideally the emitting code
                         // can tell us whether or not this is global
@@ -359,11 +360,11 @@ pub fn run(self, sess: &Session, db: &mut DiagnosticBuilder) {
                             "::"
                         };
 
-                        format!("crate{}{}", opt_colon, s)
+                        (format!("crate{}{}", opt_colon, s), Applicability::MachineApplicable)
                     }
-                    Err(_) => format!("crate::<path>")
+                    Err(_) => (format!("crate::<path>"), Applicability::HasPlaceholders)
                 };
-                db.span_suggestion(span, "use `crate`", sugg);
+                db.span_suggestion_with_applicability(span, "use `crate`", sugg, app);
             }
         }
     }
index 0beda679e69592794be9d46f30235eaaf668f551..83dac033f940863377bbba0a791903bb51c9cfa4 100644 (file)
@@ -1295,6 +1295,8 @@ fn parse_lto(slot: &mut Lto, v: Option<&str>) -> bool {
           "make the current crate share its generic instantiations"),
     chalk: bool = (false, parse_bool, [TRACKED],
           "enable the experimental Chalk-based trait solving engine"),
+    cross_lang_lto: bool = (false, parse_bool, [TRACKED],
+          "generate build artifacts that are compatible with linker-based LTO."),
 }
 
 pub fn default_lib_output() -> CrateType {
index a319b341ebbf06ee2bbc82d07829668c31393ad8..02c4b73efa1465fc89f3c2a36260b720651b7d0b 100644 (file)
@@ -1057,7 +1057,7 @@ enum StructKind {
                 }
                 tcx.intern_layout(LayoutDetails {
                     variants: Variants::Tagged {
-                        discr: tag,
+                        tag,
                         variants: layout_variants,
                     },
                     fields: FieldPlacement::Arbitrary {
@@ -1218,7 +1218,7 @@ fn record_layout_for_printing_outlined(self, layout: TyLayout<'tcx>) {
                     })
                     .collect();
                 record(adt_kind.into(), adt_packed, match layout.variants {
-                    Variants::Tagged { ref discr, .. } => Some(discr.value.size(self)),
+                    Variants::Tagged { ref tag, .. } => Some(tag.value.size(self)),
                     _ => None
                 }, variant_infos);
             }
@@ -1622,7 +1622,7 @@ fn field(this: TyLayout<'tcx>, cx: C, i: usize) -> C::TyLayout {
                     }
 
                     // Discriminant field for enums (where applicable).
-                    Variants::Tagged { ref discr, .. } |
+                    Variants::Tagged { tag: ref discr, .. } |
                     Variants::NicheFilling { niche: ref discr, .. } => {
                         assert_eq!(i, 0);
                         let layout = LayoutDetails::scalar(tcx, discr.clone());
@@ -1736,10 +1736,10 @@ fn hash_stable<W: StableHasherResult>(&self,
                 index.hash_stable(hcx, hasher);
             }
             Tagged {
-                ref discr,
+                ref tag,
                 ref variants,
             } => {
-                discr.hash_stable(hcx, hasher);
+                tag.hash_stable(hcx, hasher);
                 variants.hash_stable(hcx, hasher);
             }
             NicheFilling {
index f06062fa4ac83091dddc7945df8660ef7672d202..7ae13c803ddcaa794ec1f2b70be780eaa4f69a4c 100644 (file)
@@ -46,7 +46,7 @@
 use syntax::feature_gate::{AttributeGate, AttributeType, Stability, deprecated_attributes};
 use syntax_pos::{BytePos, Span, SyntaxContext};
 use syntax::symbol::keywords;
-use syntax::errors::DiagnosticBuilder;
+use syntax::errors::{Applicability, DiagnosticBuilder};
 
 use rustc::hir::{self, PatKind};
 use rustc::hir::intravisit::FnKind;
@@ -1300,7 +1300,19 @@ fn perform_lint(&self, cx: &LateContext, what: &str, id: ast::NodeId,
             } else {
                 "pub(crate)"
             }.to_owned();
-            err.span_suggestion(pub_span, "consider restricting its visibility", replacement);
+            let app = if span.ctxt().outer().expn_info().is_none() {
+                // even if macros aren't involved the suggestion
+                // may be incorrect -- the user may have mistakenly
+                // hidden it behind a private module and this lint is
+                // a helpful way to catch that. However, we're trying
+                // not to change the nature of the code with this lint
+                // so it's marked as machine applicable.
+                Applicability::MachineApplicable
+            } else {
+                Applicability::MaybeIncorrect
+            };
+            err.span_suggestion_with_applicability(pub_span, "consider restricting its visibility",
+                                                   replacement, app);
             if exportable {
                 err.help("or consider exporting it for use by other crates");
             }
@@ -1508,3 +1520,66 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
         }
     }
 }
+
+declare_lint! {
+    pub UNNECESSARY_EXTERN_CRATE,
+    Allow,
+    "suggest removing `extern crate` for the 2018 edition"
+}
+
+pub struct ExternCrate(/* depth */ u32);
+
+impl ExternCrate {
+    pub fn new() -> Self {
+        ExternCrate(0)
+    }
+}
+
+impl LintPass for ExternCrate {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(UNNECESSARY_EXTERN_CRATE)
+    }
+}
+
+impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExternCrate {
+    fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
+        if let hir::ItemExternCrate(ref orig) =  it.node {
+            if it.attrs.iter().any(|a| a.check_name("macro_use")) {
+                return
+            }
+            let mut err = cx.struct_span_lint(UNNECESSARY_EXTERN_CRATE,
+                it.span, "`extern crate` is unnecessary in the new edition");
+            if it.vis == hir::Visibility::Public || self.0 > 1 || orig.is_some() {
+                let pub_ = if it.vis == hir::Visibility::Public {
+                    "pub "
+                } else {
+                    ""
+                };
+
+                let help = format!("use `{}use`", pub_);
+
+                if let Some(orig) = orig {
+                    err.span_suggestion(it.span, &help,
+                        format!("{}use {} as {}", pub_, orig, it.name));
+                } else {
+                    err.span_suggestion(it.span, &help,
+                        format!("{}use {}", pub_, it.name));
+                }
+            } else {
+                err.span_suggestion(it.span, "remove it", "".into());
+            }
+
+            err.emit();
+        }
+    }
+
+    fn check_mod(&mut self, _: &LateContext, _: &hir::Mod,
+                 _: Span, _: ast::NodeId) {
+        self.0 += 1;
+    }
+
+    fn check_mod_post(&mut self, _: &LateContext, _: &hir::Mod,
+                      _: Span, _: ast::NodeId) {
+        self.0 += 1;
+    }
+}
index 4f6d23dce6dbb835c27a520e48737323c3ff8d9c..4403e1e3358b288bc174d42211a887d1cc112da4 100644 (file)
@@ -143,6 +143,7 @@ macro_rules! add_lint_group {
                           TypeLimits,
                           MissingDoc,
                           MissingDebugImplementations,
+                          ExternCrate,
                           );
 
     add_lint_group!(sess,
@@ -178,9 +179,10 @@ macro_rules! add_lint_group {
                     UNUSED_PARENS);
 
     add_lint_group!(sess,
-                    "rust_2018_idioms",
+                    "rust_2018_migration",
                     BARE_TRAIT_OBJECT,
-                    UNREACHABLE_PUB);
+                    UNREACHABLE_PUB,
+                    UNNECESSARY_EXTERN_CRATE);
 
     // Guidelines for creating a future incompatibility lint:
     //
index 904a3e4c4274f47d55edc0ecaf11824e6165d517..9e0dc4d80c8e2a3a9dfca2435d0b43a90a8888d8 100644 (file)
@@ -820,8 +820,8 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
                     bug!("failed to get layout for `{}`: {}", t, e)
                 });
 
-                if let layout::Variants::Tagged { ref variants, ref discr, .. } = layout.variants {
-                    let discr_size = discr.value.size(cx.tcx).bytes();
+                if let layout::Variants::Tagged { ref variants, ref tag, .. } = layout.variants {
+                    let discr_size = tag.value.size(cx.tcx).bytes();
 
                     debug!("enum `{}` is {} bytes large with layout:\n{:#?}",
                       t, layout.size.bytes(), layout);
index 8df40b62ddd1253d66cfd874ecce18377502ba69..845c964b986dda3cb319b7ac12c38abe98702821 100644 (file)
@@ -135,12 +135,12 @@ fn check_must_use(cx: &LateContext, def_id: DefId, sp: Span, describe_path: &str
                 if attr.check_name("must_use") {
                     let mut msg = format!("unused {}`{}` which must be used",
                                           describe_path, cx.tcx.item_path_str(def_id));
-                    // check for #[must_use="..."]
-                    if let Some(s) = attr.value_str() {
-                        msg.push_str(": ");
-                        msg.push_str(&s.as_str());
+                    let mut err = cx.struct_span_lint(UNUSED_MUST_USE, sp, &msg);
+                    // check for #[must_use = "..."]
+                    if let Some(note) = attr.value_str() {
+                        err.note(&note.as_str());
                     }
-                    cx.span_lint(UNUSED_MUST_USE, sp, &msg);
+                    err.emit();
                     return true;
                 }
             }
index bea29b6926aa63c1b48b1c6a5266a75b809885d7..d8f1324206500d2ba58c131c3bd12ec1f91fffd9 100644 (file)
@@ -654,6 +654,9 @@ pub(super) fn eval_rvalue_into_place(
                         if self.type_is_fat_ptr(src.ty) {
                             match (src.value, self.type_is_fat_ptr(dest_ty)) {
                                 (Value::ByRef { .. }, _) |
+                                // pointers to extern types
+                                (Value::ByVal(_),_) |
+                                // slices and trait objects to other slices/trait objects
                                 (Value::ByValPair(..), true) => {
                                     let valty = ValTy {
                                         value: src.value,
@@ -661,6 +664,7 @@ pub(super) fn eval_rvalue_into_place(
                                     };
                                     self.write_value(valty, dest)?;
                                 }
+                                // slices and trait objects to thin pointers (dropping the metadata)
                                 (Value::ByValPair(data, _), false) => {
                                     let valty = ValTy {
                                         value: Value::ByVal(data),
@@ -668,7 +672,6 @@ pub(super) fn eval_rvalue_into_place(
                                     };
                                     self.write_value(valty, dest)?;
                                 }
-                                (Value::ByVal(_), _) => bug!("expected fat ptr"),
                             }
                         } else {
                             let src_layout = self.layout_of(src.ty)?;
@@ -960,7 +963,7 @@ pub fn write_discriminant_value(
                                layout::Abi::Uninhabited);
                 }
             }
-            layout::Variants::Tagged { ref discr, .. } => {
+            layout::Variants::Tagged { ref tag, .. } => {
                 let discr_val = dest_ty.ty_adt_def().unwrap()
                     .discriminant_for_variant(*self.tcx, variant_index)
                     .val;
@@ -968,12 +971,12 @@ pub fn write_discriminant_value(
                 // raw discriminants for enums are isize or bigger during
                 // their computation, but the in-memory tag is the smallest possible
                 // representation
-                let size = discr.value.size(self.tcx.tcx).bits();
+                let size = tag.value.size(self.tcx.tcx).bits();
                 let amt = 128 - size;
                 let discr_val = (discr_val << amt) >> amt;
 
-                let (discr_dest, discr) = self.place_field(dest, mir::Field::new(0), layout)?;
-                self.write_primval(discr_dest, PrimVal::Bytes(discr_val), discr.ty)?;
+                let (discr_dest, tag) = self.place_field(dest, mir::Field::new(0), layout)?;
+                self.write_primval(discr_dest, PrimVal::Bytes(discr_val), tag.ty)?;
             }
             layout::Variants::NicheFilling {
                 dataful_variant,
index d4b212a15d82f9ba637f3337f9431303448e3a42..0f931d4374e59337a7e43c78ff7f1cc6f579b030 100644 (file)
@@ -3277,9 +3277,8 @@ fn resolve_path(&mut self,
                     let prev_name = path[0].name;
                     if prev_name == keywords::Extern.name() ||
                        prev_name == keywords::CrateRoot.name() &&
-                       // Note: When this feature stabilizes, this should
-                       // be gated on sess.rust_2018()
-                       self.session.features_untracked().extern_absolute_paths {
+                       self.session.features_untracked().extern_absolute_paths &&
+                       self.session.rust_2018() {
                         // `::extern_crate::a::b`
                         let crate_id = self.crate_loader.process_path_extern(name, ident.span);
                         let crate_root =
index 17aa510b565e90805ea2ae54cd31d8b14f80f2ba..6a5a31a885fb9855c880239da9df6a23358da1cc 100644 (file)
@@ -646,7 +646,8 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<(Spa
         if module_path.len() == 1 && (module_path[0].name == keywords::CrateRoot.name() ||
                                       module_path[0].name == keywords::Extern.name()) {
             let is_extern = module_path[0].name == keywords::Extern.name() ||
-                            self.session.features_untracked().extern_absolute_paths;
+                            (self.session.features_untracked().extern_absolute_paths &&
+                             self.session.rust_2018());
             match directive.subclass {
                 GlobImport { .. } if is_extern => {
                     return Some((directive.span,
index 401a280412a114eb448d13d95d2231e6ce15b2d4..cf12302d9896978cf459ee5fb54f0e8b560ad3ef 100644 (file)
@@ -40,7 +40,7 @@
 
 use rustc::hir;
 use rustc::hir::def::Def as HirDef;
-use rustc::hir::map::{Node, NodeItem};
+use rustc::hir::map::{Node, NodeTraitItem, NodeImplItem};
 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::middle::cstore::ExternCrate;
 use rustc::session::config::CrateType::CrateTypeExecutable;
@@ -418,34 +418,30 @@ pub fn get_method_data(&self, id: ast::NodeId, name: ast::Name, span: Span) -> O
                 Some(impl_id) => match self.tcx.hir.get_if_local(impl_id) {
                     Some(Node::NodeItem(item)) => match item.node {
                         hir::ItemImpl(.., ref ty, _) => {
-                            let mut result = String::from("<");
-                            result.push_str(&self.tcx.hir.node_to_pretty_string(ty.id));
+                            let mut qualname = String::from("<");
+                            qualname.push_str(&self.tcx.hir.node_to_pretty_string(ty.id));
 
                             let mut trait_id = self.tcx.trait_id_of_impl(impl_id);
                             let mut decl_id = None;
+                            let mut docs = String::new();
+                            let mut attrs = vec![];
+                            if let Some(NodeImplItem(item)) = self.tcx.hir.find(id) {
+                                docs = self.docs_for_attrs(&item.attrs);
+                                attrs = item.attrs.to_vec();
+                            }
+
                             if let Some(def_id) = trait_id {
-                                result.push_str(" as ");
-                                result.push_str(&self.tcx.item_path_str(def_id));
+                                // A method in a trait impl.
+                                qualname.push_str(" as ");
+                                qualname.push_str(&self.tcx.item_path_str(def_id));
                                 self.tcx
                                     .associated_items(def_id)
                                     .find(|item| item.name == name)
                                     .map(|item| decl_id = Some(item.def_id));
-                            } else {
-                                if let Some(NodeItem(item)) = self.tcx.hir.find(id) {
-                                    if let hir::ItemImpl(_, _, _, _, _, ref ty, _) = item.node {
-                                        trait_id = self.lookup_ref_id(ty.id);
-                                    }
-                                }
                             }
-                            result.push_str(">");
-
-                            (
-                                result,
-                                trait_id,
-                                decl_id,
-                                self.docs_for_attrs(&item.attrs),
-                                item.attrs.to_vec(),
-                            )
+                            qualname.push_str(">");
+
+                            (qualname, trait_id, decl_id, docs, attrs)
                         }
                         _ => {
                             span_bug!(
@@ -467,25 +463,23 @@ pub fn get_method_data(&self, id: ast::NodeId, name: ast::Name, span: Span) -> O
                     }
                 },
                 None => match self.tcx.trait_of_item(self.tcx.hir.local_def_id(id)) {
-                    Some(def_id) => match self.tcx.hir.get_if_local(def_id) {
-                        Some(Node::NodeItem(item)) => (
+                    Some(def_id) => {
+                        let mut docs = String::new();
+                        let mut attrs = vec![];
+
+                        if let Some(NodeTraitItem(item)) = self.tcx.hir.find(id) {
+                            docs = self.docs_for_attrs(&item.attrs);
+                            attrs = item.attrs.to_vec();
+                        }
+
+                        (
                             format!("::{}", self.tcx.item_path_str(def_id)),
                             Some(def_id),
                             None,
-                            self.docs_for_attrs(&item.attrs),
-                            item.attrs.to_vec(),
-                        ),
-                        r => {
-                            span_bug!(
-                                span,
-                                "Could not find container {:?} for \
-                                 method {}, got {:?}",
-                                def_id,
-                                id,
-                                r
-                            );
-                        }
-                    },
+                            docs,
+                            attrs,
+                        )
+                    }
                     None => {
                         debug!("Could not find container for method {} at {:?}", id, span);
                         // This is not necessarily a bug, if there was a compilation error,
index fd1f779f9ecc06168ee635e11907d2b576ed2dda..7ae4d990c8a4ec469a2ce3da7463343b1ec21119 100644 (file)
@@ -716,10 +716,10 @@ pub enum Variants {
     },
 
     /// General-case enums: for each case there is a struct, and they all have
-    /// all space reserved for the discriminant, and their first field starts
-    /// at a non-0 offset, after where the discriminant would go.
+    /// all space reserved for the tag, and their first field starts
+    /// at a non-0 offset, after where the tag would go.
     Tagged {
-        discr: Scalar,
+        tag: Scalar,
         variants: Vec<LayoutDetails>,
     },
 
index 148e3d0025c83e3cc443bf901d73fdb39553eaed..b6fae3eaff23a64cfd0cf62f5a207790562d76e8 100644 (file)
@@ -293,7 +293,8 @@ fn set_flags(&mut self, sess: &Session, no_builtins: bool) {
         self.inline_threshold = sess.opts.cg.inline_threshold;
         self.obj_is_bitcode = sess.target.target.options.obj_is_bitcode;
         let embed_bitcode = sess.target.target.options.embed_bitcode ||
-            sess.opts.debugging_opts.embed_bitcode;
+                            sess.opts.debugging_opts.embed_bitcode ||
+                            sess.opts.debugging_opts.cross_lang_lto;
         if embed_bitcode {
             match sess.opts.optimize {
                 config::OptLevel::No |
@@ -841,13 +842,18 @@ unsafe fn embed_bitcode(cgcx: &CodegenContext,
         "rustc.embedded.module\0".as_ptr() as *const _,
     );
     llvm::LLVMSetInitializer(llglobal, llconst);
-    let section = if cgcx.opts.target_triple.triple().contains("-ios") {
+
+    let is_apple = cgcx.opts.target_triple.triple().contains("-ios") ||
+                   cgcx.opts.target_triple.triple().contains("-darwin");
+
+    let section = if is_apple {
         "__LLVM,__bitcode\0"
     } else {
         ".llvmbc\0"
     };
     llvm::LLVMSetSection(llglobal, section.as_ptr() as *const _);
     llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage);
+    llvm::LLVMSetGlobalConstant(llglobal, llvm::True);
 
     let llconst = C_bytes_in_context(llcx, &[]);
     let llglobal = llvm::LLVMAddGlobal(
@@ -856,7 +862,7 @@ unsafe fn embed_bitcode(cgcx: &CodegenContext,
         "rustc.embedded.cmdline\0".as_ptr() as *const _,
     );
     llvm::LLVMSetInitializer(llglobal, llconst);
-    let section = if cgcx.opts.target_triple.triple().contains("-ios") {
+    let section = if  is_apple {
         "__LLVM,__cmdline\0"
     } else {
         ".llvmcmd\0"
@@ -1350,6 +1356,10 @@ fn execute_work_item(cgcx: &CodegenContext,
             // settings.
             let needs_lto = needs_lto && mtrans.kind != ModuleKind::Metadata;
 
+            // Don't run LTO passes when cross-lang LTO is enabled. The linker
+            // will do that for us in this case.
+            let needs_lto = needs_lto && !cgcx.opts.debugging_opts.cross_lang_lto;
+
             if needs_lto {
                 Ok(WorkItemResult::NeedsLTO(mtrans))
             } else {
index 2fc6c9d4433016f74613225759412724916744cd..f16fef5ec1e843b269e7f19801cf50e7c2c07975 100644 (file)
@@ -1429,8 +1429,8 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
     let discriminant_type_metadata = match layout.variants {
         layout::Variants::Single { .. } |
         layout::Variants::NicheFilling { .. } => None,
-        layout::Variants::Tagged { ref discr, .. } => {
-            Some(discriminant_type_metadata(discr.value))
+        layout::Variants::Tagged { ref tag, .. } => {
+            Some(discriminant_type_metadata(tag.value))
         }
     };
 
index 79859aee64d874dfddbbb6333e6521d65bf6eaf7..d4abd5fa88d31bc496ca14830d22cb4e065ee4a8 100644 (file)
@@ -273,8 +273,8 @@ pub fn trans_get_discr(self, bx: &Builder<'a, 'tcx>, cast_to: Ty<'tcx>) -> Value
         let lldiscr = discr.load(bx).immediate();
         match self.layout.variants {
             layout::Variants::Single { .. } => bug!(),
-            layout::Variants::Tagged { ref discr, .. } => {
-                let signed = match discr.value {
+            layout::Variants::Tagged { ref tag, .. } => {
+                let signed = match tag.value {
                     layout::Int(_, signed) => signed,
                     _ => false
                 };
index 23e0c2625eeeb6b0607d2d7fa8d63cdc1211e251..a8f4848bf89f2a0394aadc9b6bdd7863e827631d 100644 (file)
@@ -38,7 +38,7 @@
 ///
 /// The returned value is `None` if the definition could not be inlined,
 /// and `Some` of a vector of items if it was successfully expanded.
-pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name)
+pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name, visited: &mut FxHashSet<DefId>)
                   -> Option<Vec<clean::Item>> {
     if def == Def::Err { return None }
     let did = def.def_id();
@@ -87,7 +87,7 @@ pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name)
         Def::StructCtor(..) => return Some(Vec::new()),
         Def::Mod(did) => {
             record_extern_fqn(cx, did, clean::TypeKind::Module);
-            clean::ModuleItem(build_module(cx, did))
+            clean::ModuleItem(build_module(cx, did, visited))
         }
         Def::Static(did, mtbl) => {
             record_extern_fqn(cx, did, clean::TypeKind::Static);
@@ -385,24 +385,24 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) {
     });
 }
 
-fn build_module(cx: &DocContext, did: DefId) -> clean::Module {
+fn build_module(cx: &DocContext, did: DefId, visited: &mut FxHashSet<DefId>) -> clean::Module {
     let mut items = Vec::new();
-    fill_in(cx, did, &mut items);
+    fill_in(cx, did, &mut items, visited);
     return clean::Module {
         items,
         is_crate: false,
     };
 
-    fn fill_in(cx: &DocContext, did: DefId, items: &mut Vec<clean::Item>) {
+    fn fill_in(cx: &DocContext, did: DefId, items: &mut Vec<clean::Item>,
+               visited: &mut FxHashSet<DefId>) {
         // If we're re-exporting a re-export it may actually re-export something in
         // two namespaces, so the target may be listed twice. Make sure we only
         // visit each node at most once.
-        let mut visited = FxHashSet();
         for &item in cx.tcx.item_children(did).iter() {
             let def_id = item.def.def_id();
             if item.vis == ty::Visibility::Public {
-                if !visited.insert(def_id) { continue }
-                if let Some(i) = try_inline(cx, item.def, item.ident.name) {
+                if did == def_id || !visited.insert(def_id) { continue }
+                if let Some(i) = try_inline(cx, item.def, item.ident.name, visited) {
                     items.extend(i)
                 }
             }
index edbf5f3abd25dc534494c5951c1746d711898f03..fb0bd0e42c57edf9a7442c528beb1d2051aec39d 100644 (file)
@@ -3686,7 +3686,8 @@ fn clean(&self, cx: &DocContext) -> Vec<Item> {
         } else {
             let name = self.name;
             if !denied {
-                if let Some(items) = inline::try_inline(cx, path.def, name) {
+                let mut visited = FxHashSet();
+                if let Some(items) = inline::try_inline(cx, path.def, name, &mut visited) {
                     return items;
                 }
             }
index fc05833e28503f7eeede377f3e40601cde3a40a9..d41739ab02c6ad90c19d55dbe7fe0d644a1dbb56 100644 (file)
 // with a rustc without jemalloc.
 // FIXME(#44236) shouldn't need MSVC logic
 #![cfg_attr(all(not(target_env = "msvc"),
-                any(stage0, feature = "force_alloc_system")),
+                any(all(stage0, not(test)), feature = "force_alloc_system")),
             feature(global_allocator))]
 #[cfg(all(not(target_env = "msvc"),
-          any(stage0, feature = "force_alloc_system")))]
+          any(all(stage0, not(test)), feature = "force_alloc_system")))]
 #[global_allocator]
 static ALLOC: alloc_system::System = alloc_system::System;
 
index 3fc1c279f5a22ea971f55be431a2df2a0820e8b2..7341941c242a4a743092b4f125f6a4cf03fd87a9 100644 (file)
@@ -50,8 +50,8 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 impl Edition {
     pub fn lint_name(&self) -> &'static str {
         match *self {
-            Edition::Edition2015 => "edition_2015",
-            Edition::Edition2018 => "edition_2018",
+            Edition::Edition2015 => "rust_2015_breakage",
+            Edition::Edition2018 => "rust_2018_breakage",
         }
     }
 
index d8db76a95ff38ef1fde952f99658dd42e6d2d7b9..5155408ba63f3143372f4a1db5ea19b312dca792 100644 (file)
@@ -300,7 +300,7 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     (active, abi_unadjusted, "1.16.0", None, None),
 
     // Procedural macros 2.0.
-    (active, proc_macro, "1.16.0", Some(38356), None),
+    (active, proc_macro, "1.16.0", Some(38356), Some(Edition::Edition2018)),
 
     // Declarative macros 2.0 (`macro`).
     (active, decl_macro, "1.17.0", Some(39412), None),
@@ -324,7 +324,7 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
 
 
     // Allows the `catch {...}` expression
-    (active, catch_expr, "1.17.0", Some(31436), None),
+    (active, catch_expr, "1.17.0", Some(31436), Some(Edition::Edition2018)),
 
     // Used to preserve symbols (see llvm.used)
     (active, used, "1.18.0", Some(40289), None),
@@ -1848,6 +1848,14 @@ fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) {
 
     let mut feature_checker = FeatureChecker::default();
 
+    for &(.., f_edition, set) in ACTIVE_FEATURES.iter() {
+        if let Some(f_edition) = f_edition {
+            if f_edition <= crate_edition {
+                set(&mut features, DUMMY_SP);
+            }
+        }
+    }
+
     for attr in krate_attrs {
         if !attr.check_name("feature") {
             continue
index d8228e2b28be71ac39ed3dfdeb54ab0aef50805f..b8ddb063d98751fc94cead427f1527712adace3c 100644 (file)
@@ -656,7 +656,7 @@ fn print_string(&mut self, st: &str,
                     style: ast::StrStyle) -> io::Result<()> {
         let st = match style {
             ast::StrStyle::Cooked => {
-                (format!("\"{}\"", st.escape_default()))
+                (format!("\"{}\"", st.escape_debug()))
             }
             ast::StrStyle::Raw(n) => {
                 (format!("r{delim}\"{string}\"{delim}",
index 7352c494a426cf3c8468d1ee7c55861b5f45e32c..754f04a26e7ee038ed2eeaa5186841e6ae0850fd 100644 (file)
@@ -42,16 +42,13 @@ pub fn expand_assert<'cx>(
         tts: if let Some(ts) = custom_msg_args {
             ts.into()
         } else {
-            // `expr_to_string` escapes the string literals with `.escape_default()`
-            // which escapes all non-ASCII characters with `\u`.
-            let escaped_expr = escape_format_string(&unescape_printable_unicode(
-                &pprust::expr_to_string(&cond_expr),
-            ));
-
             TokenStream::from(TokenTree::Token(
                 DUMMY_SP,
                 token::Literal(
-                    token::Lit::Str_(Name::intern(&format!("assertion failed: {}", escaped_expr))),
+                    token::Lit::Str_(Name::intern(&format!(
+                        "assertion failed: {}",
+                        pprust::expr_to_string(&cond_expr).escape_debug()
+                    ))),
                     None,
                 ),
             )).into()
@@ -71,53 +68,3 @@ pub fn expand_assert<'cx>(
     );
     MacEager::expr(if_expr)
 }
-
-/// Escapes a string for use as a formatting string.
-fn escape_format_string(s: &str) -> String {
-    let mut res = String::with_capacity(s.len());
-    for c in s.chars() {
-        res.extend(c.escape_debug());
-        match c {
-            '{' | '}' => res.push(c),
-            _ => {}
-        }
-    }
-    res
-}
-
-#[test]
-fn test_escape_format_string() {
-    assert!(escape_format_string(r"foo{}\") == r"foo{{}}\\");
-}
-
-/// Unescapes the escaped unicodes (`\u{...}`) that are printable.
-fn unescape_printable_unicode(mut s: &str) -> String {
-    use std::{char, u32};
-
-    let mut res = String::with_capacity(s.len());
-
-    loop {
-        if let Some(start) = s.find(r"\u{") {
-            res.push_str(&s[0..start]);
-            s = &s[start..];
-            s.find('}')
-                .and_then(|end| {
-                    let v = u32::from_str_radix(&s[3..end], 16).ok()?;
-                    let c = char::from_u32(v)?;
-                    // Escape unprintable characters.
-                    res.extend(c.escape_debug());
-                    s = &s[end + 1..];
-                    Some(())
-                })
-                .expect("lexer should have rejected invalid escape sequences");
-        } else {
-            res.push_str(s);
-            return res;
-        }
-    }
-}
-
-#[test]
-fn test_unescape_printable_unicode() {
-    assert!(unescape_printable_unicode(r"\u{2603}\n\u{0}") == r"☃\n\u{0}");
-}
index 1ea18a5cb431e24aa838b652ac305acc5e394d6b..2f86c75a2479cf051b92fc98273daaf7f151e7a1 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 1ea18a5cb431e24aa838b652ac305acc5e394d6b
+Subproject commit 2f86c75a2479cf051b92fc98273daaf7f151e7a1
index 4db5c84df9a63d6f43d170da9fccb52170f8da00..d793a78799a70714ef6d1d832aa1c78eed34f8d6 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![deny(incoherent_fundamental_impls)]
-
 pub trait Trait1<X> {
     type Output;
 }
diff --git a/src/test/compile-fail/issue-50471.rs b/src/test/compile-fail/issue-50471.rs
new file mode 100644 (file)
index 0000000..ce29471
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2018 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-pass
+
+fn main() {
+    assert!({false});
+
+    assert!(r"\u{41}" == "A");
+
+    assert!(r"\u{".is_empty());
+}
index 14d5d9caa317f5ed95a9ff6f5dc6144488d89e81..fcf4714ba9695ff3c4a40a67290072ee34d57a16 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// compile-flags: --edition=2018 -Zunstable-options
+
 #![feature(extern_absolute_paths)]
 
 use xcrate::S; //~ ERROR can't find crate for `xcrate`
index defd103f9e457d55d901594a566fdd1cfb4be4ad..c256c5592c2695a1d95975db26f189cee04d9ab7 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// compile-flags: --edition=2018 -Zunstable-options
+
 #![feature(extern_absolute_paths)]
 
 fn main() {
index be1708e2b57489e333a8d68f80c517e0b74a8cb0..837dc617b3ad056cb539711b3659ddb0f6ffd3bf 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// compile-flags: --edition=2018 -Zunstable-options
+
 #![feature(extern_absolute_paths)]
 
 use ycrate; //~ ERROR can't find crate for `ycrate`
index e44465750d1ddc024999c0455e97a8c6d6a93af6..9b7baa0016344221d9de93fc676af7d0e3a727f2 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // aux-build:xcrate.rs
+// compile-flags: --edition=2018 -Zunstable-options
 
 #![feature(crate_in_paths)]
 #![feature(extern_absolute_paths)]
index 0c6c7fc5a0d75bacafd543201c0deaeddbc23694..363ab6220bd6e7fb742c4d9f98a37a013df74579 100644 (file)
@@ -8,8 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![deny(unused_results, unused_must_use)]
 #![allow(dead_code)]
+#![deny(unused_results, unused_must_use)]
+//~^ NOTE: lint level defined here
+//~| NOTE: lint level defined here
 
 #[must_use]
 enum MustUse { Test }
@@ -27,7 +29,8 @@ fn foo<T>() -> T { panic!() }
 fn test() {
     foo::<isize>();
     foo::<MustUse>(); //~ ERROR: unused `MustUse` which must be used
-    foo::<MustUseMsg>(); //~ ERROR: unused `MustUseMsg` which must be used: some message
+    foo::<MustUseMsg>(); //~ ERROR: unused `MustUseMsg` which must be used
+    //~^ NOTE: some message
 }
 
 #[allow(unused_results, unused_must_use)]
@@ -40,7 +43,8 @@ fn test2() {
 fn main() {
     foo::<isize>(); //~ ERROR: unused result
     foo::<MustUse>(); //~ ERROR: unused `MustUse` which must be used
-    foo::<MustUseMsg>(); //~ ERROR: unused `MustUseMsg` which must be used: some message
+    foo::<MustUseMsg>(); //~ ERROR: unused `MustUseMsg` which must be used
+    //~^ NOTE: some message
 
     let _ = foo::<isize>();
     let _ = foo::<MustUse>();
index a132668ec7c8a43a4e85426fe98f5976e492013e..6a67b5862a815526ed7fb103d30d77333bdfcc0b 100644 (file)
@@ -1,9 +1,9 @@
 -include ../tools.mk
 
 all: extern_absolute_paths.rs extern_in_paths.rs krate2
-       $(RUSTC) extern_absolute_paths.rs -Zsave-analysis
+       $(RUSTC) extern_absolute_paths.rs -Zsave-analysis --edition=2018
        cat $(TMPDIR)/save-analysis/extern_absolute_paths.json | "$(PYTHON)" validate_json.py
-       $(RUSTC) extern_in_paths.rs -Zsave-analysis
+       $(RUSTC) extern_in_paths.rs -Zsave-analysis --edition=2018
        cat $(TMPDIR)/save-analysis/extern_in_paths.json | "$(PYTHON)" validate_json.py
 
 krate2: krate2.rs
diff --git a/src/test/run-make/cross-lang-lto/Makefile b/src/test/run-make/cross-lang-lto/Makefile
new file mode 100644 (file)
index 0000000..98b509c
--- /dev/null
@@ -0,0 +1,53 @@
+
+# min-llvm-version 4.0
+# ignore-mingw
+
+-include ../../run-make-fulldeps/tools.mk
+
+# This test makes sure that the expected .llvmbc sections for use by
+# linker-based LTO are available in object files when compiling with
+# -Z cross-lang-lto
+
+LLVMBC_SECTION_NAME=\\.llvmbc
+
+ifeq ($(UNAME),Darwin)
+       LLVMBC_SECTION_NAME=__bitcode
+endif
+
+
+OBJDUMP=llvm-objdump
+SECTION_HEADERS=$(OBJDUMP) -section-headers
+
+BUILD_LIB=$(RUSTC) lib.rs -Copt-level=2 -Z cross-lang-lto -Ccodegen-units=1
+
+BUILD_EXE=$(RUSTC) main.rs -Copt-level=2 -Z cross-lang-lto -Ccodegen-units=1 --emit=obj
+
+all: staticlib staticlib-fat-lto staticlib-thin-lto rlib exe cdylib rdylib
+
+staticlib: lib.rs
+       $(BUILD_LIB) --crate-type=staticlib -o $(TMPDIR)/liblib.a
+       [ "$$($(SECTION_HEADERS) $(TMPDIR)/liblib.a | grep -c $(LLVMBC_SECTION_NAME))" -ne "0" ]
+
+staticlib-fat-lto: lib.rs
+       $(BUILD_LIB) --crate-type=staticlib -o $(TMPDIR)/liblib-fat-lto.a -Clto=fat
+       [ "$$($(SECTION_HEADERS) $(TMPDIR)/liblib-fat-lto.a | grep -c $(LLVMBC_SECTION_NAME))" -ne "0" ]
+
+staticlib-thin-lto: lib.rs
+       $(BUILD_LIB) --crate-type=staticlib -o $(TMPDIR)/liblib-thin-lto.a -Clto=thin
+       [ "$$($(SECTION_HEADERS) $(TMPDIR)/liblib-thin-lto.a | grep -c $(LLVMBC_SECTION_NAME))" -ne "0" ]
+
+rlib: lib.rs
+       $(BUILD_LIB) --crate-type=rlib -o $(TMPDIR)/liblib.rlib
+       [ "$$($(SECTION_HEADERS) $(TMPDIR)/liblib.rlib | grep -c $(LLVMBC_SECTION_NAME))" -ne "0" ]
+
+cdylib: lib.rs
+       $(BUILD_LIB) --crate-type=cdylib --emit=obj -o $(TMPDIR)/cdylib.o
+       [ "$$($(SECTION_HEADERS) $(TMPDIR)/cdylib.o | grep -c $(LLVMBC_SECTION_NAME))" -ne "0" ]
+
+rdylib: lib.rs
+       $(BUILD_LIB) --crate-type=dylib --emit=obj -o $(TMPDIR)/rdylib.o
+       [ "$$($(SECTION_HEADERS) $(TMPDIR)/rdylib.o | grep -c $(LLVMBC_SECTION_NAME))" -ne "0" ]
+
+exe: lib.rs
+       $(BUILD_EXE) -o $(TMPDIR)/exe.o
+       [ "$$($(SECTION_HEADERS) $(TMPDIR)/exe.o | grep -c $(LLVMBC_SECTION_NAME))" -ne "0" ]
diff --git a/src/test/run-make/cross-lang-lto/lib.rs b/src/test/run-make/cross-lang-lto/lib.rs
new file mode 100644 (file)
index 0000000..b2a5b94
--- /dev/null
@@ -0,0 +1,14 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[no_mangle]
+pub extern "C" fn foo() {
+    println!("abc");
+}
diff --git a/src/test/run-make/cross-lang-lto/main.rs b/src/test/run-make/cross-lang-lto/main.rs
new file mode 100644 (file)
index 0000000..ccd34c9
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2018 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.
+
+fn main() {
+    println!("Hello World");
+}
diff --git a/src/test/run-pass/issue-43355.rs b/src/test/run-pass/issue-43355.rs
deleted file mode 100644 (file)
index 19431a6..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Check that the code for issue #43355 can run without an ICE, please remove
-// this test when it becomes an hard error.
-
-pub trait Trait1<X> {
-    type Output;
-}
-pub trait Trait2<X> {}
-
-impl<X, T> Trait1<X> for T where T: Trait2<X> {
-    type Output = ();
-}
-impl<X> Trait1<Box<X>> for A {
-    type Output = i32;
-}
-
-pub struct A;
-
-fn f<X, T: Trait1<Box<X>>>() {
-    println!("k: {}", ::std::mem::size_of::<<T as Trait1<Box<X>>>::Output>());
-}
-
-pub fn g<X, T: Trait2<Box<X>>>() {
-    f::<X, T>();
-}
-
-fn main() {}
index 0fa125a3e503e3d600545c39301b0cdcfb1b7e43..bbe066481a8b15d313c807e0a691b334a2fcdbf7 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // aux-build:xcrate.rs
+// compile-flags: --edition=2018 -Zunstable-options
 
 #![feature(extern_absolute_paths)]
 
index 796f652d6b57ba05aebf395e102307cbb8536842..ead462cf0d2cacc09754c6718616cbaffd30e185 100644 (file)
@@ -12,7 +12,7 @@
 //
 // Regression test for #47075.
 
-// compile-flags: --test
+// compile-flags: --test --edition=2018 -Zunstable-options
 
 #![feature(extern_absolute_paths)]
 
diff --git a/src/test/rustdoc/auxiliary/mod-stackoverflow.rs b/src/test/rustdoc/auxiliary/mod-stackoverflow.rs
new file mode 100644 (file)
index 0000000..f03593d
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2018 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: -Cmetadata=aux
+
+pub mod tree {
+    pub use tree;
+}
+
+pub mod tree2 {
+    pub mod prelude {
+        pub use tree2;
+    }
+}
diff --git a/src/test/rustdoc/mod-stackoverflow.rs b/src/test/rustdoc/mod-stackoverflow.rs
new file mode 100644 (file)
index 0000000..1e2f6db
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:mod-stackoverflow.rs
+// ignore-cross-compile
+
+extern crate mod_stackoverflow;
+pub use mod_stackoverflow::tree;
+pub use mod_stackoverflow::tree2;
diff --git a/src/test/ui-fulldeps/unnecessary-extern-crate.rs b/src/test/ui-fulldeps/unnecessary-extern-crate.rs
new file mode 100644 (file)
index 0000000..9d678d9
--- /dev/null
@@ -0,0 +1,55 @@
+// 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.
+
+#![deny(unnecessary_extern_crate)]
+#![feature(alloc, test, libc)]
+
+extern crate alloc;
+//~^ ERROR `extern crate` is unnecessary in the new edition
+//~| HELP remove
+extern crate alloc as x;
+//~^ ERROR `extern crate` is unnecessary in the new edition
+//~| HELP use `use`
+
+#[macro_use]
+extern crate test;
+pub extern crate test as y;
+//~^ ERROR `extern crate` is unnecessary in the new edition
+//~| HELP use `pub use`
+pub extern crate libc;
+//~^ ERROR `extern crate` is unnecessary in the new edition
+//~| HELP use `pub use`
+
+
+mod foo {
+    extern crate alloc;
+    //~^ ERROR `extern crate` is unnecessary in the new edition
+    //~| HELP use `use`
+    extern crate alloc as x;
+    //~^ ERROR `extern crate` is unnecessary in the new edition
+    //~| HELP use `use`
+    pub extern crate test;
+    //~^ ERROR `extern crate` is unnecessary in the new edition
+    //~| HELP use `pub use`
+    pub extern crate test as y;
+    //~^ ERROR `extern crate` is unnecessary in the new edition
+    //~| HELP use `pub use`
+    mod bar {
+        extern crate alloc;
+        //~^ ERROR `extern crate` is unnecessary in the new edition
+        //~| HELP use `use`
+        extern crate alloc as x;
+        //~^ ERROR `extern crate` is unnecessary in the new edition
+        //~| HELP use `use`
+    }
+}
+
+
+fn main() {}
diff --git a/src/test/ui-fulldeps/unnecessary-extern-crate.stderr b/src/test/ui-fulldeps/unnecessary-extern-crate.stderr
new file mode 100644 (file)
index 0000000..7718808
--- /dev/null
@@ -0,0 +1,68 @@
+error: `extern crate` is unnecessary in the new edition
+  --> $DIR/unnecessary-extern-crate.rs:14:1
+   |
+LL | extern crate alloc;
+   | ^^^^^^^^^^^^^^^^^^^ help: remove it
+   |
+note: lint level defined here
+  --> $DIR/unnecessary-extern-crate.rs:11:9
+   |
+LL | #![deny(unnecessary_extern_crate)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `extern crate` is unnecessary in the new edition
+  --> $DIR/unnecessary-extern-crate.rs:17:1
+   |
+LL | extern crate alloc as x;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `use`: `use alloc as x`
+
+error: `extern crate` is unnecessary in the new edition
+  --> $DIR/unnecessary-extern-crate.rs:23:1
+   |
+LL | pub extern crate test as y;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `pub use`: `pub use test as y`
+
+error: `extern crate` is unnecessary in the new edition
+  --> $DIR/unnecessary-extern-crate.rs:26:1
+   |
+LL | pub extern crate libc;
+   | ^^^^^^^^^^^^^^^^^^^^^^ help: use `pub use`: `pub use libc`
+
+error: `extern crate` is unnecessary in the new edition
+  --> $DIR/unnecessary-extern-crate.rs:32:5
+   |
+LL |     extern crate alloc;
+   |     ^^^^^^^^^^^^^^^^^^^ help: use `use`: `use alloc`
+
+error: `extern crate` is unnecessary in the new edition
+  --> $DIR/unnecessary-extern-crate.rs:35:5
+   |
+LL |     extern crate alloc as x;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `use`: `use alloc as x`
+
+error: `extern crate` is unnecessary in the new edition
+  --> $DIR/unnecessary-extern-crate.rs:38:5
+   |
+LL |     pub extern crate test;
+   |     ^^^^^^^^^^^^^^^^^^^^^^ help: use `pub use`: `pub use test`
+
+error: `extern crate` is unnecessary in the new edition
+  --> $DIR/unnecessary-extern-crate.rs:41:5
+   |
+LL |     pub extern crate test as y;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `pub use`: `pub use test as y`
+
+error: `extern crate` is unnecessary in the new edition
+  --> $DIR/unnecessary-extern-crate.rs:45:9
+   |
+LL |         extern crate alloc;
+   |         ^^^^^^^^^^^^^^^^^^^ help: use `use`: `use alloc`
+
+error: `extern crate` is unnecessary in the new edition
+  --> $DIR/unnecessary-extern-crate.rs:48:9
+   |
+LL |         extern crate alloc as x;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `use`: `use alloc as x`
+
+error: aborting due to 10 previous errors
+
diff --git a/src/test/ui/const-eval/extern_fat_pointer.rs b/src/test/ui/const-eval/extern_fat_pointer.rs
new file mode 100644 (file)
index 0000000..0713114
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2018 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-pass
+
+#![feature(extern_types)]
+
+extern {
+    type Opaque;
+}
+
+const FOO: *const u8 = &42 as *const _ as *const Opaque as *const u8;
+
+fn main() {
+    let _foo = FOO;
+}
index 5026dac0a949e3f0da97c203deb34df5ffa59257..b5bad22f3dc78b2502353b0b56a4a8671a6180b5 100644 (file)
@@ -1,4 +1,4 @@
-warning: unused return value of `need_to_use_this_value` which must be used: it's important
+warning: unused return value of `need_to_use_this_value` which must be used
   --> $DIR/fn_must_use.rs:60:5
    |
 LL |     need_to_use_this_value(); //~ WARN unused return value
@@ -9,6 +9,7 @@ note: lint level defined here
    |
 LL | #![warn(unused_must_use)]
    |         ^^^^^^^^^^^^^^^
+   = note: it's important
 
 warning: unused return value of `MyStruct::need_to_use_this_method_value` which must be used
   --> $DIR/fn_must_use.rs:65:5
@@ -16,11 +17,13 @@ warning: unused return value of `MyStruct::need_to_use_this_method_value` which
 LL |     m.need_to_use_this_method_value(); //~ WARN unused return value
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: unused return value of `EvenNature::is_even` which must be used: no side effects
+warning: unused return value of `EvenNature::is_even` which must be used
   --> $DIR/fn_must_use.rs:66:5
    |
 LL |     m.is_even(); // trait method!
    |     ^^^^^^^^^^^^
+   |
+   = note: no side effects
 
 warning: unused return value of `std::cmp::PartialEq::eq` which must be used
   --> $DIR/fn_must_use.rs:72:5
index af3f1cd29bc872b932a13083e531255aab233a7e..9e53ac6e6525da914cb05a85e5e8eff7b5dca81f 160000 (submodule)
@@ -1 +1 @@
-Subproject commit af3f1cd29bc872b932a13083e531255aab233a7e
+Subproject commit 9e53ac6e6525da914cb05a85e5e8eff7b5dca81f
index 1742229ebb7843a65c05ee495d8de5366fcc5567..e456241f18227c7eb8d78a45daa66c756a9b65e7 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 1742229ebb7843a65c05ee495d8de5366fcc5567
+Subproject commit e456241f18227c7eb8d78a45daa66c756a9b65e7
index 7ac3f5b5b25e8e5115f7943c0b0f3594a7906a0d..32980a513f6f94a8946693aa2a7cdae0c3ad45af 100644 (file)
@@ -425,6 +425,15 @@ fn iter_header(testfile: &Path, cfg: Option<&str>, it: &mut FnMut(&str)) {
     if testfile.is_dir() {
         return;
     }
+
+    let comment = if testfile.to_string_lossy().ends_with(".rs") {
+        "//"
+    } else {
+        "#"
+    };
+
+    let comment_with_brace = comment.to_string() + "[";
+
     let rdr = BufReader::new(File::open(testfile).unwrap());
     for ln in rdr.lines() {
         // Assume that any directives will be found before the first
@@ -434,10 +443,11 @@ fn iter_header(testfile: &Path, cfg: Option<&str>, it: &mut FnMut(&str)) {
         let ln = ln.trim();
         if ln.starts_with("fn") || ln.starts_with("mod") {
             return;
-        } else if ln.starts_with("//[") {
+        } else if ln.starts_with(&comment_with_brace) {
             // A comment like `//[foo]` is specific to revision `foo`
             if let Some(close_brace) = ln.find(']') {
-                let lncfg = &ln[3..close_brace];
+                let open_brace = ln.find('[').unwrap();
+                let lncfg = &ln[open_brace + 1 .. close_brace];
                 let matches = match cfg {
                     Some(s) => s == &lncfg[..],
                     None => false,
@@ -446,11 +456,11 @@ fn iter_header(testfile: &Path, cfg: Option<&str>, it: &mut FnMut(&str)) {
                     it(ln[(close_brace + 1) ..].trim_left());
                 }
             } else {
-                panic!("malformed condition directive: expected `//[foo]`, found `{}`",
-                       ln)
+                panic!("malformed condition directive: expected `{}foo]`, found `{}`",
+                        comment_with_brace, ln)
             }
-        } else if ln.starts_with("//") {
-            it(ln[2..].trim_left());
+        } else if ln.starts_with(comment) {
+            it(ln[comment.len() ..].trim_left());
         }
     }
     return;
index e2b446c99dcc0139279beeaf230527c410459353..e8b140978b51b5a621bf38473295bc5fd67a62bb 100644 (file)
@@ -614,7 +614,12 @@ pub fn is_test(file_name: &OsString) -> bool {
 }
 
 pub fn make_test(config: &Config, testpaths: &TestPaths) -> test::TestDescAndFn {
-    let early_props = EarlyProps::from_file(config, &testpaths.file);
+
+    let early_props = if config.mode == Mode::RunMake {
+        EarlyProps::from_file(config, &testpaths.file.join("Makefile"))
+    } else {
+        EarlyProps::from_file(config, &testpaths.file)
+    };
 
     // The `should-fail` annotation doesn't apply to pretty tests,
     // since we run the pretty printer across all tests by default.
index f48fed70d4447445b586a35c4ae88683542ffc72..e0e1bd7ff778e5913b566c9e03224faecc0eb486 160000 (submodule)
@@ -1 +1 @@
-Subproject commit f48fed70d4447445b586a35c4ae88683542ffc72
+Subproject commit e0e1bd7ff778e5913b566c9e03224faecc0eb486
index 8e23519f57ebca5130913b5ceda69605ff964cfa..1539c2e25781b09d2e5ddabcbe19e63be1a2087a 100755 (executable)
@@ -86,7 +86,7 @@ def update_latest(
                         .format(tool, os, old, new)
                 elif new < old:
                     changed = True
-                    message += '💔 {} on {}: {} â†’ {} (cc {}).\n' \
+                    message += '💔 {} on {}: {} â†’ {} (cc {}, @rust-lang/infra).\n' \
                         .format(tool, os, old, new, MAINTAINERS.get(tool))
 
             if changed:
index d2f44357fef6d61f316abc403e0a5d917f2771c6..d2ade31a52a417257742de72c5936a8a342a34b5 160000 (submodule)
@@ -1 +1 @@
-Subproject commit d2f44357fef6d61f316abc403e0a5d917f2771c6
+Subproject commit d2ade31a52a417257742de72c5936a8a342a34b5
index b6cd17f28ae314f2484ff05d3ce57652d51c5e85..0f8029f251b569a010cb5cfc5a8bff8bf3c949ac 160000 (submodule)
@@ -1 +1 @@
-Subproject commit b6cd17f28ae314f2484ff05d3ce57652d51c5e85
+Subproject commit 0f8029f251b569a010cb5cfc5a8bff8bf3c949ac
index fa2274366401445737932941c876e0df8b26232d..022ef57503aaabadaec4d5e7b76525c5ca32599f 100644 (file)
@@ -51,6 +51,7 @@ macro_rules! tidy_error {
 pub mod deps;
 pub mod ui_tests;
 pub mod unstable_book;
+pub mod libcoretest;
 
 fn filter_dirs(path: &Path) -> bool {
     let skip = [
diff --git a/src/tools/tidy/src/libcoretest.rs b/src/tools/tidy/src/libcoretest.rs
new file mode 100644 (file)
index 0000000..ef8b551
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright 2018 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.
+
+//! Tidy check to ensure `#[test]` is not used directly inside `libcore`.
+//!
+//! `#![no_core]` libraries cannot be tested directly due to duplicating lang
+//! item. All tests must be written externally in `libcore/tests`.
+
+use std::path::Path;
+use std::fs::read_to_string;
+
+pub fn check(path: &Path, bad: &mut bool) {
+    let libcore_path = path.join("libcore");
+    super::walk(
+        &libcore_path,
+        &mut |subpath| t!(subpath.strip_prefix(&libcore_path)).starts_with("tests"),
+        &mut |subpath| {
+            if t!(read_to_string(subpath)).contains("#[test]") {
+                tidy_error!(
+                    bad,
+                    "{} contains #[test]; libcore tests must be placed inside `src/libcore/tests/`",
+                    subpath.display()
+                );
+            }
+        },
+    );
+}
index 24974192795608aa302b8df9ba4bb7d6cd32e62c..7b86650823a437a1366c2a1a4f0bfc198569790c 100644 (file)
@@ -41,6 +41,7 @@ fn main() {
     features::check(&path, &mut bad, quiet);
     pal::check(&path, &mut bad);
     unstable_book::check(&path, &mut bad);
+    libcoretest::check(&path, &mut bad);
     if !args.iter().any(|s| *s == "--no-vendor") {
         deps::check(&path, &mut bad);
     }