]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #47947 - goodmanjonathan:stabilize_match_beginning_vert, r=petrochenkov
authorkennytm <kennytm@gmail.com>
Sun, 4 Feb 2018 15:28:58 +0000 (23:28 +0800)
committerGitHub <noreply@github.com>
Sun, 4 Feb 2018 15:28:58 +0000 (23:28 +0800)
Stabilize feature(match_beginning_vert)

With this feature stabilized, match expressions can optionally have a `|` at the beginning of each arm.

Reference PR: rust-lang-nursery/reference#231

Closes #44101

171 files changed:
config.toml.example
src/Cargo.lock
src/bootstrap/builder.rs
src/bootstrap/compile.rs
src/bootstrap/config.rs
src/bootstrap/dist.rs
src/bootstrap/lib.rs
src/bootstrap/test.rs
src/doc/unstable-book/src/language-features/lang-items.md
src/etc/wasm32-shim.js
src/libcore/fmt/mod.rs
src/libcore/fmt/num.rs
src/libcore/intrinsics.rs
src/libcore/iter/mod.rs
src/libcore/lib.rs
src/libcore/mem.rs
src/libcore/num/f32.rs
src/libcore/num/f64.rs
src/libcore/tests/iter.rs
src/libcore/time.rs [new file with mode: 0644]
src/libpanic_abort/lib.rs
src/librustc/README.md
src/librustc/dep_graph/dep_node.rs
src/librustc/infer/error_reporting/mod.rs
src/librustc/infer/error_reporting/note.rs
src/librustc/lib.rs
src/librustc/lint/builtin.rs
src/librustc/lint/context.rs
src/librustc/middle/region.rs
src/librustc/middle/resolve_lifetime.rs
src/librustc/session/config.rs
src/librustc/session/mod.rs
src/librustc/traits/coherence.rs
src/librustc/traits/error_reporting.rs
src/librustc/traits/mod.rs
src/librustc/traits/select.rs
src/librustc/traits/specialize/specialization_graph.rs
src/librustc/traits/structural_impls.rs
src/librustc/ty/layout.rs
src/librustc/ty/maps/mod.rs
src/librustc/ty/maps/plumbing.rs
src/librustc/ty/sty.rs
src/librustc_back/target/mod.rs
src/librustc_back/target/msp430_none_elf.rs
src/librustc_back/target/wasm32_unknown_unknown.rs
src/librustc_borrowck/borrowck/unused.rs
src/librustc_const_eval/check_match.rs
src/librustc_const_eval/eval.rs
src/librustc_const_eval/pattern.rs
src/librustc_driver/lib.rs
src/librustc_errors/diagnostic.rs
src/librustc_errors/diagnostic_builder.rs
src/librustc_errors/emitter.rs
src/librustc_errors/lib.rs
src/librustc_errors/snippet.rs
src/librustc_errors/styled_buffer.rs
src/librustc_lint/types.rs
src/librustc_lint/unused.rs
src/librustc_mir/borrow_check/error_reporting.rs
src/librustc_mir/borrow_check/nll/type_check/mod.rs
src/librustc_mir/dataflow/impls/borrowed_locals.rs [new file with mode: 0644]
src/librustc_mir/dataflow/impls/borrows.rs
src/librustc_mir/dataflow/impls/mod.rs
src/librustc_mir/dataflow/mod.rs
src/librustc_mir/interpret/eval_context.rs
src/librustc_mir/monomorphize/partitioning.rs
src/librustc_mir/transform/generator.rs
src/librustc_mir/transform/inline.rs
src/librustc_passes/loops.rs
src/librustc_resolve/lib.rs
src/librustc_trans/allocator.rs
src/librustc_trans/asm.rs
src/librustc_trans/back/symbol_export.rs
src/librustc_trans/back/write.rs
src/librustc_trans/context.rs
src/librustc_trans/type_of.rs
src/librustc_typeck/check/compare_method.rs
src/librustc_typeck/check/generator_interior.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/coherence/inherent_impls_overlap.rs
src/librustdoc/clean/mod.rs
src/librustdoc/html/static/rustdoc.css
src/librustdoc/test.rs
src/libstd/Cargo.toml
src/libstd/f32.rs
src/libstd/io/error.rs
src/libstd/sys/cloudabi/thread.rs
src/libstd/sys/redox/thread.rs
src/libstd/sys/unix/stack_overflow.rs
src/libstd/sys/unix/thread.rs
src/libstd/sys/wasm/args.rs
src/libstd/sys/wasm/mod.rs
src/libstd/sys/wasm/os.rs
src/libstd/sys/wasm/stdio.rs
src/libstd/sys/wasm/thread.rs
src/libstd/sys/wasm/time.rs
src/libstd/sys/windows/thread.rs
src/libstd/sys_common/thread_info.rs
src/libstd/time.rs [new file with mode: 0644]
src/libstd/time/duration.rs [deleted file]
src/libstd/time/mod.rs [deleted file]
src/libsyntax/codemap.rs
src/libsyntax/feature_gate.rs
src/libsyntax/json.rs
src/libsyntax/lib.rs
src/libsyntax/parse/lexer/mod.rs
src/libsyntax/parse/token.rs
src/libsyntax/test_snippet.rs
src/libsyntax_ext/deriving/encodable.rs
src/libsyntax_pos/lib.rs
src/rustllvm/PassWrapper.cpp
src/test/codegen/function-arguments.rs
src/test/codegen/stack-probes.rs
src/test/compile-fail/E0195.rs
src/test/compile-fail/associated-const-type-parameter-arms.rs
src/test/compile-fail/issue-16048.rs
src/test/compile-fail/nll/do-not-ignore-lifetime-bounds-in-copy.rs [new file with mode: 0644]
src/test/compile-fail/regions-bound-missing-bound-in-impl.rs [deleted file]
src/test/parse-fail/bad-char-literals.rs
src/test/parse-fail/lex-stray-backslash.rs [new file with mode: 0644]
src/test/run-make/stdin-non-utf8/Makefile [new file with mode: 0644]
src/test/run-make/stdin-non-utf8/non-utf8 [new file with mode: 0644]
src/test/run-pass/generator/too-live-local-in-immovable-gen.rs [new file with mode: 0644]
src/test/run-pass/issue-47139-1.rs [new file with mode: 0644]
src/test/run-pass/issue-47139-2.rs [new file with mode: 0644]
src/test/run-pass/issue-47638.rs [new file with mode: 0644]
src/test/run-pass/issue-47789.rs [new file with mode: 0644]
src/test/run-pass/sse2.rs
src/test/run-pass/stack-probes-lto.rs
src/test/run-pass/stack-probes.rs
src/test/rustdoc/const-evalutation-ice.rs [new file with mode: 0644]
src/test/ui/associated-const-impl-wrong-lifetime.stderr
src/test/ui/blind-item-item-shadow.stderr
src/test/ui/borrowck/regions-bound-missing-bound-in-impl.rs [new file with mode: 0644]
src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr [new file with mode: 0644]
src/test/ui/closure-expected-type/expect-region-supply-region.stderr
src/test/ui/double-import.stderr
src/test/ui/generator/generator-with-nll.stderr
src/test/ui/generator/pattern-borrow.rs [new file with mode: 0644]
src/test/ui/generator/pattern-borrow.stderr [new file with mode: 0644]
src/test/ui/generator/sized-yield.rs [new file with mode: 0644]
src/test/ui/generator/sized-yield.stderr [new file with mode: 0644]
src/test/ui/generator/yield-while-local-borrowed.stderr
src/test/ui/impl-trait/trait_type.stderr
src/test/ui/imports/duplicate.stderr
src/test/ui/in-band-lifetimes/ellided-lifetimes.rs [new file with mode: 0644]
src/test/ui/in-band-lifetimes/ellided-lifetimes.stderr [new file with mode: 0644]
src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs [new file with mode: 0644]
src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr [new file with mode: 0644]
src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr
src/test/ui/issue-26886.stderr
src/test/ui/issue-27942.stderr
src/test/ui/issue-37884.stderr
src/test/ui/issue-46472.stderr
src/test/ui/issue-47706-trait.rs [new file with mode: 0644]
src/test/ui/issue-47706-trait.stderr [new file with mode: 0644]
src/test/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.rs [new file with mode: 0644]
src/test/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.stderr [new file with mode: 0644]
src/test/ui/lint/suggestions.rs
src/test/ui/lint/suggestions.stderr
src/test/ui/loop-break-value-no-repeat.stderr
src/test/ui/macros/span-covering-argument-1.rs [new file with mode: 0644]
src/test/ui/macros/span-covering-argument-1.stderr [new file with mode: 0644]
src/test/ui/resolve-conflict-item-vs-import.stderr
src/test/ui/span/macro-span-replacement.stderr
src/test/ui/static-lifetime.stderr
src/test/ui/suggestions/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr
src/test/ui/use-mod.stderr
src/tools/compiletest/src/header.rs
src/tools/rls
src/tools/rustfmt

index 1d60d8c949441527c16b6f4eda11ca832186aaf2..9ca0f563d0af1472c489b179118d3eb94c5ffa0a 100644 (file)
 # bootstrap)
 #codegen-backends = ["llvm"]
 
+# Flag indicating whether `libstd` calls an imported function to hande basic IO
+# when targetting WebAssembly. Enable this to debug tests for the `wasm32-unknown-unknown`
+# target, as without this option the test output will not be captured.
+#wasm-syscall = false
+
 # =============================================================================
 # Options for specific targets
 #
index d26098903eec5a05931545f94a6a665c149c9290..fc89cc4ea9ee3786a71a780ae6df283abfb7b7ab 100644 (file)
@@ -1618,7 +1618,7 @@ version = "0.1.0"
 
 [[package]]
 name = "rls"
-version = "0.124.0"
+version = "0.125.0"
 dependencies = [
  "cargo 0.26.0",
  "env_logger 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1635,7 +1635,7 @@ dependencies = [
  "rls-rustc 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-vfs 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustfmt-nightly 0.3.6",
+ "rustfmt-nightly 0.3.8",
  "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1723,7 +1723,7 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_cratesio_shim"
-version = "12.0.0"
+version = "29.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1732,57 +1732,57 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_data_structures"
-version = "12.0.0"
+version = "29.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot_core 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rustc-ap-rustc_errors"
-version = "12.0.0"
+version = "29.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rustc-ap-rustc_data_structures 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax_pos 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rustc-ap-serialize"
-version = "12.0.0"
+version = "29.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "rustc-ap-syntax"
-version = "12.0.0"
+version = "29.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_cratesio_shim 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_data_structures 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_errors 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax_pos 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_cratesio_shim 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_errors 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rustc-ap-syntax_pos"
-version = "12.0.0"
+version = "29.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rustc-ap-rustc_data_structures 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -2207,7 +2207,7 @@ dependencies = [
 
 [[package]]
 name = "rustfmt-nightly"
-version = "0.3.6"
+version = "0.3.8"
 dependencies = [
  "cargo_metadata 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "derive-new 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2219,8 +2219,8 @@ dependencies = [
  "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_errors 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_errors 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3068,12 +3068,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum rls-rustc 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "85cfb9dde19e313da3e47738008f8a472e470cc42d910b71595a9238494701f2"
 "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a"
 "checksum rls-vfs 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ffd34691a510938bb67fe0444fb363103c73ffb31c121d1e16bc92d8945ea8ff"
-"checksum rustc-ap-rustc_cratesio_shim 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f1a51c10af5abd5d698b7e3487e869e6d15f6feb04cbedb5c792e2824f9d845e"
-"checksum rustc-ap-rustc_data_structures 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1aa227490501072780d57f74b1164d361833ff8e172f817da0da2cdf2e4280cc"
-"checksum rustc-ap-rustc_errors 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "21ff6c6e13ac4fc04b7d4d398828b024c4b6577045cb3175b33d35fea35ff6d0"
-"checksum rustc-ap-serialize 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6b4e7f51e298675c2bf830f7265621a8936fb09e63b825b58144cbaac969e604"
-"checksum rustc-ap-syntax 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8bf5639869ba2f7fa581939cd217cb71a85506b82ad0ea520614fb0dceb2386c"
-"checksum rustc-ap-syntax_pos 12.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1c020cdb7379e1c733ae0a311ae47c748337ba584d2dd7b7f53baaae78de6f8b"
+"checksum rustc-ap-rustc_cratesio_shim 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ad5e562044ea78a6764dd75ae8afe4b21fde49f4548024b5fdf6345c21fb524"
+"checksum rustc-ap-rustc_data_structures 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c0d65325492aba7db72899e3edbab34d39af98c42ab7c7e450c9a288ffe4ad"
+"checksum rustc-ap-rustc_errors 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "87d4ab2e06a671b5b5c5b0359dac346f164c99d059dce6a22feb08f2f56bd182"
+"checksum rustc-ap-serialize 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e0745fa445ff41c4b6699936cf35ce3ca49502377dd7b3929c829594772c3a7b"
+"checksum rustc-ap-syntax 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "82efedabe30f393161e11214a9130edfa01ad476372d1c6f3fec1f8d30488c9d"
+"checksum rustc-ap-syntax_pos 29.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db9de2e927e280c75b8efab9c5f591ad31082d5d2c4c562c68fdba2ee77286b0"
 "checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e"
 "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
 "checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7"
index 1272643edd2599d9d5b8a95428eaa0fbb3f10059..780513dd943946853c7085980219fd85c5778729 100644 (file)
@@ -377,6 +377,11 @@ fn run(self, builder: &Builder) -> Interned<PathBuf> {
         self.ensure(Libdir { compiler, target })
     }
 
+    pub fn sysroot_codegen_backends(&self, compiler: Compiler) -> PathBuf {
+        self.sysroot_libdir(compiler, compiler.host)
+            .with_file_name("codegen-backends")
+    }
+
     /// Returns the compiler's libdir where it stores the dynamic libraries that
     /// it itself links against.
     ///
index fa289bbd76a8bc5924c9700e24ededf554c70e81..1d5e11c5d6d41c06f55d088a82b6be93914928e1 100644 (file)
@@ -724,8 +724,7 @@ fn copy_codegen_backends_to_sysroot(builder: &Builder,
     //
     // Here we're looking for the output dylib of the `CodegenBackend` step and
     // we're copying that into the `codegen-backends` folder.
-    let libdir = builder.sysroot_libdir(target_compiler, target);
-    let dst = libdir.join("codegen-backends");
+    let dst = builder.sysroot_codegen_backends(target_compiler);
     t!(fs::create_dir_all(&dst));
 
     for backend in builder.config.rust_codegen_backends.iter() {
index dbeb27cbfb7d36d5b1f8e377da977f86a7af37bf..0da04bebac51386995a44ddda9102a78f0671fb9 100644 (file)
@@ -107,6 +107,7 @@ pub struct Config {
     pub debug_jemalloc: bool,
     pub use_jemalloc: bool,
     pub backtrace: bool, // support for RUST_BACKTRACE
+    pub wasm_syscall: bool,
 
     // misc
     pub low_priority: bool,
@@ -282,6 +283,7 @@ struct Rust {
     test_miri: Option<bool>,
     save_toolstates: Option<String>,
     codegen_backends: Option<Vec<String>>,
+    wasm_syscall: Option<bool>,
 }
 
 /// TOML representation of how each build target is configured.
@@ -463,6 +465,7 @@ pub fn parse(args: &[String]) -> Config {
             set(&mut config.rust_dist_src, rust.dist_src);
             set(&mut config.quiet_tests, rust.quiet_tests);
             set(&mut config.test_miri, rust.test_miri);
+            set(&mut config.wasm_syscall, rust.wasm_syscall);
             config.rustc_parallel_queries = rust.experimental_parallel_queries.unwrap_or(false);
             config.rustc_default_linker = rust.default_linker.clone();
             config.musl_root = rust.musl_root.clone().map(PathBuf::from);
index 4127239dc49b87d27eed38ff93fa3f7302f290dd..dbb7d19e43285089515cb0c0878214ccc7181b13 100644 (file)
@@ -435,11 +435,9 @@ fn prepare_image(builder: &Builder, compiler: Compiler, image: &Path) {
             }
 
             // Copy over the codegen backends
-            let backends_src = builder.sysroot_libdir(compiler, host)
-                .join("codegen-backends");
-            let backends_dst = image.join("lib/rustlib")
-                .join(&*host)
-                .join("lib/codegen-backends");
+            let backends_src = builder.sysroot_codegen_backends(compiler);
+            let backends_rel = backends_src.strip_prefix(&src).unwrap();
+            let backends_dst = image.join(&backends_rel);
             t!(fs::create_dir_all(&backends_dst));
             cp_r(&backends_src, &backends_dst);
 
index aae0a4f056f08b9ef32ce2f3dde7dd740c1f8912..f2a7ce30c8ac77195ef9c0ef23487befd7a7afa1 100644 (file)
@@ -423,6 +423,9 @@ fn std_features(&self) -> String {
         if self.config.profiler {
             features.push_str(" profiler");
         }
+        if self.config.wasm_syscall {
+            features.push_str(" wasm_syscall");
+        }
         features
     }
 
index a316b0f7ef91b7ef1da39d9c64a6bc212b66e141..5fdc6e009206458a42d7939af533c284e12a0bc8 100644 (file)
@@ -1286,6 +1286,14 @@ fn run(self, builder: &Builder) {
             cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target)),
                       build.config.nodejs.as_ref().expect("nodejs not configured"));
         } else if target.starts_with("wasm32") {
+            // Warn about running tests without the `wasm_syscall` feature enabled.
+            // The javascript shim implements the syscall interface so that test
+            // output can be correctly reported.
+            if !build.config.wasm_syscall {
+                println!("Libstd was built without `wasm_syscall` feature enabled: \
+                          test output may not be visible.");
+            }
+
             // On the wasm32-unknown-unknown target we're using LTO which is
             // incompatible with `-C prefer-dynamic`, so disable that here
             cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");
index 0137a052a62d868f02fcfded212f49fc0e634ba9..c51674186146be3bc1f076adf32f8bd4a8f1a717 100644 (file)
@@ -37,28 +37,23 @@ unsafe fn allocate(size: usize, _align: usize) -> *mut u8 {
     p
 }
 
-#[lang = "exchange_free"]
-unsafe fn deallocate(ptr: *mut u8, _size: usize, _align: usize) {
-    libc::free(ptr as *mut libc::c_void)
-}
-
 #[lang = "box_free"]
 unsafe fn box_free<T: ?Sized>(ptr: *mut T) {
-    deallocate(ptr as *mut u8, ::core::mem::size_of_val(&*ptr), ::core::mem::align_of_val(&*ptr));
+    libc::free(ptr as *mut libc::c_void)
 }
 
 #[start]
-fn main(argc: isize, argv: *const *const u8) -> isize {
-    let x = box 1;
+fn main(_argc: isize, _argv: *const *const u8) -> isize {
+    let _x = box 1;
 
     0
 }
 
 #[lang = "eh_personality"] extern fn rust_eh_personality() {}
 #[lang = "panic_fmt"] extern fn rust_begin_panic() -> ! { unsafe { intrinsics::abort() } }
-# #[lang = "eh_unwind_resume"] extern fn rust_eh_unwind_resume() {}
-# #[no_mangle] pub extern fn rust_eh_register_frames () {}
-# #[no_mangle] pub extern fn rust_eh_unregister_frames () {}
+#[lang = "eh_unwind_resume"] extern fn rust_eh_unwind_resume() {}
+#[no_mangle] pub extern fn rust_eh_register_frames () {}
+#[no_mangle] pub extern fn rust_eh_unregister_frames () {}
 ```
 
 Note the use of `abort`: the `exchange_malloc` lang item is assumed to
@@ -80,7 +75,7 @@ Other features provided by lang items include:
 
 Lang items are loaded lazily by the compiler; e.g. if one never uses
 `Box` then there is no need to define functions for `exchange_malloc`
-and `exchange_free`. `rustc` will emit an error when an item is needed
+and `box_free`. `rustc` will emit an error when an item is needed
 but not found in the current crate or any that it depends on.
 
 Most lang items are defined by `libcore`, but if you're trying to build
@@ -318,4 +313,4 @@ the source code.
   - `phantom_data`: `libcore/marker.rs`
   - `freeze`: `libcore/marker.rs`
   - `debug_trait`: `libcore/fmt/mod.rs`
-  - `non_zero`: `libcore/nonzero.rs`
\ No newline at end of file
+  - `non_zero`: `libcore/nonzero.rs`
index d55083e0f8e03490aa23dea88ea1acfc810fe169..69647f37eecc6a8e98334bb13eb78d6fe06234ba 100644 (file)
@@ -28,14 +28,76 @@ let m = new WebAssembly.Module(buffer);
 
 let memory = null;
 
+function viewstruct(data, fields) {
+  return new Uint32Array(memory.buffer).subarray(data/4, data/4 + fields);
+}
+
 function copystr(a, b) {
-  if (memory === null) {
-    return null
-  }
-  let view = new Uint8Array(memory.buffer).slice(a, a + b);
+  let view = new Uint8Array(memory.buffer).subarray(a, a + b);
   return String.fromCharCode.apply(null, view);
 }
 
+function syscall_write([fd, ptr, len]) {
+  let s = copystr(ptr, len);
+  switch (fd) {
+    case 1: process.stdout.write(s); break;
+    case 2: process.stderr.write(s); break;
+  }
+}
+
+function syscall_exit([code]) {
+  process.exit(code);
+}
+
+function syscall_args(params) {
+  let [ptr, len] = params;
+
+  // Calculate total required buffer size
+  let totalLen = -1;
+  for (let i = 2; i < process.argv.length; ++i) {
+    totalLen += Buffer.byteLength(process.argv[i]) + 1;
+  }
+  if (totalLen < 0) { totalLen = 0; }
+  params[2] = totalLen;
+
+  // If buffer is large enough, copy data
+  if (len >= totalLen) {
+    let view = new Uint8Array(memory.buffer);
+    for (let i = 2; i < process.argv.length; ++i) {
+      let value = process.argv[i];
+      Buffer.from(value).copy(view, ptr);
+      ptr += Buffer.byteLength(process.argv[i]) + 1;
+    }
+  }
+}
+
+function syscall_getenv(params) {
+  let [keyPtr, keyLen, valuePtr, valueLen] = params;
+
+  let key = copystr(keyPtr, keyLen);
+  let value = process.env[key];
+
+  if (value == null) {
+    params[4] = 0xFFFFFFFF;
+  } else {
+    let view = new Uint8Array(memory.buffer);
+    let totalLen = Buffer.byteLength(value);
+    params[4] = totalLen;
+    if (valueLen >= totalLen) {
+      Buffer.from(value).copy(view, valuePtr);
+    }
+  }
+}
+
+function syscall_time(params) {
+  let t = Date.now();
+  let secs = Math.floor(t / 1000);
+  let millis = t % 1000;
+  params[1] = Math.floor(secs / 0x100000000);
+  params[2] = secs % 0x100000000;
+  params[3] = Math.floor(millis * 1000000);
+}
+
 let imports = {};
 imports.env = {
   // These are generated by LLVM itself for various intrinsic calls. Hopefully
@@ -48,68 +110,25 @@ imports.env = {
   log10: Math.log10,
   log10f: Math.log10,
 
-  // These are called in src/libstd/sys/wasm/stdio.rs and are used when
-  // debugging is enabled.
-  rust_wasm_write_stdout: function(a, b) {
-    let s = copystr(a, b);
-    if (s !== null) {
-      process.stdout.write(s);
-    }
-  },
-  rust_wasm_write_stderr: function(a, b) {
-    let s = copystr(a, b);
-    if (s !== null) {
-      process.stderr.write(s);
-    }
-  },
-
-  // These are called in src/libstd/sys/wasm/args.rs and are used when
-  // debugging is enabled.
-  rust_wasm_args_count: function() {
-    if (memory === null)
-      return 0;
-    return process.argv.length - 2;
-  },
-  rust_wasm_args_arg_size: function(i) {
-    return Buffer.byteLength(process.argv[i + 2]);
-  },
-  rust_wasm_args_arg_fill: function(idx, ptr) {
-    let arg = process.argv[idx + 2];
-    let view = new Uint8Array(memory.buffer);
-    Buffer.from(arg).copy(view, ptr);
-  },
-
-  // These are called in src/libstd/sys/wasm/os.rs and are used when
-  // debugging is enabled.
-  rust_wasm_getenv_len: function(a, b) {
-    let key = copystr(a, b);
-    if (key === null) {
-      return -1;
+  rust_wasm_syscall: function(index, data) {
+    switch (index) {
+      case 1: syscall_write(viewstruct(data, 3)); return true;
+      case 2: syscall_exit(viewstruct(data, 1)); return true;
+      case 3: syscall_args(viewstruct(data, 3)); return true;
+      case 4: syscall_getenv(viewstruct(data, 5)); return true;
+      case 6: syscall_time(viewstruct(data, 4)); return true;
+      default:
+        console.log("Unsupported syscall: " + index);
+        return false;
     }
-    if (!(key in process.env)) {
-      return -1;
-    }
-    return Buffer.byteLength(process.env[key]);
-  },
-  rust_wasm_getenv_data: function(a, b, ptr) {
-    let key = copystr(a, b);
-    let value = process.env[key];
-    let view = new Uint8Array(memory.buffer);
-    Buffer.from(value).copy(view, ptr);
-  },
-};
-
-let module_imports = WebAssembly.Module.imports(m);
-
-for (var i = 0; i < module_imports.length; i++) {
-  let imp = module_imports[i];
-  if (imp.module != 'env') {
-    continue
   }
-  if (imp.name == 'memory' && imp.kind == 'memory') {
-    memory = new WebAssembly.Memory({initial: 20});
-    imports.env.memory = memory;
-  }
-}
+};
 
 let instance = new WebAssembly.Instance(m, imports);
+memory = instance.exports.memory;
+try {
+  instance.exports.main();
+} catch (e) {
+  console.error(e);
+  process.exit(101);
+}
index 65aacb23bd76813511c1381d85f73b17b1a1a344..6c8a1c3062b00633619ba56a7c7296ce8119d19d 100644 (file)
@@ -1586,6 +1586,7 @@ fn fmt(&self, _: &mut Formatter) -> Result {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Debug for bool {
+    #[inline]
     fn fmt(&self, f: &mut Formatter) -> Result {
         Display::fmt(self, f)
     }
@@ -1748,6 +1749,7 @@ fn fmt(&self, f: &mut Formatter) -> Result {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Debug for () {
+    #[inline]
     fn fmt(&self, f: &mut Formatter) -> Result {
         f.pad("()")
     }
index ee989854a3772e29362d6dc94250bb18b94a7b73..2992e7cf8db341cf0fde7730212752b19ed70096 100644 (file)
@@ -157,6 +157,7 @@ macro_rules! debug {
     ($T:ident) => {
         #[stable(feature = "rust1", since = "1.0.0")]
         impl fmt::Debug for $T {
+            #[inline]
             fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                 fmt::Display::fmt(self, f)
             }
index a611dc02469e8abc68f2ff67c171b4d6f4ea8c59..a05d67a304fa02669a6cbc6cf3c09b291fd53b40 100644 (file)
     ///         ptr::copy_nonoverlapping(y, x, 1);
     ///         ptr::copy_nonoverlapping(&t, y, 1);
     ///
-    ///         // y and t now point to the same thing, but we need to completely forget `tmp`
+    ///         // y and t now point to the same thing, but we need to completely forget `t`
     ///         // because it's no longer relevant.
     ///         mem::forget(t);
     ///     }
index 06c29b47bf9217db2fe131db59099d0f807e6fc8..7314fac282b664fe2e92de6ee8fd7a694e955e18 100644 (file)
 use iter_private::TrustedRandomAccess;
 use ops::Try;
 use usize;
+use intrinsics;
 
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::iterator::Iterator;
@@ -694,6 +695,49 @@ fn size_hint(&self) -> (usize, Option<usize>) {
             (f(inner_hint.0), inner_hint.1.map(f))
         }
     }
+
+    #[inline]
+    fn nth(&mut self, mut n: usize) -> Option<Self::Item> {
+        if self.first_take {
+            self.first_take = false;
+            let first = self.iter.next();
+            if n == 0 {
+                return first;
+            }
+            n -= 1;
+        }
+        // n and self.step are indices, we need to add 1 to get the amount of elements
+        // When calling `.nth`, we need to subtract 1 again to convert back to an index
+        // step + 1 can't overflow because `.step_by` sets `self.step` to `step - 1`
+        let mut step = self.step + 1;
+        // n + 1 could overflow
+        // thus, if n is usize::MAX, instead of adding one, we call .nth(step)
+        if n == usize::MAX {
+            self.iter.nth(step - 1);
+        } else {
+            n += 1;
+        }
+
+        // overflow handling
+        loop {
+            let mul = n.checked_mul(step);
+            if unsafe { intrinsics::likely(mul.is_some()) } {
+                return self.iter.nth(mul.unwrap() - 1);
+            }
+            let div_n = usize::MAX / n;
+            let div_step = usize::MAX / step;
+            let nth_n = div_n * n;
+            let nth_step = div_step * step;
+            let nth = if nth_n > nth_step {
+                step -= div_n;
+                nth_n
+            } else {
+                n -= div_step;
+                nth_step
+            };
+            self.iter.nth(nth - 1);
+        }
+    }
 }
 
 // StepBy can only make the iterator shorter, so the len will still fit.
index d5190b65863cb3f0178a377af311600f423eeb10..2e1f925c49a36ba1fa1ca82f1b2e5be911235cfe 100644 (file)
 pub mod str;
 pub mod hash;
 pub mod fmt;
+pub mod time;
 
 // note: does not need to be public
 mod char_private;
index 93f6a0214d77d487b67edf144bce2d8875dc167a..21a0beccbf64d604e32dcfbfd86daa9da116197c 100644 (file)
@@ -189,6 +189,7 @@ pub fn forget<T>(t: T) {
 /// Type | size_of::\<Type>()
 /// ---- | ---------------
 /// () | 0
+/// bool | 1
 /// u8 | 1
 /// u16 | 2
 /// u32 | 4
index 207df84d080f2856d5407a15181443f288b9a8c6..3586fa5442fb44a1712882cbc8864570fa5ea04a 100644 (file)
@@ -239,7 +239,9 @@ fn powi(self, n: i32) -> f32 {
     /// Converts to degrees, assuming the number is in radians.
     #[inline]
     fn to_degrees(self) -> f32 {
-        self * (180.0f32 / consts::PI)
+        // Use a constant for better precision.
+        const PIS_IN_180: f32 = 57.2957795130823208767981548141051703_f32;
+        self * PIS_IN_180
     }
 
     /// Converts to radians, assuming the number is in degrees.
index 9206132e8b46ff8be695108e516e5986a16cd6a0..64c0d508b388cf6b41b8a3df3e0567af55092822 100644 (file)
@@ -237,6 +237,9 @@ fn powi(self, n: i32) -> f64 {
     /// Converts to degrees, assuming the number is in radians.
     #[inline]
     fn to_degrees(self) -> f64 {
+        // The division here is correctly rounded with respect to the true
+        // value of 180/π. (This differs from f32, where a constant must be
+        // used to ensure a correctly rounded result.)
         self * (180.0f64 / consts::PI)
     }
 
index 8997cf9c6bff9d1e50af8d14e7efeb6582b6012a..e52e119ff59b954389dbd2ec87266f57e22c9b09 100644 (file)
@@ -161,6 +161,68 @@ fn test_iterator_step_by() {
     assert_eq!(it.next(), None);
 }
 
+#[test]
+fn test_iterator_step_by_nth() {
+    let mut it = (0..16).step_by(5);
+    assert_eq!(it.nth(0), Some(0));
+    assert_eq!(it.nth(0), Some(5));
+    assert_eq!(it.nth(0), Some(10));
+    assert_eq!(it.nth(0), Some(15));
+    assert_eq!(it.nth(0), None);
+
+    let it = (0..18).step_by(5);
+    assert_eq!(it.clone().nth(0), Some(0));
+    assert_eq!(it.clone().nth(1), Some(5));
+    assert_eq!(it.clone().nth(2), Some(10));
+    assert_eq!(it.clone().nth(3), Some(15));
+    assert_eq!(it.clone().nth(4), None);
+    assert_eq!(it.clone().nth(42), None);
+}
+
+#[test]
+fn test_iterator_step_by_nth_overflow() {
+    #[cfg(target_pointer_width = "8")]
+    type Bigger = u16;
+    #[cfg(target_pointer_width = "16")]
+    type Bigger = u32;
+    #[cfg(target_pointer_width = "32")]
+    type Bigger = u64;
+    #[cfg(target_pointer_width = "64")]
+    type Bigger = u128;
+
+    #[derive(Clone)]
+    struct Test(Bigger);
+    impl<'a> Iterator for &'a mut Test {
+        type Item = i32;
+        fn next(&mut self) -> Option<Self::Item> { Some(21) }
+        fn nth(&mut self, n: usize) -> Option<Self::Item> {
+            self.0 += n as Bigger + 1;
+            Some(42)
+        }
+    }
+
+    let mut it = Test(0);
+    let root = usize::MAX >> (::std::mem::size_of::<usize>() * 8 / 2);
+    let n = root + 20;
+    (&mut it).step_by(n).nth(n);
+    assert_eq!(it.0, n as Bigger * n as Bigger);
+
+    // large step
+    let mut it = Test(0);
+    (&mut it).step_by(usize::MAX).nth(5);
+    assert_eq!(it.0, (usize::MAX as Bigger) * 5);
+
+    // n + 1 overflows
+    let mut it = Test(0);
+    (&mut it).step_by(2).nth(usize::MAX);
+    assert_eq!(it.0, (usize::MAX as Bigger) * 2);
+
+    // n + 1 overflows
+    let mut it = Test(0);
+    (&mut it).step_by(1).nth(usize::MAX);
+    assert_eq!(it.0, (usize::MAX as Bigger) * 1);
+}
+
 #[test]
 #[should_panic]
 fn test_iterator_step_by_zero() {
diff --git a/src/libcore/time.rs b/src/libcore/time.rs
new file mode 100644 (file)
index 0000000..1a0208d
--- /dev/null
@@ -0,0 +1,603 @@
+// Copyright 2012-2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+#![stable(feature = "duration_core", since = "1.24.0")]
+
+//! Temporal quantification.
+//!
+//! Example:
+//!
+//! ```
+//! use std::time::Duration;
+//!
+//! let five_seconds = Duration::new(5, 0);
+//! // both declarations are equivalent
+//! assert_eq!(Duration::new(5, 0), Duration::from_secs(5));
+//! ```
+
+use iter::Sum;
+use ops::{Add, Sub, Mul, Div, AddAssign, SubAssign, MulAssign, DivAssign};
+
+const NANOS_PER_SEC: u32 = 1_000_000_000;
+const NANOS_PER_MILLI: u32 = 1_000_000;
+const NANOS_PER_MICRO: u32 = 1_000;
+const MILLIS_PER_SEC: u64 = 1_000;
+const MICROS_PER_SEC: u64 = 1_000_000;
+
+/// A `Duration` type to represent a span of time, typically used for system
+/// timeouts.
+///
+/// Each `Duration` is composed of a whole number of seconds and a fractional part
+/// represented in nanoseconds.  If the underlying system does not support
+/// nanosecond-level precision, APIs binding a system timeout will typically round up
+/// the number of nanoseconds.
+///
+/// `Duration`s implement many common traits, including [`Add`], [`Sub`], and other
+/// [`ops`] traits.
+///
+/// [`Add`]: ../../std/ops/trait.Add.html
+/// [`Sub`]: ../../std/ops/trait.Sub.html
+/// [`ops`]: ../../std/ops/index.html
+///
+/// # Examples
+///
+/// ```
+/// use std::time::Duration;
+///
+/// let five_seconds = Duration::new(5, 0);
+/// let five_seconds_and_five_nanos = five_seconds + Duration::new(0, 5);
+///
+/// assert_eq!(five_seconds_and_five_nanos.as_secs(), 5);
+/// assert_eq!(five_seconds_and_five_nanos.subsec_nanos(), 5);
+///
+/// let ten_millis = Duration::from_millis(10);
+/// ```
+#[stable(feature = "duration_core", since = "1.24.0")]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash, Default)]
+pub struct Duration {
+    secs: u64,
+    nanos: u32, // Always 0 <= nanos < NANOS_PER_SEC
+}
+
+impl Duration {
+    /// Creates a new `Duration` from the specified number of whole seconds and
+    /// additional nanoseconds.
+    ///
+    /// If the number of nanoseconds is greater than 1 billion (the number of
+    /// nanoseconds in a second), then it will carry over into the seconds provided.
+    ///
+    /// # Panics
+    ///
+    /// This constructor will panic if the carry from the nanoseconds overflows
+    /// the seconds counter.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::time::Duration;
+    ///
+    /// let five_seconds = Duration::new(5, 0);
+    /// ```
+    #[stable(feature = "duration", since = "1.3.0")]
+    #[inline]
+    pub fn new(secs: u64, nanos: u32) -> Duration {
+        let secs = secs.checked_add((nanos / NANOS_PER_SEC) as u64)
+            .expect("overflow in Duration::new");
+        let nanos = nanos % NANOS_PER_SEC;
+        Duration { secs: secs, nanos: nanos }
+    }
+
+    /// Creates a new `Duration` from the specified number of whole seconds.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::time::Duration;
+    ///
+    /// let duration = Duration::from_secs(5);
+    ///
+    /// assert_eq!(5, duration.as_secs());
+    /// assert_eq!(0, duration.subsec_nanos());
+    /// ```
+    #[stable(feature = "duration", since = "1.3.0")]
+    #[inline]
+    pub const fn from_secs(secs: u64) -> Duration {
+        Duration { secs: secs, nanos: 0 }
+    }
+
+    /// Creates a new `Duration` from the specified number of milliseconds.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::time::Duration;
+    ///
+    /// let duration = Duration::from_millis(2569);
+    ///
+    /// assert_eq!(2, duration.as_secs());
+    /// assert_eq!(569_000_000, duration.subsec_nanos());
+    /// ```
+    #[stable(feature = "duration", since = "1.3.0")]
+    #[inline]
+    pub const fn from_millis(millis: u64) -> Duration {
+        Duration {
+            secs: millis / MILLIS_PER_SEC,
+            nanos: ((millis % MILLIS_PER_SEC) as u32) * NANOS_PER_MILLI,
+        }
+    }
+
+    /// Creates a new `Duration` from the specified number of microseconds.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(duration_from_micros)]
+    /// use std::time::Duration;
+    ///
+    /// let duration = Duration::from_micros(1_000_002);
+    ///
+    /// assert_eq!(1, duration.as_secs());
+    /// assert_eq!(2000, duration.subsec_nanos());
+    /// ```
+    #[unstable(feature = "duration_from_micros", issue = "44400")]
+    #[inline]
+    pub const fn from_micros(micros: u64) -> Duration {
+        Duration {
+            secs: micros / MICROS_PER_SEC,
+            nanos: ((micros % MICROS_PER_SEC) as u32) * NANOS_PER_MICRO,
+        }
+    }
+
+    /// Creates a new `Duration` from the specified number of nanoseconds.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(duration_extras)]
+    /// use std::time::Duration;
+    ///
+    /// let duration = Duration::from_nanos(1_000_000_123);
+    ///
+    /// assert_eq!(1, duration.as_secs());
+    /// assert_eq!(123, duration.subsec_nanos());
+    /// ```
+    #[unstable(feature = "duration_extras", issue = "46507")]
+    #[inline]
+    pub const fn from_nanos(nanos: u64) -> Duration {
+        Duration {
+            secs: nanos / (NANOS_PER_SEC as u64),
+            nanos: (nanos % (NANOS_PER_SEC as u64)) as u32,
+        }
+    }
+
+    /// Returns the number of _whole_ seconds contained by this `Duration`.
+    ///
+    /// The returned value does not include the fractional (nanosecond) part of the
+    /// duration, which can be obtained using [`subsec_nanos`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::time::Duration;
+    ///
+    /// let duration = Duration::new(5, 730023852);
+    /// assert_eq!(duration.as_secs(), 5);
+    /// ```
+    ///
+    /// To determine the total number of seconds represented by the `Duration`,
+    /// use `as_secs` in combination with [`subsec_nanos`]:
+    ///
+    /// ```
+    /// use std::time::Duration;
+    ///
+    /// let duration = Duration::new(5, 730023852);
+    ///
+    /// assert_eq!(5.730023852,
+    ///            duration.as_secs() as f64
+    ///            + duration.subsec_nanos() as f64 * 1e-9);
+    /// ```
+    ///
+    /// [`subsec_nanos`]: #method.subsec_nanos
+    #[stable(feature = "duration", since = "1.3.0")]
+    #[inline]
+    pub fn as_secs(&self) -> u64 { self.secs }
+
+    /// Returns the fractional part of this `Duration`, in milliseconds.
+    ///
+    /// This method does **not** return the length of the duration when
+    /// represented by milliseconds. The returned number always represents a
+    /// fractional portion of a second (i.e. it is less than one thousand).
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(duration_extras)]
+    /// use std::time::Duration;
+    ///
+    /// let duration = Duration::from_millis(5432);
+    /// assert_eq!(duration.as_secs(), 5);
+    /// assert_eq!(duration.subsec_millis(), 432);
+    /// ```
+    #[unstable(feature = "duration_extras", issue = "46507")]
+    #[inline]
+    pub fn subsec_millis(&self) -> u32 { self.nanos / NANOS_PER_MILLI }
+
+    /// Returns the fractional part of this `Duration`, in microseconds.
+    ///
+    /// This method does **not** return the length of the duration when
+    /// represented by microseconds. The returned number always represents a
+    /// fractional portion of a second (i.e. it is less than one million).
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(duration_extras, duration_from_micros)]
+    /// use std::time::Duration;
+    ///
+    /// let duration = Duration::from_micros(1_234_567);
+    /// assert_eq!(duration.as_secs(), 1);
+    /// assert_eq!(duration.subsec_micros(), 234_567);
+    /// ```
+    #[unstable(feature = "duration_extras", issue = "46507")]
+    #[inline]
+    pub fn subsec_micros(&self) -> u32 { self.nanos / NANOS_PER_MICRO }
+
+    /// Returns the fractional part of this `Duration`, in nanoseconds.
+    ///
+    /// This method does **not** return the length of the duration when
+    /// represented by nanoseconds. The returned number always represents a
+    /// fractional portion of a second (i.e. it is less than one billion).
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::time::Duration;
+    ///
+    /// let duration = Duration::from_millis(5010);
+    /// assert_eq!(duration.as_secs(), 5);
+    /// assert_eq!(duration.subsec_nanos(), 10_000_000);
+    /// ```
+    #[stable(feature = "duration", since = "1.3.0")]
+    #[inline]
+    pub fn subsec_nanos(&self) -> u32 { self.nanos }
+
+    /// Checked `Duration` addition. Computes `self + other`, returning [`None`]
+    /// if overflow occurred.
+    ///
+    /// [`None`]: ../../std/option/enum.Option.html#variant.None
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// use std::time::Duration;
+    ///
+    /// assert_eq!(Duration::new(0, 0).checked_add(Duration::new(0, 1)), Some(Duration::new(0, 1)));
+    /// assert_eq!(Duration::new(1, 0).checked_add(Duration::new(std::u64::MAX, 0)), None);
+    /// ```
+    #[stable(feature = "duration_checked_ops", since = "1.16.0")]
+    #[inline]
+    pub fn checked_add(self, rhs: Duration) -> Option<Duration> {
+        if let Some(mut secs) = self.secs.checked_add(rhs.secs) {
+            let mut nanos = self.nanos + rhs.nanos;
+            if nanos >= NANOS_PER_SEC {
+                nanos -= NANOS_PER_SEC;
+                if let Some(new_secs) = secs.checked_add(1) {
+                    secs = new_secs;
+                } else {
+                    return None;
+                }
+            }
+            debug_assert!(nanos < NANOS_PER_SEC);
+            Some(Duration {
+                secs,
+                nanos,
+            })
+        } else {
+            None
+        }
+    }
+
+    /// Checked `Duration` subtraction. Computes `self - other`, returning [`None`]
+    /// if the result would be negative or if overflow occurred.
+    ///
+    /// [`None`]: ../../std/option/enum.Option.html#variant.None
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// use std::time::Duration;
+    ///
+    /// assert_eq!(Duration::new(0, 1).checked_sub(Duration::new(0, 0)), Some(Duration::new(0, 1)));
+    /// assert_eq!(Duration::new(0, 0).checked_sub(Duration::new(0, 1)), None);
+    /// ```
+    #[stable(feature = "duration_checked_ops", since = "1.16.0")]
+    #[inline]
+    pub fn checked_sub(self, rhs: Duration) -> Option<Duration> {
+        if let Some(mut secs) = self.secs.checked_sub(rhs.secs) {
+            let nanos = if self.nanos >= rhs.nanos {
+                self.nanos - rhs.nanos
+            } else {
+                if let Some(sub_secs) = secs.checked_sub(1) {
+                    secs = sub_secs;
+                    self.nanos + NANOS_PER_SEC - rhs.nanos
+                } else {
+                    return None;
+                }
+            };
+            debug_assert!(nanos < NANOS_PER_SEC);
+            Some(Duration { secs: secs, nanos: nanos })
+        } else {
+            None
+        }
+    }
+
+    /// Checked `Duration` multiplication. Computes `self * other`, returning
+    /// [`None`] if overflow occurred.
+    ///
+    /// [`None`]: ../../std/option/enum.Option.html#variant.None
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// use std::time::Duration;
+    ///
+    /// assert_eq!(Duration::new(0, 500_000_001).checked_mul(2), Some(Duration::new(1, 2)));
+    /// assert_eq!(Duration::new(std::u64::MAX - 1, 0).checked_mul(2), None);
+    /// ```
+    #[stable(feature = "duration_checked_ops", since = "1.16.0")]
+    #[inline]
+    pub fn checked_mul(self, rhs: u32) -> Option<Duration> {
+        // Multiply nanoseconds as u64, because it cannot overflow that way.
+        let total_nanos = self.nanos as u64 * rhs as u64;
+        let extra_secs = total_nanos / (NANOS_PER_SEC as u64);
+        let nanos = (total_nanos % (NANOS_PER_SEC as u64)) as u32;
+        if let Some(secs) = self.secs
+            .checked_mul(rhs as u64)
+            .and_then(|s| s.checked_add(extra_secs)) {
+            debug_assert!(nanos < NANOS_PER_SEC);
+            Some(Duration {
+                secs,
+                nanos,
+            })
+        } else {
+            None
+        }
+    }
+
+    /// Checked `Duration` division. Computes `self / other`, returning [`None`]
+    /// if `other == 0`.
+    ///
+    /// [`None`]: ../../std/option/enum.Option.html#variant.None
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// use std::time::Duration;
+    ///
+    /// 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);
+    /// ```
+    #[stable(feature = "duration_checked_ops", since = "1.16.0")]
+    #[inline]
+    pub fn checked_div(self, rhs: u32) -> Option<Duration> {
+        if rhs != 0 {
+            let secs = self.secs / (rhs as u64);
+            let carry = self.secs - secs * (rhs as u64);
+            let extra_nanos = carry * (NANOS_PER_SEC as u64) / (rhs as u64);
+            let nanos = self.nanos / rhs + (extra_nanos as u32);
+            debug_assert!(nanos < NANOS_PER_SEC);
+            Some(Duration { secs: secs, nanos: nanos })
+        } else {
+            None
+        }
+    }
+}
+
+#[stable(feature = "duration", since = "1.3.0")]
+impl Add for Duration {
+    type Output = Duration;
+
+    fn add(self, rhs: Duration) -> Duration {
+        self.checked_add(rhs).expect("overflow when adding durations")
+    }
+}
+
+#[stable(feature = "time_augmented_assignment", since = "1.9.0")]
+impl AddAssign for Duration {
+    fn add_assign(&mut self, rhs: Duration) {
+        *self = *self + rhs;
+    }
+}
+
+#[stable(feature = "duration", since = "1.3.0")]
+impl Sub for Duration {
+    type Output = Duration;
+
+    fn sub(self, rhs: Duration) -> Duration {
+        self.checked_sub(rhs).expect("overflow when subtracting durations")
+    }
+}
+
+#[stable(feature = "time_augmented_assignment", since = "1.9.0")]
+impl SubAssign for Duration {
+    fn sub_assign(&mut self, rhs: Duration) {
+        *self = *self - rhs;
+    }
+}
+
+#[stable(feature = "duration", since = "1.3.0")]
+impl Mul<u32> for Duration {
+    type Output = Duration;
+
+    fn mul(self, rhs: u32) -> Duration {
+        self.checked_mul(rhs).expect("overflow when multiplying duration by scalar")
+    }
+}
+
+#[stable(feature = "time_augmented_assignment", since = "1.9.0")]
+impl MulAssign<u32> for Duration {
+    fn mul_assign(&mut self, rhs: u32) {
+        *self = *self * rhs;
+    }
+}
+
+#[stable(feature = "duration", since = "1.3.0")]
+impl Div<u32> for Duration {
+    type Output = Duration;
+
+    fn div(self, rhs: u32) -> Duration {
+        self.checked_div(rhs).expect("divide by zero error when dividing duration by scalar")
+    }
+}
+
+#[stable(feature = "time_augmented_assignment", since = "1.9.0")]
+impl DivAssign<u32> for Duration {
+    fn div_assign(&mut self, rhs: u32) {
+        *self = *self / rhs;
+    }
+}
+
+#[stable(feature = "duration_sum", since = "1.16.0")]
+impl Sum for Duration {
+    fn sum<I: Iterator<Item=Duration>>(iter: I) -> Duration {
+        iter.fold(Duration::new(0, 0), |a, b| a + b)
+    }
+}
+
+#[stable(feature = "duration_sum", since = "1.16.0")]
+impl<'a> Sum<&'a Duration> for Duration {
+    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 c3bd6a2bc187d38cdd176fa19c4df2f369f9c2be..5f768ef4399e88fc12771aab5a6f892c263a66be 100644 (file)
 #![feature(libc)]
 #![feature(panic_runtime)]
 #![feature(staged_api)]
+#![feature(rustc_attrs)]
 
 // Rust's "try" function, but if we're aborting on panics we just call the
 // function as there's nothing else we need to do here.
 #[no_mangle]
+#[rustc_std_internal_symbol]
 pub unsafe extern fn __rust_maybe_catch_panic(f: fn(*mut u8),
                                               data: *mut u8,
                                               _data_ptr: *mut usize,
@@ -50,6 +52,7 @@
 // will kill us with an illegal instruction, which will do a good enough job for
 // now hopefully.
 #[no_mangle]
+#[rustc_std_internal_symbol]
 pub unsafe extern fn __rust_start_panic(_data: usize, _vtable: usize) -> u32 {
     abort();
 
index ddf71a06d607c7f7016546b0cc6fdb7da8ee3bef..722456a76ce591a6377853ad958b04e353ee0586 100644 (file)
@@ -176,6 +176,7 @@ pointers for understanding them better.
 - `'gcx` -- the lifetime of the global arena (see `librustc/ty`).
 - generics -- the set of generic type parameters defined on a type or item
 - ICE -- internal compiler error. When the compiler crashes.
+- ICH -- incremental compilation hash.
 - infcx -- the inference context (see `librustc/infer`)
 - MIR -- the **Mid-level IR** that is created after type-checking for use by borrowck and trans.
   Defined in the `src/librustc/mir/` module, but much of the code that manipulates it is
index 1de9091b5df7d34f059aa9418186f7bf1d4ea24f..4034055d041558f2360e5227c9fdbe3a32451aa1 100644 (file)
@@ -639,6 +639,9 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool {
     [] TargetFeaturesEnabled(DefId),
 
     [] InstanceDefSizeEstimate { instance_def: InstanceDef<'tcx> },
+
+    [] GetSymbolExportLevel(DefId),
+
 );
 
 trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug {
index b10e742595720dc595863c124d1404ce9d74f8b8..03fc40b2e39fcb79fe374ecd17bfcaa42861f07a 100644 (file)
@@ -175,25 +175,6 @@ fn explain_span<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
             ty::ReEarlyBound(_) |
             ty::ReFree(_) => {
                 let scope = region.free_region_binding_scope(self);
-                let prefix = match *region {
-                    ty::ReEarlyBound(ref br) => {
-                        format!("the lifetime {} as defined on", br.name)
-                    }
-                    ty::ReFree(ref fr) => {
-                        match fr.bound_region {
-                            ty::BrAnon(idx) => {
-                                format!("the anonymous lifetime #{} defined on", idx + 1)
-                            }
-                            ty::BrFresh(_) => "an anonymous lifetime defined on".to_owned(),
-                            _ => {
-                                format!("the lifetime {} as defined on",
-                                        fr.bound_region)
-                            }
-                        }
-                    }
-                    _ => bug!()
-                };
-
                 let node = self.hir.as_local_node_id(scope)
                                    .unwrap_or(DUMMY_NODE_ID);
                 let unknown;
@@ -218,7 +199,26 @@ fn explain_span<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                         &unknown
                     }
                 };
-                let (msg, opt_span) = explain_span(self, tag, self.hir.span(node));
+                let (prefix, span) = match *region {
+                    ty::ReEarlyBound(ref br) => {
+                        (format!("the lifetime {} as defined on", br.name),
+                         self.sess.codemap().def_span(self.hir.span(node)))
+                    }
+                    ty::ReFree(ref fr) => {
+                        match fr.bound_region {
+                            ty::BrAnon(idx) => {
+                                (format!("the anonymous lifetime #{} defined on", idx + 1),
+                                 self.hir.span(node))
+                            }
+                            ty::BrFresh(_) => ("an anonymous lifetime defined on".to_owned(),
+                                               self.hir.span(node)),
+                            _ => (format!("the lifetime {} as defined on", fr.bound_region),
+                                  self.sess.codemap().def_span(self.hir.span(node))),
+                        }
+                    }
+                    _ => bug!()
+                };
+                let (msg, opt_span) = explain_span(self, tag, span);
                 (format!("{} {}", prefix, msg), opt_span)
             }
 
@@ -807,7 +807,7 @@ pub fn note_type_err(&self,
             }
         };
 
-        let span = cause.span;
+        let span = cause.span(&self.tcx);
 
         diag.span_label(span, terr.to_string());
         if let Some((sp, msg)) = secondary_span {
@@ -842,7 +842,7 @@ pub fn note_type_err(&self,
                                     "did you mean `{}(/* fields */)`?",
                                     self.tcx.item_path_str(def_id)
                                 );
-                                diag.span_label(cause.span, message);
+                                diag.span_label(span, message);
                             }
                         }
                     }
@@ -870,7 +870,7 @@ pub fn report_and_explain_type_error(&self,
                trace,
                terr);
 
-        let span = trace.cause.span;
+        let span = trace.cause.span(&self.tcx);
         let failure_code = trace.cause.as_failure_code(terr);
         let mut diag = match failure_code {
             FailureCode::Error0317(failure_str) => {
@@ -1076,6 +1076,31 @@ fn report_sub_sup_conflict(&self,
             sup_region,
             "...");
 
+        match (&sup_origin, &sub_origin) {
+            (&infer::Subtype(ref sup_trace), &infer::Subtype(ref sub_trace)) => {
+                if let (Some((sup_expected, sup_found)),
+                        Some((sub_expected, sub_found))) = (self.values_str(&sup_trace.values),
+                                                            self.values_str(&sub_trace.values)) {
+                    if sub_expected == sup_expected && sub_found == sup_found {
+                        self.tcx.note_and_explain_region(
+                            region_scope_tree,
+                            &mut err,
+                            "...but the lifetime must also be valid for ",
+                            sub_region,
+                            "...",
+                        );
+                        err.note(&format!("...so that the {}:\nexpected {}\n   found {}",
+                                          sup_trace.cause.as_requirement_str(),
+                                          sup_expected.content(),
+                                          sup_found.content()));
+                        err.emit();
+                        return;
+                    }
+                }
+            }
+            _ => {}
+        }
+
         self.note_region_origin(&mut err, &sup_origin);
 
         self.tcx.note_and_explain_region(region_scope_tree, &mut err,
index e46613b3e4da0cd0fa804878c50ae8d1c12193fc..02ec9fe74c1fe693bf5c24e60da393c93c170266 100644 (file)
@@ -23,12 +23,10 @@ pub(super) fn note_region_origin(&self,
                 if let Some((expected, found)) = self.values_str(&trace.values) {
                     let expected = expected.content();
                     let found = found.content();
-                    // FIXME: do we want a "the" here?
-                    err.span_note(trace.cause.span,
-                                  &format!("...so that {} (expected {}, found {})",
-                                           trace.cause.as_requirement_str(),
-                                           expected,
-                                           found));
+                    err.note(&format!("...so that the {}:\nexpected {}\n   found {}",
+                                      trace.cause.as_requirement_str(),
+                                      expected,
+                                      found));
                 } else {
                     // FIXME: this really should be handled at some earlier stage. Our
                     // handling of region checking when type errors are present is
index d727dfb0c4b2deef220d33c0f16cefa057ad8e37..db6863d6dadc272a0d01fc86296d6c92d4ec38ea 100644 (file)
@@ -66,6 +66,7 @@
 #![feature(specialization)]
 #![feature(unboxed_closures)]
 #![feature(underscore_lifetimes)]
+#![feature(universal_impl_trait)]
 #![feature(trace_macros)]
 #![feature(catch_expr)]
 #![feature(test)]
index 143d2c2ea28bba8361cdf48539715bb418d45d39..0577800f3f4113f92e9534a3a4b5d991126af718 100644 (file)
     "raw pointer to an inference variable"
 }
 
+declare_lint! {
+    pub ELIDED_LIFETIME_IN_PATH,
+    Allow,
+    "hidden lifetime parameters are deprecated, try `Foo<'_>`"
+}
+
 /// Does nothing as a lint pass, but registers some `Lint`s
 /// which are used by other parts of the compiler.
 #[derive(Copy, Clone)]
@@ -291,7 +297,9 @@ fn get_lints(&self) -> LintArray {
             UNUSED_MUT,
             COERCE_NEVER,
             SINGLE_USE_LIFETIME,
-            TYVAR_BEHIND_RAW_POINTER
+            TYVAR_BEHIND_RAW_POINTER,
+            ELIDED_LIFETIME_IN_PATH
+
         )
     }
 }
index 5336c1944e8c4d905f66c5928574b5c832cbeafd..929d5e7ec62bb055274509b9618daf70727fec9d 100644 (file)
@@ -631,7 +631,7 @@ impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for &'a LateContext<'a, 'tcx> {
     type TyLayout = Result<TyLayout<'tcx>, LayoutError<'tcx>>;
 
     fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
-        (self.tcx, self.param_env.reveal_all()).layout_of(ty)
+        self.tcx.layout_of(self.param_env.and(ty))
     }
 }
 
index dad2d7a7c90fb4ffd33668b8b9844de3cd9cefa9..e5619f469e774bd22b8c6af6cf981bc4eec9d863 100644 (file)
@@ -467,9 +467,13 @@ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
     }
 
     fn visit_pat(&mut self, pat: &'tcx Pat) {
+        intravisit::walk_pat(self, pat);
+
         self.expr_and_pat_count += 1;
 
-        intravisit::walk_pat(self, pat);
+        if pat.id == self.id {
+            self.result = Some(self.expr_and_pat_count);
+        }
     }
 
     fn visit_expr(&mut self, expr: &'tcx Expr) {
@@ -814,7 +818,8 @@ pub fn free_scope<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, fr: &ty::FreeReg
 
     /// Checks whether the given scope contains a `yield`. If so,
     /// returns `Some((span, expr_count))` with the span of a yield we found and
-    /// the number of expressions appearing before the `yield` in the body.
+    /// the number of expressions and patterns appearing before the `yield` in the body + 1.
+    /// If there a are multiple yields in a scope, the one with the highest number is returned.
     pub fn yield_in_scope(&self, scope: Scope) -> Option<(Span, usize)> {
         self.yield_in_scope.get(&scope).cloned()
     }
index 944d770516375ea20dd03aad6cd987722f7f3c8f..59460141166b113585fd203453f2269035fd6df0 100644 (file)
@@ -737,7 +737,7 @@ fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem) {
 
     fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
         if lifetime_ref.is_elided() {
-            self.resolve_elided_lifetimes(slice::from_ref(lifetime_ref));
+            self.resolve_elided_lifetimes(slice::from_ref(lifetime_ref), false);
             return;
         }
         if lifetime_ref.is_static() {
@@ -1444,7 +1444,7 @@ fn visit_segment_parameters(
         }
 
         if params.lifetimes.iter().all(|l| l.is_elided()) {
-            self.resolve_elided_lifetimes(&params.lifetimes);
+            self.resolve_elided_lifetimes(&params.lifetimes, true);
         } else {
             for l in &params.lifetimes {
                 self.visit_lifetime(l);
@@ -1803,14 +1803,24 @@ fn visit_lifetime(&mut self, lifetime_ref: &hir::Lifetime) {
         }
     }
 
-    fn resolve_elided_lifetimes(&mut self, lifetime_refs: &'tcx [hir::Lifetime]) {
+    fn resolve_elided_lifetimes(&mut self, lifetime_refs: &'tcx [hir::Lifetime], deprecated: bool) {
         if lifetime_refs.is_empty() {
             return;
         }
 
         let span = lifetime_refs[0].span;
+        let id = lifetime_refs[0].id;
         let mut late_depth = 0;
         let mut scope = self.scope;
+        if deprecated {
+            self.tcx
+                .struct_span_lint_node(
+                    lint::builtin::ELIDED_LIFETIME_IN_PATH,
+                    id,
+                    span,
+                    &format!("hidden lifetime parameters are deprecated, try `Foo<'_>`"))
+                .emit();
+        }
         let error = loop {
             match *scope {
                 // Do not assign any resolution, it will be inferred.
index b9546143a054b32af67f2b88bf2ddd72cf5edfe5..9543d01597d04b0d6a8769c8de54f9a339711fd8 100644 (file)
@@ -1288,6 +1288,8 @@ fn parse_lto(slot: &mut Lto, v: Option<&str>) -> bool {
     dep_info_omit_d_target: bool = (false, parse_bool, [TRACKED],
         "in dep-info output, omit targets for tracking dependencies of the dep-info files \
          themselves"),
+    approximate_suggestions: bool = (false, parse_bool, [UNTRACKED],
+        "include machine-applicability of suggestions in JSON output"),
     unpretty: Option<String> = (None, parse_unpretty, [UNTRACKED],
         "Present the input source, unstable (and less-pretty) variants;
         valid types are any of the types for `--pretty`, as well as:
index 2765239d5e6494cc0c1d84dae5307164ba3b2025..f4a00a43d8d92b5dcb471e5bb1c3e973906bab0b 100644 (file)
@@ -904,22 +904,27 @@ pub fn build_session_with_codemap(sopts: config::Options,
 
     let emitter: Box<Emitter> = match (sopts.error_format, emitter_dest) {
         (config::ErrorOutputType::HumanReadable(color_config), None) => {
-            Box::new(EmitterWriter::stderr(color_config, Some(codemap.clone()), false))
+            Box::new(EmitterWriter::stderr(color_config,
+                                           Some(codemap.clone()),
+                                           false,
+                                           sopts.debugging_opts.teach))
         }
         (config::ErrorOutputType::HumanReadable(_), Some(dst)) => {
-            Box::new(EmitterWriter::new(dst, Some(codemap.clone()), false))
+            Box::new(EmitterWriter::new(dst, Some(codemap.clone()), false, false))
         }
         (config::ErrorOutputType::Json(pretty), None) => {
-            Box::new(JsonEmitter::stderr(Some(registry), codemap.clone(), pretty))
+            Box::new(JsonEmitter::stderr(Some(registry), codemap.clone(),
+                     pretty, sopts.debugging_opts.approximate_suggestions))
         }
         (config::ErrorOutputType::Json(pretty), Some(dst)) => {
-            Box::new(JsonEmitter::new(dst, Some(registry), codemap.clone(), pretty))
+            Box::new(JsonEmitter::new(dst, Some(registry), codemap.clone(),
+                     pretty, sopts.debugging_opts.approximate_suggestions))
         }
         (config::ErrorOutputType::Short(color_config), None) => {
-            Box::new(EmitterWriter::stderr(color_config, Some(codemap.clone()), true))
+            Box::new(EmitterWriter::stderr(color_config, Some(codemap.clone()), true, false))
         }
         (config::ErrorOutputType::Short(_), Some(dst)) => {
-            Box::new(EmitterWriter::new(dst, Some(codemap.clone()), true))
+            Box::new(EmitterWriter::new(dst, Some(codemap.clone()), true, false))
         }
     };
 
@@ -1095,11 +1100,11 @@ pub enum IncrCompSession {
 pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
     let emitter: Box<Emitter> = match output {
         config::ErrorOutputType::HumanReadable(color_config) => {
-            Box::new(EmitterWriter::stderr(color_config, None, false))
+            Box::new(EmitterWriter::stderr(color_config, None, false, false))
         }
         config::ErrorOutputType::Json(pretty) => Box::new(JsonEmitter::basic(pretty)),
         config::ErrorOutputType::Short(color_config) => {
-            Box::new(EmitterWriter::stderr(color_config, None, true))
+            Box::new(EmitterWriter::stderr(color_config, None, true, false))
         }
     };
     let handler = errors::Handler::with_emitter(true, false, emitter);
@@ -1110,11 +1115,11 @@ pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
 pub fn early_warn(output: config::ErrorOutputType, msg: &str) {
     let emitter: Box<Emitter> = match output {
         config::ErrorOutputType::HumanReadable(color_config) => {
-            Box::new(EmitterWriter::stderr(color_config, None, false))
+            Box::new(EmitterWriter::stderr(color_config, None, false, false))
         }
         config::ErrorOutputType::Json(pretty) => Box::new(JsonEmitter::basic(pretty)),
         config::ErrorOutputType::Short(color_config) => {
-            Box::new(EmitterWriter::stderr(color_config, None, true))
+            Box::new(EmitterWriter::stderr(color_config, None, true, false))
         }
     };
     let handler = errors::Handler::with_emitter(true, false, emitter);
index ae68e3fe8d01f065c2954ff6465fcccceecca21b..9de18612d816c468db047ff0bab636e344c9f690 100644 (file)
@@ -19,7 +19,7 @@
 use ty::fold::TypeFoldable;
 use ty::subst::Subst;
 
-use infer::{InferCtxt, InferOk};
+use infer::{InferOk};
 
 /// Whether we do the orphan check relative to this crate or
 /// to some remote crate.
@@ -40,13 +40,20 @@ pub struct OverlapResult<'tcx> {
     pub intercrate_ambiguity_causes: Vec<IntercrateAmbiguityCause>,
 }
 
-/// If there are types that satisfy both impls, returns a suitably-freshened
-/// `ImplHeader` with those types substituted
-pub fn overlapping_impls<'cx, 'gcx, 'tcx>(infcx: &InferCtxt<'cx, 'gcx, 'tcx>,
-                                          impl1_def_id: DefId,
-                                          impl2_def_id: DefId,
-                                          intercrate_mode: IntercrateMode)
-                                          -> Option<OverlapResult<'tcx>>
+/// If there are types that satisfy both impls, invokes `on_overlap`
+/// with a suitably-freshened `ImplHeader` with those types
+/// substituted. Otherwise, invokes `no_overlap`.
+pub fn overlapping_impls<'gcx, F1, F2, R>(
+    tcx: TyCtxt<'_, 'gcx, 'gcx>,
+    impl1_def_id: DefId,
+    impl2_def_id: DefId,
+    intercrate_mode: IntercrateMode,
+    on_overlap: F1,
+    no_overlap: F2,
+) -> R
+where
+    F1: FnOnce(OverlapResult<'_>) -> R,
+    F2: FnOnce() -> R,
 {
     debug!("impl_can_satisfy(\
            impl1_def_id={:?}, \
@@ -56,8 +63,23 @@ pub fn overlapping_impls<'cx, 'gcx, 'tcx>(infcx: &InferCtxt<'cx, 'gcx, 'tcx>,
            impl2_def_id,
            intercrate_mode);
 
-    let selcx = &mut SelectionContext::intercrate(infcx, intercrate_mode);
-    overlap(selcx, impl1_def_id, impl2_def_id)
+    let overlaps = tcx.infer_ctxt().enter(|infcx| {
+        let selcx = &mut SelectionContext::intercrate(&infcx, intercrate_mode);
+        overlap(selcx, impl1_def_id, impl2_def_id).is_some()
+    });
+
+    if !overlaps {
+        return no_overlap();
+    }
+
+    // In the case where we detect an error, run the check again, but
+    // this time tracking intercrate ambuiguity causes for better
+    // diagnostics. (These take time and can lead to false errors.)
+    tcx.infer_ctxt().enter(|infcx| {
+        let selcx = &mut SelectionContext::intercrate(&infcx, intercrate_mode);
+        selcx.enable_tracking_intercrate_ambiguity_causes();
+        on_overlap(overlap(selcx, impl1_def_id, impl2_def_id).unwrap())
+    })
 }
 
 fn with_fresh_ty_vars<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>,
@@ -135,10 +157,10 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>,
         return None
     }
 
-    Some(OverlapResult {
-        impl_header: selcx.infcx().resolve_type_vars_if_possible(&a_impl_header),
-        intercrate_ambiguity_causes: selcx.intercrate_ambiguity_causes().to_vec(),
-    })
+    let impl_header =  selcx.infcx().resolve_type_vars_if_possible(&a_impl_header);
+    let intercrate_ambiguity_causes = selcx.take_intercrate_ambiguity_causes();
+    debug!("overlap: intercrate_ambiguity_causes={:#?}", intercrate_ambiguity_causes);
+    Some(OverlapResult { impl_header, intercrate_ambiguity_causes })
 }
 
 pub fn trait_ref_is_knowable<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
index 42200a3a44728335967a229640ddbb4501e33953..7b86791026b415e30d32a131c9051962d7bdfd42 100644 (file)
@@ -831,6 +831,11 @@ fn get_fn_like_arguments(&self, node: hir::map::Node) -> (Span, Vec<ArgKind>) {
                 span,
                 node: hir::ImplItemKind::Method(hir::MethodSig { ref decl, .. }, _),
                 ..
+            }) |
+            hir::map::NodeTraitItem(&hir::TraitItem {
+                span,
+                node: hir::TraitItemKind::Method(hir::MethodSig { ref decl, .. }, _),
+                ..
             }) => {
                 (self.tcx.sess.codemap().def_span(span), decl.inputs.iter()
                         .map(|arg| match arg.clone().into_inner().node {
@@ -1261,6 +1266,10 @@ fn note_obligation_cause_code<T>(&self,
                 err.note("the return type of a function must have a \
                           statically known size");
             }
+            ObligationCauseCode::SizedYieldType => {
+                err.note("the yield type of a generator must have a \
+                          statically known size");
+            }
             ObligationCauseCode::AssignmentLhsSized => {
                 err.note("the left-hand-side of an assignment must have a statically known size");
             }
index fd47e09aad7f9119270981d8af3d3eb6f2d97b1d..80819a86b7c4655f8a3a41b0baacb29f4a37d1de 100644 (file)
@@ -100,6 +100,19 @@ pub struct ObligationCause<'tcx> {
     pub code: ObligationCauseCode<'tcx>
 }
 
+impl<'tcx> ObligationCause<'tcx> {
+    pub fn span<'a, 'gcx>(&self, tcx: &TyCtxt<'a, 'gcx, 'tcx>) -> Span {
+        match self.code {
+            ObligationCauseCode::CompareImplMethodObligation { .. } |
+            ObligationCauseCode::MainFunctionType |
+            ObligationCauseCode::StartFunctionType => {
+                tcx.sess.codemap().def_span(self.span)
+            }
+            _ => self.span,
+        }
+    }
+}
+
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub enum ObligationCauseCode<'tcx> {
     /// Not well classified or should be obvious from span.
@@ -138,6 +151,8 @@ pub enum ObligationCauseCode<'tcx> {
     VariableType(ast::NodeId),
     /// Return type must be Sized
     SizedReturnType,
+    /// Yield type must be Sized
+    SizedYieldType,
     /// [T,..n] --> T must be Copy
     RepeatVec,
 
index 55cbc890e1e91de2c39b45c9975ccb686fee9305..4ed25646d436d03671852d1d3a0fcd0f625e9c85 100644 (file)
@@ -92,10 +92,10 @@ pub struct SelectionContext<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
 
     inferred_obligations: SnapshotVec<InferredObligationsSnapshotVecDelegate<'tcx>>,
 
-    intercrate_ambiguity_causes: Vec<IntercrateAmbiguityCause>,
+    intercrate_ambiguity_causes: Option<Vec<IntercrateAmbiguityCause>>,
 }
 
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 pub enum IntercrateAmbiguityCause {
     DownstreamCrate {
         trait_desc: String,
@@ -423,7 +423,7 @@ pub fn new(infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>) -> SelectionContext<'cx, 'gcx
             freshener: infcx.freshener(),
             intercrate: None,
             inferred_obligations: SnapshotVec::new(),
-            intercrate_ambiguity_causes: Vec::new(),
+            intercrate_ambiguity_causes: None,
         }
     }
 
@@ -435,10 +435,30 @@ pub fn intercrate(infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
             freshener: infcx.freshener(),
             intercrate: Some(mode),
             inferred_obligations: SnapshotVec::new(),
-            intercrate_ambiguity_causes: Vec::new(),
+            intercrate_ambiguity_causes: None,
         }
     }
 
+    /// Enables tracking of intercrate ambiguity causes. These are
+    /// used in coherence to give improved diagnostics. We don't do
+    /// this until we detect a coherence error because it can lead to
+    /// false overflow results (#47139) and because it costs
+    /// computation time.
+    pub fn enable_tracking_intercrate_ambiguity_causes(&mut self) {
+        assert!(self.intercrate.is_some());
+        assert!(self.intercrate_ambiguity_causes.is_none());
+        self.intercrate_ambiguity_causes = Some(vec![]);
+        debug!("selcx: enable_tracking_intercrate_ambiguity_causes");
+    }
+
+    /// Gets the intercrate ambiguity causes collected since tracking
+    /// was enabled and disables tracking at the same time. If
+    /// tracking is not enabled, just returns an empty vector.
+    pub fn take_intercrate_ambiguity_causes(&mut self) -> Vec<IntercrateAmbiguityCause> {
+        assert!(self.intercrate.is_some());
+        self.intercrate_ambiguity_causes.take().unwrap_or(vec![])
+    }
+
     pub fn infcx(&self) -> &'cx InferCtxt<'cx, 'gcx, 'tcx> {
         self.infcx
     }
@@ -451,10 +471,6 @@ pub fn closure_typer(&self) -> &'cx InferCtxt<'cx, 'gcx, 'tcx> {
         self.infcx
     }
 
-    pub fn intercrate_ambiguity_causes(&self) -> &[IntercrateAmbiguityCause] {
-        &self.intercrate_ambiguity_causes
-    }
-
     /// Wraps the inference context's in_snapshot s.t. snapshot handling is only from the selection
     /// context's self.
     fn in_snapshot<R, F>(&mut self, f: F) -> R
@@ -828,19 +844,23 @@ fn evaluate_stack<'o>(&mut self,
             debug!("evaluate_stack({:?}) --> unbound argument, intercrate -->  ambiguous",
                    stack.fresh_trait_ref);
             // Heuristics: show the diagnostics when there are no candidates in crate.
-            if let Ok(candidate_set) = self.assemble_candidates(stack) {
-                if !candidate_set.ambiguous && candidate_set.vec.is_empty() {
-                    let trait_ref = stack.obligation.predicate.skip_binder().trait_ref;
-                    let self_ty = trait_ref.self_ty();
-                    let cause = IntercrateAmbiguityCause::DownstreamCrate {
-                        trait_desc: trait_ref.to_string(),
-                        self_desc: if self_ty.has_concrete_skeleton() {
-                            Some(self_ty.to_string())
-                        } else {
-                            None
-                        },
-                    };
-                    self.intercrate_ambiguity_causes.push(cause);
+            if self.intercrate_ambiguity_causes.is_some() {
+                debug!("evaluate_stack: intercrate_ambiguity_causes is some");
+                if let Ok(candidate_set) = self.assemble_candidates(stack) {
+                    if !candidate_set.ambiguous && candidate_set.vec.is_empty() {
+                        let trait_ref = stack.obligation.predicate.skip_binder().trait_ref;
+                        let self_ty = trait_ref.self_ty();
+                        let cause = IntercrateAmbiguityCause::DownstreamCrate {
+                            trait_desc: trait_ref.to_string(),
+                            self_desc: if self_ty.has_concrete_skeleton() {
+                                Some(self_ty.to_string())
+                            } else {
+                                None
+                            },
+                        };
+                        debug!("evaluate_stack: pushing cause = {:?}", cause);
+                        self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause);
+                    }
                 }
             }
             return EvaluatedToAmbig;
@@ -1092,25 +1112,29 @@ fn candidate_from_obligation_no_cache<'o>(&mut self,
             None => {}
             Some(conflict) => {
                 debug!("coherence stage: not knowable");
-                // Heuristics: show the diagnostics when there are no candidates in crate.
-                let candidate_set = self.assemble_candidates(stack)?;
-                if !candidate_set.ambiguous && candidate_set.vec.iter().all(|c| {
-                    !self.evaluate_candidate(stack, &c).may_apply()
-                }) {
-                    let trait_ref = stack.obligation.predicate.skip_binder().trait_ref;
-                    let self_ty = trait_ref.self_ty();
-                    let trait_desc = trait_ref.to_string();
-                    let self_desc = if self_ty.has_concrete_skeleton() {
-                        Some(self_ty.to_string())
-                    } else {
-                        None
-                    };
-                    let cause = if let Conflict::Upstream = conflict {
-                        IntercrateAmbiguityCause::UpstreamCrateUpdate { trait_desc, self_desc }
-                    } else {
-                        IntercrateAmbiguityCause::DownstreamCrate { trait_desc, self_desc }
-                    };
-                    self.intercrate_ambiguity_causes.push(cause);
+                if self.intercrate_ambiguity_causes.is_some() {
+                    debug!("evaluate_stack: intercrate_ambiguity_causes is some");
+                    // Heuristics: show the diagnostics when there are no candidates in crate.
+                    let candidate_set = self.assemble_candidates(stack)?;
+                    if !candidate_set.ambiguous && candidate_set.vec.iter().all(|c| {
+                        !self.evaluate_candidate(stack, &c).may_apply()
+                    }) {
+                        let trait_ref = stack.obligation.predicate.skip_binder().trait_ref;
+                        let self_ty = trait_ref.self_ty();
+                        let trait_desc = trait_ref.to_string();
+                        let self_desc = if self_ty.has_concrete_skeleton() {
+                            Some(self_ty.to_string())
+                        } else {
+                            None
+                        };
+                        let cause = if let Conflict::Upstream = conflict {
+                            IntercrateAmbiguityCause::UpstreamCrateUpdate { trait_desc, self_desc }
+                        } else {
+                            IntercrateAmbiguityCause::DownstreamCrate { trait_desc, self_desc }
+                        };
+                        debug!("evaluate_stack: pushing cause = {:?}", cause);
+                        self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause);
+                    }
                 }
                 return Ok(None);
             }
index 834389e5d009c62145d41e7fd88b2d0698e62265..a10169e13e60a705e4bc9e0bc3d6cf75cf5a4a75 100644 (file)
@@ -133,12 +133,12 @@ fn insert(&mut self,
             };
 
             let tcx = tcx.global_tcx();
-            let (le, ge) = tcx.infer_ctxt().enter(|infcx| {
-                let overlap = traits::overlapping_impls(&infcx,
-                                                        possible_sibling,
-                                                        impl_def_id,
-                                                        traits::IntercrateMode::Issue43355);
-                if let Some(overlap) = overlap {
+            let (le, ge) = traits::overlapping_impls(
+                tcx,
+                possible_sibling,
+                impl_def_id,
+                traits::IntercrateMode::Issue43355,
+                |overlap| {
                     if tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) {
                         return Ok((false, false));
                     }
@@ -151,10 +151,9 @@ fn insert(&mut self,
                     } else {
                         Ok((le, ge))
                     }
-                } else {
-                    Ok((false, false))
-                }
-            })?;
+                },
+                || Ok((false, false)),
+            )?;
 
             if le && !ge {
                 debug!("descending as child of TraitRef {:?}",
@@ -171,16 +170,14 @@ fn insert(&mut self,
                 return Ok(Inserted::Replaced(possible_sibling));
             } else {
                 if !tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) {
-                    tcx.infer_ctxt().enter(|infcx| {
-                        if let Some(overlap) = traits::overlapping_impls(
-                            &infcx,
-                            possible_sibling,
-                            impl_def_id,
-                            traits::IntercrateMode::Fixed)
-                        {
-                            last_lint = Some(overlap_error(overlap));
-                        }
-                    });
+                    traits::overlapping_impls(
+                        tcx,
+                        possible_sibling,
+                        impl_def_id,
+                        traits::IntercrateMode::Fixed,
+                        |overlap| last_lint = Some(overlap_error(overlap)),
+                        || (),
+                    );
                 }
 
                 // no overlap (error bailed already via ?)
index e1e2798ecb51c052d61d483b742d4a623ef6f4ae..1eb14a222787db67a998033be8cae3e884d47f7b 100644 (file)
@@ -209,6 +209,7 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
             super::VariableType(id) => Some(super::VariableType(id)),
             super::ReturnType(id) => Some(super::ReturnType(id)),
             super::SizedReturnType => Some(super::SizedReturnType),
+            super::SizedYieldType => Some(super::SizedYieldType),
             super::RepeatVec => Some(super::RepeatVec),
             super::FieldSized(item) => Some(super::FieldSized(item)),
             super::ConstSized => Some(super::ConstSized),
@@ -526,6 +527,7 @@ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F)
             super::VariableType(_) |
             super::ReturnType(_) |
             super::SizedReturnType |
+            super::SizedYieldType |
             super::ReturnNoExpression |
             super::RepeatVec |
             super::FieldSized(_) |
@@ -574,6 +576,7 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
             super::VariableType(_) |
             super::ReturnType(_) |
             super::SizedReturnType |
+            super::SizedYieldType |
             super::ReturnNoExpression |
             super::RepeatVec |
             super::FieldSized(_) |
index 69d07eafdca7a3481a8e03d4f3826d41a354be4b..63b91ff110161f6c7d375071a14bf6be8c0d55c9 100644 (file)
@@ -895,7 +895,8 @@ fn layout_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 
     tcx.layout_depth.set(depth+1);
-    let layout = LayoutDetails::compute_uncached(tcx, param_env, ty);
+    let cx = LayoutCx { tcx, param_env };
+    let layout = cx.layout_raw_uncached(ty);
     tcx.layout_depth.set(depth);
 
     layout
@@ -908,13 +909,18 @@ pub fn provide(providers: &mut ty::maps::Providers) {
     };
 }
 
-impl<'a, 'tcx> LayoutDetails {
-    fn compute_uncached(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                        param_env: ty::ParamEnv<'tcx>,
-                        ty: Ty<'tcx>)
-                        -> Result<&'tcx Self, LayoutError<'tcx>> {
-        let cx = (tcx, param_env);
-        let dl = cx.data_layout();
+#[derive(Copy, Clone)]
+pub struct LayoutCx<'tcx, C> {
+    pub tcx: C,
+    pub param_env: ty::ParamEnv<'tcx>
+}
+
+impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
+    fn layout_raw_uncached(self, ty: Ty<'tcx>)
+                           -> Result<&'tcx LayoutDetails, LayoutError<'tcx>> {
+        let tcx = self.tcx;
+        let param_env = self.param_env;
+        let dl = self.data_layout();
         let scalar_unit = |value: Primitive| {
             let bits = value.size(dl).bits();
             assert!(bits <= 128);
@@ -924,7 +930,7 @@ fn compute_uncached(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             }
         };
         let scalar = |value: Primitive| {
-            tcx.intern_layout(LayoutDetails::scalar(cx, scalar_unit(value)))
+            tcx.intern_layout(LayoutDetails::scalar(self, scalar_unit(value)))
         };
         let scalar_pair = |a: Scalar, b: Scalar| {
             let align = a.value.align(dl).max(b.value.align(dl)).max(dl.aggregate_align);
@@ -1158,13 +1164,13 @@ enum StructKind {
         Ok(match ty.sty {
             // Basic scalars.
             ty::TyBool => {
-                tcx.intern_layout(LayoutDetails::scalar(cx, Scalar {
+                tcx.intern_layout(LayoutDetails::scalar(self, Scalar {
                     value: Int(I8, false),
                     valid_range: 0..=1
                 }))
             }
             ty::TyChar => {
-                tcx.intern_layout(LayoutDetails::scalar(cx, Scalar {
+                tcx.intern_layout(LayoutDetails::scalar(self, Scalar {
                     value: Int(I32, false),
                     valid_range: 0..=0x10FFFF
                 }))
@@ -1180,7 +1186,7 @@ enum StructKind {
             ty::TyFnPtr(_) => {
                 let mut ptr = scalar_unit(Pointer);
                 ptr.valid_range.start = 1;
-                tcx.intern_layout(LayoutDetails::scalar(cx, ptr))
+                tcx.intern_layout(LayoutDetails::scalar(self, ptr))
             }
 
             // The never type.
@@ -1198,13 +1204,13 @@ enum StructKind {
 
                 let pointee = tcx.normalize_associated_type_in_env(&pointee, param_env);
                 if pointee.is_sized(tcx, param_env, DUMMY_SP) {
-                    return Ok(tcx.intern_layout(LayoutDetails::scalar(cx, data_ptr)));
+                    return Ok(tcx.intern_layout(LayoutDetails::scalar(self, data_ptr)));
                 }
 
                 let unsized_part = tcx.struct_tail(pointee);
                 let metadata = match unsized_part.sty {
                     ty::TyForeign(..) => {
-                        return Ok(tcx.intern_layout(LayoutDetails::scalar(cx, data_ptr)));
+                        return Ok(tcx.intern_layout(LayoutDetails::scalar(self, data_ptr)));
                     }
                     ty::TySlice(_) | ty::TyStr => {
                         scalar_unit(Int(dl.ptr_sized_integer(), false))
@@ -1230,7 +1236,7 @@ enum StructKind {
                     }
                 }
 
-                let element = cx.layout_of(element)?;
+                let element = self.layout_of(element)?;
                 let count = count.val.to_const_int().unwrap().to_u64().unwrap();
                 let size = element.size.checked_mul(count, dl)
                     .ok_or(LayoutError::SizeOverflow(ty))?;
@@ -1247,7 +1253,7 @@ enum StructKind {
                 })
             }
             ty::TySlice(element) => {
-                let element = cx.layout_of(element)?;
+                let element = self.layout_of(element)?;
                 tcx.intern_layout(LayoutDetails {
                     variants: Variants::Single { index: 0 },
                     fields: FieldPlacement::Array {
@@ -1289,14 +1295,14 @@ enum StructKind {
             // Tuples, generators and closures.
             ty::TyGenerator(def_id, ref substs, _) => {
                 let tys = substs.field_tys(def_id, tcx);
-                univariant(&tys.map(|ty| cx.layout_of(ty)).collect::<Result<Vec<_>, _>>()?,
+                univariant(&tys.map(|ty| self.layout_of(ty)).collect::<Result<Vec<_>, _>>()?,
                     &ReprOptions::default(),
                     StructKind::AlwaysSized)?
             }
 
             ty::TyClosure(def_id, ref substs) => {
                 let tys = substs.upvar_tys(def_id, tcx);
-                univariant(&tys.map(|ty| cx.layout_of(ty)).collect::<Result<Vec<_>, _>>()?,
+                univariant(&tys.map(|ty| self.layout_of(ty)).collect::<Result<Vec<_>, _>>()?,
                     &ReprOptions::default(),
                     StructKind::AlwaysSized)?
             }
@@ -1308,13 +1314,13 @@ enum StructKind {
                     StructKind::MaybeUnsized
                 };
 
-                univariant(&tys.iter().map(|ty| cx.layout_of(ty)).collect::<Result<Vec<_>, _>>()?,
+                univariant(&tys.iter().map(|ty| self.layout_of(ty)).collect::<Result<Vec<_>, _>>()?,
                     &ReprOptions::default(), kind)?
             }
 
             // SIMD vector types.
             ty::TyAdt(def, ..) if def.repr.simd() => {
-                let element = cx.layout_of(ty.simd_type(tcx))?;
+                let element = self.layout_of(ty.simd_type(tcx))?;
                 let count = ty.simd_size(tcx) as u64;
                 assert!(count > 0);
                 let scalar = match element.abi {
@@ -1350,7 +1356,7 @@ enum StructKind {
                 // Cache the field layouts.
                 let variants = def.variants.iter().map(|v| {
                     v.fields.iter().map(|field| {
-                        cx.layout_of(field.ty(tcx, substs))
+                        self.layout_of(field.ty(tcx, substs))
                     }).collect::<Result<Vec<_>, _>>()
                 }).collect::<Result<Vec<_>, _>>()?;
 
@@ -1430,7 +1436,7 @@ enum StructKind {
                     let mut st = univariant_uninterned(&variants[v], &def.repr, kind)?;
                     st.variants = Variants::Single { index: v };
                     // Exclude 0 from the range of a newtype ABI NonZero<T>.
-                    if Some(def.did) == cx.tcx().lang_items().non_zero() {
+                    if Some(def.did) == self.tcx.lang_items().non_zero() {
                         match st.abi {
                             Abi::Scalar(ref mut scalar) |
                             Abi::ScalarPair(ref mut scalar, _) => {
@@ -1482,7 +1488,7 @@ enum StructKind {
                         let count = (niche_variants.end - niche_variants.start + 1) as u128;
                         for (field_index, field) in variants[i].iter().enumerate() {
                             let (offset, niche, niche_start) =
-                                match field.find_niche(cx, count)? {
+                                match field.find_niche(self, count)? {
                                     Some(niche) => niche,
                                     None => continue
                                 };
@@ -1687,56 +1693,49 @@ enum StructKind {
     /// This is invoked by the `layout_raw` query to record the final
     /// layout of each type.
     #[inline]
-    fn record_layout_for_printing(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                  ty: Ty<'tcx>,
-                                  param_env: ty::ParamEnv<'tcx>,
-                                  layout: TyLayout<'tcx>) {
+    fn record_layout_for_printing(self, layout: TyLayout<'tcx>) {
         // If we are running with `-Zprint-type-sizes`, record layouts for
         // dumping later. Ignore layouts that are done with non-empty
         // environments or non-monomorphic layouts, as the user only wants
         // to see the stuff resulting from the final trans session.
         if
-            !tcx.sess.opts.debugging_opts.print_type_sizes ||
-            ty.has_param_types() ||
-            ty.has_self_ty() ||
-            !param_env.caller_bounds.is_empty()
+            !self.tcx.sess.opts.debugging_opts.print_type_sizes ||
+            layout.ty.has_param_types() ||
+            layout.ty.has_self_ty() ||
+            !self.param_env.caller_bounds.is_empty()
         {
             return;
         }
 
-        Self::record_layout_for_printing_outlined(tcx, ty, param_env, layout)
+        self.record_layout_for_printing_outlined(layout)
     }
 
-    fn record_layout_for_printing_outlined(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                           ty: Ty<'tcx>,
-                                           param_env: ty::ParamEnv<'tcx>,
-                                           layout: TyLayout<'tcx>) {
-        let cx = (tcx, param_env);
+    fn record_layout_for_printing_outlined(self, layout: TyLayout<'tcx>) {
         // (delay format until we actually need it)
         let record = |kind, opt_discr_size, variants| {
-            let type_desc = format!("{:?}", ty);
-            tcx.sess.code_stats.borrow_mut().record_type_size(kind,
-                                                              type_desc,
-                                                              layout.align,
-                                                              layout.size,
-                                                              opt_discr_size,
-                                                              variants);
+            let type_desc = format!("{:?}", layout.ty);
+            self.tcx.sess.code_stats.borrow_mut().record_type_size(kind,
+                                                                   type_desc,
+                                                                   layout.align,
+                                                                   layout.size,
+                                                                   opt_discr_size,
+                                                                   variants);
         };
 
-        let adt_def = match ty.sty {
+        let adt_def = match layout.ty.sty {
             ty::TyAdt(ref adt_def, _) => {
-                debug!("print-type-size t: `{:?}` process adt", ty);
+                debug!("print-type-size t: `{:?}` process adt", layout.ty);
                 adt_def
             }
 
             ty::TyClosure(..) => {
-                debug!("print-type-size t: `{:?}` record closure", ty);
+                debug!("print-type-size t: `{:?}` record closure", layout.ty);
                 record(DataTypeKind::Closure, None, vec![]);
                 return;
             }
 
             _ => {
-                debug!("print-type-size t: `{:?}` skip non-nominal", ty);
+                debug!("print-type-size t: `{:?}` skip non-nominal", layout.ty);
                 return;
             }
         };
@@ -1748,7 +1747,7 @@ fn record_layout_for_printing_outlined(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                   layout: TyLayout<'tcx>| {
             let mut min_size = Size::from_bytes(0);
             let field_info: Vec<_> = flds.iter().enumerate().map(|(i, &name)| {
-                match layout.field(cx, i) {
+                match layout.field(self, i) {
                     Err(err) => {
                         bug!("no layout found for field {}: `{:?}`", name, err);
                     }
@@ -1808,18 +1807,18 @@ fn record_layout_for_printing_outlined(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             Variants::NicheFilling { .. } |
             Variants::Tagged { .. } => {
                 debug!("print-type-size `{:#?}` adt general variants def {}",
-                       ty, adt_def.variants.len());
+                       layout.ty, adt_def.variants.len());
                 let variant_infos: Vec<_> =
                     adt_def.variants.iter().enumerate().map(|(i, variant_def)| {
                         let fields: Vec<_> =
                             variant_def.fields.iter().map(|f| f.name).collect();
                         build_variant_info(Some(variant_def.name),
                                             &fields,
-                                            layout.for_variant(cx, i))
+                                            layout.for_variant(self, i))
                     })
                     .collect();
                 record(adt_kind.into(), match layout.variants {
-                    Variants::Tagged { ref discr, .. } => Some(discr.value.size(tcx)),
+                    Variants::Tagged { ref discr, .. } => Some(discr.value.size(self)),
                     _ => None
                 }, variant_infos);
             }
@@ -1855,7 +1854,7 @@ pub fn compute(ty: Ty<'tcx>,
         assert!(!ty.has_infer_types());
 
         // First try computing a static layout.
-        let err = match (tcx, param_env).layout_of(ty) {
+        let err = match tcx.layout_of(param_env.and(ty)) {
             Ok(layout) => {
                 return Ok(SizeSkeleton::Known(layout.size));
             }
@@ -2001,15 +2000,15 @@ fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'gcx> {
     }
 }
 
-impl<'a, 'gcx, 'tcx, T: Copy> HasDataLayout for (TyCtxt<'a, 'gcx, 'tcx>, T) {
+impl<'tcx, T: HasDataLayout> HasDataLayout for LayoutCx<'tcx, T> {
     fn data_layout(&self) -> &TargetDataLayout {
-        self.0.data_layout()
+        self.tcx.data_layout()
     }
 }
 
-impl<'a, 'gcx, 'tcx, T: Copy> HasTyCtxt<'gcx> for (TyCtxt<'a, 'gcx, 'tcx>, T) {
+impl<'gcx, 'tcx, T: HasTyCtxt<'gcx>> HasTyCtxt<'gcx> for LayoutCx<'tcx, T> {
     fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'gcx> {
-        self.0.tcx()
+        self.tcx.tcx()
     }
 }
 
@@ -2042,17 +2041,15 @@ pub trait LayoutOf<T> {
     fn layout_of(self, ty: T) -> Self::TyLayout;
 }
 
-impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for (TyCtxt<'a, 'tcx, 'tcx>, ty::ParamEnv<'tcx>) {
+impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
     type TyLayout = Result<TyLayout<'tcx>, LayoutError<'tcx>>;
 
     /// Computes the layout of a type. Note that this implicitly
     /// executes in "reveal all" mode.
-    #[inline]
     fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
-        let (tcx, param_env) = self;
-
-        let ty = tcx.normalize_associated_type_in_env(&ty, param_env.reveal_all());
-        let details = tcx.layout_raw(param_env.reveal_all().and(ty))?;
+        let param_env = self.param_env.reveal_all();
+        let ty = self.tcx.normalize_associated_type_in_env(&ty, param_env);
+        let details = self.tcx.layout_raw(param_env.and(ty))?;
         let layout = TyLayout {
             ty,
             details
@@ -2064,24 +2061,21 @@ fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
         // completed, to avoid problems around recursive structures
         // and the like. (Admitedly, I wasn't able to reproduce a problem
         // here, but it seems like the right thing to do. -nmatsakis)
-        LayoutDetails::record_layout_for_printing(tcx, ty, param_env, layout);
+        self.record_layout_for_printing(layout);
 
         Ok(layout)
     }
 }
 
-impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for (ty::maps::TyCtxtAt<'a, 'tcx, 'tcx>,
-                                       ty::ParamEnv<'tcx>) {
+impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for LayoutCx<'tcx, ty::maps::TyCtxtAt<'a, 'tcx, 'tcx>> {
     type TyLayout = Result<TyLayout<'tcx>, LayoutError<'tcx>>;
 
     /// Computes the layout of a type. Note that this implicitly
     /// executes in "reveal all" mode.
-    #[inline]
     fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
-        let (tcx_at, param_env) = self;
-
-        let ty = tcx_at.tcx.normalize_associated_type_in_env(&ty, param_env.reveal_all());
-        let details = tcx_at.layout_raw(param_env.reveal_all().and(ty))?;
+        let param_env = self.param_env.reveal_all();
+        let ty = self.tcx.normalize_associated_type_in_env(&ty, param_env.reveal_all());
+        let details = self.tcx.layout_raw(param_env.reveal_all().and(ty))?;
         let layout = TyLayout {
             ty,
             details
@@ -2093,12 +2087,45 @@ fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
         // completed, to avoid problems around recursive structures
         // and the like. (Admitedly, I wasn't able to reproduce a problem
         // here, but it seems like the right thing to do. -nmatsakis)
-        LayoutDetails::record_layout_for_printing(tcx_at.tcx, ty, param_env, layout);
+        let cx = LayoutCx {
+            tcx: *self.tcx,
+            param_env: self.param_env
+        };
+        cx.record_layout_for_printing(layout);
 
         Ok(layout)
     }
 }
 
+// Helper (inherent) `layout_of` methods to avoid pushing `LayoutCx` to users.
+impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
+    /// Computes the layout of a type. Note that this implicitly
+    /// executes in "reveal all" mode.
+    #[inline]
+    pub fn layout_of(self, param_env_and_ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
+                     -> Result<TyLayout<'tcx>, LayoutError<'tcx>> {
+        let cx = LayoutCx {
+            tcx: self,
+            param_env: param_env_and_ty.param_env
+        };
+        cx.layout_of(param_env_and_ty.value)
+    }
+}
+
+impl<'a, 'tcx> ty::maps::TyCtxtAt<'a, 'tcx, 'tcx> {
+    /// Computes the layout of a type. Note that this implicitly
+    /// executes in "reveal all" mode.
+    #[inline]
+    pub fn layout_of(self, param_env_and_ty: ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
+                     -> Result<TyLayout<'tcx>, LayoutError<'tcx>> {
+        let cx = LayoutCx {
+            tcx: self,
+            param_env: param_env_and_ty.param_env
+        };
+        cx.layout_of(param_env_and_ty.value)
+    }
+}
+
 impl<'a, 'tcx> TyLayout<'tcx> {
     pub fn for_variant<C>(&self, cx: C, variant_index: usize) -> Self
         where C: LayoutOf<Ty<'tcx>> + HasTyCtxt<'tcx>,
index 6c79f6a62fa0b3779861edcddbe7bf95b300c89d..85fca68187fe661fc82f9084cd94aea5719144cd 100644 (file)
         -> (Arc<DefIdSet>, Arc<Vec<Arc<CodegenUnit<'tcx>>>>),
     [] fn export_name: ExportName(DefId) -> Option<Symbol>,
     [] fn contains_extern_indicator: ContainsExternIndicator(DefId) -> bool,
+    [] fn symbol_export_level: GetSymbolExportLevel(DefId) -> SymbolExportLevel,
     [] fn is_translated_function: IsTranslatedFunction(DefId) -> bool,
     [] fn codegen_unit: CodegenUnit(InternedString) -> Arc<CodegenUnit<'tcx>>,
     [] fn compile_codegen_unit: CompileCodegenUnit(InternedString) -> Stats,
index c9eebc3d2a0a723e9f486ced5063d4d54699ae9b..0ab6ee1a54a9b1a02ac866b6e6f3839c97c2296a 100644 (file)
@@ -921,6 +921,8 @@ macro_rules! force {
 
         DepKind::TargetFeaturesWhitelist => { force!(target_features_whitelist, LOCAL_CRATE); }
         DepKind::TargetFeaturesEnabled => { force!(target_features_enabled, def_id!()); }
+
+        DepKind::GetSymbolExportLevel => { force!(symbol_export_level, def_id!()); }
     }
 
     true
index 0c1ebd1a2ba2f2f0c754d1ed8067c4bbdefcbfb1..1593b452cdffc3c4541819d71e1e8cb36a2d58d1 100644 (file)
@@ -390,14 +390,21 @@ impl Iterator<Item=Ty<'tcx>> + 'a
         state.map(move |d| d.ty.subst(tcx, self.substs))
     }
 
+    /// This is the types of the fields of a generate which
+    /// is available before the generator transformation.
+    /// It includes the upvars and the state discriminant which is u32.
+    pub fn pre_transforms_tys(self, def_id: DefId, tcx: TyCtxt<'a, 'gcx, 'tcx>) ->
+        impl Iterator<Item=Ty<'tcx>> + 'a
+    {
+        self.upvar_tys(def_id, tcx).chain(iter::once(tcx.types.u32))
+    }
+
     /// This is the types of all the fields stored in a generator.
     /// It includes the upvars, state types and the state discriminant which is u32.
     pub fn field_tys(self, def_id: DefId, tcx: TyCtxt<'a, 'gcx, 'tcx>) ->
         impl Iterator<Item=Ty<'tcx>> + 'a
     {
-        let upvars = self.upvar_tys(def_id, tcx);
-        let state = self.state_tys(def_id, tcx);
-        upvars.chain(iter::once(tcx.types.u32)).chain(state)
+        self.pre_transforms_tys(def_id, tcx).chain(self.state_tys(def_id, tcx))
     }
 }
 
index 3c8a676dcc20062c5765d7122a62e4b219079904..2872c59157d6be1cf1b5d73aec7f39d8e0aa584b 100644 (file)
@@ -468,6 +468,10 @@ pub struct TargetOptions {
 
     /// The codegen backend to use for this target, typically "llvm"
     pub codegen_backend: String,
+
+    /// The default visibility for symbols in this target should be "hidden"
+    /// rather than "default"
+    pub default_hidden_visibility: bool,
 }
 
 impl Default for TargetOptions {
@@ -538,6 +542,7 @@ fn default() -> TargetOptions {
             no_builtins: false,
             i128_lowering: false,
             codegen_backend: "llvm".to_string(),
+            default_hidden_visibility: false,
         }
     }
 }
@@ -785,6 +790,7 @@ macro_rules! key {
         key!(singlethread, bool);
         key!(no_builtins, bool);
         key!(codegen_backend);
+        key!(default_hidden_visibility, bool);
 
         if let Some(array) = obj.find("abi-blacklist").and_then(Json::as_array) {
             for name in array.iter().filter_map(|abi| abi.as_string()) {
@@ -982,6 +988,7 @@ macro_rules! target_option_val {
         target_option_val!(singlethread);
         target_option_val!(no_builtins);
         target_option_val!(codegen_backend);
+        target_option_val!(default_hidden_visibility);
 
         if default.abi_blacklist != self.options.abi_blacklist {
             d.insert("abi-blacklist".to_string(), self.options.abi_blacklist.iter()
index 509a7cf5e03234158d70a61ca70ec53cbb749b74..966df897f01f1e09295b609d7c3530fbb5e4378a 100644 (file)
@@ -53,6 +53,12 @@ pub fn target() -> TargetResult {
             // don't want to invoke that many gcc instances.
             default_codegen_units: Some(1),
 
+            // Since MSP430 doesn't meaningfully support faulting on illegal
+            // instructions, LLVM generates a call to abort() function instead
+            // of a trap instruction. Such calls are 4 bytes long, and that is
+            // too much overhead for such small target.
+            trap_unreachable: false,
+
             .. Default::default( )
         }
     })
index 7e1011ab8af96a2bd47b721b2fbf4f0c3f629498..242860e5c6e9285034cc5946e8a626a40275ec99 100644 (file)
@@ -83,6 +83,9 @@ pub fn target() -> Result<Target, String> {
         // performing LTO with compiler-builtins.
         no_builtins: true,
 
+        // no dynamic linking, no need for default visibility!
+        default_hidden_visibility: true,
+
         .. Default::default()
     };
     Ok(Target {
index ddee122d0a6bd1a4d91d7a248892ced94b2a7bff..7bcd8a185453b11004648411493a1bf70febb5dd 100644 (file)
@@ -77,7 +77,7 @@ fn check_unused_mut_pat(&self, pats: &[P<hir::Pat>]) {
                 continue
             }
 
-            let mut_span = tcx.sess.codemap().span_until_char(ids[0].2, ' ');
+            let mut_span = tcx.sess.codemap().span_until_non_whitespace(ids[0].2);
 
             // Ok, every name wasn't used mutably, so issue a warning that this
             // didn't need to be mutable.
index fd171b89924701f7a268edc9c37f0dd46603646c..ae53ed0e1140d1226e4ba29f8ba45041ad13c40e 100644 (file)
@@ -127,13 +127,16 @@ fn visit_body(&mut self, body: &'tcx hir::Body) {
     }
 }
 
+
 impl<'a, 'tcx> PatternContext<'a, 'tcx> {
     fn report_inlining_errors(&self, pat_span: Span) {
         for error in &self.errors {
             match *error {
                 PatternError::StaticInPattern(span) => {
-                    span_err!(self.tcx.sess, span, E0158,
-                              "statics cannot be referenced in patterns");
+                    self.span_e0158(span, "statics cannot be referenced in patterns")
+                }
+                PatternError::AssociatedConstInPattern(span) => {
+                    self.span_e0158(span, "associated consts cannot be referenced in patterns")
                 }
                 PatternError::ConstEval(ref err) => {
                     err.report(self.tcx, pat_span, "pattern");
@@ -141,6 +144,10 @@ fn report_inlining_errors(&self, pat_span: Span) {
             }
         }
     }
+
+    fn span_e0158(&self, span: Span, text: &str) {
+        span_err!(self.tcx.sess, span, E0158, "{}", text)
+    }
 }
 
 impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
index 418bd4b5effc6b08ba01d3a50dc4e4313fbad51a..1d2813e4f6704fac35e5f489e844c6fd32221f72 100644 (file)
@@ -17,7 +17,6 @@
 use rustc::hir::def::{Def, CtorKind};
 use rustc::hir::def_id::DefId;
 use rustc::ty::{self, Ty, TyCtxt};
-use rustc::ty::layout::LayoutOf;
 use rustc::ty::util::IntTypeExt;
 use rustc::ty::subst::{Substs, Subst};
 use rustc::util::common::ErrorReported;
@@ -313,7 +312,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
           if tcx.fn_sig(def_id).abi() == Abi::RustIntrinsic {
             let layout_of = |ty: Ty<'tcx>| {
                 let ty = tcx.erase_regions(&ty);
-                (tcx.at(e.span), cx.param_env).layout_of(ty).map_err(|err| {
+                tcx.at(e.span).layout_of(cx.param_env.and(ty)).map_err(|err| {
                     ConstEvalErr { span: e.span, kind: LayoutError(err) }
                 })
             };
index 3577feaf90c1abb2b7a1040f6c61aa8b131f55bc..e0b3929e32a8d9686b3cc0b9cfb0fabf6d622dad 100644 (file)
@@ -27,6 +27,7 @@
 
 #[derive(Clone, Debug)]
 pub enum PatternError<'tcx> {
+    AssociatedConstInPattern(Span),
     StaticInPattern(Span),
     ConstEval(ConstEvalErr<'tcx>),
 }
@@ -635,6 +636,10 @@ fn lower_path(&mut self,
                   -> Pattern<'tcx> {
         let ty = self.tables.node_id_to_type(id);
         let def = self.tables.qpath_def(qpath, id);
+        let is_associated_const = match def {
+            Def::AssociatedConst(_) => true,
+            _ => false,
+        };
         let kind = match def {
             Def::Const(def_id) | Def::AssociatedConst(def_id) => {
                 let substs = self.tables.node_substs(id);
@@ -656,7 +661,11 @@ fn lower_path(&mut self,
                         return pat;
                     }
                     None => {
-                        self.errors.push(PatternError::StaticInPattern(span));
+                        self.errors.push(if is_associated_const {
+                            PatternError::AssociatedConstInPattern(span)
+                        } else {
+                            PatternError::StaticInPattern(span)
+                        });
                         PatternKind::Wild
                     }
                 }
index 6118ee94c84cff354350d57f5b60302890f03131..05dcaf731352a36074af2240764ca8c328d324b8 100644 (file)
@@ -167,7 +167,8 @@ pub fn run<F>(run_compiler: F) -> isize
                     let emitter =
                         errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto,
                                                                None,
-                                                               true);
+                                                               true,
+                                                               false);
                     let handler = errors::Handler::with_emitter(true, false, Box::new(emitter));
                     handler.emit(&MultiSpan::new(),
                                  "aborting due to previous error(s)",
@@ -289,7 +290,7 @@ fn get_trans_sysroot(backend_name: &str) -> fn() -> Box<TransCrate> {
     let sysroot = sysroot_candidates.iter()
         .map(|sysroot| {
             let libdir = filesearch::relative_target_lib_path(&sysroot, &target);
-            sysroot.join(&libdir).join("codegen-backends")
+            sysroot.join(libdir).with_file_name("codegen-backends")
         })
         .filter(|f| {
             info!("codegen backend candidate: {}", f.display());
@@ -456,10 +457,13 @@ macro_rules! do_or_return {($expr: expr, $sess: expr) => {
                                            None);
 
     let (odir, ofile) = make_output(&matches);
-    let (input, input_file_path) = match make_input(&matches.free) {
-        Some((input, input_file_path)) => callbacks.some_input(input, input_file_path),
+    let (input, input_file_path, input_err) = match make_input(&matches.free) {
+        Some((input, input_file_path, input_err)) => {
+            let (input, input_file_path) = callbacks.some_input(input, input_file_path);
+            (input, input_file_path, input_err)
+        },
         None => match callbacks.no_input(&matches, &sopts, &cfg, &odir, &ofile, &descriptions) {
-            Some((input, input_file_path)) => (input, input_file_path),
+            Some((input, input_file_path)) => (input, input_file_path, None),
             None => return (Ok(()), None),
         },
     };
@@ -470,6 +474,13 @@ macro_rules! do_or_return {($expr: expr, $sess: expr) => {
         sopts, input_file_path.clone(), descriptions, codemap, emitter_dest,
     );
 
+    if let Some(err) = input_err {
+        // Immediately stop compilation if there was an issue reading
+        // the input (for example if the input stream is not UTF-8).
+        sess.err(&format!("{}", err));
+        return (Err(CompileIncomplete::Stopped), Some(sess));
+    }
+
     let trans = get_trans(&sess);
 
     rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
@@ -512,17 +523,22 @@ fn make_output(matches: &getopts::Matches) -> (Option<PathBuf>, Option<PathBuf>)
 }
 
 // Extract input (string or file and optional path) from matches.
-fn make_input(free_matches: &[String]) -> Option<(Input, Option<PathBuf>)> {
+fn make_input(free_matches: &[String]) -> Option<(Input, Option<PathBuf>, Option<io::Error>)> {
     if free_matches.len() == 1 {
         let ifile = &free_matches[0];
         if ifile == "-" {
             let mut src = String::new();
-            io::stdin().read_to_string(&mut src).unwrap();
+            let err = if io::stdin().read_to_string(&mut src).is_err() {
+                Some(io::Error::new(io::ErrorKind::InvalidData,
+                                    "couldn't read from stdin, as it did not contain valid UTF-8"))
+            } else {
+                None
+            };
             Some((Input::Str { name: FileName::Anon, input: src },
-                  None))
+                  None, err))
         } else {
             Some((Input::File(PathBuf::from(ifile)),
-                  Some(PathBuf::from(ifile))))
+                  Some(PathBuf::from(ifile)), None))
         }
     } else {
         None
@@ -1434,6 +1450,7 @@ pub fn monitor<F: FnOnce() + Send + 'static>(f: F) {
             let emitter =
                 Box::new(errors::emitter::EmitterWriter::stderr(errors::ColorConfig::Auto,
                                                                 None,
+                                                                false,
                                                                 false));
             let handler = errors::Handler::with_emitter(true, false, emitter);
 
index 2e654fe9929a6af7801755994f0dcc8147c29043..40e4efb397d305087b223e4cad8d8143f3d771a7 100644 (file)
@@ -222,6 +222,7 @@ pub fn span_suggestion_short(&mut self, sp: Span, msg: &str, suggestion: String)
             }],
             msg: msg.to_owned(),
             show_code_when_inline: false,
+            approximate: false,
         });
         self
     }
@@ -252,6 +253,7 @@ pub fn span_suggestion(&mut self, sp: Span, msg: &str, suggestion: String) -> &m
             }],
             msg: msg.to_owned(),
             show_code_when_inline: true,
+            approximate: false,
         });
         self
     }
@@ -267,6 +269,41 @@ pub fn span_suggestions(&mut self, sp: Span, msg: &str, suggestions: Vec<String>
             }).collect(),
             msg: msg.to_owned(),
             show_code_when_inline: true,
+            approximate: false,
+        });
+        self
+    }
+
+    /// This is a suggestion that may contain mistakes or fillers and should
+    /// be read and understood by a human.
+    pub fn span_approximate_suggestion(&mut self, sp: Span, msg: &str,
+                                       suggestion: String) -> &mut Self {
+        self.suggestions.push(CodeSuggestion {
+            substitutions: vec![Substitution {
+                parts: vec![SubstitutionPart {
+                    snippet: suggestion,
+                    span: sp,
+                }],
+            }],
+            msg: msg.to_owned(),
+            show_code_when_inline: true,
+            approximate: true,
+        });
+        self
+    }
+
+    pub fn span_approximate_suggestions(&mut self, sp: Span, msg: &str,
+                                        suggestions: Vec<String>) -> &mut Self {
+        self.suggestions.push(CodeSuggestion {
+            substitutions: suggestions.into_iter().map(|snippet| Substitution {
+                parts: vec![SubstitutionPart {
+                    snippet,
+                    span: sp,
+                }],
+            }).collect(),
+            msg: msg.to_owned(),
+            show_code_when_inline: true,
+            approximate: true,
         });
         self
     }
index 61674ada6fa63c1bc37a7ff3e7b09d92a57801e7..2536fc648c70ad693f8356b6dfc8d2bf9345e11f 100644 (file)
@@ -186,6 +186,16 @@ pub fn span_label<T: Into<String>>(&mut self, span: Span, label: T) -> &mut Self
                                      msg: &str,
                                      suggestions: Vec<String>)
                                      -> &mut Self);
+    forward!(pub fn span_approximate_suggestion(&mut self,
+                                                sp: Span,
+                                                msg: &str,
+                                                suggestion: String)
+                                                -> &mut Self);
+    forward!(pub fn span_approximate_suggestions(&mut self,
+                                                 sp: Span,
+                                                 msg: &str,
+                                                 suggestions: Vec<String>)
+                                                 -> &mut Self);
     forward!(pub fn set_span<S: Into<MultiSpan>>(&mut self, sp: S) -> &mut Self);
     forward!(pub fn code(&mut self, s: DiagnosticId) -> &mut Self);
 
index ffb5efd93ed54fad04029b4638b20703e95ab719..a49284eb55a465aae7d0aae87744fc34833530db 100644 (file)
@@ -106,6 +106,7 @@ pub struct EmitterWriter {
     dst: Destination,
     cm: Option<Rc<CodeMapper>>,
     short_message: bool,
+    teach: bool,
 }
 
 struct FileWithAnnotatedLines {
@@ -117,32 +118,37 @@ struct FileWithAnnotatedLines {
 impl EmitterWriter {
     pub fn stderr(color_config: ColorConfig,
                   code_map: Option<Rc<CodeMapper>>,
-                  short_message: bool)
+                  short_message: bool,
+                  teach: bool)
                   -> EmitterWriter {
         if color_config.use_color() {
             let dst = Destination::from_stderr();
             EmitterWriter {
                 dst,
                 cm: code_map,
-                short_message: short_message,
+                short_message,
+                teach,
             }
         } else {
             EmitterWriter {
                 dst: Raw(Box::new(io::stderr())),
                 cm: code_map,
-                short_message: short_message,
+                short_message,
+                teach,
             }
         }
     }
 
     pub fn new(dst: Box<Write + Send>,
                code_map: Option<Rc<CodeMapper>>,
-               short_message: bool)
+               short_message: bool,
+               teach: bool)
                -> EmitterWriter {
         EmitterWriter {
             dst: Raw(dst),
             cm: code_map,
-            short_message: short_message,
+            short_message,
+            teach,
         }
     }
 
@@ -284,6 +290,10 @@ fn render_source_line(&self,
                           line: &Line,
                           width_offset: usize,
                           code_offset: usize) -> Vec<(usize, Style)> {
+        if line.line_index == 0 {
+            return Vec::new();
+        }
+
         let source_string = match file.get_line(line.line_index - 1) {
             Some(s) => s,
             None => return Vec::new(),
@@ -551,7 +561,14 @@ fn render_source_line(&self,
                                code_offset + annotation.start_col,
                                style);
                 }
-                _ => (),
+                _ if self.teach => {
+                    buffer.set_style_range(line_offset,
+                                           code_offset + annotation.start_col,
+                                           code_offset + annotation.end_col,
+                                           style,
+                                           annotation.is_primary);
+                }
+                _ => {}
             }
         }
 
index 3d50c95d3f4f9857d542155d2518474ca84fcaff..236698ed2d45d77ba5099953daf89ba83b626201 100644 (file)
@@ -83,6 +83,12 @@ pub struct CodeSuggestion {
     pub substitutions: Vec<Substitution>,
     pub msg: String,
     pub show_code_when_inline: bool,
+    /// Whether or not the suggestion is approximate
+    ///
+    /// Sometimes we may show suggestions with placeholders,
+    /// which are useful for users but not useful for
+    /// tools like rustfix
+    pub approximate: bool,
 }
 
 #[derive(Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
@@ -297,7 +303,7 @@ pub fn with_tty_emitter_and_flags(color_config: ColorConfig,
                                       cm: Option<Rc<CodeMapper>>,
                                       flags: HandlerFlags)
                                       -> Handler {
-        let emitter = Box::new(EmitterWriter::stderr(color_config, cm, false));
+        let emitter = Box::new(EmitterWriter::stderr(color_config, cm, false, false));
         Handler::with_emitter_and_flags(emitter, flags)
     }
 
index 6035f33c822cee1eedf6b87ad412c1b4d9f87fb8..7d416f13ffc8a0f77d5f951c1641c2e07534d0f2 100644 (file)
 
 // Code for annotating snippets.
 
-use syntax_pos::{Span, FileMap};
-use CodeMapper;
-use std::rc::Rc;
 use Level;
 
-#[derive(Clone)]
-pub struct SnippetData {
-    codemap: Rc<CodeMapper>,
-    files: Vec<FileInfo>,
-}
-
-#[derive(Clone)]
-pub struct FileInfo {
-    file: Rc<FileMap>,
-
-    /// The "primary file", if any, gets a `-->` marker instead of
-    /// `>>>`, and has a line-number/column printed and not just a
-    /// filename (other files are not guaranteed to have line numbers
-    /// or columns). It appears first in the listing. It is known to
-    /// contain at least one primary span, though primary spans (which
-    /// are designated with `^^^`) may also occur in other files.
-    primary_span: Option<Span>,
-
-    lines: Vec<Line>,
-}
-
 #[derive(Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
 pub struct Line {
     pub line_index: usize,
index 2c33f80520360a83fa741b114d4f7d56c3b4c46d..2c736ec22c3b3fd76b97e47dafe1848b3ebd6fac 100644 (file)
@@ -144,4 +144,25 @@ pub fn append(&mut self, line: usize, string: &str, style: Style) {
     pub fn num_lines(&self) -> usize {
         self.text.len()
     }
+
+    pub fn set_style_range(&mut self,
+                           line: usize,
+                           col_start: usize,
+                           col_end: usize,
+                           style: Style,
+                           overwrite: bool) {
+        for col in col_start..col_end {
+            self.set_style(line, col, style, overwrite);
+        }
+    }
+
+    pub fn set_style(&mut self, line: usize, col: usize, style: Style, overwrite: bool) {
+        if let Some(ref mut line) = self.styles.get_mut(line) {
+            if let Some(s) = line.get_mut(col) {
+                if *s == Style::NoStyle || *s == Style::Quotation || overwrite {
+                    *s = style;
+                }
+            }
+        }
+    }
 }
index e0999db6e3e66d3930e9c6ac6ffd4470023aedfd..e7e4119b9999bee72eb0558cfe216057e8e9e176 100644 (file)
@@ -437,8 +437,8 @@ fn check_type_for_ffi(&self,
                             // repr(transparent) types are allowed to have arbitrary ZSTs, not just
                             // PhantomData -- skip checking all ZST fields
                             if def.repr.transparent() {
-                                let is_zst = (cx, cx.param_env(field.did))
-                                    .layout_of(field_ty)
+                                let is_zst = cx
+                                    .layout_of(cx.param_env(field.did).and(field_ty))
                                     .map(|layout| layout.is_zst())
                                     .unwrap_or(false);
                                 if is_zst {
index ef6475f9ee4c7b403aa607845363774d633425aa..56f863ab3aa84e6ae881cab222e422793ea3cdbd 100644 (file)
@@ -302,19 +302,38 @@ fn check_expr(&mut self, cx: &EarlyContext, e: &ast::Expr) {
             Assign(_, ref value) => (value, "assigned value", false),
             AssignOp(.., ref value) => (value, "assigned value", false),
             InPlace(_, ref value) => (value, "emplacement value", false),
-            Call(_, ref args) => {
-                for arg in args {
-                    self.check_unused_parens_core(cx, arg, "function argument", false)
+            // either function/method call, or something this lint doesn't care about
+            ref call_or_other => {
+                let args_to_check;
+                let call_kind;
+                match *call_or_other {
+                    Call(_, ref args) => {
+                        call_kind = "function";
+                        args_to_check = &args[..];
+                    },
+                    MethodCall(_, ref args) => {
+                        call_kind = "method";
+                        // first "argument" is self (which sometimes needs parens)
+                        args_to_check = &args[1..];
+                    }
+                    // actual catch-all arm
+                    _ => { return; }
                 }
-                return;
-            },
-            MethodCall(_, ref args) => {
-                for arg in &args[1..] { // first "argument" is self (which sometimes needs parens)
-                    self.check_unused_parens_core(cx, arg, "method argument", false)
+                // Don't lint if this is a nested macro expansion: otherwise, the lint could
+                // trigger in situations that macro authors shouldn't have to care about, e.g.,
+                // when a parenthesized token tree matched in one macro expansion is matched as
+                // an expression in another and used as a fn/method argument (Issue #47775)
+                if e.span.ctxt().outer().expn_info()
+                    .map_or(false, |info| info.call_site.ctxt().outer()
+                            .expn_info().is_some()) {
+                        return;
+                }
+                let msg = format!("{} argument", call_kind);
+                for arg in args_to_check {
+                    self.check_unused_parens_core(cx, arg, &msg, false);
                 }
                 return;
             }
-            _ => return,
         };
         self.check_unused_parens_core(cx, &value, msg, struct_lit_needs_parens);
     }
index 7bd3b6e39f053b46ca7ab2ce3558049c6ede6ee6..7fadc4b36e44fe4ab6c5b3abef36d7bd7fa13db1 100644 (file)
@@ -746,12 +746,12 @@ fn describe_field_from_ty(&self, ty: &ty::Ty, field: Field) -> String {
                     self.describe_field_from_ty(&tnm.ty, field)
                 }
                 ty::TyArray(ty, _) | ty::TySlice(ty) => self.describe_field_from_ty(&ty, field),
-                ty::TyClosure(closure_def_id, _) => {
+                ty::TyClosure(def_id, _) | ty::TyGenerator(def_id, _, _) => {
                     // Convert the def-id into a node-id. node-ids are only valid for
                     // the local code in the current crate, so this returns an `Option` in case
                     // the closure comes from another crate. But in that case we wouldn't
                     // be borrowck'ing it, so we can just unwrap:
-                    let node_id = self.tcx.hir.as_local_node_id(closure_def_id).unwrap();
+                    let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap();
                     let freevar = self.tcx.with_freevars(node_id, |fv| fv[field.index()]);
 
                     self.tcx.hir.name(freevar.var_id()).to_string()
index 015eb8a3b6643bfddf5ddaed9837fc899cd70433..c0c680a4ddcbceae0b361f7af3ffb86800a1e3e5 100644 (file)
@@ -374,13 +374,20 @@ fn sanitize_place(
             }
         };
         if let PlaceContext::Copy = context {
-            let ty = place_ty.to_ty(self.tcx());
-            if self.cx
-                .infcx
-                .type_moves_by_default(self.cx.param_env, ty, DUMMY_SP)
-            {
-                span_mirbug!(self, place, "attempted copy of non-Copy type ({:?})", ty);
-            }
+            let tcx = self.tcx();
+            let trait_ref = ty::TraitRef {
+                def_id: tcx.lang_items().copy_trait().unwrap(),
+                substs: tcx.mk_substs_trait(place_ty.to_ty(tcx), &[]),
+            };
+
+            // In order to have a Copy operand, the type T of the value must be Copy. Note that we
+            // prove that T: Copy, rather than using the type_moves_by_default test. This is
+            // important because type_moves_by_default ignores the resulting region obligations and
+            // assumes they pass. This can result in bounds from Copy impls being unsoundly ignored
+            // (e.g., #29149). Note that we decide to use Copy before knowing whether the bounds
+            // fully apply: in effect, the rule is that if a value of some type could implement
+            // Copy, then it must.
+            self.cx.prove_trait_ref(trait_ref, location);
         }
         place_ty
     }
@@ -533,15 +540,17 @@ fn field_ty(
                     }
                 }
                 ty::TyGenerator(def_id, substs, _) => {
-                    // Try upvars first. `field_tys` requires final optimized MIR.
-                    if let Some(ty) = substs.upvar_tys(def_id, tcx).nth(field.index()) {
+                    // Try pre-transform fields first (upvars and current state)
+                    if let Some(ty) = substs.pre_transforms_tys(def_id, tcx).nth(field.index()) {
                         return Ok(ty);
                     }
 
+                    // Then try `field_tys` which contains all the fields, but it
+                    // requires the final optimized MIR.
                     return match substs.field_tys(def_id, tcx).nth(field.index()) {
                         Some(ty) => Ok(ty),
                         None => Err(FieldAccessError::OutOfRange {
-                            field_count: substs.field_tys(def_id, tcx).count() + 1,
+                            field_count: substs.field_tys(def_id, tcx).count(),
                         }),
                     };
                 }
@@ -1233,13 +1242,16 @@ fn aggregate_field_ty(
                 }
             }
             AggregateKind::Generator(def_id, substs, _) => {
-                if let Some(ty) = substs.upvar_tys(def_id, tcx).nth(field_index) {
+                // Try pre-transform fields first (upvars and current state)
+                if let Some(ty) = substs.pre_transforms_tys(def_id, tcx).nth(field_index) {
                     Ok(ty)
                 } else {
+                    // Then try `field_tys` which contains all the fields, but it
+                    // requires the final optimized MIR.
                     match substs.field_tys(def_id, tcx).nth(field_index) {
                         Some(ty) => Ok(ty),
                         None => Err(FieldAccessError::OutOfRange {
-                            field_count: substs.field_tys(def_id, tcx).count() + 1,
+                            field_count: substs.field_tys(def_id, tcx).count(),
                         }),
                     }
                 }
diff --git a/src/librustc_mir/dataflow/impls/borrowed_locals.rs b/src/librustc_mir/dataflow/impls/borrowed_locals.rs
new file mode 100644 (file)
index 0000000..244e8b5
--- /dev/null
@@ -0,0 +1,118 @@
+// 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.
+
+pub use super::*;
+
+use rustc::mir::*;
+use rustc::mir::visit::Visitor;
+use dataflow::BitDenotation;
+
+/// This calculates if any part of a MIR local could have previously been borrowed.
+/// This means that once a local has been borrowed, its bit will always be set
+/// from that point and onwards, even if the borrow ends. You could also think of this
+/// as computing the lifetimes of infinite borrows.
+/// This is used to compute which locals are live during a yield expression for
+/// immovable generators.
+#[derive(Copy, Clone)]
+pub struct HaveBeenBorrowedLocals<'a, 'tcx: 'a> {
+    mir: &'a Mir<'tcx>,
+}
+
+impl<'a, 'tcx: 'a> HaveBeenBorrowedLocals<'a, 'tcx> {
+    pub fn new(mir: &'a Mir<'tcx>)
+               -> Self {
+        HaveBeenBorrowedLocals { mir: mir }
+    }
+
+    pub fn mir(&self) -> &Mir<'tcx> {
+        self.mir
+    }
+}
+
+impl<'a, 'tcx> BitDenotation for HaveBeenBorrowedLocals<'a, 'tcx> {
+    type Idx = Local;
+    fn name() -> &'static str { "has_been_borrowed_locals" }
+    fn bits_per_block(&self) -> usize {
+        self.mir.local_decls.len()
+    }
+
+    fn start_block_effect(&self, _sets: &mut IdxSet<Local>) {
+        // Nothing is borrowed on function entry
+    }
+
+    fn statement_effect(&self,
+                        sets: &mut BlockSets<Local>,
+                        loc: Location) {
+        BorrowedLocalsVisitor {
+            sets,
+        }.visit_statement(loc.block, &self.mir[loc.block].statements[loc.statement_index], loc);
+    }
+
+    fn terminator_effect(&self,
+                         sets: &mut BlockSets<Local>,
+                         loc: Location) {
+        BorrowedLocalsVisitor {
+            sets,
+        }.visit_terminator(loc.block, self.mir[loc.block].terminator(), loc);
+    }
+
+    fn propagate_call_return(&self,
+                             _in_out: &mut IdxSet<Local>,
+                             _call_bb: mir::BasicBlock,
+                             _dest_bb: mir::BasicBlock,
+                             _dest_place: &mir::Place) {
+        // Nothing to do when a call returns successfully
+    }
+}
+
+impl<'a, 'tcx> BitwiseOperator for HaveBeenBorrowedLocals<'a, 'tcx> {
+    #[inline]
+    fn join(&self, pred1: usize, pred2: usize) -> usize {
+        pred1 | pred2 // "maybe" means we union effects of both preds
+    }
+}
+
+impl<'a, 'tcx> InitialFlow for HaveBeenBorrowedLocals<'a, 'tcx> {
+    #[inline]
+    fn bottom_value() -> bool {
+        false // bottom = unborrowed
+    }
+}
+
+struct BorrowedLocalsVisitor<'b, 'c: 'b> {
+    sets: &'b mut BlockSets<'c, Local>,
+}
+
+fn find_local<'tcx>(place: &Place<'tcx>) -> Option<Local> {
+    match *place {
+        Place::Local(l) => Some(l),
+        Place::Static(..) => None,
+        Place::Projection(ref proj) => {
+            match proj.elem {
+                ProjectionElem::Deref => None,
+                _ => find_local(&proj.base)
+            }
+        }
+    }
+}
+
+impl<'tcx, 'b, 'c> Visitor<'tcx> for BorrowedLocalsVisitor<'b, 'c> {
+    fn visit_rvalue(&mut self,
+                    rvalue: &Rvalue<'tcx>,
+                    location: Location) {
+        if let Rvalue::Ref(_, _, ref place) = *rvalue {
+            if let Some(local) = find_local(place) {
+                self.sets.gen(&local);
+            }
+        }
+
+        self.super_rvalue(rvalue, location)
+    }
+}
index 632bb5b34284da8e3eb2fab4607dbbc01437a3fb..80990bcc080891ef93478a602019248137560710 100644 (file)
@@ -396,8 +396,7 @@ fn statement_effect_on_borrows(&self,
                         // Issue #46746: Two-phase borrows handles
                         // stmts of form `Tmp = &mut Borrow` ...
                         match lhs {
-                            Place::Local(..) => {} // okay
-                            Place::Static(..) => unreachable!(), // (filtered by is_unsafe_place)
+                            Place::Local(..) | Place::Static(..) => {} // okay
                             Place::Projection(..) => {
                                 // ... can assign into projections,
                                 // e.g. `box (&mut _)`. Current
index e7c15625cbe2be9bbf946c81395ef3a0d8cde61c..c5f5492cd2c2c20cefc36c6c75e1ab5f6cbebee1 100644 (file)
 
 pub use self::storage_liveness::*;
 
+mod borrowed_locals;
+
+pub use self::borrowed_locals::*;
+
 #[allow(dead_code)]
 pub(super) mod borrows;
 
index bd63198ecd0d273c127723a49efb48e62b00345d..291c22b5e1ed0f0aa32081534a97ff24f396cd21 100644 (file)
@@ -30,6 +30,7 @@
 pub use self::impls::{DefinitelyInitializedPlaces, MovingOutStatements};
 pub use self::impls::EverInitializedPlaces;
 pub use self::impls::borrows::{Borrows, BorrowData};
+pub use self::impls::HaveBeenBorrowedLocals;
 pub(crate) use self::impls::borrows::{ActiveBorrows, Reservations, ReserveOrActivateIndex};
 pub use self::at_location::{FlowAtLocation, FlowsAtLocation};
 pub(crate) use self::drop_flag_effects::*;
index baec0fea50f1ef18df029ea03cc885403679d8f7..02fcb69fef5acff1889cd234cd77650d6603cfd9 100644 (file)
@@ -172,7 +172,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> LayoutOf<Ty<'tcx>> for &'a EvalContext<'a, 'tcx
     type TyLayout = EvalResult<'tcx, TyLayout<'tcx>>;
 
     fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
-        (self.tcx, self.param_env).layout_of(ty)
+        self.tcx.layout_of(self.param_env.and(ty))
             .map_err(|layout| EvalErrorKind::Layout(layout).into())
     }
 }
index 806d787c84522601c69c4a56fde4acbc7f547ba4..e9471cdb4f9497658b91a27108906d88f72e98dc 100644 (file)
 use rustc::hir::def_id::DefId;
 use rustc::hir::map::DefPathData;
 use rustc::mir::mono::{Linkage, Visibility};
+use rustc::middle::exported_symbols::SymbolExportLevel;
 use rustc::ty::{self, TyCtxt, InstanceDef};
 use rustc::ty::item_path::characteristic_def_id_of_type;
 use rustc::util::nodemap::{FxHashMap, FxHashSet};
@@ -322,7 +323,16 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                             .or_insert_with(make_codegen_unit);
 
         let mut can_be_internalized = true;
-        let (linkage, visibility) = match trans_item.explicit_linkage(tcx) {
+        let default_visibility = |id: DefId| {
+            if tcx.sess.target.target.options.default_hidden_visibility &&
+                tcx.symbol_export_level(id) != SymbolExportLevel::C
+            {
+                Visibility::Hidden
+            } else {
+                Visibility::Default
+            }
+        };
+        let (linkage, mut visibility) = match trans_item.explicit_linkage(tcx) {
             Some(explicit_linkage) => (explicit_linkage, Visibility::Default),
             None => {
                 match trans_item {
@@ -352,7 +362,8 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                     Visibility::Hidden
                                 } else if def_id.is_local() {
                                     if tcx.is_exported_symbol(def_id) {
-                                        Visibility::Default
+                                        can_be_internalized = false;
+                                        default_visibility(def_id)
                                     } else {
                                         Visibility::Hidden
                                     }
@@ -375,7 +386,8 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     MonoItem::GlobalAsm(node_id) => {
                         let def_id = tcx.hir.local_def_id(node_id);
                         let visibility = if tcx.is_exported_symbol(def_id) {
-                            Visibility::Default
+                            can_be_internalized = false;
+                            default_visibility(def_id)
                         } else {
                             Visibility::Hidden
                         };
index ebd34f81deb2958dce2985446d95a89b23170d8f..812665f5fa49804d3b2648206e50496bce011977 100644 (file)
@@ -78,7 +78,8 @@
 use transform::{MirPass, MirSource};
 use transform::simplify;
 use transform::no_landing_pads::no_landing_pads;
-use dataflow::{do_dataflow, DebugFormatted, MaybeStorageLive, state_for_location};
+use dataflow::{do_dataflow, DebugFormatted, state_for_location};
+use dataflow::{MaybeStorageLive, HaveBeenBorrowedLocals};
 
 pub struct StateTransform;
 
@@ -369,17 +370,33 @@ fn locals_live_across_suspend_points<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                 HashMap<BasicBlock, liveness::LocalSet>) {
     let dead_unwinds = IdxSetBuf::new_empty(mir.basic_blocks().len());
     let node_id = tcx.hir.as_local_node_id(source.def_id).unwrap();
-    let analysis = MaybeStorageLive::new(mir);
+
+    // Calculate when MIR locals have live storage. This gives us an upper bound of their
+    // lifetimes.
+    let storage_live_analysis = MaybeStorageLive::new(mir);
     let storage_live =
-        do_dataflow(tcx, mir, node_id, &[], &dead_unwinds, analysis,
+        do_dataflow(tcx, mir, node_id, &[], &dead_unwinds, storage_live_analysis,
                     |bd, p| DebugFormatted::new(&bd.mir().local_decls[p]));
 
+    // Find the MIR locals which do not use StorageLive/StorageDead statements.
+    // The storage of these locals are always live.
     let mut ignored = StorageIgnored(IdxSetBuf::new_filled(mir.local_decls.len()));
     ignored.visit_mir(mir);
 
-    let mut borrowed_locals = BorrowedLocals(IdxSetBuf::new_empty(mir.local_decls.len()));
-    borrowed_locals.visit_mir(mir);
+    // Calculate the MIR locals which have been previously
+    // borrowed (even if they are still active).
+    // This is only used for immovable generators.
+    let borrowed_locals = if !movable {
+        let analysis = HaveBeenBorrowedLocals::new(mir);
+        let result =
+            do_dataflow(tcx, mir, node_id, &[], &dead_unwinds, analysis,
+                        |bd, p| DebugFormatted::new(&bd.mir().local_decls[p]));
+        Some((analysis, result))
+    } else {
+        None
+    };
 
+    // Calculate the liveness of MIR locals ignoring borrows.
     let mut set = liveness::LocalSet::new_empty(mir.local_decls.len());
     let mut liveness = liveness::liveness_of_locals(mir, LivenessMode {
         include_regular_use: true,
@@ -396,24 +413,41 @@ fn locals_live_across_suspend_points<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 statement_index: data.statements.len(),
             };
 
-            let storage_liveness = state_for_location(loc, &analysis, &storage_live, mir);
+            if let Some((ref analysis, ref result)) = borrowed_locals {
+                let borrowed_locals = state_for_location(loc,
+                                                         analysis,
+                                                         result,
+                                                         mir);
+                // The `liveness` variable contains the liveness of MIR locals ignoring borrows.
+                // This is correct for movable generators since borrows cannot live across
+                // suspension points. However for immovable generators we need to account for
+                // borrows, so we conseratively assume that all borrowed locals live forever.
+                // To do this we just union our `liveness` result with `borrowed_locals`, which
+                // contains all the locals which has been borrowed before this suspension point.
+                // If a borrow is converted to a raw reference, we must also assume that it lives
+                // forever. Note that the final liveness is still bounded by the storage liveness
+                // of the local, which happens using the `intersect` operation below.
+                liveness.outs[block].union(&borrowed_locals);
+            }
+
+            let mut storage_liveness = state_for_location(loc,
+                                                          &storage_live_analysis,
+                                                          &storage_live,
+                                                          mir);
 
+            // Store the storage liveness for later use so we can restore the state
+            // after a suspension point
             storage_liveness_map.insert(block, storage_liveness.clone());
 
-            let mut live_locals = storage_liveness;
-
             // Mark locals without storage statements as always having live storage
-            live_locals.union(&ignored.0);
+            storage_liveness.union(&ignored.0);
 
-            if !movable {
-                // For immovable generators we consider borrowed locals to always be live.
-                // This effectively makes those locals use just the storage liveness.
-                liveness.outs[block].union(&borrowed_locals.0);
-            }
+            // Locals live are live at this point only if they are used across
+            // suspension points (the `liveness` variable)
+            // and their storage is live (the `storage_liveness` variable)
+            storage_liveness.intersect(&liveness.outs[block]);
 
-            // Locals live are live at this point only if they are used across suspension points
-            // and their storage is live
-            live_locals.intersect(&liveness.outs[block]);
+            let live_locals = storage_liveness;
 
             // Add the locals life at this suspension point to the set of locals which live across
             // any suspension points
index 43ee75d1e2ba255b7515530b2cda076464262fdc..ceea97e3ed3b0f1276757873ff053c99e2b295bf 100644 (file)
@@ -19,7 +19,6 @@
 use rustc::mir::*;
 use rustc::mir::visit::*;
 use rustc::ty::{self, Instance, Ty, TyCtxt, TypeFoldable};
-use rustc::ty::layout::LayoutOf;
 use rustc::ty::subst::{Subst,Substs};
 
 use std::collections::VecDeque;
@@ -655,7 +654,7 @@ fn create_temp_if_necessary(
 fn type_size_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           param_env: ty::ParamEnv<'tcx>,
                           ty: Ty<'tcx>) -> Option<u64> {
-    (tcx, param_env).layout_of(ty).ok().map(|layout| layout.size.bytes())
+    tcx.layout_of(param_env.and(ty)).ok().map(|layout| layout.size.bytes())
 }
 
 fn subst_and_normalize<'a, 'tcx: 'a>(
index c23f28fe2205f943d4cfec7fc727d1993141dc13..008c71cc9ce3d2129a892f08753ff1c4e2eb8faa 100644 (file)
@@ -119,6 +119,11 @@ fn visit_expr(&mut self, e: &'hir hir::Expr) {
                                              kind.name())
                                 .span_label(e.span,
                                             "can only break with a value inside `loop`")
+                                .span_suggestion(e.span,
+                                                 &format!("instead, use `break` on its own \
+                                                           without a value inside this `{}` loop",
+                                                          kind.name()),
+                                                 "break".to_string())
                                 .emit();
                         }
                     }
index ecf3c9e42d58f598cb8871664780765109677d1f..2da4bfedd3a175252a230f2d9a17a01ccfdf8dd1 100644 (file)
@@ -3998,14 +3998,20 @@ fn report_conflict<'b>(&mut self,
 
             if let (Ok(snippet), false) = (cm.span_to_snippet(binding.span),
                                            binding.is_renamed_extern_crate()) {
+                let suggested_name = if name.as_str().chars().next().unwrap().is_uppercase() {
+                    format!("Other{}", name)
+                } else {
+                    format!("other_{}", name)
+                };
+
                 err.span_suggestion(binding.span,
                                     rename_msg,
                                     if snippet.ends_with(';') {
-                                        format!("{} as Other{};",
+                                        format!("{} as {};",
                                                 &snippet[..snippet.len()-1],
-                                                name)
+                                                suggested_name)
                                     } else {
-                                        format!("{} as Other{}", snippet, name)
+                                        format!("{} as {}", snippet, suggested_name)
                                     });
             } else {
                 err.span_label(binding.span, rename_msg);
index fd5aa1364d381951bcf3025a77b4f62164064da5..e1c145b122d761044a6057c2f670591150701576 100644 (file)
@@ -86,6 +86,10 @@ pub(crate) unsafe fn trans(tcx: TyCtxt, mods: &ModuleLlvm, kind: AllocatorKind)
                                                      name.as_ptr(),
                                                      ty);
 
+        if tcx.sess.target.target.options.default_hidden_visibility {
+            llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
+        }
+
         let callee = CString::new(kind.fn_name(method.name)).unwrap();
         let callee = llvm::LLVMRustGetOrInsertFunction(llmod,
                                                        callee.as_ptr(),
index c7be0c4e67d712a3617e9a16f5884f23314dbedd..751f8148a2a9086fde59c055a8b22d83890e6ef3 100644 (file)
@@ -59,8 +59,9 @@ pub fn trans_inline_asm<'a, 'tcx>(
     // Default per-arch clobbers
     // Basically what clang does
     let arch_clobbers = match &bx.sess().target.target.arch[..] {
-        "x86" | "x86_64" => vec!["~{dirflag}", "~{fpsr}", "~{flags}"],
-        _                => Vec::new()
+        "x86" | "x86_64"  => vec!["~{dirflag}", "~{fpsr}", "~{flags}"],
+        "mips" | "mips64" => vec!["~{$1}"],
+        _                 => Vec::new()
     };
 
     let all_constraints =
index 15ff59c7df998098603d60a101b40dd164864f77..989ef8a953746161a09b433fae785aa639b393a4 100644 (file)
@@ -133,6 +133,8 @@ pub fn provide(providers: &mut Providers) {
 
         Arc::new(local_crate)
     };
+
+    providers.symbol_export_level = export_level;
 }
 
 pub fn provide_extern(providers: &mut Providers) {
@@ -203,6 +205,7 @@ pub fn provide_extern(providers: &mut Providers) {
 
         Arc::new(crate_exports)
     };
+    providers.symbol_export_level = export_level;
 }
 
 fn export_level(tcx: TyCtxt, sym_def_id: DefId) -> SymbolExportLevel {
index 8afa63a5e9735e113bceac783870cdca3d54d91f..206c73b017459b077b05dd78a719fc242113d806 100644 (file)
@@ -824,9 +824,7 @@ fn binaryen_assemble(cgcx: &CodegenContext,
     if cgcx.debuginfo != config::NoDebugInfo {
         options.debuginfo(true);
     }
-    if cgcx.crate_types.contains(&config::CrateTypeExecutable) {
-        options.start("main");
-    }
+
     options.stack(1024 * 1024);
     options.import_memory(cgcx.wasm_import_memory);
     let assembled = input.and_then(|input| {
@@ -1452,7 +1450,7 @@ fn start_executing_work(tcx: TyCtxt,
         target_pointer_width: tcx.sess.target.target.target_pointer_width.clone(),
         binaryen_linker: tcx.sess.linker_flavor() == LinkerFlavor::Binaryen,
         debuginfo: tcx.sess.opts.debuginfo,
-        wasm_import_memory: wasm_import_memory,
+        wasm_import_memory,
         assembler_cmd,
     };
 
index 06b8d9ff7b306d1e8ae9eacfb1662baa72e90d08..a285e5f263ab7037b3f0df4045203f6a89ab639b 100644 (file)
@@ -464,8 +464,7 @@ impl<'a, 'tcx> LayoutOf<Ty<'tcx>> for &'a CodegenCx<'a, 'tcx> {
     type TyLayout = TyLayout<'tcx>;
 
     fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
-        (self.tcx, ty::ParamEnv::empty(traits::Reveal::All))
-            .layout_of(ty)
+        self.tcx.layout_of(ty::ParamEnv::empty(traits::Reveal::All).and(ty))
             .unwrap_or_else(|e| match e {
                 LayoutError::SizeOverflow(_) => self.sess().fatal(&e.to_string()),
                 _ => bug!("failed to get layout for `{}`: {}", ty, e)
index b1533cfad19f524fd6e0e8baa5bb237fbbc8f0ff..af957500f700268b33fc3880fe79b5e0da72fa35 100644 (file)
@@ -57,7 +57,9 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
         ty::TyClosure(..) |
         ty::TyGenerator(..) |
         ty::TyAdt(..) |
-        ty::TyDynamic(..) |
+        // FIXME(eddyb) producing readable type names for trait objects can result
+        // in problematically distinct types due to HRTB and subtyping (see #47638).
+        // ty::TyDynamic(..) |
         ty::TyForeign(..) |
         ty::TyStr => {
             let mut name = String::with_capacity(32);
index 570eecfc267deea3ff5fa8f7fe7dc044c5bfc141..4c10f28eb8e5de23d9987a82c087f716adf4f92c 100644 (file)
@@ -40,6 +40,8 @@ pub fn compare_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     debug!("compare_impl_method(impl_trait_ref={:?})",
            impl_trait_ref);
 
+    let impl_m_span = tcx.sess.codemap().def_span(impl_m_span);
+
     if let Err(ErrorReported) = compare_self_type(tcx,
                                                   impl_m,
                                                   impl_m_span,
@@ -186,6 +188,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     check_region_bounds_on_impl_method(tcx,
                                        impl_m_span,
                                        impl_m,
+                                       trait_m,
                                        &trait_m_generics,
                                        &impl_m_generics,
                                        trait_to_skol_substs)?;
@@ -310,7 +313,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             };
 
             let mut diag = struct_span_err!(tcx.sess,
-                                            cause.span,
+                                            cause.span(&tcx),
                                             E0053,
                                             "method `{}` has an incompatible type for trait",
                                             trait_m.name);
@@ -346,10 +349,12 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 fn check_region_bounds_on_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                 span: Span,
                                                 impl_m: &ty::AssociatedItem,
+                                                trait_m: &ty::AssociatedItem,
                                                 trait_generics: &ty::Generics,
                                                 impl_generics: &ty::Generics,
                                                 trait_to_skol_substs: &Substs<'tcx>)
                                                 -> Result<(), ErrorReported> {
+    let span = tcx.sess.codemap().def_span(span);
     let trait_params = &trait_generics.regions[..];
     let impl_params = &impl_generics.regions[..];
 
@@ -371,14 +376,18 @@ fn check_region_bounds_on_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // are zero. Since I don't quite know how to phrase things at
     // the moment, give a kind of vague error message.
     if trait_params.len() != impl_params.len() {
-        struct_span_err!(tcx.sess,
-                         span,
-                         E0195,
-                         "lifetime parameters or bounds on method `{}` do not match the \
-                          trait declaration",
-                         impl_m.name)
-            .span_label(span, "lifetimes do not match trait")
-            .emit();
+        let mut err = struct_span_err!(tcx.sess,
+                                       span,
+                                       E0195,
+                                       "lifetime parameters or bounds on method `{}` do not match \
+                                        the trait declaration",
+                                       impl_m.name);
+        err.span_label(span, "lifetimes do not match method in trait");
+        if let Some(sp) = tcx.hir.span_if_local(trait_m.def_id) {
+            err.span_label(tcx.sess.codemap().def_span(sp),
+                           "lifetimes in impl do not match this method in trait");
+        }
+        err.emit();
         return Err(ErrorReported);
     }
 
@@ -424,9 +433,9 @@ fn extract_spans_for_error_reporting<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a
                 }).map(|(ref impl_arg, ref trait_arg)| {
                     (impl_arg.span, Some(trait_arg.span))
                 })
-                .unwrap_or_else(|| (cause.span, tcx.hir.span_if_local(trait_m.def_id)))
+                .unwrap_or_else(|| (cause.span(&tcx), tcx.hir.span_if_local(trait_m.def_id)))
             } else {
-                (cause.span, tcx.hir.span_if_local(trait_m.def_id))
+                (cause.span(&tcx), tcx.hir.span_if_local(trait_m.def_id))
             }
         }
         TypeError::Sorts(ExpectedFound { .. }) => {
@@ -459,14 +468,14 @@ fn extract_spans_for_error_reporting<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a
                              {
                                  (impl_m_output.span(), Some(trait_m_output.span()))
                              } else {
-                                 (cause.span, tcx.hir.span_if_local(trait_m.def_id))
+                                 (cause.span(&tcx), tcx.hir.span_if_local(trait_m.def_id))
                              }
                          })
             } else {
-                (cause.span, tcx.hir.span_if_local(trait_m.def_id))
+                (cause.span(&tcx), tcx.hir.span_if_local(trait_m.def_id))
             }
         }
-        _ => (cause.span, tcx.hir.span_if_local(trait_m.def_id)),
+        _ => (cause.span(&tcx), tcx.hir.span_if_local(trait_m.def_id)),
     }
 }
 
index 781eeaef2482cca189ca56db038b243f01a1f666..2e45e3b1f3521db331ef2d9fc537bbd6e0dba346 100644 (file)
@@ -150,15 +150,15 @@ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
     }
 
     fn visit_pat(&mut self, pat: &'tcx Pat) {
+        intravisit::walk_pat(self, pat);
+
+        self.expr_count += 1;
+
         if let PatKind::Binding(..) = pat.node {
             let scope = self.region_scope_tree.var_scope(pat.hir_id.local_id);
             let ty = self.fcx.tables.borrow().pat_ty(pat);
             self.record(ty, Some(scope), None, pat.span);
         }
-
-        self.expr_count += 1;
-
-        intravisit::walk_pat(self, pat);
     }
 
     fn visit_expr(&mut self, expr: &'tcx Expr) {
index 483dd345286d433601cdd3d2728b73ee6ff5865a..363d4a9dc0cd3eb5ff388df588b28a9fcba6b4d5 100644 (file)
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::maps::Providers;
 use rustc::ty::util::{Representability, IntTypeExt};
-use rustc::ty::layout::LayoutOf;
 use errors::{DiagnosticBuilder, DiagnosticId};
 
 use require_c_abi_if_variadic;
@@ -1015,7 +1014,9 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
     let span = body.value.span;
 
     if body.is_generator && can_be_generator.is_some() {
-        fcx.yield_ty = Some(fcx.next_ty_var(TypeVariableOrigin::TypeInference(span)));
+        let yield_ty = fcx.next_ty_var(TypeVariableOrigin::TypeInference(span));
+        fcx.require_type_is_sized(yield_ty, span, traits::SizedYieldType);
+        fcx.yield_ty = Some(yield_ty);
     }
 
     GatherLocalsVisitor { fcx: &fcx, }.visit_body(body);
@@ -1551,7 +1552,7 @@ fn check_transparent<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, def_id: De
     let field_infos: Vec<_> = adt.non_enum_variant().fields.iter().map(|field| {
         let ty = field.ty(tcx, Substs::identity_for_item(tcx, field.did));
         let param_env = tcx.param_env(field.did);
-        let layout = (tcx, param_env).layout_of(ty);
+        let layout = tcx.layout_of(param_env.and(ty));
         // We are currently checking the type this field came from, so it must be local
         let span = tcx.hir.span_if_local(field.did).unwrap();
         let zst = layout.map(|layout| layout.is_zst()).unwrap_or(false);
index 07d5f813cbbce76977700c569af80bdd868a8ea3..88a2dc817ae63f139f1ad1a38bee016c777fa732 100644 (file)
@@ -82,29 +82,37 @@ fn check_for_overlapping_inherent_impls(&self, ty_def_id: DefId) {
 
         for (i, &impl1_def_id) in impls.iter().enumerate() {
             for &impl2_def_id in &impls[(i + 1)..] {
-                let used_to_be_allowed = self.tcx.infer_ctxt().enter(|infcx| {
-                    if let Some(overlap) =
-                        traits::overlapping_impls(&infcx, impl1_def_id, impl2_def_id,
-                                                  IntercrateMode::Issue43355)
-                    {
+                let used_to_be_allowed = traits::overlapping_impls(
+                    self.tcx,
+                    impl1_def_id,
+                    impl2_def_id,
+                    IntercrateMode::Issue43355,
+                    |overlap| {
                         self.check_for_common_items_in_impls(
-                            impl1_def_id, impl2_def_id, overlap, false);
+                            impl1_def_id,
+                            impl2_def_id,
+                            overlap,
+                            false,
+                        );
                         false
-                    } else {
-                        true
-                    }
-                });
+                    },
+                    || true,
+                );
 
                 if used_to_be_allowed {
-                    self.tcx.infer_ctxt().enter(|infcx| {
-                        if let Some(overlap) =
-                            traits::overlapping_impls(&infcx, impl1_def_id, impl2_def_id,
-                                                      IntercrateMode::Fixed)
-                        {
-                            self.check_for_common_items_in_impls(
-                                impl1_def_id, impl2_def_id, overlap, true);
-                        }
-                    });
+                    traits::overlapping_impls(
+                        self.tcx,
+                        impl1_def_id,
+                        impl2_def_id,
+                        IntercrateMode::Fixed,
+                        |overlap| self.check_for_common_items_in_impls(
+                            impl1_def_id,
+                            impl2_def_id,
+                            overlap,
+                            true,
+                        ),
+                        || (),
+                    );
                 }
             }
         }
index 0929b833c1965395337753946980f8f4db38ec84..7c9a49c82a9395b186eab37471140cd64c368ab6 100644 (file)
@@ -2447,7 +2447,12 @@ fn clean(&self, cx: &DocContext) -> Type {
                 let def_id = cx.tcx.hir.body_owner_def_id(n);
                 let param_env = cx.tcx.param_env(def_id);
                 let substs = Substs::identity_for_item(cx.tcx, def_id);
-                let n = cx.tcx.const_eval(param_env.and((def_id, substs))).unwrap();
+                let n = cx.tcx.const_eval(param_env.and((def_id, substs))).unwrap_or_else(|_| {
+                    cx.tcx.mk_const(ty::Const {
+                        val: ConstVal::Unevaluated(def_id, substs),
+                        ty: cx.tcx.types.usize
+                    })
+                });
                 let n = if let ConstVal::Integral(ConstInt::Usize(n)) = n.val {
                     n.to_string()
                 } else if let ConstVal::Unevaluated(def_id, _) = n.val {
@@ -2577,7 +2582,9 @@ fn clean(&self, cx: &DocContext) -> Type {
                 let mut n = cx.tcx.lift(&n).unwrap();
                 if let ConstVal::Unevaluated(def_id, substs) = n.val {
                     let param_env = cx.tcx.param_env(def_id);
-                    n = cx.tcx.const_eval(param_env.and((def_id, substs))).unwrap()
+                    if let Ok(new_n) = cx.tcx.const_eval(param_env.and((def_id, substs))) {
+                        n = new_n;
+                    }
                 };
                 let n = if let ConstVal::Integral(ConstInt::Usize(n)) = n.val {
                     n.to_string()
index d2eeb2e15b3ddbfedb492999eb56113451c9c2bf..2b1f920bba0b3cc439a2cc171a3c168b9a48a7a1 100644 (file)
@@ -181,15 +181,19 @@ nav.sub {
        overflow: auto;
 }
 
-.sidebar .current {
+.sidebar .block > ul > li {
        margin-right: -20px;
 }
 
-.content, nav { max-width: 960px; }
+.content, nav {
+       max-width: 960px;
+}
 
 /* Everything else */
 
-.js-only, .hidden { display: none !important; }
+.js-only, .hidden {
+       display: none !important;
+}
 
 .sidebar img {
        margin: 20px auto;
@@ -218,7 +222,9 @@ nav.sub {
        border: none;
 }
 
-.location a:first-child { font-weight: 500; }
+.location a:first-child {
+       font-weight: 500;
+}
 
 .block {
        padding: 0;
@@ -299,7 +305,9 @@ nav.sub {
        -ms-user-select: none;
        user-select: none;
 }
-.line-numbers span { cursor: pointer; }
+.line-numbers span {
+       cursor: pointer;
+}
 
 .docblock-short p {
        display: inline;
@@ -317,7 +325,9 @@ nav.sub {
        text-overflow: ellipsis;
        margin: 0;
 }
-.docblock-short code { white-space: nowrap; }
+.docblock-short code {
+       white-space: nowrap;
+}
 
 .docblock h1, .docblock h2, .docblock h3, .docblock h4, .docblock h5 {
        border-bottom: 1px solid;
@@ -384,7 +394,9 @@ h4 > code, h3 > code, .invisible > code {
        display: inline-block;
 }
 
-#main { position: relative; }
+#main {
+       position: relative;
+}
 #main > .since {
        top: inherit;
        font-family: "Fira Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
@@ -428,7 +440,9 @@ h4 > code, h3 > code, .invisible > code {
        padding: 0;
 }
 
-.content .item-list li { margin-bottom: 1em; }
+.content .item-list li {
+       margin-bottom: 1em;
+}
 
 .content .multi-column {
        -moz-column-count: 5;
index d61b80c9aa03efae6e6504473926a20c96fe68e8..087d88419bc84dbef204b1dc5085b8a4242c9b5e 100644 (file)
@@ -238,6 +238,7 @@ fn drop(&mut self) {
     ));
     let emitter = errors::emitter::EmitterWriter::new(box Sink(data.clone()),
                                                       Some(codemap.clone()),
+                                                      false,
                                                       false);
     let old = io::set_panic(Some(box Sink(data.clone())));
     let _bomb = Bomb(data.clone(), old.unwrap_or(box io::stdout()));
index 3430ecabcbeaea079874ef3406e77c19491ac5aa..c1fe4a89d6ac0f9a750a49727cab3be1c4514321 100644 (file)
@@ -48,3 +48,4 @@ jemalloc = ["alloc_jemalloc"]
 force_alloc_system = []
 panic-unwind = ["panic_unwind"]
 profiler = ["profiler_builtins"]
+wasm_syscall = []
index 9810dede61821e03c80c3405e7f32b2c28744146..ecf68f29d6f1f7c80c4324d1c71073b09a8a019c 100644 (file)
@@ -1531,6 +1531,7 @@ fn test_to_degrees() {
         assert!(nan.to_degrees().is_nan());
         assert_eq!(inf.to_degrees(), inf);
         assert_eq!(neg_inf.to_degrees(), neg_inf);
+        assert_eq!(1_f32.to_degrees(), 57.2957795130823208767981548141051703);
     }
 
     #[test]
index f0b41f30251e09d10209422ea9cd23eb139588ad..bdd675e6e2b851d8f581190902a913ac140ce26b 100644 (file)
@@ -292,8 +292,8 @@ pub fn last_os_error() -> Error {
     /// # if cfg!(target_os = "linux") {
     /// use std::io;
     ///
-    /// let error = io::Error::from_raw_os_error(98);
-    /// assert_eq!(error.kind(), io::ErrorKind::AddrInUse);
+    /// let error = io::Error::from_raw_os_error(22);
+    /// assert_eq!(error.kind(), io::ErrorKind::InvalidInput);
     /// # }
     /// ```
     ///
@@ -303,8 +303,8 @@ pub fn last_os_error() -> Error {
     /// # if cfg!(windows) {
     /// use std::io;
     ///
-    /// let error = io::Error::from_raw_os_error(10048);
-    /// assert_eq!(error.kind(), io::ErrorKind::AddrInUse);
+    /// let error = io::Error::from_raw_os_error(10022);
+    /// assert_eq!(error.kind(), io::ErrorKind::InvalidInput);
     /// # }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
index c980ae75261caad971960e712a5259ba0da5cb96..78a3b82546e3a93258d753b810c6846f45ad1da9 100644 (file)
@@ -111,10 +111,11 @@ fn drop(&mut self) {
 
 #[cfg_attr(test, allow(dead_code))]
 pub mod guard {
-    pub unsafe fn current() -> Option<usize> {
+    pub type Guard = !;
+    pub unsafe fn current() -> Option<Guard> {
         None
     }
-    pub unsafe fn init() -> Option<usize> {
+    pub unsafe fn init() -> Option<Guard> {
         None
     }
 }
index c4aad8d86f8b1f5e4b6fba452c4eb64e9476cf6d..c4719a94c7e9dfa15252e216af2180c62b886a14 100644 (file)
@@ -88,6 +88,7 @@ pub fn into_id(self) -> usize {
 }
 
 pub mod guard {
-    pub unsafe fn current() -> Option<usize> { None }
-    pub unsafe fn init() -> Option<usize> { None }
+    pub type Guard = !;
+    pub unsafe fn current() -> Option<Guard> { None }
+    pub unsafe fn init() -> Option<Guard> { None }
 }
index 51adbc24ae04779ed6eaba4f2ec7c6014bf2989e..40453f9b8a15b4e1dcdb2ddf64bb18332f33a734 100644 (file)
@@ -57,9 +57,6 @@ mod imp {
     use sys_common::thread_info;
 
 
-    // This is initialized in init() and only read from after
-    static mut PAGE_SIZE: usize = 0;
-
     #[cfg(any(target_os = "linux", target_os = "android"))]
     unsafe fn siginfo_si_addr(info: *mut libc::siginfo_t) -> usize {
         #[repr(C)]
@@ -102,12 +99,12 @@ unsafe fn siginfo_si_addr(info: *mut libc::siginfo_t) -> usize {
                                     _data: *mut libc::c_void) {
         use sys_common::util::report_overflow;
 
-        let guard = thread_info::stack_guard().unwrap_or(0);
+        let guard = thread_info::stack_guard().unwrap_or(0..0);
         let addr = siginfo_si_addr(info);
 
         // If the faulting address is within the guard page, then we print a
         // message saying so and abort.
-        if guard != 0 && guard - PAGE_SIZE <= addr && addr < guard {
+        if guard.start <= addr && addr < guard.end {
             report_overflow();
             rtabort!("stack overflow");
         } else {
@@ -123,8 +120,6 @@ unsafe fn siginfo_si_addr(info: *mut libc::siginfo_t) -> usize {
     static mut MAIN_ALTSTACK: *mut libc::c_void = ptr::null_mut();
 
     pub unsafe fn init() {
-        PAGE_SIZE = ::sys::os::page_size();
-
         let mut action: sigaction = mem::zeroed();
         action.sa_flags = SA_SIGINFO | SA_ONSTACK;
         action.sa_sigaction = signal_handler as sighandler_t;
index 525882c1e1ebb8134973b2c989474a0242da40e9..72cdb9440b8e7e3bdae6a51ebf554f0268dbdf10 100644 (file)
@@ -205,8 +205,10 @@ fn drop(&mut self) {
           not(target_os = "solaris")))]
 #[cfg_attr(test, allow(dead_code))]
 pub mod guard {
-    pub unsafe fn current() -> Option<usize> { None }
-    pub unsafe fn init() -> Option<usize> { None }
+    use ops::Range;
+    pub type Guard = Range<usize>;
+    pub unsafe fn current() -> Option<Guard> { None }
+    pub unsafe fn init() -> Option<Guard> { None }
 }
 
 
@@ -222,14 +224,43 @@ pub mod guard {
     use libc;
     use libc::mmap;
     use libc::{PROT_NONE, MAP_PRIVATE, MAP_ANON, MAP_FAILED, MAP_FIXED};
+    use ops::Range;
     use sys::os;
 
-    #[cfg(any(target_os = "macos",
-              target_os = "bitrig",
-              target_os = "openbsd",
-              target_os = "solaris"))]
+    // This is initialized in init() and only read from after
+    static mut PAGE_SIZE: usize = 0;
+
+    pub type Guard = Range<usize>;
+
+    #[cfg(target_os = "solaris")]
+    unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
+        let mut current_stack: libc::stack_t = ::mem::zeroed();
+        assert_eq!(libc::stack_getbounds(&mut current_stack), 0);
+        Some(current_stack.ss_sp)
+    }
+
+    #[cfg(target_os = "macos")]
     unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
-        current().map(|s| s as *mut libc::c_void)
+        let stackaddr = libc::pthread_get_stackaddr_np(libc::pthread_self()) as usize -
+             libc::pthread_get_stacksize_np(libc::pthread_self());
+        Some(stackaddr as *mut libc::c_void)
+    }
+
+    #[cfg(any(target_os = "openbsd", target_os = "bitrig"))]
+    unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
+        let mut current_stack: libc::stack_t = ::mem::zeroed();
+        assert_eq!(libc::pthread_stackseg_np(libc::pthread_self(),
+                                             &mut current_stack), 0);
+
+        let extra = if cfg!(target_os = "bitrig") {3} else {1} * PAGE_SIZE;
+        let stackaddr = if libc::pthread_main_np() == 1 {
+            // main thread
+            current_stack.ss_sp as usize - current_stack.ss_size + extra
+        } else {
+            // new thread
+            current_stack.ss_sp as usize - current_stack.ss_size
+        };
+        Some(stackaddr as *mut libc::c_void)
     }
 
     #[cfg(any(target_os = "android", target_os = "freebsd",
@@ -253,8 +284,9 @@ unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
         ret
     }
 
-    pub unsafe fn init() -> Option<usize> {
-        let psize = os::page_size();
+    pub unsafe fn init() -> Option<Guard> {
+        PAGE_SIZE = os::page_size();
+
         let mut stackaddr = get_stack_start()?;
 
         // Ensure stackaddr is page aligned! A parent process might
@@ -263,9 +295,9 @@ pub unsafe fn init() -> Option<usize> {
         // stackaddr < stackaddr + stacksize, so if stackaddr is not
         // page-aligned, calculate the fix such that stackaddr <
         // new_page_aligned_stackaddr < stackaddr + stacksize
-        let remainder = (stackaddr as usize) % psize;
+        let remainder = (stackaddr as usize) % PAGE_SIZE;
         if remainder != 0 {
-            stackaddr = ((stackaddr as usize) + psize - remainder)
+            stackaddr = ((stackaddr as usize) + PAGE_SIZE - remainder)
                 as *mut libc::c_void;
         }
 
@@ -280,60 +312,42 @@ pub unsafe fn init() -> Option<usize> {
             // Instead, we'll just note where we expect rlimit to start
             // faulting, so our handler can report "stack overflow", and
             // trust that the kernel's own stack guard will work.
-            Some(stackaddr as usize)
+            let stackaddr = stackaddr as usize;
+            Some(stackaddr - PAGE_SIZE..stackaddr)
         } else {
             // Reallocate the last page of the stack.
             // This ensures SIGBUS will be raised on
             // stack overflow.
-            let result = mmap(stackaddr, psize, PROT_NONE,
+            let result = mmap(stackaddr, PAGE_SIZE, PROT_NONE,
                               MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
 
             if result != stackaddr || result == MAP_FAILED {
                 panic!("failed to allocate a guard page");
             }
 
+            let guardaddr = stackaddr as usize;
             let offset = if cfg!(target_os = "freebsd") {
                 2
             } else {
                 1
             };
 
-            Some(stackaddr as usize + offset * psize)
+            Some(guardaddr..guardaddr + offset * PAGE_SIZE)
         }
     }
 
-    #[cfg(target_os = "solaris")]
-    pub unsafe fn current() -> Option<usize> {
-        let mut current_stack: libc::stack_t = ::mem::zeroed();
-        assert_eq!(libc::stack_getbounds(&mut current_stack), 0);
-        Some(current_stack.ss_sp as usize)
-    }
-
-    #[cfg(target_os = "macos")]
-    pub unsafe fn current() -> Option<usize> {
-        Some(libc::pthread_get_stackaddr_np(libc::pthread_self()) as usize -
-             libc::pthread_get_stacksize_np(libc::pthread_self()))
-    }
-
-    #[cfg(any(target_os = "openbsd", target_os = "bitrig"))]
-    pub unsafe fn current() -> Option<usize> {
-        let mut current_stack: libc::stack_t = ::mem::zeroed();
-        assert_eq!(libc::pthread_stackseg_np(libc::pthread_self(),
-                                             &mut current_stack), 0);
-
-        let extra = if cfg!(target_os = "bitrig") {3} else {1} * os::page_size();
-        Some(if libc::pthread_main_np() == 1 {
-            // main thread
-            current_stack.ss_sp as usize - current_stack.ss_size + extra
-        } else {
-            // new thread
-            current_stack.ss_sp as usize - current_stack.ss_size
-        })
+    #[cfg(any(target_os = "macos",
+              target_os = "bitrig",
+              target_os = "openbsd",
+              target_os = "solaris"))]
+    pub unsafe fn current() -> Option<Guard> {
+        let stackaddr = get_stack_start()? as usize;
+        Some(stackaddr - PAGE_SIZE..stackaddr)
     }
 
     #[cfg(any(target_os = "android", target_os = "freebsd",
               target_os = "linux", target_os = "netbsd", target_os = "l4re"))]
-    pub unsafe fn current() -> Option<usize> {
+    pub unsafe fn current() -> Option<Guard> {
         let mut ret = None;
         let mut attr: libc::pthread_attr_t = ::mem::zeroed();
         assert_eq!(libc::pthread_attr_init(&mut attr), 0);
@@ -352,12 +366,23 @@ pub unsafe fn current() -> Option<usize> {
             assert_eq!(libc::pthread_attr_getstack(&attr, &mut stackaddr,
                                                    &mut size), 0);
 
+            let stackaddr = stackaddr as usize;
             ret = if cfg!(target_os = "freebsd") {
-                Some(stackaddr as usize - guardsize)
+                // FIXME does freebsd really fault *below* the guard addr?
+                let guardaddr = stackaddr - guardsize;
+                Some(guardaddr - PAGE_SIZE..guardaddr)
             } else if cfg!(target_os = "netbsd") {
-                Some(stackaddr as usize)
+                Some(stackaddr - guardsize..stackaddr)
+            } else if cfg!(all(target_os = "linux", target_env = "gnu")) {
+                // glibc used to include the guard area within the stack, as noted in the BUGS
+                // section of `man pthread_attr_getguardsize`.  This has been corrected starting
+                // with glibc 2.27, and in some distro backports, so the guard is now placed at the
+                // end (below) the stack.  There's no easy way for us to know which we have at
+                // runtime, so we'll just match any fault in the range right above or below the
+                // stack base to call that fault a stack overflow.
+                Some(stackaddr - guardsize..stackaddr + guardsize)
             } else {
-                Some(stackaddr as usize + guardsize)
+                Some(stackaddr..stackaddr + guardsize)
             };
         }
         assert_eq!(libc::pthread_attr_destroy(&mut attr), 0);
index d2a4a7b19d548427711a0068c8ae1214dacf73a3..b3c6b671e809949c9bca2b0d43bdc68999f42a5e 100644 (file)
@@ -10,8 +10,8 @@
 
 use ffi::OsString;
 use marker::PhantomData;
-use mem;
 use vec;
+use sys::ArgsSysCall;
 
 pub unsafe fn init(_argc: isize, _argv: *const *const u8) {
     // On wasm these should always be null, so there's nothing for us to do here
@@ -21,38 +21,10 @@ pub unsafe fn cleanup() {
 }
 
 pub fn args() -> Args {
-    // When the runtime debugging is enabled we'll link to some extra runtime
-    // functions to actually implement this. These are for now just implemented
-    // in a node.js script but they're off by default as they're sort of weird
-    // in a web-wasm world.
-    if !super::DEBUG {
-        return Args {
-            iter: Vec::new().into_iter(),
-            _dont_send_or_sync_me: PhantomData,
-        }
-    }
-
-    // You'll find the definitions of these in `src/etc/wasm32-shim.js`. These
-    // are just meant for debugging and should not be relied on.
-    extern {
-        fn rust_wasm_args_count() -> usize;
-        fn rust_wasm_args_arg_size(a: usize) -> usize;
-        fn rust_wasm_args_arg_fill(a: usize, ptr: *mut u8);
-    }
-
-    unsafe {
-        let cnt = rust_wasm_args_count();
-        let mut v = Vec::with_capacity(cnt);
-        for i in 0..cnt {
-            let n = rust_wasm_args_arg_size(i);
-            let mut data = vec![0; n];
-            rust_wasm_args_arg_fill(i, data.as_mut_ptr());
-            v.push(mem::transmute::<Vec<u8>, OsString>(data));
-        }
-        Args {
-            iter: v.into_iter(),
-            _dont_send_or_sync_me: PhantomData,
-        }
+    let v = ArgsSysCall::perform();
+    Args {
+        iter: v.into_iter(),
+        _dont_send_or_sync_me: PhantomData,
     }
 }
 
index ba3d6a2813a451a28573303ccbd08cfe625584db..c02e5e809c8bb33cb81553eec35607420553fbd4 100644 (file)
 
 use io;
 use os::raw::c_char;
-
-// Right now the wasm backend doesn't even have the ability to print to the
-// console by default. Wasm can't import anything from JS! (you have to
-// explicitly provide it).
-//
-// Sometimes that's a real bummer, though, so this flag can be set to `true` to
-// enable calling various shims defined in `src/etc/wasm32-shim.js` which should
-// help receive debug output and see what's going on. In general this flag
-// currently controls "will we call out to our own defined shims in node.js",
-// and this flag should always be `false` for release builds.
-const DEBUG: bool = false;
+use ptr;
+use sys::os_str::Buf;
+use sys_common::{AsInner, FromInner};
+use ffi::{OsString, OsStr};
+use time::Duration;
 
 pub mod args;
 #[cfg(feature = "backtrace")]
@@ -92,7 +86,7 @@ pub unsafe fn strlen(mut s: *const c_char) -> usize {
 }
 
 pub unsafe fn abort_internal() -> ! {
-    ::intrinsics::abort();
+    ExitSysCall::perform(1)
 }
 
 // We don't have randomness yet, but I totally used a random number generator to
@@ -103,3 +97,218 @@ pub unsafe fn abort_internal() -> ! {
 pub fn hashmap_random_keys() -> (u64, u64) {
     (1, 2)
 }
+
+// Implement a minimal set of system calls to enable basic IO
+pub enum SysCallIndex {
+    Read = 0,
+    Write = 1,
+    Exit = 2,
+    Args = 3,
+    GetEnv = 4,
+    SetEnv = 5,
+    Time = 6,
+}
+
+#[repr(C)]
+pub struct ReadSysCall {
+    fd: usize,
+    ptr: *mut u8,
+    len: usize,
+    result: usize,
+}
+
+impl ReadSysCall {
+    pub fn perform(fd: usize, buffer: &mut [u8]) -> usize {
+        let mut call_record = ReadSysCall {
+            fd,
+            len: buffer.len(),
+            ptr: buffer.as_mut_ptr(),
+            result: 0
+        };
+        if unsafe { syscall(SysCallIndex::Read, &mut call_record) } {
+            call_record.result
+        } else {
+            0
+        }
+    }
+}
+
+#[repr(C)]
+pub struct WriteSysCall {
+    fd: usize,
+    ptr: *const u8,
+    len: usize,
+}
+
+impl WriteSysCall {
+    pub fn perform(fd: usize, buffer: &[u8]) {
+        let mut call_record = WriteSysCall {
+            fd,
+            len: buffer.len(),
+            ptr: buffer.as_ptr()
+        };
+        unsafe { syscall(SysCallIndex::Write, &mut call_record); }
+    }
+}
+
+#[repr(C)]
+pub struct ExitSysCall {
+    code: usize,
+}
+
+impl ExitSysCall {
+    pub fn perform(code: usize) -> ! {
+        let mut call_record = ExitSysCall {
+            code
+        };
+        unsafe {
+            syscall(SysCallIndex::Exit, &mut call_record);
+            ::intrinsics::abort();
+        }
+    }
+}
+
+fn receive_buffer<E, F: FnMut(&mut [u8]) -> Result<usize, E>>(estimate: usize, mut f: F)
+    -> Result<Vec<u8>, E>
+{
+    let mut buffer = vec![0; estimate];
+    loop {
+        let result = f(&mut buffer)?;
+        if result <= buffer.len() {
+            buffer.truncate(result);
+            break;
+        }
+        buffer.resize(result, 0);
+    }
+    Ok(buffer)
+}
+
+#[repr(C)]
+pub struct ArgsSysCall {
+    ptr: *mut u8,
+    len: usize,
+    result: usize
+}
+
+impl ArgsSysCall {
+    pub fn perform() -> Vec<OsString> {
+        receive_buffer(1024, |buffer| -> Result<usize, !> {
+            let mut call_record = ArgsSysCall {
+                len: buffer.len(),
+                ptr: buffer.as_mut_ptr(),
+                result: 0
+            };
+            if unsafe { syscall(SysCallIndex::Args, &mut call_record) } {
+                Ok(call_record.result)
+            } else {
+                Ok(0)
+            }
+        })
+            .unwrap()
+            .split(|b| *b == 0)
+            .map(|s| FromInner::from_inner(Buf { inner: s.to_owned() }))
+            .collect()
+    }
+}
+
+#[repr(C)]
+pub struct GetEnvSysCall {
+    key_ptr: *const u8,
+    key_len: usize,
+    value_ptr: *mut u8,
+    value_len: usize,
+    result: usize
+}
+
+impl GetEnvSysCall {
+    pub fn perform(key: &OsStr) -> Option<OsString> {
+        let key_buf = &AsInner::as_inner(key).inner;
+        receive_buffer(64, |buffer| {
+            let mut call_record = GetEnvSysCall {
+                key_len: key_buf.len(),
+                key_ptr: key_buf.as_ptr(),
+                value_len: buffer.len(),
+                value_ptr: buffer.as_mut_ptr(),
+                result: !0usize
+            };
+            if unsafe { syscall(SysCallIndex::GetEnv, &mut call_record) } {
+                if call_record.result == !0usize {
+                    Err(())
+                } else {
+                    Ok(call_record.result)
+                }
+            } else {
+                Err(())
+            }
+        }).ok().map(|s| {
+            FromInner::from_inner(Buf { inner: s })
+        })
+    }
+}
+
+#[repr(C)]
+pub struct SetEnvSysCall {
+    key_ptr: *const u8,
+    key_len: usize,
+    value_ptr: *const u8,
+    value_len: usize
+}
+
+impl SetEnvSysCall {
+    pub fn perform(key: &OsStr, value: Option<&OsStr>) {
+        let key_buf = &AsInner::as_inner(key).inner;
+        let value_buf = value.map(|v| &AsInner::as_inner(v).inner);
+        let mut call_record = SetEnvSysCall {
+            key_len: key_buf.len(),
+            key_ptr: key_buf.as_ptr(),
+            value_len: value_buf.map(|v| v.len()).unwrap_or(!0usize),
+            value_ptr: value_buf.map(|v| v.as_ptr()).unwrap_or(ptr::null())
+        };
+        unsafe { syscall(SysCallIndex::SetEnv, &mut call_record); }
+    }
+}
+
+pub enum TimeClock {
+    Monotonic = 0,
+    System = 1,
+}
+
+#[repr(C)]
+pub struct TimeSysCall {
+    clock: usize,
+    secs_hi: usize,
+    secs_lo: usize,
+    nanos: usize
+}
+
+impl TimeSysCall {
+    pub fn perform(clock: TimeClock) -> Duration {
+        let mut call_record = TimeSysCall {
+            clock: clock as usize,
+            secs_hi: 0,
+            secs_lo: 0,
+            nanos: 0
+        };
+        if unsafe { syscall(SysCallIndex::Time, &mut call_record) } {
+            Duration::new(
+                ((call_record.secs_hi as u64) << 32) | (call_record.secs_lo as u64),
+                call_record.nanos as u32
+            )
+        } else {
+            panic!("Time system call is not implemented by WebAssembly host");
+        }
+    }
+}
+
+unsafe fn syscall<T>(index: SysCallIndex, data: &mut T) -> bool {
+    #[cfg(feature = "wasm_syscall")]
+    extern {
+        #[no_mangle]
+        fn rust_wasm_syscall(index: usize, data: *mut Void) -> usize;
+    }
+
+    #[cfg(not(feature = "wasm_syscall"))]
+    unsafe fn rust_wasm_syscall(_index: usize, _data: *mut Void) -> usize { 0 }
+
+    rust_wasm_syscall(index as usize, data as *mut T as *mut Void) != 0
+}
index c98030f7ebf532f7bd843f981d6ea48dacfbba90..23ca1754719be9905fcdb27e102710ca83277ccd 100644 (file)
@@ -8,16 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use core::intrinsics;
-
 use error::Error as StdError;
 use ffi::{OsString, OsStr};
 use fmt;
 use io;
-use mem;
 use path::{self, PathBuf};
 use str;
-use sys::{unsupported, Void};
+use sys::{unsupported, Void, ExitSysCall, GetEnvSysCall, SetEnvSysCall};
 
 pub fn errno() -> i32 {
     0
@@ -87,36 +84,15 @@ pub fn env() -> Env {
 }
 
 pub fn getenv(k: &OsStr) -> io::Result<Option<OsString>> {
-    // If we're debugging the runtime then we actually probe node.js to ask for
-    // the value of environment variables to help provide inputs to programs.
-    // The `extern` shims here are defined in `src/etc/wasm32-shim.js` and are
-    // intended for debugging only, you should not rely on them.
-    if !super::DEBUG {
-        return Ok(None)
-    }
-
-    extern {
-        fn rust_wasm_getenv_len(k: *const u8, kl: usize) -> isize;
-        fn rust_wasm_getenv_data(k: *const u8, kl: usize, v: *mut u8);
-    }
-    unsafe {
-        let k: &[u8] = mem::transmute(k);
-        let n = rust_wasm_getenv_len(k.as_ptr(), k.len());
-        if n == -1 {
-            return Ok(None)
-        }
-        let mut data = vec![0; n as usize];
-        rust_wasm_getenv_data(k.as_ptr(), k.len(), data.as_mut_ptr());
-        Ok(Some(mem::transmute(data)))
-    }
+    Ok(GetEnvSysCall::perform(k))
 }
 
-pub fn setenv(_k: &OsStr, _v: &OsStr) -> io::Result<()> {
-    unsupported()
+pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
+    Ok(SetEnvSysCall::perform(k, Some(v)))
 }
 
-pub fn unsetenv(_n: &OsStr) -> io::Result<()> {
-    unsupported()
+pub fn unsetenv(k: &OsStr) -> io::Result<()> {
+    Ok(SetEnvSysCall::perform(k, None))
 }
 
 pub fn temp_dir() -> PathBuf {
@@ -128,7 +104,7 @@ pub fn home_dir() -> Option<PathBuf> {
 }
 
 pub fn exit(_code: i32) -> ! {
-    unsafe { intrinsics::abort() }
+    ExitSysCall::perform(_code as isize as usize)
 }
 
 pub fn getpid() -> u32 {
index 0f75f240251832e5587aac6334afcf6db590916b..beb19c0ed2c1f62bd17b1611db911eb9a04eb7af 100644 (file)
@@ -9,19 +9,19 @@
 // except according to those terms.
 
 use io;
-use sys::{Void, unsupported};
+use sys::{ReadSysCall, WriteSysCall};
 
-pub struct Stdin(Void);
+pub struct Stdin;
 pub struct Stdout;
 pub struct Stderr;
 
 impl Stdin {
     pub fn new() -> io::Result<Stdin> {
-        unsupported()
+        Ok(Stdin)
     }
 
-    pub fn read(&self, _data: &mut [u8]) -> io::Result<usize> {
-        match self.0 {}
+    pub fn read(&self, data: &mut [u8]) -> io::Result<usize> {
+        Ok(ReadSysCall::perform(0, data))
     }
 }
 
@@ -31,19 +31,7 @@ pub fn new() -> io::Result<Stdout> {
     }
 
     pub fn write(&self, data: &[u8]) -> io::Result<usize> {
-        // If runtime debugging is enabled at compile time we'll invoke some
-        // runtime functions that are defined in our src/etc/wasm32-shim.js
-        // debugging script. Note that this ffi function call is intended
-        // *purely* for debugging only and should not be relied upon.
-        if !super::DEBUG {
-            return unsupported()
-        }
-        extern {
-            fn rust_wasm_write_stdout(data: *const u8, len: usize);
-        }
-        unsafe {
-            rust_wasm_write_stdout(data.as_ptr(), data.len())
-        }
+        WriteSysCall::perform(1, data);
         Ok(data.len())
     }
 
@@ -58,16 +46,7 @@ pub fn new() -> io::Result<Stderr> {
     }
 
     pub fn write(&self, data: &[u8]) -> io::Result<usize> {
-        // See comments in stdout for what's going on here.
-        if !super::DEBUG {
-            return unsupported()
-        }
-        extern {
-            fn rust_wasm_write_stderr(data: *const u8, len: usize);
-        }
-        unsafe {
-            rust_wasm_write_stderr(data.as_ptr(), data.len())
-        }
+        WriteSysCall::perform(2, data);
         Ok(data.len())
     }
 
index 13980e0cc19d1bae2fc8a161467283ec01c3c41e..6a066509b492a6c1adac441367f233e1ed7c2726 100644 (file)
@@ -43,6 +43,7 @@ pub fn join(self) {
 }
 
 pub mod guard {
-    pub unsafe fn current() -> Option<usize> { None }
-    pub unsafe fn init() -> Option<usize> { None }
+    pub type Guard = !;
+    pub unsafe fn current() -> Option<Guard> { None }
+    pub unsafe fn init() -> Option<Guard> { None }
 }
index c269def98f6ffdae4f226414e678871adc3e6df7..e52435e63398f226e6cb735a431012f7eb0b3350 100644 (file)
@@ -8,56 +8,50 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use fmt;
 use time::Duration;
+use sys::{TimeSysCall, TimeClock};
 
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
-pub struct Instant;
+pub struct Instant(Duration);
 
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub struct SystemTime;
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
+pub struct SystemTime(Duration);
 
-pub const UNIX_EPOCH: SystemTime = SystemTime;
+pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::from_secs(0));
 
 impl Instant {
     pub fn now() -> Instant {
-        panic!("not supported on web assembly");
+        Instant(TimeSysCall::perform(TimeClock::Monotonic))
     }
 
-    pub fn sub_instant(&self, _other: &Instant) -> Duration {
-        panic!("can't sub yet");
+    pub fn sub_instant(&self, other: &Instant) -> Duration {
+        self.0 - other.0
     }
 
-    pub fn add_duration(&self, _other: &Duration) -> Instant {
-        panic!("can't add yet");
+    pub fn add_duration(&self, other: &Duration) -> Instant {
+        Instant(self.0 + *other)
     }
 
-    pub fn sub_duration(&self, _other: &Duration) -> Instant {
-        panic!("can't sub yet");
+    pub fn sub_duration(&self, other: &Duration) -> Instant {
+        Instant(self.0 - *other)
     }
 }
 
 impl SystemTime {
     pub fn now() -> SystemTime {
-        panic!("not supported on web assembly");
+        SystemTime(TimeSysCall::perform(TimeClock::System))
     }
 
-    pub fn sub_time(&self, _other: &SystemTime)
+    pub fn sub_time(&self, other: &SystemTime)
                     -> Result<Duration, Duration> {
-        panic!()
-    }
-
-    pub fn add_duration(&self, _other: &Duration) -> SystemTime {
-        panic!()
+        self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0)
     }
 
-    pub fn sub_duration(&self, _other: &Duration) -> SystemTime {
-        panic!()
+    pub fn add_duration(&self, other: &Duration) -> SystemTime {
+        SystemTime(self.0 + *other)
     }
-}
 
-impl fmt::Debug for SystemTime {
-    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
-        panic!()
+    pub fn sub_duration(&self, other: &Duration) -> SystemTime {
+        SystemTime(self.0 - *other)
     }
 }
index 74786d092855f091d8b51e9d837d2040d72d1a29..43abfbb1f645e9852974df82d7a26f2dc706787d 100644 (file)
@@ -93,6 +93,7 @@ pub fn into_handle(self) -> Handle { self.handle }
 
 #[cfg_attr(test, allow(dead_code))]
 pub mod guard {
-    pub unsafe fn current() -> Option<usize> { None }
-    pub unsafe fn init() -> Option<usize> { None }
+    pub type Guard = !;
+    pub unsafe fn current() -> Option<Guard> { None }
+    pub unsafe fn init() -> Option<Guard> { None }
 }
index 7970042b1d67ded6faaccfdebb8e4bc762bfba0e..6a2b6742367a5b4ce6032cfe943b9708fb9b9da9 100644 (file)
 #![allow(dead_code)] // stack_guard isn't used right now on all platforms
 
 use cell::RefCell;
+use sys::thread::guard::Guard;
 use thread::Thread;
 
 struct ThreadInfo {
-    stack_guard: Option<usize>,
+    stack_guard: Option<Guard>,
     thread: Thread,
 }
 
@@ -38,11 +39,11 @@ pub fn current_thread() -> Option<Thread> {
     ThreadInfo::with(|info| info.thread.clone())
 }
 
-pub fn stack_guard() -> Option<usize> {
-    ThreadInfo::with(|info| info.stack_guard).and_then(|o| o)
+pub fn stack_guard() -> Option<Guard> {
+    ThreadInfo::with(|info| info.stack_guard.clone()).and_then(|o| o)
 }
 
-pub fn set(stack_guard: Option<usize>, thread: Thread) {
+pub fn set(stack_guard: Option<Guard>, thread: Thread) {
     THREAD_INFO.with(|c| assert!(c.borrow().is_none()));
     THREAD_INFO.with(move |c| *c.borrow_mut() = Some(ThreadInfo{
         stack_guard,
diff --git a/src/libstd/time.rs b/src/libstd/time.rs
new file mode 100644 (file)
index 0000000..12f2a9b
--- /dev/null
@@ -0,0 +1,565 @@
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Temporal quantification.
+//!
+//! Example:
+//!
+//! ```
+//! use std::time::Duration;
+//!
+//! let five_seconds = Duration::new(5, 0);
+//! // both declarations are equivalent
+//! assert_eq!(Duration::new(5, 0), Duration::from_secs(5));
+//! ```
+
+#![stable(feature = "time", since = "1.3.0")]
+
+use error::Error;
+use fmt;
+use ops::{Add, Sub, AddAssign, SubAssign};
+use sys::time;
+use sys_common::FromInner;
+
+#[stable(feature = "time", since = "1.3.0")]
+pub use core::time::Duration;
+
+/// A measurement of a monotonically nondecreasing clock.
+/// Opaque and useful only with `Duration`.
+///
+/// Instants are always guaranteed to be no less than any previously measured
+/// instant when created, and are often useful for tasks such as measuring
+/// benchmarks or timing how long an operation takes.
+///
+/// Note, however, that instants are not guaranteed to be **steady**.  In other
+/// words, each tick of the underlying clock may not be the same length (e.g.
+/// some seconds may be longer than others). An instant may jump forwards or
+/// experience time dilation (slow down or speed up), but it will never go
+/// backwards.
+///
+/// Instants are opaque types that can only be compared to one another. There is
+/// no method to get "the number of seconds" from an instant. Instead, it only
+/// allows measuring the duration between two instants (or comparing two
+/// instants).
+///
+/// Example:
+///
+/// ```no_run
+/// use std::time::{Duration, Instant};
+/// use std::thread::sleep;
+///
+/// fn main() {
+///    let now = Instant::now();
+///
+///    // we sleep for 2 seconds
+///    sleep(Duration::new(2, 0));
+///    // it prints '2'
+///    println!("{}", now.elapsed().as_secs());
+/// }
+/// ```
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[stable(feature = "time2", since = "1.8.0")]
+pub struct Instant(time::Instant);
+
+/// A measurement of the system clock, useful for talking to
+/// external entities like the file system or other processes.
+///
+/// Distinct from the [`Instant`] type, this time measurement **is not
+/// monotonic**. This means that you can save a file to the file system, then
+/// save another file to the file system, **and the second file has a
+/// `SystemTime` measurement earlier than the first**. In other words, an
+/// operation that happens after another operation in real time may have an
+/// earlier `SystemTime`!
+///
+/// Consequently, comparing two `SystemTime` instances to learn about the
+/// duration between them returns a [`Result`] instead of an infallible [`Duration`]
+/// to indicate that this sort of time drift may happen and needs to be handled.
+///
+/// Although a `SystemTime` cannot be directly inspected, the [`UNIX_EPOCH`]
+/// constant is provided in this module as an anchor in time to learn
+/// information about a `SystemTime`. By calculating the duration from this
+/// fixed point in time, a `SystemTime` can be converted to a human-readable time,
+/// or perhaps some other string representation.
+///
+/// [`Instant`]: ../../std/time/struct.Instant.html
+/// [`Result`]: ../../std/result/enum.Result.html
+/// [`Duration`]: ../../std/time/struct.Duration.html
+/// [`UNIX_EPOCH`]: ../../std/time/constant.UNIX_EPOCH.html
+///
+/// Example:
+///
+/// ```no_run
+/// use std::time::{Duration, SystemTime};
+/// use std::thread::sleep;
+///
+/// fn main() {
+///    let now = SystemTime::now();
+///
+///    // we sleep for 2 seconds
+///    sleep(Duration::new(2, 0));
+///    match now.elapsed() {
+///        Ok(elapsed) => {
+///            // it prints '2'
+///            println!("{}", elapsed.as_secs());
+///        }
+///        Err(e) => {
+///            // an error occurred!
+///            println!("Error: {:?}", e);
+///        }
+///    }
+/// }
+/// ```
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[stable(feature = "time2", since = "1.8.0")]
+pub struct SystemTime(time::SystemTime);
+
+/// An error returned from the `duration_since` and `elapsed` methods on
+/// `SystemTime`, used to learn how far in the opposite direction a system time
+/// lies.
+///
+/// # Examples
+///
+/// ```no_run
+/// use std::thread::sleep;
+/// use std::time::{Duration, SystemTime};
+///
+/// let sys_time = SystemTime::now();
+/// sleep(Duration::from_secs(1));
+/// let new_sys_time = SystemTime::now();
+/// match sys_time.duration_since(new_sys_time) {
+///     Ok(_) => {}
+///     Err(e) => println!("SystemTimeError difference: {:?}", e.duration()),
+/// }
+/// ```
+#[derive(Clone, Debug)]
+#[stable(feature = "time2", since = "1.8.0")]
+pub struct SystemTimeError(Duration);
+
+impl Instant {
+    /// Returns an instant corresponding to "now".
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::time::Instant;
+    ///
+    /// let now = Instant::now();
+    /// ```
+    #[stable(feature = "time2", since = "1.8.0")]
+    pub fn now() -> Instant {
+        Instant(time::Instant::now())
+    }
+
+    /// Returns the amount of time elapsed from another instant to this one.
+    ///
+    /// # Panics
+    ///
+    /// This function will panic if `earlier` is later than `self`.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::time::{Duration, Instant};
+    /// use std::thread::sleep;
+    ///
+    /// let now = Instant::now();
+    /// sleep(Duration::new(1, 0));
+    /// let new_now = Instant::now();
+    /// println!("{:?}", new_now.duration_since(now));
+    /// ```
+    #[stable(feature = "time2", since = "1.8.0")]
+    pub fn duration_since(&self, earlier: Instant) -> Duration {
+        self.0.sub_instant(&earlier.0)
+    }
+
+    /// Returns the amount of time elapsed since this instant was created.
+    ///
+    /// # Panics
+    ///
+    /// This function may panic if the current time is earlier than this
+    /// instant, which is something that can happen if an `Instant` is
+    /// produced synthetically.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::thread::sleep;
+    /// use std::time::{Duration, Instant};
+    ///
+    /// let instant = Instant::now();
+    /// let three_secs = Duration::from_secs(3);
+    /// sleep(three_secs);
+    /// assert!(instant.elapsed() >= three_secs);
+    /// ```
+    #[stable(feature = "time2", since = "1.8.0")]
+    pub fn elapsed(&self) -> Duration {
+        Instant::now() - *self
+    }
+}
+
+#[stable(feature = "time2", since = "1.8.0")]
+impl Add<Duration> for Instant {
+    type Output = Instant;
+
+    fn add(self, other: Duration) -> Instant {
+        Instant(self.0.add_duration(&other))
+    }
+}
+
+#[stable(feature = "time_augmented_assignment", since = "1.9.0")]
+impl AddAssign<Duration> for Instant {
+    fn add_assign(&mut self, other: Duration) {
+        *self = *self + other;
+    }
+}
+
+#[stable(feature = "time2", since = "1.8.0")]
+impl Sub<Duration> for Instant {
+    type Output = Instant;
+
+    fn sub(self, other: Duration) -> Instant {
+        Instant(self.0.sub_duration(&other))
+    }
+}
+
+#[stable(feature = "time_augmented_assignment", since = "1.9.0")]
+impl SubAssign<Duration> for Instant {
+    fn sub_assign(&mut self, other: Duration) {
+        *self = *self - other;
+    }
+}
+
+#[stable(feature = "time2", since = "1.8.0")]
+impl Sub<Instant> for Instant {
+    type Output = Duration;
+
+    fn sub(self, other: Instant) -> Duration {
+        self.duration_since(other)
+    }
+}
+
+#[stable(feature = "time2", since = "1.8.0")]
+impl fmt::Debug for Instant {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.0.fmt(f)
+    }
+}
+
+impl SystemTime {
+    /// Returns the system time corresponding to "now".
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::time::SystemTime;
+    ///
+    /// let sys_time = SystemTime::now();
+    /// ```
+    #[stable(feature = "time2", since = "1.8.0")]
+    pub fn now() -> SystemTime {
+        SystemTime(time::SystemTime::now())
+    }
+
+    /// Returns the amount of time elapsed from an earlier point in time.
+    ///
+    /// This function may fail because measurements taken earlier are not
+    /// guaranteed to always be before later measurements (due to anomalies such
+    /// as the system clock being adjusted either forwards or backwards).
+    ///
+    /// If successful, [`Ok`]`(`[`Duration`]`)` is returned where the duration represents
+    /// the amount of time elapsed from the specified measurement to this one.
+    ///
+    /// Returns an [`Err`] if `earlier` is later than `self`, and the error
+    /// contains how far from `self` the time is.
+    ///
+    /// [`Ok`]: ../../std/result/enum.Result.html#variant.Ok
+    /// [`Duration`]: ../../std/time/struct.Duration.html
+    /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::time::SystemTime;
+    ///
+    /// let sys_time = SystemTime::now();
+    /// let difference = sys_time.duration_since(sys_time)
+    ///                          .expect("SystemTime::duration_since failed");
+    /// println!("{:?}", difference);
+    /// ```
+    #[stable(feature = "time2", since = "1.8.0")]
+    pub fn duration_since(&self, earlier: SystemTime)
+                          -> Result<Duration, SystemTimeError> {
+        self.0.sub_time(&earlier.0).map_err(SystemTimeError)
+    }
+
+    /// Returns the amount of time elapsed since this system time was created.
+    ///
+    /// This function may fail as the underlying system clock is susceptible to
+    /// drift and updates (e.g. the system clock could go backwards), so this
+    /// function may not always succeed. If successful, [`Ok`]`(`[`Duration`]`)` is
+    /// returned where the duration represents the amount of time elapsed from
+    /// this time measurement to the current time.
+    ///
+    /// Returns an [`Err`] if `self` is later than the current system time, and
+    /// the error contains how far from the current system time `self` is.
+    ///
+    /// [`Ok`]: ../../std/result/enum.Result.html#variant.Ok
+    /// [`Duration`]: ../../std/time/struct.Duration.html
+    /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::thread::sleep;
+    /// use std::time::{Duration, SystemTime};
+    ///
+    /// let sys_time = SystemTime::now();
+    /// let one_sec = Duration::from_secs(1);
+    /// sleep(one_sec);
+    /// assert!(sys_time.elapsed().unwrap() >= one_sec);
+    /// ```
+    #[stable(feature = "time2", since = "1.8.0")]
+    pub fn elapsed(&self) -> Result<Duration, SystemTimeError> {
+        SystemTime::now().duration_since(*self)
+    }
+}
+
+#[stable(feature = "time2", since = "1.8.0")]
+impl Add<Duration> for SystemTime {
+    type Output = SystemTime;
+
+    fn add(self, dur: Duration) -> SystemTime {
+        SystemTime(self.0.add_duration(&dur))
+    }
+}
+
+#[stable(feature = "time_augmented_assignment", since = "1.9.0")]
+impl AddAssign<Duration> for SystemTime {
+    fn add_assign(&mut self, other: Duration) {
+        *self = *self + other;
+    }
+}
+
+#[stable(feature = "time2", since = "1.8.0")]
+impl Sub<Duration> for SystemTime {
+    type Output = SystemTime;
+
+    fn sub(self, dur: Duration) -> SystemTime {
+        SystemTime(self.0.sub_duration(&dur))
+    }
+}
+
+#[stable(feature = "time_augmented_assignment", since = "1.9.0")]
+impl SubAssign<Duration> for SystemTime {
+    fn sub_assign(&mut self, other: Duration) {
+        *self = *self - other;
+    }
+}
+
+#[stable(feature = "time2", since = "1.8.0")]
+impl fmt::Debug for SystemTime {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        self.0.fmt(f)
+    }
+}
+
+/// An anchor in time which can be used to create new `SystemTime` instances or
+/// learn about where in time a `SystemTime` lies.
+///
+/// This constant is defined to be "1970-01-01 00:00:00 UTC" on all systems with
+/// respect to the system clock. Using `duration_since` on an existing
+/// [`SystemTime`] instance can tell how far away from this point in time a
+/// measurement lies, and using `UNIX_EPOCH + duration` can be used to create a
+/// [`SystemTime`] instance to represent another fixed point in time.
+///
+/// [`SystemTime`]: ../../std/time/struct.SystemTime.html
+///
+/// # Examples
+///
+/// ```no_run
+/// use std::time::{SystemTime, UNIX_EPOCH};
+///
+/// match SystemTime::now().duration_since(UNIX_EPOCH) {
+///     Ok(n) => println!("1970-01-01 00:00:00 UTC was {} seconds ago!", n.as_secs()),
+///     Err(_) => panic!("SystemTime before UNIX EPOCH!"),
+/// }
+/// ```
+#[stable(feature = "time2", since = "1.8.0")]
+pub const UNIX_EPOCH: SystemTime = SystemTime(time::UNIX_EPOCH);
+
+impl SystemTimeError {
+    /// Returns the positive duration which represents how far forward the
+    /// second system time was from the first.
+    ///
+    /// A `SystemTimeError` is returned from the [`duration_since`] and [`elapsed`]
+    /// methods of [`SystemTime`] whenever the second system time represents a point later
+    /// in time than the `self` of the method call.
+    ///
+    /// [`duration_since`]: ../../std/time/struct.SystemTime.html#method.duration_since
+    /// [`elapsed`]: ../../std/time/struct.SystemTime.html#method.elapsed
+    /// [`SystemTime`]: ../../std/time/struct.SystemTime.html
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::thread::sleep;
+    /// use std::time::{Duration, SystemTime};
+    ///
+    /// let sys_time = SystemTime::now();
+    /// sleep(Duration::from_secs(1));
+    /// let new_sys_time = SystemTime::now();
+    /// match sys_time.duration_since(new_sys_time) {
+    ///     Ok(_) => {}
+    ///     Err(e) => println!("SystemTimeError difference: {:?}", e.duration()),
+    /// }
+    /// ```
+    #[stable(feature = "time2", since = "1.8.0")]
+    pub fn duration(&self) -> Duration {
+        self.0
+    }
+}
+
+#[stable(feature = "time2", since = "1.8.0")]
+impl Error for SystemTimeError {
+    fn description(&self) -> &str { "other time was not earlier than self" }
+}
+
+#[stable(feature = "time2", since = "1.8.0")]
+impl fmt::Display for SystemTimeError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "second time provided was later than self")
+    }
+}
+
+impl FromInner<time::SystemTime> for SystemTime {
+    fn from_inner(time: time::SystemTime) -> SystemTime {
+        SystemTime(time)
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::{Instant, SystemTime, Duration, UNIX_EPOCH};
+
+    macro_rules! assert_almost_eq {
+        ($a:expr, $b:expr) => ({
+            let (a, b) = ($a, $b);
+            if a != b {
+                let (a, b) = if a > b {(a, b)} else {(b, a)};
+                assert!(a - Duration::new(0, 100) <= b);
+            }
+        })
+    }
+
+    #[test]
+    fn instant_monotonic() {
+        let a = Instant::now();
+        let b = Instant::now();
+        assert!(b >= a);
+    }
+
+    #[test]
+    fn instant_elapsed() {
+        let a = Instant::now();
+        a.elapsed();
+    }
+
+    #[test]
+    fn instant_math() {
+        let a = Instant::now();
+        let b = Instant::now();
+        let dur = b.duration_since(a);
+        assert_almost_eq!(b - dur, a);
+        assert_almost_eq!(a + dur, b);
+
+        let second = Duration::new(1, 0);
+        assert_almost_eq!(a - second + second, a);
+    }
+
+    #[test]
+    #[should_panic]
+    fn instant_duration_panic() {
+        let a = Instant::now();
+        (a - Duration::new(1, 0)).duration_since(a);
+    }
+
+    #[test]
+    fn system_time_math() {
+        let a = SystemTime::now();
+        let b = SystemTime::now();
+        match b.duration_since(a) {
+            Ok(dur) if dur == Duration::new(0, 0) => {
+                assert_almost_eq!(a, b);
+            }
+            Ok(dur) => {
+                assert!(b > a);
+                assert_almost_eq!(b - dur, a);
+                assert_almost_eq!(a + dur, b);
+            }
+            Err(dur) => {
+                let dur = dur.duration();
+                assert!(a > b);
+                assert_almost_eq!(b + dur, a);
+                assert_almost_eq!(a - dur, b);
+            }
+        }
+
+        let second = Duration::new(1, 0);
+        assert_almost_eq!(a.duration_since(a - second).unwrap(), second);
+        assert_almost_eq!(a.duration_since(a + second).unwrap_err()
+                           .duration(), second);
+
+        assert_almost_eq!(a - second + second, a);
+
+        // A difference of 80 and 800 years cannot fit inside a 32-bit time_t
+        if !(cfg!(unix) && ::mem::size_of::<::libc::time_t>() <= 4) {
+            let eighty_years = second * 60 * 60 * 24 * 365 * 80;
+            assert_almost_eq!(a - eighty_years + eighty_years, a);
+            assert_almost_eq!(a - (eighty_years * 10) + (eighty_years * 10), a);
+        }
+
+        let one_second_from_epoch = UNIX_EPOCH + Duration::new(1, 0);
+        let one_second_from_epoch2 = UNIX_EPOCH + Duration::new(0, 500_000_000)
+            + Duration::new(0, 500_000_000);
+        assert_eq!(one_second_from_epoch, one_second_from_epoch2);
+    }
+
+    #[test]
+    fn system_time_elapsed() {
+        let a = SystemTime::now();
+        drop(a.elapsed());
+    }
+
+    #[test]
+    fn since_epoch() {
+        let ts = SystemTime::now();
+        let a = ts.duration_since(UNIX_EPOCH).unwrap();
+        let b = ts.duration_since(UNIX_EPOCH - Duration::new(1, 0)).unwrap();
+        assert!(b > a);
+        assert_eq!(b - a, Duration::new(1, 0));
+
+        let thirty_years = Duration::new(1, 0) * 60 * 60 * 24 * 365 * 30;
+
+        // Right now for CI this test is run in an emulator, and apparently the
+        // aarch64 emulator's sense of time is that we're still living in the
+        // 70s.
+        //
+        // Otherwise let's assume that we're all running computers later than
+        // 2000.
+        if !cfg!(target_arch = "aarch64") {
+            assert!(a > thirty_years);
+        }
+
+        // let's assume that we're all running computers earlier than 2090.
+        // Should give us ~70 years to fix this!
+        let hundred_twenty_years = thirty_years * 4;
+        assert!(a < hundred_twenty_years);
+    }
+}
diff --git a/src/libstd/time/duration.rs b/src/libstd/time/duration.rs
deleted file mode 100644 (file)
index ee44483..0000000
+++ /dev/null
@@ -1,590 +0,0 @@
-// Copyright 2012-2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use iter::Sum;
-use ops::{Add, Sub, Mul, Div, AddAssign, SubAssign, MulAssign, DivAssign};
-
-const NANOS_PER_SEC: u32 = 1_000_000_000;
-const NANOS_PER_MILLI: u32 = 1_000_000;
-const NANOS_PER_MICRO: u32 = 1_000;
-const MILLIS_PER_SEC: u64 = 1_000;
-const MICROS_PER_SEC: u64 = 1_000_000;
-
-/// A `Duration` type to represent a span of time, typically used for system
-/// timeouts.
-///
-/// Each `Duration` is composed of a whole number of seconds and a fractional part
-/// represented in nanoseconds.  If the underlying system does not support
-/// nanosecond-level precision, APIs binding a system timeout will typically round up
-/// the number of nanoseconds.
-///
-/// `Duration`s implement many common traits, including [`Add`], [`Sub`], and other
-/// [`ops`] traits.
-///
-/// [`Add`]: ../../std/ops/trait.Add.html
-/// [`Sub`]: ../../std/ops/trait.Sub.html
-/// [`ops`]: ../../std/ops/index.html
-///
-/// # Examples
-///
-/// ```
-/// use std::time::Duration;
-///
-/// let five_seconds = Duration::new(5, 0);
-/// let five_seconds_and_five_nanos = five_seconds + Duration::new(0, 5);
-///
-/// assert_eq!(five_seconds_and_five_nanos.as_secs(), 5);
-/// assert_eq!(five_seconds_and_five_nanos.subsec_nanos(), 5);
-///
-/// let ten_millis = Duration::from_millis(10);
-/// ```
-#[stable(feature = "duration", since = "1.3.0")]
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash, Default)]
-pub struct Duration {
-    secs: u64,
-    nanos: u32, // Always 0 <= nanos < NANOS_PER_SEC
-}
-
-impl Duration {
-    /// Creates a new `Duration` from the specified number of whole seconds and
-    /// additional nanoseconds.
-    ///
-    /// If the number of nanoseconds is greater than 1 billion (the number of
-    /// nanoseconds in a second), then it will carry over into the seconds provided.
-    ///
-    /// # Panics
-    ///
-    /// This constructor will panic if the carry from the nanoseconds overflows
-    /// the seconds counter.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::time::Duration;
-    ///
-    /// let five_seconds = Duration::new(5, 0);
-    /// ```
-    #[stable(feature = "duration", since = "1.3.0")]
-    #[inline]
-    pub fn new(secs: u64, nanos: u32) -> Duration {
-        let secs = secs.checked_add((nanos / NANOS_PER_SEC) as u64)
-            .expect("overflow in Duration::new");
-        let nanos = nanos % NANOS_PER_SEC;
-        Duration { secs: secs, nanos: nanos }
-    }
-
-    /// Creates a new `Duration` from the specified number of whole seconds.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::time::Duration;
-    ///
-    /// let duration = Duration::from_secs(5);
-    ///
-    /// assert_eq!(5, duration.as_secs());
-    /// assert_eq!(0, duration.subsec_nanos());
-    /// ```
-    #[stable(feature = "duration", since = "1.3.0")]
-    #[inline]
-    pub const fn from_secs(secs: u64) -> Duration {
-        Duration { secs: secs, nanos: 0 }
-    }
-
-    /// Creates a new `Duration` from the specified number of milliseconds.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::time::Duration;
-    ///
-    /// let duration = Duration::from_millis(2569);
-    ///
-    /// assert_eq!(2, duration.as_secs());
-    /// assert_eq!(569_000_000, duration.subsec_nanos());
-    /// ```
-    #[stable(feature = "duration", since = "1.3.0")]
-    #[inline]
-    pub const fn from_millis(millis: u64) -> Duration {
-        Duration {
-            secs: millis / MILLIS_PER_SEC,
-            nanos: ((millis % MILLIS_PER_SEC) as u32) * NANOS_PER_MILLI,
-        }
-    }
-
-    /// Creates a new `Duration` from the specified number of microseconds.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(duration_from_micros)]
-    /// use std::time::Duration;
-    ///
-    /// let duration = Duration::from_micros(1_000_002);
-    ///
-    /// assert_eq!(1, duration.as_secs());
-    /// assert_eq!(2000, duration.subsec_nanos());
-    /// ```
-    #[unstable(feature = "duration_from_micros", issue = "44400")]
-    #[inline]
-    pub const fn from_micros(micros: u64) -> Duration {
-        Duration {
-            secs: micros / MICROS_PER_SEC,
-            nanos: ((micros % MICROS_PER_SEC) as u32) * NANOS_PER_MICRO,
-        }
-    }
-
-    /// Creates a new `Duration` from the specified number of nanoseconds.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(duration_extras)]
-    /// use std::time::Duration;
-    ///
-    /// let duration = Duration::from_nanos(1_000_000_123);
-    ///
-    /// assert_eq!(1, duration.as_secs());
-    /// assert_eq!(123, duration.subsec_nanos());
-    /// ```
-    #[unstable(feature = "duration_extras", issue = "46507")]
-    #[inline]
-    pub const fn from_nanos(nanos: u64) -> Duration {
-        Duration {
-            secs: nanos / (NANOS_PER_SEC as u64),
-            nanos: (nanos % (NANOS_PER_SEC as u64)) as u32,
-        }
-    }
-
-    /// Returns the number of _whole_ seconds contained by this `Duration`.
-    ///
-    /// The returned value does not include the fractional (nanosecond) part of the
-    /// duration, which can be obtained using [`subsec_nanos`].
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::time::Duration;
-    ///
-    /// let duration = Duration::new(5, 730023852);
-    /// assert_eq!(duration.as_secs(), 5);
-    /// ```
-    ///
-    /// To determine the total number of seconds represented by the `Duration`,
-    /// use `as_secs` in combination with [`subsec_nanos`]:
-    ///
-    /// ```
-    /// use std::time::Duration;
-    ///
-    /// let duration = Duration::new(5, 730023852);
-    ///
-    /// assert_eq!(5.730023852,
-    ///            duration.as_secs() as f64
-    ///            + duration.subsec_nanos() as f64 * 1e-9);
-    /// ```
-    ///
-    /// [`subsec_nanos`]: #method.subsec_nanos
-    #[stable(feature = "duration", since = "1.3.0")]
-    #[inline]
-    pub fn as_secs(&self) -> u64 { self.secs }
-
-    /// Returns the fractional part of this `Duration`, in milliseconds.
-    ///
-    /// This method does **not** return the length of the duration when
-    /// represented by milliseconds. The returned number always represents a
-    /// fractional portion of a second (i.e. it is less than one thousand).
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(duration_extras)]
-    /// use std::time::Duration;
-    ///
-    /// let duration = Duration::from_millis(5432);
-    /// assert_eq!(duration.as_secs(), 5);
-    /// assert_eq!(duration.subsec_millis(), 432);
-    /// ```
-    #[unstable(feature = "duration_extras", issue = "46507")]
-    #[inline]
-    pub fn subsec_millis(&self) -> u32 { self.nanos / NANOS_PER_MILLI }
-
-    /// Returns the fractional part of this `Duration`, in microseconds.
-    ///
-    /// This method does **not** return the length of the duration when
-    /// represented by microseconds. The returned number always represents a
-    /// fractional portion of a second (i.e. it is less than one million).
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(duration_extras, duration_from_micros)]
-    /// use std::time::Duration;
-    ///
-    /// let duration = Duration::from_micros(1_234_567);
-    /// assert_eq!(duration.as_secs(), 1);
-    /// assert_eq!(duration.subsec_micros(), 234_567);
-    /// ```
-    #[unstable(feature = "duration_extras", issue = "46507")]
-    #[inline]
-    pub fn subsec_micros(&self) -> u32 { self.nanos / NANOS_PER_MICRO }
-
-    /// Returns the fractional part of this `Duration`, in nanoseconds.
-    ///
-    /// This method does **not** return the length of the duration when
-    /// represented by nanoseconds. The returned number always represents a
-    /// fractional portion of a second (i.e. it is less than one billion).
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::time::Duration;
-    ///
-    /// let duration = Duration::from_millis(5010);
-    /// assert_eq!(duration.as_secs(), 5);
-    /// assert_eq!(duration.subsec_nanos(), 10_000_000);
-    /// ```
-    #[stable(feature = "duration", since = "1.3.0")]
-    #[inline]
-    pub fn subsec_nanos(&self) -> u32 { self.nanos }
-
-    /// Checked `Duration` addition. Computes `self + other`, returning [`None`]
-    /// if overflow occurred.
-    ///
-    /// [`None`]: ../../std/option/enum.Option.html#variant.None
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// use std::time::Duration;
-    ///
-    /// assert_eq!(Duration::new(0, 0).checked_add(Duration::new(0, 1)), Some(Duration::new(0, 1)));
-    /// assert_eq!(Duration::new(1, 0).checked_add(Duration::new(std::u64::MAX, 0)), None);
-    /// ```
-    #[stable(feature = "duration_checked_ops", since = "1.16.0")]
-    #[inline]
-    pub fn checked_add(self, rhs: Duration) -> Option<Duration> {
-        if let Some(mut secs) = self.secs.checked_add(rhs.secs) {
-            let mut nanos = self.nanos + rhs.nanos;
-            if nanos >= NANOS_PER_SEC {
-                nanos -= NANOS_PER_SEC;
-                if let Some(new_secs) = secs.checked_add(1) {
-                    secs = new_secs;
-                } else {
-                    return None;
-                }
-            }
-            debug_assert!(nanos < NANOS_PER_SEC);
-            Some(Duration {
-                secs,
-                nanos,
-            })
-        } else {
-            None
-        }
-    }
-
-    /// Checked `Duration` subtraction. Computes `self - other`, returning [`None`]
-    /// if the result would be negative or if overflow occurred.
-    ///
-    /// [`None`]: ../../std/option/enum.Option.html#variant.None
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// use std::time::Duration;
-    ///
-    /// assert_eq!(Duration::new(0, 1).checked_sub(Duration::new(0, 0)), Some(Duration::new(0, 1)));
-    /// assert_eq!(Duration::new(0, 0).checked_sub(Duration::new(0, 1)), None);
-    /// ```
-    #[stable(feature = "duration_checked_ops", since = "1.16.0")]
-    #[inline]
-    pub fn checked_sub(self, rhs: Duration) -> Option<Duration> {
-        if let Some(mut secs) = self.secs.checked_sub(rhs.secs) {
-            let nanos = if self.nanos >= rhs.nanos {
-                self.nanos - rhs.nanos
-            } else {
-                if let Some(sub_secs) = secs.checked_sub(1) {
-                    secs = sub_secs;
-                    self.nanos + NANOS_PER_SEC - rhs.nanos
-                } else {
-                    return None;
-                }
-            };
-            debug_assert!(nanos < NANOS_PER_SEC);
-            Some(Duration { secs: secs, nanos: nanos })
-        } else {
-            None
-        }
-    }
-
-    /// Checked `Duration` multiplication. Computes `self * other`, returning
-    /// [`None`] if overflow occurred.
-    ///
-    /// [`None`]: ../../std/option/enum.Option.html#variant.None
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// use std::time::Duration;
-    ///
-    /// assert_eq!(Duration::new(0, 500_000_001).checked_mul(2), Some(Duration::new(1, 2)));
-    /// assert_eq!(Duration::new(std::u64::MAX - 1, 0).checked_mul(2), None);
-    /// ```
-    #[stable(feature = "duration_checked_ops", since = "1.16.0")]
-    #[inline]
-    pub fn checked_mul(self, rhs: u32) -> Option<Duration> {
-        // Multiply nanoseconds as u64, because it cannot overflow that way.
-        let total_nanos = self.nanos as u64 * rhs as u64;
-        let extra_secs = total_nanos / (NANOS_PER_SEC as u64);
-        let nanos = (total_nanos % (NANOS_PER_SEC as u64)) as u32;
-        if let Some(secs) = self.secs
-            .checked_mul(rhs as u64)
-            .and_then(|s| s.checked_add(extra_secs)) {
-            debug_assert!(nanos < NANOS_PER_SEC);
-            Some(Duration {
-                secs,
-                nanos,
-            })
-        } else {
-            None
-        }
-    }
-
-    /// Checked `Duration` division. Computes `self / other`, returning [`None`]
-    /// if `other == 0`.
-    ///
-    /// [`None`]: ../../std/option/enum.Option.html#variant.None
-    ///
-    /// # Examples
-    ///
-    /// Basic usage:
-    ///
-    /// ```
-    /// use std::time::Duration;
-    ///
-    /// 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);
-    /// ```
-    #[stable(feature = "duration_checked_ops", since = "1.16.0")]
-    #[inline]
-    pub fn checked_div(self, rhs: u32) -> Option<Duration> {
-        if rhs != 0 {
-            let secs = self.secs / (rhs as u64);
-            let carry = self.secs - secs * (rhs as u64);
-            let extra_nanos = carry * (NANOS_PER_SEC as u64) / (rhs as u64);
-            let nanos = self.nanos / rhs + (extra_nanos as u32);
-            debug_assert!(nanos < NANOS_PER_SEC);
-            Some(Duration { secs: secs, nanos: nanos })
-        } else {
-            None
-        }
-    }
-}
-
-#[stable(feature = "duration", since = "1.3.0")]
-impl Add for Duration {
-    type Output = Duration;
-
-    fn add(self, rhs: Duration) -> Duration {
-        self.checked_add(rhs).expect("overflow when adding durations")
-    }
-}
-
-#[stable(feature = "time_augmented_assignment", since = "1.9.0")]
-impl AddAssign for Duration {
-    fn add_assign(&mut self, rhs: Duration) {
-        *self = *self + rhs;
-    }
-}
-
-#[stable(feature = "duration", since = "1.3.0")]
-impl Sub for Duration {
-    type Output = Duration;
-
-    fn sub(self, rhs: Duration) -> Duration {
-        self.checked_sub(rhs).expect("overflow when subtracting durations")
-    }
-}
-
-#[stable(feature = "time_augmented_assignment", since = "1.9.0")]
-impl SubAssign for Duration {
-    fn sub_assign(&mut self, rhs: Duration) {
-        *self = *self - rhs;
-    }
-}
-
-#[stable(feature = "duration", since = "1.3.0")]
-impl Mul<u32> for Duration {
-    type Output = Duration;
-
-    fn mul(self, rhs: u32) -> Duration {
-        self.checked_mul(rhs).expect("overflow when multiplying duration by scalar")
-    }
-}
-
-#[stable(feature = "time_augmented_assignment", since = "1.9.0")]
-impl MulAssign<u32> for Duration {
-    fn mul_assign(&mut self, rhs: u32) {
-        *self = *self * rhs;
-    }
-}
-
-#[stable(feature = "duration", since = "1.3.0")]
-impl Div<u32> for Duration {
-    type Output = Duration;
-
-    fn div(self, rhs: u32) -> Duration {
-        self.checked_div(rhs).expect("divide by zero error when dividing duration by scalar")
-    }
-}
-
-#[stable(feature = "time_augmented_assignment", since = "1.9.0")]
-impl DivAssign<u32> for Duration {
-    fn div_assign(&mut self, rhs: u32) {
-        *self = *self / rhs;
-    }
-}
-
-#[stable(feature = "duration_sum", since = "1.16.0")]
-impl Sum for Duration {
-    fn sum<I: Iterator<Item=Duration>>(iter: I) -> Duration {
-        iter.fold(Duration::new(0, 0), |a, b| a + b)
-    }
-}
-
-#[stable(feature = "duration_sum", since = "1.16.0")]
-impl<'a> Sum<&'a Duration> for Duration {
-    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);
-    }
-}
diff --git a/src/libstd/time/mod.rs b/src/libstd/time/mod.rs
deleted file mode 100644 (file)
index 6ce3b3e..0000000
+++ /dev/null
@@ -1,567 +0,0 @@
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Temporal quantification.
-//!
-//! Example:
-//!
-//! ```
-//! use std::time::Duration;
-//!
-//! let five_seconds = Duration::new(5, 0);
-//! // both declarations are equivalent
-//! assert_eq!(Duration::new(5, 0), Duration::from_secs(5));
-//! ```
-
-#![stable(feature = "time", since = "1.3.0")]
-
-use error::Error;
-use fmt;
-use ops::{Add, Sub, AddAssign, SubAssign};
-use sys::time;
-use sys_common::FromInner;
-
-#[stable(feature = "time", since = "1.3.0")]
-pub use self::duration::Duration;
-
-mod duration;
-
-/// A measurement of a monotonically nondecreasing clock.
-/// Opaque and useful only with `Duration`.
-///
-/// Instants are always guaranteed to be no less than any previously measured
-/// instant when created, and are often useful for tasks such as measuring
-/// benchmarks or timing how long an operation takes.
-///
-/// Note, however, that instants are not guaranteed to be **steady**.  In other
-/// words, each tick of the underlying clock may not be the same length (e.g.
-/// some seconds may be longer than others). An instant may jump forwards or
-/// experience time dilation (slow down or speed up), but it will never go
-/// backwards.
-///
-/// Instants are opaque types that can only be compared to one another. There is
-/// no method to get "the number of seconds" from an instant. Instead, it only
-/// allows measuring the duration between two instants (or comparing two
-/// instants).
-///
-/// Example:
-///
-/// ```no_run
-/// use std::time::{Duration, Instant};
-/// use std::thread::sleep;
-///
-/// fn main() {
-///    let now = Instant::now();
-///
-///    // we sleep for 2 seconds
-///    sleep(Duration::new(2, 0));
-///    // it prints '2'
-///    println!("{}", now.elapsed().as_secs());
-/// }
-/// ```
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
-#[stable(feature = "time2", since = "1.8.0")]
-pub struct Instant(time::Instant);
-
-/// A measurement of the system clock, useful for talking to
-/// external entities like the file system or other processes.
-///
-/// Distinct from the [`Instant`] type, this time measurement **is not
-/// monotonic**. This means that you can save a file to the file system, then
-/// save another file to the file system, **and the second file has a
-/// `SystemTime` measurement earlier than the first**. In other words, an
-/// operation that happens after another operation in real time may have an
-/// earlier `SystemTime`!
-///
-/// Consequently, comparing two `SystemTime` instances to learn about the
-/// duration between them returns a [`Result`] instead of an infallible [`Duration`]
-/// to indicate that this sort of time drift may happen and needs to be handled.
-///
-/// Although a `SystemTime` cannot be directly inspected, the [`UNIX_EPOCH`]
-/// constant is provided in this module as an anchor in time to learn
-/// information about a `SystemTime`. By calculating the duration from this
-/// fixed point in time, a `SystemTime` can be converted to a human-readable time,
-/// or perhaps some other string representation.
-///
-/// [`Instant`]: ../../std/time/struct.Instant.html
-/// [`Result`]: ../../std/result/enum.Result.html
-/// [`Duration`]: ../../std/time/struct.Duration.html
-/// [`UNIX_EPOCH`]: ../../std/time/constant.UNIX_EPOCH.html
-///
-/// Example:
-///
-/// ```no_run
-/// use std::time::{Duration, SystemTime};
-/// use std::thread::sleep;
-///
-/// fn main() {
-///    let now = SystemTime::now();
-///
-///    // we sleep for 2 seconds
-///    sleep(Duration::new(2, 0));
-///    match now.elapsed() {
-///        Ok(elapsed) => {
-///            // it prints '2'
-///            println!("{}", elapsed.as_secs());
-///        }
-///        Err(e) => {
-///            // an error occurred!
-///            println!("Error: {:?}", e);
-///        }
-///    }
-/// }
-/// ```
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
-#[stable(feature = "time2", since = "1.8.0")]
-pub struct SystemTime(time::SystemTime);
-
-/// An error returned from the `duration_since` and `elapsed` methods on
-/// `SystemTime`, used to learn how far in the opposite direction a system time
-/// lies.
-///
-/// # Examples
-///
-/// ```no_run
-/// use std::thread::sleep;
-/// use std::time::{Duration, SystemTime};
-///
-/// let sys_time = SystemTime::now();
-/// sleep(Duration::from_secs(1));
-/// let new_sys_time = SystemTime::now();
-/// match sys_time.duration_since(new_sys_time) {
-///     Ok(_) => {}
-///     Err(e) => println!("SystemTimeError difference: {:?}", e.duration()),
-/// }
-/// ```
-#[derive(Clone, Debug)]
-#[stable(feature = "time2", since = "1.8.0")]
-pub struct SystemTimeError(Duration);
-
-impl Instant {
-    /// Returns an instant corresponding to "now".
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::time::Instant;
-    ///
-    /// let now = Instant::now();
-    /// ```
-    #[stable(feature = "time2", since = "1.8.0")]
-    pub fn now() -> Instant {
-        Instant(time::Instant::now())
-    }
-
-    /// Returns the amount of time elapsed from another instant to this one.
-    ///
-    /// # Panics
-    ///
-    /// This function will panic if `earlier` is later than `self`.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::time::{Duration, Instant};
-    /// use std::thread::sleep;
-    ///
-    /// let now = Instant::now();
-    /// sleep(Duration::new(1, 0));
-    /// let new_now = Instant::now();
-    /// println!("{:?}", new_now.duration_since(now));
-    /// ```
-    #[stable(feature = "time2", since = "1.8.0")]
-    pub fn duration_since(&self, earlier: Instant) -> Duration {
-        self.0.sub_instant(&earlier.0)
-    }
-
-    /// Returns the amount of time elapsed since this instant was created.
-    ///
-    /// # Panics
-    ///
-    /// This function may panic if the current time is earlier than this
-    /// instant, which is something that can happen if an `Instant` is
-    /// produced synthetically.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::thread::sleep;
-    /// use std::time::{Duration, Instant};
-    ///
-    /// let instant = Instant::now();
-    /// let three_secs = Duration::from_secs(3);
-    /// sleep(three_secs);
-    /// assert!(instant.elapsed() >= three_secs);
-    /// ```
-    #[stable(feature = "time2", since = "1.8.0")]
-    pub fn elapsed(&self) -> Duration {
-        Instant::now() - *self
-    }
-}
-
-#[stable(feature = "time2", since = "1.8.0")]
-impl Add<Duration> for Instant {
-    type Output = Instant;
-
-    fn add(self, other: Duration) -> Instant {
-        Instant(self.0.add_duration(&other))
-    }
-}
-
-#[stable(feature = "time_augmented_assignment", since = "1.9.0")]
-impl AddAssign<Duration> for Instant {
-    fn add_assign(&mut self, other: Duration) {
-        *self = *self + other;
-    }
-}
-
-#[stable(feature = "time2", since = "1.8.0")]
-impl Sub<Duration> for Instant {
-    type Output = Instant;
-
-    fn sub(self, other: Duration) -> Instant {
-        Instant(self.0.sub_duration(&other))
-    }
-}
-
-#[stable(feature = "time_augmented_assignment", since = "1.9.0")]
-impl SubAssign<Duration> for Instant {
-    fn sub_assign(&mut self, other: Duration) {
-        *self = *self - other;
-    }
-}
-
-#[stable(feature = "time2", since = "1.8.0")]
-impl Sub<Instant> for Instant {
-    type Output = Duration;
-
-    fn sub(self, other: Instant) -> Duration {
-        self.duration_since(other)
-    }
-}
-
-#[stable(feature = "time2", since = "1.8.0")]
-impl fmt::Debug for Instant {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.0.fmt(f)
-    }
-}
-
-impl SystemTime {
-    /// Returns the system time corresponding to "now".
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::time::SystemTime;
-    ///
-    /// let sys_time = SystemTime::now();
-    /// ```
-    #[stable(feature = "time2", since = "1.8.0")]
-    pub fn now() -> SystemTime {
-        SystemTime(time::SystemTime::now())
-    }
-
-    /// Returns the amount of time elapsed from an earlier point in time.
-    ///
-    /// This function may fail because measurements taken earlier are not
-    /// guaranteed to always be before later measurements (due to anomalies such
-    /// as the system clock being adjusted either forwards or backwards).
-    ///
-    /// If successful, [`Ok`]`(`[`Duration`]`)` is returned where the duration represents
-    /// the amount of time elapsed from the specified measurement to this one.
-    ///
-    /// Returns an [`Err`] if `earlier` is later than `self`, and the error
-    /// contains how far from `self` the time is.
-    ///
-    /// [`Ok`]: ../../std/result/enum.Result.html#variant.Ok
-    /// [`Duration`]: ../../std/time/struct.Duration.html
-    /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::time::SystemTime;
-    ///
-    /// let sys_time = SystemTime::now();
-    /// let difference = sys_time.duration_since(sys_time)
-    ///                          .expect("SystemTime::duration_since failed");
-    /// println!("{:?}", difference);
-    /// ```
-    #[stable(feature = "time2", since = "1.8.0")]
-    pub fn duration_since(&self, earlier: SystemTime)
-                          -> Result<Duration, SystemTimeError> {
-        self.0.sub_time(&earlier.0).map_err(SystemTimeError)
-    }
-
-    /// Returns the amount of time elapsed since this system time was created.
-    ///
-    /// This function may fail as the underlying system clock is susceptible to
-    /// drift and updates (e.g. the system clock could go backwards), so this
-    /// function may not always succeed. If successful, [`Ok`]`(`[`Duration`]`)` is
-    /// returned where the duration represents the amount of time elapsed from
-    /// this time measurement to the current time.
-    ///
-    /// Returns an [`Err`] if `self` is later than the current system time, and
-    /// the error contains how far from the current system time `self` is.
-    ///
-    /// [`Ok`]: ../../std/result/enum.Result.html#variant.Ok
-    /// [`Duration`]: ../../std/time/struct.Duration.html
-    /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::thread::sleep;
-    /// use std::time::{Duration, SystemTime};
-    ///
-    /// let sys_time = SystemTime::now();
-    /// let one_sec = Duration::from_secs(1);
-    /// sleep(one_sec);
-    /// assert!(sys_time.elapsed().unwrap() >= one_sec);
-    /// ```
-    #[stable(feature = "time2", since = "1.8.0")]
-    pub fn elapsed(&self) -> Result<Duration, SystemTimeError> {
-        SystemTime::now().duration_since(*self)
-    }
-}
-
-#[stable(feature = "time2", since = "1.8.0")]
-impl Add<Duration> for SystemTime {
-    type Output = SystemTime;
-
-    fn add(self, dur: Duration) -> SystemTime {
-        SystemTime(self.0.add_duration(&dur))
-    }
-}
-
-#[stable(feature = "time_augmented_assignment", since = "1.9.0")]
-impl AddAssign<Duration> for SystemTime {
-    fn add_assign(&mut self, other: Duration) {
-        *self = *self + other;
-    }
-}
-
-#[stable(feature = "time2", since = "1.8.0")]
-impl Sub<Duration> for SystemTime {
-    type Output = SystemTime;
-
-    fn sub(self, dur: Duration) -> SystemTime {
-        SystemTime(self.0.sub_duration(&dur))
-    }
-}
-
-#[stable(feature = "time_augmented_assignment", since = "1.9.0")]
-impl SubAssign<Duration> for SystemTime {
-    fn sub_assign(&mut self, other: Duration) {
-        *self = *self - other;
-    }
-}
-
-#[stable(feature = "time2", since = "1.8.0")]
-impl fmt::Debug for SystemTime {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.0.fmt(f)
-    }
-}
-
-/// An anchor in time which can be used to create new `SystemTime` instances or
-/// learn about where in time a `SystemTime` lies.
-///
-/// This constant is defined to be "1970-01-01 00:00:00 UTC" on all systems with
-/// respect to the system clock. Using `duration_since` on an existing
-/// [`SystemTime`] instance can tell how far away from this point in time a
-/// measurement lies, and using `UNIX_EPOCH + duration` can be used to create a
-/// [`SystemTime`] instance to represent another fixed point in time.
-///
-/// [`SystemTime`]: ../../std/time/struct.SystemTime.html
-///
-/// # Examples
-///
-/// ```no_run
-/// use std::time::{SystemTime, UNIX_EPOCH};
-///
-/// match SystemTime::now().duration_since(UNIX_EPOCH) {
-///     Ok(n) => println!("1970-01-01 00:00:00 UTC was {} seconds ago!", n.as_secs()),
-///     Err(_) => panic!("SystemTime before UNIX EPOCH!"),
-/// }
-/// ```
-#[stable(feature = "time2", since = "1.8.0")]
-pub const UNIX_EPOCH: SystemTime = SystemTime(time::UNIX_EPOCH);
-
-impl SystemTimeError {
-    /// Returns the positive duration which represents how far forward the
-    /// second system time was from the first.
-    ///
-    /// A `SystemTimeError` is returned from the [`duration_since`] and [`elapsed`]
-    /// methods of [`SystemTime`] whenever the second system time represents a point later
-    /// in time than the `self` of the method call.
-    ///
-    /// [`duration_since`]: ../../std/time/struct.SystemTime.html#method.duration_since
-    /// [`elapsed`]: ../../std/time/struct.SystemTime.html#method.elapsed
-    /// [`SystemTime`]: ../../std/time/struct.SystemTime.html
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::thread::sleep;
-    /// use std::time::{Duration, SystemTime};
-    ///
-    /// let sys_time = SystemTime::now();
-    /// sleep(Duration::from_secs(1));
-    /// let new_sys_time = SystemTime::now();
-    /// match sys_time.duration_since(new_sys_time) {
-    ///     Ok(_) => {}
-    ///     Err(e) => println!("SystemTimeError difference: {:?}", e.duration()),
-    /// }
-    /// ```
-    #[stable(feature = "time2", since = "1.8.0")]
-    pub fn duration(&self) -> Duration {
-        self.0
-    }
-}
-
-#[stable(feature = "time2", since = "1.8.0")]
-impl Error for SystemTimeError {
-    fn description(&self) -> &str { "other time was not earlier than self" }
-}
-
-#[stable(feature = "time2", since = "1.8.0")]
-impl fmt::Display for SystemTimeError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(f, "second time provided was later than self")
-    }
-}
-
-impl FromInner<time::SystemTime> for SystemTime {
-    fn from_inner(time: time::SystemTime) -> SystemTime {
-        SystemTime(time)
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use super::{Instant, SystemTime, Duration, UNIX_EPOCH};
-
-    macro_rules! assert_almost_eq {
-        ($a:expr, $b:expr) => ({
-            let (a, b) = ($a, $b);
-            if a != b {
-                let (a, b) = if a > b {(a, b)} else {(b, a)};
-                assert!(a - Duration::new(0, 100) <= b);
-            }
-        })
-    }
-
-    #[test]
-    fn instant_monotonic() {
-        let a = Instant::now();
-        let b = Instant::now();
-        assert!(b >= a);
-    }
-
-    #[test]
-    fn instant_elapsed() {
-        let a = Instant::now();
-        a.elapsed();
-    }
-
-    #[test]
-    fn instant_math() {
-        let a = Instant::now();
-        let b = Instant::now();
-        let dur = b.duration_since(a);
-        assert_almost_eq!(b - dur, a);
-        assert_almost_eq!(a + dur, b);
-
-        let second = Duration::new(1, 0);
-        assert_almost_eq!(a - second + second, a);
-    }
-
-    #[test]
-    #[should_panic]
-    fn instant_duration_panic() {
-        let a = Instant::now();
-        (a - Duration::new(1, 0)).duration_since(a);
-    }
-
-    #[test]
-    fn system_time_math() {
-        let a = SystemTime::now();
-        let b = SystemTime::now();
-        match b.duration_since(a) {
-            Ok(dur) if dur == Duration::new(0, 0) => {
-                assert_almost_eq!(a, b);
-            }
-            Ok(dur) => {
-                assert!(b > a);
-                assert_almost_eq!(b - dur, a);
-                assert_almost_eq!(a + dur, b);
-            }
-            Err(dur) => {
-                let dur = dur.duration();
-                assert!(a > b);
-                assert_almost_eq!(b + dur, a);
-                assert_almost_eq!(a - dur, b);
-            }
-        }
-
-        let second = Duration::new(1, 0);
-        assert_almost_eq!(a.duration_since(a - second).unwrap(), second);
-        assert_almost_eq!(a.duration_since(a + second).unwrap_err()
-                           .duration(), second);
-
-        assert_almost_eq!(a - second + second, a);
-
-        // A difference of 80 and 800 years cannot fit inside a 32-bit time_t
-        if !(cfg!(unix) && ::mem::size_of::<::libc::time_t>() <= 4) {
-            let eighty_years = second * 60 * 60 * 24 * 365 * 80;
-            assert_almost_eq!(a - eighty_years + eighty_years, a);
-            assert_almost_eq!(a - (eighty_years * 10) + (eighty_years * 10), a);
-        }
-
-        let one_second_from_epoch = UNIX_EPOCH + Duration::new(1, 0);
-        let one_second_from_epoch2 = UNIX_EPOCH + Duration::new(0, 500_000_000)
-            + Duration::new(0, 500_000_000);
-        assert_eq!(one_second_from_epoch, one_second_from_epoch2);
-    }
-
-    #[test]
-    fn system_time_elapsed() {
-        let a = SystemTime::now();
-        drop(a.elapsed());
-    }
-
-    #[test]
-    fn since_epoch() {
-        let ts = SystemTime::now();
-        let a = ts.duration_since(UNIX_EPOCH).unwrap();
-        let b = ts.duration_since(UNIX_EPOCH - Duration::new(1, 0)).unwrap();
-        assert!(b > a);
-        assert_eq!(b - a, Duration::new(1, 0));
-
-        let thirty_years = Duration::new(1, 0) * 60 * 60 * 24 * 365 * 30;
-
-        // Right now for CI this test is run in an emulator, and apparently the
-        // aarch64 emulator's sense of time is that we're still living in the
-        // 70s.
-        //
-        // Otherwise let's assume that we're all running computers later than
-        // 2000.
-        if !cfg!(target_arch = "aarch64") {
-            assert!(a > thirty_years);
-        }
-
-        // let's assume that we're all running computers earlier than 2090.
-        // Should give us ~70 years to fix this!
-        let hundred_twenty_years = thirty_years * 4;
-        assert!(a < hundred_twenty_years);
-    }
-}
index a6a7f9e20b3a925fa9a236881fd045d0f37080ec..3601b9ba8a8c1cdbf8b5669f1fd42e5f0b17cf17 100644 (file)
@@ -593,8 +593,30 @@ pub fn span_until_char(&self, sp: Span, c: char) -> Span {
         }
     }
 
-    /// Given a `Span`, try to get a shorter span ending just after the first
-    /// occurrence of `char` `c`.
+    /// Given a `Span`, get a new `Span` covering the first token and all its trailing whitespace or
+    /// the original `Span`.
+    ///
+    /// If `sp` points to `"let mut x"`, then a span pointing at `"let "` will be returned.
+    pub fn span_until_non_whitespace(&self, sp: Span) -> Span {
+        if let Ok(snippet) = self.span_to_snippet(sp) {
+            let mut offset = 0;
+            // get the bytes width of all the non-whitespace characters
+            for c in snippet.chars().take_while(|c| !c.is_whitespace()) {
+                offset += c.len_utf8();
+            }
+            // get the bytes width of all the whitespace characters after that
+            for c in snippet[offset..].chars().take_while(|c| c.is_whitespace()) {
+                offset += c.len_utf8();
+            }
+            if offset > 1 {
+                return sp.with_hi(BytePos(sp.lo().0 + offset as u32));
+            }
+        }
+        sp
+    }
+
+    /// Given a `Span`, try to get a shorter span ending just after the first occurrence of `char`
+    /// `c`.
     pub fn span_through_char(&self, sp: Span, c: char) -> Span {
         if let Ok(snippet) = self.span_to_snippet(sp) {
             if let Some(offset) = snippet.find(c) {
index 6a4f338485b3e8de0ca3f4d55330b4b1c0488ec7..3e858c3b923a1154d218359b1f928bc37b9a6fe6 100644 (file)
@@ -787,6 +787,11 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
                                                        is just used for rustc unit tests \
                                                        and will never be stable",
                                                       cfg_fn!(rustc_attrs))),
+    ("rustc_serialize_exclude_null", Normal, Gated(Stability::Unstable,
+                                             "rustc_attrs",
+                                             "the `#[rustc_serialize_exclude_null]` attribute \
+                                              is an internal-only feature",
+                                             cfg_fn!(rustc_attrs))),
     ("rustc_synthetic", Whitelisted, Gated(Stability::Unstable,
                                                       "rustc_attrs",
                                                       "this attribute \
index 54c726d84621fe36f1bd28adf5cc338b2c8325e8..98d5fa8f797fa7e105838655419bfd607feb29b7 100644 (file)
@@ -38,34 +38,41 @@ pub struct JsonEmitter {
     registry: Option<Registry>,
     cm: Rc<CodeMapper + 'static>,
     pretty: bool,
+    /// Whether "approximate suggestions" are enabled in the config
+    approximate_suggestions: bool,
 }
 
 impl JsonEmitter {
     pub fn stderr(registry: Option<Registry>,
                   code_map: Rc<CodeMap>,
-                  pretty: bool) -> JsonEmitter {
+                  pretty: bool,
+                  approximate_suggestions: bool) -> JsonEmitter {
         JsonEmitter {
             dst: Box::new(io::stderr()),
             registry,
             cm: code_map,
             pretty,
+            approximate_suggestions,
         }
     }
 
     pub fn basic(pretty: bool) -> JsonEmitter {
         let file_path_mapping = FilePathMapping::empty();
-        JsonEmitter::stderr(None, Rc::new(CodeMap::new(file_path_mapping)), pretty)
+        JsonEmitter::stderr(None, Rc::new(CodeMap::new(file_path_mapping)),
+                            pretty, false)
     }
 
     pub fn new(dst: Box<Write + Send>,
                registry: Option<Registry>,
                code_map: Rc<CodeMap>,
-               pretty: bool) -> JsonEmitter {
+               pretty: bool,
+               approximate_suggestions: bool) -> JsonEmitter {
         JsonEmitter {
             dst,
             registry,
             cm: code_map,
             pretty,
+            approximate_suggestions,
         }
     }
 }
@@ -101,6 +108,7 @@ struct Diagnostic {
 }
 
 #[derive(RustcEncodable)]
+#[allow(unused_attributes)]
 struct DiagnosticSpan {
     file_name: String,
     byte_start: u32,
@@ -121,6 +129,9 @@ struct DiagnosticSpan {
     /// If we are suggesting a replacement, this will contain text
     /// that should be sliced in atop this span.
     suggested_replacement: Option<String>,
+    /// If the suggestion is approximate
+    #[rustc_serialize_exclude_null]
+    suggestion_approximate: Option<bool>,
     /// Macro invocations that created the code at this span, if any.
     expansion: Option<Box<DiagnosticSpanMacroExpansion>>,
 }
@@ -188,7 +199,7 @@ fn flush(&mut self) -> io::Result<()> {
         }
         let buf = BufWriter::default();
         let output = buf.clone();
-        EmitterWriter::new(Box::new(buf), Some(je.cm.clone()), false).emit(db);
+        EmitterWriter::new(Box::new(buf), Some(je.cm.clone()), false, false).emit(db);
         let output = Arc::try_unwrap(output.0).unwrap().into_inner().unwrap();
         let output = String::from_utf8(output).unwrap();
 
@@ -220,7 +231,7 @@ fn from_sub_diagnostic(db: &SubDiagnostic, je: &JsonEmitter) -> Diagnostic {
 
 impl DiagnosticSpan {
     fn from_span_label(span: SpanLabel,
-                       suggestion: Option<&String>,
+                       suggestion: Option<(&String, bool)>,
                        je: &JsonEmitter)
                        -> DiagnosticSpan {
         Self::from_span_etc(span.span,
@@ -233,7 +244,7 @@ fn from_span_label(span: SpanLabel,
     fn from_span_etc(span: Span,
                      is_primary: bool,
                      label: Option<String>,
-                     suggestion: Option<&String>,
+                     suggestion: Option<(&String, bool)>,
                      je: &JsonEmitter)
                      -> DiagnosticSpan {
         // obtain the full backtrace from the `macro_backtrace`
@@ -253,7 +264,7 @@ fn from_span_etc(span: Span,
     fn from_span_full(span: Span,
                       is_primary: bool,
                       label: Option<String>,
-                      suggestion: Option<&String>,
+                      suggestion: Option<(&String, bool)>,
                       mut backtrace: vec::IntoIter<MacroBacktrace>,
                       je: &JsonEmitter)
                       -> DiagnosticSpan {
@@ -281,6 +292,13 @@ fn from_span_full(span: Span,
                 def_site_span,
             })
         });
+
+        let suggestion_approximate = if je.approximate_suggestions {
+             suggestion.map(|x| x.1)
+        } else {
+            None
+        };
+
         DiagnosticSpan {
             file_name: start.file.name.to_string(),
             byte_start: span.lo().0 - start.file.start_pos.0,
@@ -291,7 +309,8 @@ fn from_span_full(span: Span,
             column_end: end.col.0 + 1,
             is_primary,
             text: DiagnosticSpanLine::from_span(span, je),
-            suggested_replacement: suggestion.cloned(),
+            suggested_replacement: suggestion.map(|x| x.0.clone()),
+            suggestion_approximate,
             expansion: backtrace_step,
             label,
         }
@@ -309,14 +328,15 @@ fn from_suggestion(suggestion: &CodeSuggestion, je: &JsonEmitter)
         suggestion.substitutions
                       .iter()
                       .flat_map(|substitution| {
-                          substitution.parts.iter().map(move |suggestion| {
+                          substitution.parts.iter().map(move |suggestion_inner| {
                               let span_label = SpanLabel {
-                                  span: suggestion.span,
+                                  span: suggestion_inner.span,
                                   is_primary: true,
                                   label: None,
                               };
                               DiagnosticSpan::from_span_label(span_label,
-                                                              Some(&suggestion.snippet),
+                                                              Some((&suggestion_inner.snippet,
+                                                                   suggestion.approximate)),
                                                               je)
                           })
                       })
index 3b4c5da10f20b35b5f0014a956419e00b4125d11..9181cca215c848602d3f8bbe1a93a3ac45561588 100644 (file)
@@ -25,6 +25,7 @@
 #![feature(match_default_bindings)]
 #![feature(i128_type)]
 #![feature(const_atomic_usize_new)]
+#![feature(rustc_attrs)]
 
 // See librustc_cratesio_shim/Cargo.toml for a comment explaining this.
 #[allow(unused_extern_crates)]
index b95c91548d00b99954ed70701f9e1cc87eed12ed..11ab84a572916e76edc6f7473f6e4cb17cf74787 100644 (file)
@@ -246,14 +246,27 @@ fn err_span_(&self, from_pos: BytePos, to_pos: BytePos, m: &str) {
         self.err_span(self.mk_sp(from_pos, to_pos), m)
     }
 
+    /// Pushes a character to a message string for error reporting
+    fn push_escaped_char_for_msg(m: &mut String, c: char) {
+        match c {
+            '\u{20}'...'\u{7e}' => {
+                // Don't escape \, ' or " for user-facing messages
+                m.push(c);
+            }
+            _ => {
+                for c in c.escape_default() {
+                    m.push(c);
+                }
+            }
+        }
+    }
+
     /// Report a lexical error spanning [`from_pos`, `to_pos`), appending an
     /// escaped character to the error message
     fn fatal_span_char(&self, from_pos: BytePos, to_pos: BytePos, m: &str, c: char) -> FatalError {
         let mut m = m.to_string();
         m.push_str(": ");
-        for c in c.escape_default() {
-            m.push(c)
-        }
+        Self::push_escaped_char_for_msg(&mut m, c);
         self.fatal_span_(from_pos, to_pos, &m[..])
     }
     fn struct_fatal_span_char(&self,
@@ -264,9 +277,7 @@ fn struct_fatal_span_char(&self,
                               -> DiagnosticBuilder<'a> {
         let mut m = m.to_string();
         m.push_str(": ");
-        for c in c.escape_default() {
-            m.push(c)
-        }
+        Self::push_escaped_char_for_msg(&mut m, c);
         self.sess.span_diagnostic.struct_span_fatal(self.mk_sp(from_pos, to_pos), &m[..])
     }
 
@@ -275,9 +286,7 @@ fn struct_fatal_span_char(&self,
     fn err_span_char(&self, from_pos: BytePos, to_pos: BytePos, m: &str, c: char) {
         let mut m = m.to_string();
         m.push_str(": ");
-        for c in c.escape_default() {
-            m.push(c)
-        }
+        Self::push_escaped_char_for_msg(&mut m, c);
         self.err_span_(from_pos, to_pos, &m[..]);
     }
     fn struct_err_span_char(&self,
@@ -288,9 +297,7 @@ fn struct_err_span_char(&self,
                             -> DiagnosticBuilder<'a> {
         let mut m = m.to_string();
         m.push_str(": ");
-        for c in c.escape_default() {
-            m.push(c)
-        }
+        Self::push_escaped_char_for_msg(&mut m, c);
         self.sess.span_diagnostic.struct_span_err(self.mk_sp(from_pos, to_pos), &m[..])
     }
 
@@ -1745,6 +1752,7 @@ mod tests {
     fn mk_sess(cm: Rc<CodeMap>) -> ParseSess {
         let emitter = errors::emitter::EmitterWriter::new(Box::new(io::sink()),
                                                           Some(cm.clone()),
+                                                          false,
                                                           false);
         ParseSess {
             span_diagnostic: errors::Handler::with_emitter(true, false, Box::new(emitter)),
index 2be93c07d5ad771774fd5beaa727d9a284db04d1..7fbe781e9a1f6c74b0071394677b3b5d6df3f09c 100644 (file)
@@ -112,6 +112,7 @@ fn ident_can_begin_expr(ident: ast::Ident) -> bool {
         keywords::Unsafe.name(),
         keywords::While.name(),
         keywords::Yield.name(),
+        keywords::Static.name(),
     ].contains(&ident.name)
 }
 
index 5072f2e2793f1bea2f5d9033aa3988cea9636579..3b4bba24d779b6d0176fdc8c3e8f5b9461e83aa8 100644 (file)
@@ -62,6 +62,7 @@ fn test_harness(file_text: &str, span_labels: Vec<SpanLabel>, expected_output: &
 
     let emitter = EmitterWriter::new(Box::new(Shared { data: output.clone() }),
                                      Some(code_map.clone()),
+                                     false,
                                      false);
     let handler = Handler::with_emitter(true, false, Box::new(emitter));
     handler.span_err(msp, "foo");
index 0e6e96438d8176ffc16065ee9fc21d3d5c41ae1c..743f22b6b314075a34d3a76c9cc44de77fb6abab 100644 (file)
@@ -190,7 +190,7 @@ fn encodable_substructure(cx: &mut ExtCtxt,
         Struct(_, ref fields) => {
             let emit_struct_field = cx.ident_of("emit_struct_field");
             let mut stmts = Vec::new();
-            for (i, &FieldInfo { name, ref self_, span, .. }) in fields.iter().enumerate() {
+            for (i, &FieldInfo { name, ref self_, span, attrs, .. }) in fields.iter().enumerate() {
                 let name = match name {
                     Some(id) => id.name,
                     None => Symbol::intern(&format!("_field{}", i)),
@@ -212,7 +212,19 @@ fn encodable_substructure(cx: &mut ExtCtxt,
                 } else {
                     cx.expr(span, ExprKind::Ret(Some(call)))
                 };
-                stmts.push(cx.stmt_expr(call));
+
+                // This exists for https://github.com/rust-lang/rust/pull/47540
+                //
+                // If we decide to stabilize that flag this can be removed
+                let expr = if attrs.iter().any(|a| a.check_name("rustc_serialize_exclude_null")) {
+                    let is_some = cx.ident_of("is_some");
+                    let condition = cx.expr_method_call(span, self_.clone(), is_some, vec![]);
+                    cx.expr_if(span, condition, call, None)
+                } else {
+                    call
+                };
+                let stmt = cx.stmt_expr(expr);
+                stmts.push(stmt);
             }
 
             // unit structs have no fields and need to return Ok()
index dd1ec7284f6901320987f68a3bd325bf2ad5201f..294506625bc05bc1c07f9ae6f3b3816630821b66 100644 (file)
@@ -347,13 +347,24 @@ pub fn macro_backtrace(mut self) -> Vec<MacroBacktrace> {
 
     /// Return a `Span` that would enclose both `self` and `end`.
     pub fn to(self, end: Span) -> Span {
-        let span = self.data();
-        let end = end.data();
+        let span_data = self.data();
+        let end_data = end.data();
+        // FIXME(jseyfried): self.ctxt should always equal end.ctxt here (c.f. issue #23480)
+        // Return the macro span on its own to avoid weird diagnostic output. It is preferable to
+        // have an incomplete span than a completely nonsensical one.
+        if span_data.ctxt != end_data.ctxt {
+            if span_data.ctxt == SyntaxContext::empty() {
+                return end;
+            } else if end_data.ctxt == SyntaxContext::empty() {
+                return self;
+            }
+            // both span fall within a macro
+            // FIXME(estebank) check if it is the *same* macro
+        }
         Span::new(
-            cmp::min(span.lo, end.lo),
-            cmp::max(span.hi, end.hi),
-            // FIXME(jseyfried): self.ctxt should always equal end.ctxt here (c.f. issue #23480)
-            if span.ctxt == SyntaxContext::empty() { end.ctxt } else { span.ctxt },
+            cmp::min(span_data.lo, end_data.lo),
+            cmp::max(span_data.hi, end_data.hi),
+            if span_data.ctxt == SyntaxContext::empty() { end_data.ctxt } else { span_data.ctxt },
         )
     }
 
index b2f1229891d261dd4758130671f1a87ec46f0de3..06d1301d70003bafb0da71f268a04999a655d220 100644 (file)
@@ -836,6 +836,10 @@ struct LLVMRustThinLTOData {
   StringMap<FunctionImporter::ImportMapTy> ImportLists;
   StringMap<FunctionImporter::ExportSetTy> ExportLists;
   StringMap<GVSummaryMapTy> ModuleToDefinedGVSummaries;
+
+#if LLVM_VERSION_GE(7, 0)
+  LLVMRustThinLTOData() : Index(/* isPerformingAnalysis = */ false) {}
+#endif
 };
 
 // Just an argument to the `LLVMRustCreateThinLTOData` function below.
@@ -918,7 +922,14 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules,
   //
   // This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp`
 #if LLVM_VERSION_GE(5, 0)
+#if LLVM_VERSION_GE(7, 0)
+  auto deadIsPrevailing = [&](GlobalValue::GUID G) {
+    return PrevailingType::Unknown;
+  };
+  computeDeadSymbols(Ret->Index, Ret->GUIDPreservedSymbols, deadIsPrevailing);
+#else
   computeDeadSymbols(Ret->Index, Ret->GUIDPreservedSymbols);
+#endif
   ComputeCrossModuleImport(
     Ret->Index,
     Ret->ModuleToDefinedGVSummaries,
index f8945a6ee8d93aeb0eba51b16923d601f02b0f59..0e98d3f9050a8194573bdf8a23ef43955bc97869 100644 (file)
@@ -122,13 +122,13 @@ pub fn unsafe_slice(_: &[UnsafeInner]) {
 pub fn str(_: &[u8]) {
 }
 
-// CHECK: @trait_borrow(%"core::ops::drop::Drop"* nonnull %arg0.0, {}* noalias nonnull readonly %arg0.1)
+// CHECK: @trait_borrow({}* nonnull %arg0.0, {}* noalias nonnull readonly %arg0.1)
 // FIXME #25759 This should also have `nocapture`
 #[no_mangle]
 pub fn trait_borrow(_: &Drop) {
 }
 
-// CHECK: @trait_box(%"core::ops::drop::Drop"* noalias nonnull, {}* noalias nonnull readonly)
+// CHECK: @trait_box({}* noalias nonnull, {}* noalias nonnull readonly)
 #[no_mangle]
 pub fn trait_box(_: Box<Drop>) {
 }
index 5b26dade9aff06f4f0c264ebab519ac63063186b..4a489f1edb3b8cbf5f509f29ef7fc0f0409b705b 100644 (file)
@@ -15,7 +15,7 @@
 // ignore-wasm
 // ignore-emscripten
 // ignore-windows
-// no-system-llvm
+// min-system-llvm-version 5.0
 // compile-flags: -C no-prepopulate-passes
 
 #![crate_type = "lib"]
index 06dd903b23db83925187cd1b49838c15f8468884..4f4d7ce0dba839126787a7c1f798a5a6d8c51bff 100644 (file)
 
 trait Trait {
     fn bar<'a,'b:'a>(x: &'a str, y: &'b str);
+    //~^ NOTE lifetimes in impl do not match this method in trait
 }
 
 struct Foo;
 
 impl Trait for Foo {
     fn bar<'a,'b>(x: &'a str, y: &'b str) { //~ ERROR E0195
-                                            //~^ lifetimes do not match trait
+    //~^ NOTE lifetimes do not match method in trait
     }
 }
 
index 52bb4a1b463b4b7f75709c567bdb0481aef7d439..630a234fa66410e2cf886b0bc15244759c1a99e4 100644 (file)
@@ -16,6 +16,7 @@ pub trait Foo {
 }
 
 struct Abc;
+
 impl Foo for Abc {
     const X: EFoo = EFoo::B;
 }
@@ -27,8 +28,10 @@ impl Foo for Def {
 
 pub fn test<A: Foo, B: Foo>(arg: EFoo) {
     match arg {
-        A::X => println!("A::X"), //~ error: statics cannot be referenced in patterns [E0158]
-        B::X => println!("B::X"), //~ error: statics cannot be referenced in patterns [E0158]
+        A::X => println!("A::X"),
+        //~^ error: associated consts cannot be referenced in patterns [E0158]
+        B::X => println!("B::X"),
+        //~^ error: associated consts cannot be referenced in patterns [E0158]
         _ => (),
     }
 }
index 5012556dedddc3c98c3fc1e0a912243f97568a89..cda83fe54b09ab527acdca32c31a484d28327565 100644 (file)
@@ -10,6 +10,7 @@
 
 trait NoLifetime {
     fn get<'p, T : Test<'p>>(&self) -> T;
+    //~^ NOTE lifetimes in impl do not match this method in trait
 }
 
 trait Test<'p> {
@@ -28,8 +29,8 @@ fn new(buf: &'a mut [u8]) -> Foo<'a> {
 
 impl<'a> NoLifetime for Foo<'a> {
     fn get<'p, T : Test<'a>>(&self) -> T {
-//~^ ERROR E0195
-//~| lifetimes do not match trait
+    //~^ ERROR E0195
+    //~| NOTE lifetimes do not match method in trait
         return *self as T;
     }
 }
diff --git a/src/test/compile-fail/nll/do-not-ignore-lifetime-bounds-in-copy.rs b/src/test/compile-fail/nll/do-not-ignore-lifetime-bounds-in-copy.rs
new file mode 100644 (file)
index 0000000..2a4295f
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that the 'static bound from the Copy impl is respected. Regression test for #29149.
+
+#![feature(nll)]
+
+#[derive(Clone)] struct Foo<'a>(&'a u32);
+impl Copy for Foo<'static> {}
+
+fn main() {
+    let s = 2;
+    let a = Foo(&s); //~ ERROR `s` does not live long enough [E0597]
+    drop(a);
+    drop(a);
+}
diff --git a/src/test/compile-fail/regions-bound-missing-bound-in-impl.rs b/src/test/compile-fail/regions-bound-missing-bound-in-impl.rs
deleted file mode 100644 (file)
index 617de2c..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Check that explicit region bounds are allowed on the various
-// nominal types (but not on other types) and that they are type
-// checked.
-
-struct Inv<'a> { // invariant w/r/t 'a
-    x: &'a mut &'a isize
-}
-
-pub trait Foo<'a, 't> {
-    fn no_bound<'b>(self, b: Inv<'b>);
-    fn has_bound<'b:'a>(self, b: Inv<'b>);
-    fn wrong_bound1<'b,'c,'d:'a+'b>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>);
-    fn okay_bound<'b,'c,'d:'a+'b+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>);
-    fn another_bound<'x: 'a>(self, x: Inv<'x>, y: Inv<'t>);
-}
-
-impl<'a, 't> Foo<'a, 't> for &'a isize {
-    fn no_bound<'b:'a>(self, b: Inv<'b>) {
-        //~^ ERROR lifetime parameters or bounds on method `no_bound` do not match
-    }
-
-    fn has_bound<'b>(self, b: Inv<'b>) {
-        //~^ ERROR lifetime parameters or bounds on method `has_bound` do not match
-    }
-
-    fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
-        //~^ ERROR method not compatible with trait
-        //
-        // Note: This is a terrible error message. It is caused
-        // because, in the trait, 'b is early bound, and in the impl,
-        // 'c is early bound, so -- after substitution -- the
-        // lifetimes themselves look isomorphic.  We fail because the
-        // lifetimes that appear in the types are in the wrong
-        // order. This should really be fixed by keeping more
-        // information about the lifetime declarations in the trait so
-        // that we can compare better to the impl, even in cross-crate
-        // cases.
-    }
-
-    fn okay_bound<'b,'c,'e:'b+'c>(self, b: Inv<'b>, c: Inv<'c>, e: Inv<'e>) {
-    }
-
-    fn another_bound<'x: 't>(self, x: Inv<'x>, y: Inv<'t>) {
-        //~^ ERROR E0276
-    }
-}
-
-fn main() { }
index 96311d6de176c64a824e9364e06db938c7c75a74..821015ece77124acff5bd042fc7e4d21960964a4 100644 (file)
@@ -15,7 +15,7 @@
 fn main() {
     // these literals are just silly.
     ''';
-    //~^ ERROR: character constant must be escaped: \'
+    //~^ ERROR: character constant must be escaped: '
 
     // note that this is a literal "\n" byte
     '
diff --git a/src/test/parse-fail/lex-stray-backslash.rs b/src/test/parse-fail/lex-stray-backslash.rs
new file mode 100644 (file)
index 0000000..b6042bb
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -Z parse-only
+
+\ //~ ERROR: unknown start of token: \
diff --git a/src/test/run-make/stdin-non-utf8/Makefile b/src/test/run-make/stdin-non-utf8/Makefile
new file mode 100644 (file)
index 0000000..7948c44
--- /dev/null
@@ -0,0 +1,6 @@
+-include ../tools.mk
+
+all:
+       cp non-utf8 $(TMPDIR)/non-utf.rs
+       cat $(TMPDIR)/non-utf.rs | $(RUSTC) - 2>&1 \
+               | $(CGREP) "error: couldn't read from stdin, as it did not contain valid UTF-8"
diff --git a/src/test/run-make/stdin-non-utf8/non-utf8 b/src/test/run-make/stdin-non-utf8/non-utf8
new file mode 100644 (file)
index 0000000..bc87051
--- /dev/null
@@ -0,0 +1 @@
diff --git a/src/test/run-pass/generator/too-live-local-in-immovable-gen.rs b/src/test/run-pass/generator/too-live-local-in-immovable-gen.rs
new file mode 100644 (file)
index 0000000..2314533
--- /dev/null
@@ -0,0 +1,28 @@
+// 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.
+
+#![feature(generators)]
+
+fn main() {
+    unsafe {
+        static move || {
+            // Tests that the generator transformation finds out that `a` is not live
+            // during the yield expression. Type checking will also compute liveness
+            // and it should also find out that `a` is not live.
+            // The compiler will panic if the generator transformation finds that
+            // `a` is live and type checking finds it dead.
+            let a = {
+                yield ();
+                4i32
+            };
+            &a;
+        };
+    }
+}
diff --git a/src/test/run-pass/issue-47139-1.rs b/src/test/run-pass/issue-47139-1.rs
new file mode 100644 (file)
index 0000000..cb87991
--- /dev/null
@@ -0,0 +1,87 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Regression test for issue #47139:
+//
+// Coherence was encountering an (unnecessary) overflow trying to
+// decide if the two impls of dummy overlap.
+//
+// The overflow went something like:
+//
+// - `&'a ?T: Insertable` ?
+// - let ?T = Option<?U> ?
+// - `Option<?U>: Insertable` ?
+// - `Option<&'a ?U>: Insertable` ?
+// - `&'a ?U: Insertable` ?
+//
+// While somewhere in the middle, a projection would occur, which
+// broke cycle detection.
+//
+// It turned out that this cycle was being kicked off due to some
+// extended diagnostic attempts in coherence, so removing those
+// sidestepped the issue for now.
+
+#![allow(dead_code)]
+
+pub trait Insertable {
+    type Values;
+
+    fn values(self) -> Self::Values;
+}
+
+impl<T> Insertable for Option<T>
+    where
+    T: Insertable,
+    T::Values: Default,
+{
+    type Values = T::Values;
+
+    fn values(self) -> Self::Values {
+        self.map(Insertable::values).unwrap_or_default()
+    }
+}
+
+impl<'a, T> Insertable for &'a Option<T>
+    where
+    Option<&'a T>: Insertable,
+{
+    type Values = <Option<&'a T> as Insertable>::Values;
+
+    fn values(self) -> Self::Values {
+        self.as_ref().values()
+    }
+}
+
+impl<'a, T> Insertable for &'a [T]
+{
+    type Values = Self;
+
+    fn values(self) -> Self::Values {
+        self
+    }
+}
+
+trait Unimplemented { }
+
+trait Dummy { }
+
+struct Foo<T> { t: T }
+
+impl<'a, U> Dummy for Foo<&'a U>
+    where &'a U: Insertable
+{
+}
+
+impl<T> Dummy for T
+    where T: Unimplemented
+{ }
+
+fn main() {
+}
diff --git a/src/test/run-pass/issue-47139-2.rs b/src/test/run-pass/issue-47139-2.rs
new file mode 100644 (file)
index 0000000..08eaee5
--- /dev/null
@@ -0,0 +1,75 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Regression test for issue #47139:
+//
+// Same as issue-47139-1.rs, but the impls of dummy are in the
+// opposite order. This influenced the way that coherence ran and in
+// some cases caused the overflow to occur when it wouldn't otherwise.
+// In an effort to make the regr test more robust, I am including both
+// orderings.
+
+#![allow(dead_code)]
+
+pub trait Insertable {
+    type Values;
+
+    fn values(self) -> Self::Values;
+}
+
+impl<T> Insertable for Option<T>
+    where
+    T: Insertable,
+    T::Values: Default,
+{
+    type Values = T::Values;
+
+    fn values(self) -> Self::Values {
+        self.map(Insertable::values).unwrap_or_default()
+    }
+}
+
+impl<'a, T> Insertable for &'a Option<T>
+    where
+    Option<&'a T>: Insertable,
+{
+    type Values = <Option<&'a T> as Insertable>::Values;
+
+    fn values(self) -> Self::Values {
+        self.as_ref().values()
+    }
+}
+
+impl<'a, T> Insertable for &'a [T]
+{
+    type Values = Self;
+
+    fn values(self) -> Self::Values {
+        self
+    }
+}
+
+trait Unimplemented { }
+
+trait Dummy { }
+
+struct Foo<T> { t: T }
+
+impl<T> Dummy for T
+    where T: Unimplemented
+{ }
+
+impl<'a, U> Dummy for Foo<&'a U>
+    where &'a U: Insertable
+{
+}
+
+fn main() {
+}
diff --git a/src/test/run-pass/issue-47638.rs b/src/test/run-pass/issue-47638.rs
new file mode 100644 (file)
index 0000000..6f627b2
--- /dev/null
@@ -0,0 +1,18 @@
+// 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 id<'c, 'b>(f: &'c &'b Fn(&i32)) -> &'c &'b Fn(&'static i32) {
+    f
+}
+
+fn main() {
+    let f: &Fn(&i32) = &|x| {};
+    id(&f);
+}
diff --git a/src/test/run-pass/issue-47789.rs b/src/test/run-pass/issue-47789.rs
new file mode 100644 (file)
index 0000000..3148939
--- /dev/null
@@ -0,0 +1,20 @@
+// 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.
+
+
+#![feature(nll)]
+
+static mut x: &'static u32 = &0;
+
+fn foo() {
+    unsafe { x = &1; }
+}
+
+fn main() { }
index c2414e5ff5d96c98cebb88c54fef144dfa36bcda..22469b2fde058180210fd9e58efd4c6b87809b6b 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// min-llvm-version 4.0
+// no-system-llvm -- needs MCSubtargetInfo::getFeatureTable()
 // ignore-cloudabi no std::env
 
 #![feature(cfg_target_feature)]
index 22555c8d6a779edbf75a49d3822f8dcb870748c1..4deced1297bd11d78332c3f28f7a70b15d9e1c94 100644 (file)
@@ -15,7 +15,7 @@
 // ignore-emscripten no processes
 // ignore-musl FIXME #31506
 // ignore-pretty
-// no-system-llvm
+// min-system-llvm-version 5.0
 // compile-flags: -C lto
 // no-prefer-dynamic
 
index 248ad7019261d1abdfa09e4e0f7c97215e5189a0..4224a65ffd7c71da83ff371af64a6c393338da77 100644 (file)
@@ -14,7 +14,7 @@
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
 // ignore-musl FIXME #31506
-// no-system-llvm
+// min-system-llvm-version 5.0
 
 use std::mem;
 use std::process::Command;
diff --git a/src/test/rustdoc/const-evalutation-ice.rs b/src/test/rustdoc/const-evalutation-ice.rs
new file mode 100644 (file)
index 0000000..9fed67e
--- /dev/null
@@ -0,0 +1,22 @@
+// 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.
+
+// Just check if we don't get an ICE for the _S type.
+
+#![feature(const_size_of)]
+
+use std::cell::Cell;
+use std::mem;
+
+pub struct S {
+    s: Cell<usize>
+}
+
+pub type _S = [usize; 0 - (mem::size_of::<S>() != 4) as usize];
index a7aee9b19f1a1e7c0f80e8c9bb739000fb585554..ab0e1003a9e10d76dad53b835907c202538eef02 100644 (file)
@@ -9,11 +9,8 @@ error[E0308]: mismatched types
 note: the lifetime 'a as defined on the impl at 17:1...
   --> $DIR/associated-const-impl-wrong-lifetime.rs:17:1
    |
-17 | / impl<'a> Foo for &'a () {
-18 | |     const NAME: &'a str = "unit";
-19 | |     //~^ ERROR mismatched types [E0308]
-20 | | }
-   | |_^
+17 | impl<'a> Foo for &'a () {
+   | ^^^^^^^^^^^^^^^^^^^^^^^
    = note: ...does not necessarily outlive the static lifetime
 
 error: aborting due to previous error
index 855b3799eb5db106dc305b2d74a821a9cb091c3d..d3588be26697583a60f8ebc43170c2eeeb1d32fa 100644 (file)
@@ -10,8 +10,8 @@ error[E0255]: the name `foo` is defined multiple times
    = note: `foo` must be defined only once in the type namespace of this module
 help: You can use `as` to change the binding name of the import
    |
-13 | use foo::foo as Otherfoo;
-   |     ^^^^^^^^^^^^^^^^^^^^
+13 | use foo::foo as other_foo;
+   |     ^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.rs b/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.rs
new file mode 100644 (file)
index 0000000..617de2c
--- /dev/null
@@ -0,0 +1,58 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check that explicit region bounds are allowed on the various
+// nominal types (but not on other types) and that they are type
+// checked.
+
+struct Inv<'a> { // invariant w/r/t 'a
+    x: &'a mut &'a isize
+}
+
+pub trait Foo<'a, 't> {
+    fn no_bound<'b>(self, b: Inv<'b>);
+    fn has_bound<'b:'a>(self, b: Inv<'b>);
+    fn wrong_bound1<'b,'c,'d:'a+'b>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>);
+    fn okay_bound<'b,'c,'d:'a+'b+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>);
+    fn another_bound<'x: 'a>(self, x: Inv<'x>, y: Inv<'t>);
+}
+
+impl<'a, 't> Foo<'a, 't> for &'a isize {
+    fn no_bound<'b:'a>(self, b: Inv<'b>) {
+        //~^ ERROR lifetime parameters or bounds on method `no_bound` do not match
+    }
+
+    fn has_bound<'b>(self, b: Inv<'b>) {
+        //~^ ERROR lifetime parameters or bounds on method `has_bound` do not match
+    }
+
+    fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
+        //~^ ERROR method not compatible with trait
+        //
+        // Note: This is a terrible error message. It is caused
+        // because, in the trait, 'b is early bound, and in the impl,
+        // 'c is early bound, so -- after substitution -- the
+        // lifetimes themselves look isomorphic.  We fail because the
+        // lifetimes that appear in the types are in the wrong
+        // order. This should really be fixed by keeping more
+        // information about the lifetime declarations in the trait so
+        // that we can compare better to the impl, even in cross-crate
+        // cases.
+    }
+
+    fn okay_bound<'b,'c,'e:'b+'c>(self, b: Inv<'b>, c: Inv<'c>, e: Inv<'e>) {
+    }
+
+    fn another_bound<'x: 't>(self, x: Inv<'x>, y: Inv<'t>) {
+        //~^ ERROR E0276
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr b/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr
new file mode 100644 (file)
index 0000000..e832324
--- /dev/null
@@ -0,0 +1,48 @@
+error[E0195]: lifetime parameters or bounds on method `no_bound` do not match the trait declaration
+  --> $DIR/regions-bound-missing-bound-in-impl.rs:28:5
+   |
+20 |     fn no_bound<'b>(self, b: Inv<'b>);
+   |     ---------------------------------- lifetimes in impl do not match this method in trait
+...
+28 |     fn no_bound<'b:'a>(self, b: Inv<'b>) {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetimes do not match method in trait
+
+error[E0195]: lifetime parameters or bounds on method `has_bound` do not match the trait declaration
+  --> $DIR/regions-bound-missing-bound-in-impl.rs:32:5
+   |
+21 |     fn has_bound<'b:'a>(self, b: Inv<'b>);
+   |     -------------------------------------- lifetimes in impl do not match this method in trait
+...
+32 |     fn has_bound<'b>(self, b: Inv<'b>) {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetimes do not match method in trait
+
+error[E0308]: method not compatible with trait
+  --> $DIR/regions-bound-missing-bound-in-impl.rs:36:5
+   |
+36 |     fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
+   |
+   = note: expected type `fn(&'a isize, Inv<'c>, Inv<'c>, Inv<'d>)`
+              found type `fn(&'a isize, Inv<'_>, Inv<'c>, Inv<'d>)`
+note: the lifetime 'c as defined on the method body at 36:5...
+  --> $DIR/regions-bound-missing-bound-in-impl.rs:36:5
+   |
+36 |     fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...does not necessarily outlive the lifetime 'c as defined on the method body at 36:5
+  --> $DIR/regions-bound-missing-bound-in-impl.rs:36:5
+   |
+36 |     fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0276]: impl has stricter requirements than trait
+  --> $DIR/regions-bound-missing-bound-in-impl.rs:53:5
+   |
+24 |     fn another_bound<'x: 'a>(self, x: Inv<'x>, y: Inv<'t>);
+   |     ------------------------------------------------------- definition of `another_bound` from trait
+...
+53 |     fn another_bound<'x: 't>(self, x: Inv<'x>, y: Inv<'t>) {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `'x: 't`
+
+error: aborting due to 4 previous errors
+
index ebb1e561e57ab6acec3dd4f1e24e891f7b0fd186..5c612522d9a318ae436994942cc92562d383c89a 100644 (file)
@@ -41,14 +41,8 @@ note: the anonymous lifetime #2 defined on the body at 47:29...
 note: ...does not necessarily outlive the lifetime 'x as defined on the function body at 42:1
   --> $DIR/expect-region-supply-region.rs:42:1
    |
-42 | / fn expect_bound_supply_named<'x>() {
-43 | |     let mut f: Option<&u32> = None;
-44 | |
-45 | |     // Here we give a type annotation that `x` should be free. We get
-...  |
-54 | |     });
-55 | | }
-   | |_^
+42 | fn expect_bound_supply_named<'x>() {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/expect-region-supply-region.rs:47:33
@@ -61,14 +55,8 @@ error[E0308]: mismatched types
 note: the lifetime 'x as defined on the function body at 42:1...
   --> $DIR/expect-region-supply-region.rs:42:1
    |
-42 | / fn expect_bound_supply_named<'x>() {
-43 | |     let mut f: Option<&u32> = None;
-44 | |
-45 | |     // Here we give a type annotation that `x` should be free. We get
-...  |
-54 | |     });
-55 | | }
-   | |_^
+42 | fn expect_bound_supply_named<'x>() {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...does not necessarily outlive the anonymous lifetime #2 defined on the body at 47:29
   --> $DIR/expect-region-supply-region.rs:47:29
    |
index fcd3f2696f200122d19bd51677572e20aecd1190..2a0f9ee34f2befdbb71013c6c901effa4e6bb9ee 100644 (file)
@@ -9,8 +9,8 @@ error[E0252]: the name `foo` is defined multiple times
    = note: `foo` must be defined only once in the value namespace of this module
 help: You can use `as` to change the binding name of the import
    |
-23 | use sub2::foo as Otherfoo; //~ ERROR the name `foo` is defined multiple times
-   |     ^^^^^^^^^^^^^^^^^^^^^
+23 | use sub2::foo as other_foo; //~ ERROR the name `foo` is defined multiple times
+   |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 0a52a928f69d48bf269625e95b585e95420857d0..0f7d2e540d80a8b6e5f3b5aa063f45f999509e7e 100644 (file)
@@ -1,12 +1,3 @@
-error[E0626]: borrow may still be in use when generator yields (Mir)
-  --> $DIR/generator-with-nll.rs:20:17
-   |
-20 |         let b = &mut true; //~ ERROR borrow may still be in use when generator yields (Ast)
-   |                 ^^^^^^^^^
-21 |         //~^ borrow may still be in use when generator yields (Mir)
-22 |         yield ();
-   |         -------- possible yield occurs here
-
 error[E0626]: borrow may still be in use when generator yields (Ast)
   --> $DIR/generator-with-nll.rs:19:23
    |
@@ -25,5 +16,14 @@ error[E0626]: borrow may still be in use when generator yields (Ast)
 22 |         yield ();
    |         -------- possible yield occurs here
 
+error[E0626]: borrow may still be in use when generator yields (Mir)
+  --> $DIR/generator-with-nll.rs:20:17
+   |
+20 |         let b = &mut true; //~ ERROR borrow may still be in use when generator yields (Ast)
+   |                 ^^^^^^^^^
+21 |         //~^ borrow may still be in use when generator yields (Mir)
+22 |         yield ();
+   |         -------- possible yield occurs here
+
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/generator/pattern-borrow.rs b/src/test/ui/generator/pattern-borrow.rs
new file mode 100644 (file)
index 0000000..557a5e6
--- /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.
+
+#![feature(generators)]
+
+enum Test { A(i32), B, }
+
+fn main() { }
+
+fn fun(test: Test) {
+    move || {
+        if let Test::A(ref _a) = test { //~ ERROR borrow may still be in use when generator yields
+            yield ();
+        }
+    };
+}
diff --git a/src/test/ui/generator/pattern-borrow.stderr b/src/test/ui/generator/pattern-borrow.stderr
new file mode 100644 (file)
index 0000000..6b39b27
--- /dev/null
@@ -0,0 +1,10 @@
+error[E0626]: borrow may still be in use when generator yields
+  --> $DIR/pattern-borrow.rs:19:24
+   |
+19 |         if let Test::A(ref _a) = test { //~ ERROR borrow may still be in use when generator yields
+   |                        ^^^^^^
+20 |             yield ();
+   |             -------- possible yield occurs here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/generator/sized-yield.rs b/src/test/ui/generator/sized-yield.rs
new file mode 100644 (file)
index 0000000..f38ebf8
--- /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.
+
+#![feature(generators, generator_trait)]
+
+use std::ops::Generator;
+
+fn main() {
+   let s = String::from("foo");
+   let mut gen = move || { //~ ERROR the trait bound `str: std::marker::Sized` is not satisfied
+       yield s[..];
+   };
+   gen.resume(); //~ ERROR the trait bound `str: std::marker::Sized` is not satisfied
+}
diff --git a/src/test/ui/generator/sized-yield.stderr b/src/test/ui/generator/sized-yield.stderr
new file mode 100644 (file)
index 0000000..7adb2cc
--- /dev/null
@@ -0,0 +1,22 @@
+error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
+  --> $DIR/sized-yield.rs:17:26
+   |
+17 |      let mut gen = move || { //~ ERROR the trait bound `str: std::marker::Sized` is not satisfied
+   |  __________________________^
+18 | |        yield s[..];
+19 | |    };
+   | |____^ `str` does not have a constant size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `str`
+   = note: the yield type of a generator must have a statically known size
+
+error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
+  --> $DIR/sized-yield.rs:20:8
+   |
+20 |    gen.resume(); //~ ERROR the trait bound `str: std::marker::Sized` is not satisfied
+   |        ^^^^^^ `str` does not have a constant size known at compile-time
+   |
+   = help: the trait `std::marker::Sized` is not implemented for `str`
+
+error: aborting due to 2 previous errors
+
index 7961dd97441369edef268f752aeb66f7dcbfcb01..114fe8ffcab0e02d6d3d0282c84b63d3b690eac1 100644 (file)
@@ -1,12 +1,3 @@
-error[E0626]: borrow may still be in use when generator yields (Mir)
-  --> $DIR/yield-while-local-borrowed.rs:24:17
-   |
-24 |         let a = &mut 3;
-   |                 ^^^^^^
-...
-27 |         yield();
-   |         ------- possible yield occurs here
-
 error[E0626]: borrow may still be in use when generator yields (Ast)
   --> $DIR/yield-while-local-borrowed.rs:24:22
    |
@@ -25,6 +16,15 @@ error[E0626]: borrow may still be in use when generator yields (Ast)
 55 |             yield();
    |             ------- possible yield occurs here
 
+error[E0626]: borrow may still be in use when generator yields (Mir)
+  --> $DIR/yield-while-local-borrowed.rs:24:17
+   |
+24 |         let a = &mut 3;
+   |                 ^^^^^^
+...
+27 |         yield();
+   |         ------- possible yield occurs here
+
 error[E0626]: borrow may still be in use when generator yields (Mir)
   --> $DIR/yield-while-local-borrowed.rs:52:21
    |
index 7a0d01a8ec2156234c3ed4b82aa90af25830d8a3..1417c71ca1244d3a605722497b42baf3334cacf1 100644 (file)
@@ -2,7 +2,7 @@ error[E0053]: method `fmt` has an incompatible type for trait
   --> $DIR/trait_type.rs:17:4
    |
 17 |    fn fmt(&self, x: &str) -> () { }
-   |    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ in mutability
+   |    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ in mutability
    |
    = note: expected type `fn(&MyType, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>`
               found type `fn(&MyType, &str)`
@@ -19,7 +19,7 @@ error[E0186]: method `fmt` has a `&self` declaration in the trait, but not in th
   --> $DIR/trait_type.rs:27:4
    |
 27 |    fn fmt() -> () { }
-   |    ^^^^^^^^^^^^^^^^^^ expected `&self` in impl
+   |    ^^^^^^^^^^^^^^ expected `&self` in impl
    |
    = note: `fmt` from trait: `fn(&Self, &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error>`
 
index a74401314a18cb3698e6ac419087d5872bcbd23e..6e5b91a11c900e43f054f7eda9a062696a176053 100644 (file)
@@ -9,8 +9,8 @@ error[E0252]: the name `foo` is defined multiple times
    = note: `foo` must be defined only once in the value namespace of this module
 help: You can use `as` to change the binding name of the import
    |
-25 |     use a::foo as Otherfoo; //~ ERROR the name `foo` is defined multiple times
-   |         ^^^^^^^^^^^^^^^^^^
+25 |     use a::foo as other_foo; //~ ERROR the name `foo` is defined multiple times
+   |         ^^^^^^^^^^^^^^^^^^^
 
 error[E0659]: `foo` is ambiguous
   --> $DIR/duplicate.rs:56:9
diff --git a/src/test/ui/in-band-lifetimes/ellided-lifetimes.rs b/src/test/ui/in-band-lifetimes/ellided-lifetimes.rs
new file mode 100644 (file)
index 0000000..5151abd
--- /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.
+#![allow(warnings)]
+#![allow(unused_variables, dead_code, unused, bad_style)]
+#![deny(elided_lifetime_in_path)]
+
+struct Foo<'a> { x: &'a u32 }
+fn foo(x: &Foo) {
+    //~^ ERROR: hidden lifetime parameters are deprecated, try `Foo<'_>`
+}
+
+fn main() {}
diff --git a/src/test/ui/in-band-lifetimes/ellided-lifetimes.stderr b/src/test/ui/in-band-lifetimes/ellided-lifetimes.stderr
new file mode 100644 (file)
index 0000000..613a7be
--- /dev/null
@@ -0,0 +1,14 @@
+error: hidden lifetime parameters are deprecated, try `Foo<'_>`
+  --> $DIR/ellided-lifetimes.rs:15:12
+   |
+15 | fn foo(x: &Foo) {
+   |            ^^^
+   |
+note: lint level defined here
+  --> $DIR/ellided-lifetimes.rs:12:9
+   |
+12 | #![deny(elided_lifetime_in_path)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.rs
new file mode 100644 (file)
index 0000000..f845762
--- /dev/null
@@ -0,0 +1,22 @@
+// 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 std::ops::Deref;
+trait Trait {}
+
+struct Struct;
+
+impl Deref for Struct {
+    type Target = Trait;
+    fn deref(&self) -> &Trait {
+        unimplemented!();
+    }
+}
+//~^^^^ ERROR cannot infer an appropriate lifetime for lifetime parameter
diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr
new file mode 100644 (file)
index 0000000..7aab31e
--- /dev/null
@@ -0,0 +1,22 @@
+error[E0601]: main function not found
+
+error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in generic type due to conflicting requirements
+  --> $DIR/mismatched_trait_impl-2.rs:18:5
+   |
+18 |     fn deref(&self) -> &Trait {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 18:5...
+  --> $DIR/mismatched_trait_impl-2.rs:18:5
+   |
+18 | /     fn deref(&self) -> &Trait {
+19 | |         unimplemented!();
+20 | |     }
+   | |_____^
+   = note: ...but the lifetime must also be valid for the static lifetime...
+   = note: ...so that the method type is compatible with trait:
+           expected fn(&Struct) -> &Trait + 'static
+              found fn(&Struct) -> &Trait
+
+error: aborting due to 2 previous errors
+
index e96f7181a6daeb80aa2d6774227e74fb786f013d..fd6be01da9f460a44c7066dbcbfd2724ce00980f 100644 (file)
@@ -1,10 +1,8 @@
 error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'a in generic type due to conflicting requirements
   --> $DIR/mismatched_trait_impl.rs:19:5
    |
-19 | /     fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { //~ ERROR cannot infer
-20 | |         x
-21 | |     }
-   | |_____^
+19 |     fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { //~ ERROR cannot infer
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the method body at 19:5...
   --> $DIR/mismatched_trait_impl.rs:19:5
@@ -13,27 +11,14 @@ note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on th
 20 | |         x
 21 | |     }
    | |_____^
-note: ...so that method type is compatible with trait (expected fn(&i32, &'a u32, &u32) -> &'a u32, found fn(&i32, &u32, &u32) -> &u32)
-  --> $DIR/mismatched_trait_impl.rs:19:5
-   |
-19 | /     fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { //~ ERROR cannot infer
-20 | |         x
-21 | |     }
-   | |_____^
-note: but, the lifetime must be valid for the lifetime 'a as defined on the method body at 19:5...
+note: ...but the lifetime must also be valid for the lifetime 'a as defined on the method body at 19:5...
   --> $DIR/mismatched_trait_impl.rs:19:5
    |
-19 | /     fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { //~ ERROR cannot infer
-20 | |         x
-21 | |     }
-   | |_____^
-note: ...so that method type is compatible with trait (expected fn(&i32, &'a u32, &u32) -> &'a u32, found fn(&i32, &u32, &u32) -> &u32)
-  --> $DIR/mismatched_trait_impl.rs:19:5
-   |
-19 | /     fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { //~ ERROR cannot infer
-20 | |         x
-21 | |     }
-   | |_____^
+19 |     fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { //~ ERROR cannot infer
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...so that the method type is compatible with trait:
+           expected fn(&i32, &'a u32, &u32) -> &'a u32
+              found fn(&i32, &u32, &u32) -> &u32
 
 error: aborting due to previous error
 
index cb2eca87068f813e555a954509c5965d6a28b027..e6424e535ee329e36577f216a937efc8c2c3fff8 100644 (file)
@@ -24,8 +24,8 @@ error[E0252]: the name `sync` is defined multiple times
    = note: `sync` must be defined only once in the type namespace of this module
 help: You can use `as` to change the binding name of the import
    |
-14 | use std::sync as Othersync; //~ ERROR the name `sync` is defined multiple times
-   |     ^^^^^^^^^^^^^^^^^^^^^^
+14 | use std::sync as other_sync; //~ ERROR the name `sync` is defined multiple times
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
index b580b8e73137b134e5d43df72fe13e9003a3a70d..b24544743d87da84c5e64e6432854df272775864 100644 (file)
@@ -14,14 +14,8 @@ note: the anonymous lifetime #1 defined on the method body at 15:5...
 note: ...does not necessarily outlive the lifetime 'a as defined on the trait at 13:1
   --> $DIR/issue-27942.rs:13:1
    |
-13 | / pub trait Buffer<'a, R: Resources<'a>> {
-14 | |
-15 | |     fn select(&self) -> BufferViewHandle<R>;
-16 | |     //~^ ERROR mismatched types
-...  |
-19 | |     //~| lifetime mismatch
-20 | | }
-   | |_^
+13 | pub trait Buffer<'a, R: Resources<'a>> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
   --> $DIR/issue-27942.rs:15:5
@@ -34,14 +28,8 @@ error[E0308]: mismatched types
 note: the lifetime 'a as defined on the trait at 13:1...
   --> $DIR/issue-27942.rs:13:1
    |
-13 | / pub trait Buffer<'a, R: Resources<'a>> {
-14 | |
-15 | |     fn select(&self) -> BufferViewHandle<R>;
-16 | |     //~^ ERROR mismatched types
-...  |
-19 | |     //~| lifetime mismatch
-20 | | }
-   | |_^
+13 | pub trait Buffer<'a, R: Resources<'a>> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...does not necessarily outlive the anonymous lifetime #1 defined on the method body at 15:5
   --> $DIR/issue-27942.rs:15:5
    |
index 439b123975f82616802892ed5876344424ad0a84..c4ad232ae7eba6f5b11af4182801ea27da2af831 100644 (file)
@@ -24,14 +24,8 @@ note: the anonymous lifetime #1 defined on the method body at 16:5...
 note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 13:1
   --> $DIR/issue-37884.rs:13:1
    |
-13 | / impl<'a, T: 'a> Iterator for RepeatMut<'a, T> {
-14 | |
-15 | |     type Item = &'a mut T;
-16 | |     fn next(&'a mut self) -> Option<Self::Item>
-...  |
-21 | |     }
-22 | | }
-   | |_^
+13 | impl<'a, T: 'a> Iterator for RepeatMut<'a, T> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 2f332a7a55850dc5f74789d067fe88958306f979..7b5cce218e9f26ad8fe4ee1e82a5fb299db62a04 100644 (file)
@@ -10,12 +10,8 @@ error[E0597]: borrowed value does not live long enough (Ast)
 note: borrowed value must be valid for the lifetime 'a as defined on the function body at 13:1...
   --> $DIR/issue-46472.rs:13:1
    |
-13 | / fn bar<'a>() -> &'a mut u32 {
-14 | |     &mut 4
-15 | |     //~^ ERROR borrowed value does not live long enough (Ast) [E0597]
-16 | |     //~| ERROR borrowed value does not live long enough (Mir) [E0597]
-17 | | }
-   | |_^
+13 | fn bar<'a>() -> &'a mut u32 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0597]: borrowed value does not live long enough (Mir)
   --> $DIR/issue-46472.rs:14:10
@@ -29,12 +25,8 @@ error[E0597]: borrowed value does not live long enough (Mir)
 note: borrowed value must be valid for the lifetime 'a as defined on the function body at 13:1...
   --> $DIR/issue-46472.rs:13:1
    |
-13 | / fn bar<'a>() -> &'a mut u32 {
-14 | |     &mut 4
-15 | |     //~^ ERROR borrowed value does not live long enough (Ast) [E0597]
-16 | |     //~| ERROR borrowed value does not live long enough (Mir) [E0597]
-17 | | }
-   | |_^
+13 | fn bar<'a>() -> &'a mut u32 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issue-47706-trait.rs b/src/test/ui/issue-47706-trait.rs
new file mode 100644 (file)
index 0000000..86a9da4
--- /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.
+
+trait T {
+    fn f(&self, _: ()) {
+        None::<()>.map(Self::f);
+    }
+    //~^^ ERROR function is expected to take a single 0-tuple as argument
+}
diff --git a/src/test/ui/issue-47706-trait.stderr b/src/test/ui/issue-47706-trait.stderr
new file mode 100644 (file)
index 0000000..320e98d
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0601]: main function not found
+
+error[E0593]: function is expected to take a single 0-tuple as argument, but it takes 2 distinct arguments
+  --> $DIR/issue-47706-trait.rs:13:20
+   |
+12 |     fn f(&self, _: ()) {
+   |     ------------------ takes 2 distinct arguments
+13 |         None::<()>.map(Self::f);
+   |                    ^^^ expected function that takes a single 0-tuple as argument
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.rs b/src/test/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.rs
new file mode 100644 (file)
index 0000000..b4e6c50
--- /dev/null
@@ -0,0 +1,40 @@
+// 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.
+
+// must-compile-successfully
+
+#![warn(unused_parens)]
+
+macro_rules! the_worship_the_heart_lifts_above {
+    ( @as_expr, $e:expr) => { $e };
+    ( @generate_fn, $name:tt) => {
+        #[allow(dead_code)] fn the_moth_for_the_star<'a>() -> Option<&'a str> {
+            Some(the_worship_the_heart_lifts_above!( @as_expr, $name ))
+        }
+    };
+    ( $name:ident ) => { the_worship_the_heart_lifts_above!( @generate_fn, (stringify!($name))); }
+    // ↑ Notably, this does 𝘯𝘰𝘵 warn: we're declining to lint unused parens in
+    // function/method arguments inside of nested macros because of situations
+    // like those reported in Issue #47775
+}
+
+macro_rules! and_the_heavens_reject_not {
+    () => {
+        // ↓ But let's test that we still lint for unused parens around
+        // function args inside of simple, one-deep macros.
+        #[allow(dead_code)] fn the_night_for_the_morrow() -> Option<isize> { Some((2)) }
+        //~^ WARN unnecessary parentheses around function argument
+    }
+}
+
+the_worship_the_heart_lifts_above!(rah);
+and_the_heavens_reject_not!();
+
+fn main() {}
diff --git a/src/test/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.stderr b/src/test/ui/lint/issue-47775-nested-macro-unnecessary-parens-arg.stderr
new file mode 100644 (file)
index 0000000..097ec1b
--- /dev/null
@@ -0,0 +1,15 @@
+warning: unnecessary parentheses around function argument
+  --> $DIR/issue-47775-nested-macro-unnecessary-parens-arg.rs:32:83
+   |
+32 |         #[allow(dead_code)] fn the_night_for_the_morrow() -> Option<isize> { Some((2)) }
+   |                                                                                   ^^^ help: remove these parentheses
+...
+38 | and_the_heavens_reject_not!();
+   | ------------------------------ in this macro invocation
+   |
+note: lint level defined here
+  --> $DIR/issue-47775-nested-macro-unnecessary-parens-arg.rs:13:9
+   |
+13 | #![warn(unused_parens)]
+   |         ^^^^^^^^^^^^^
+
index dfcaede1402da372ac99f6bc1bcd12964503189c..e35675eacd835cc88f1d7f7e7e25165ec751f7c0 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-tidy-tab
+
 #![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issue #43896
 #![feature(no_debug)]
 
@@ -46,11 +48,15 @@ fn main() {
         let mut a = (1); // should suggest no `mut`, no parens
         //~^ WARN does not need to be mutable
         //~| WARN unnecessary parentheses
+        // the line after `mut` has a `\t` at the beginning, this is on purpose
+        let mut
+               b = 1;
+        //~^^ WARN does not need to be mutable
         let d = Equinox { warp_factor: 9.975 };
         match d {
             Equinox { warp_factor: warp_factor } => {} // should suggest shorthand
             //~^ WARN this pattern is redundant
         }
-        println!("{}", a);
+        println!("{} {}", a, b);
     }
 }
index 8b30f552d377140a0d49f171ab67e46685819a8b..90d6bd312e419505974bf7d8db881e1f323c87f4 100644 (file)
@@ -1,41 +1,53 @@
 warning: unnecessary parentheses around assigned value
-  --> $DIR/suggestions.rs:46:21
+  --> $DIR/suggestions.rs:48:21
    |
-46 |         let mut a = (1); // should suggest no `mut`, no parens
+48 |         let mut a = (1); // should suggest no `mut`, no parens
    |                     ^^^ help: remove these parentheses
    |
 note: lint level defined here
-  --> $DIR/suggestions.rs:11:21
+  --> $DIR/suggestions.rs:13:21
    |
-11 | #![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issue #43896
+13 | #![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issue #43896
    |                     ^^^^^^^^^^^^^
 
 warning: use of deprecated attribute `no_debug`: the `#[no_debug]` attribute was an experimental feature that has been deprecated due to lack of demand. See https://github.com/rust-lang/rust/issues/29721
-  --> $DIR/suggestions.rs:41:1
+  --> $DIR/suggestions.rs:43:1
    |
-41 | #[no_debug] // should suggest removal of deprecated attribute
+43 | #[no_debug] // should suggest removal of deprecated attribute
    | ^^^^^^^^^^^ help: remove this attribute
    |
    = note: #[warn(deprecated)] on by default
 
 warning: variable does not need to be mutable
-  --> $DIR/suggestions.rs:46:13
+  --> $DIR/suggestions.rs:48:13
    |
-46 |         let mut a = (1); // should suggest no `mut`, no parens
-   |             ---^^
+48 |         let mut a = (1); // should suggest no `mut`, no parens
+   |             ----^
    |             |
    |             help: remove this `mut`
    |
 note: lint level defined here
-  --> $DIR/suggestions.rs:11:9
+  --> $DIR/suggestions.rs:13:9
    |
-11 | #![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issue #43896
+13 | #![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issue #43896
    |         ^^^^^^^^^^
 
+warning: variable does not need to be mutable
+  --> $DIR/suggestions.rs:52:13
+   |
+52 |            let mut
+   |   _____________^
+   |  |_____________|
+   | ||
+53 | ||             b = 1;
+   | ||____________-^
+   |  |____________|
+   |               help: remove this `mut`
+
 warning: static is marked #[no_mangle], but not exported
-  --> $DIR/suggestions.rs:14:14
+  --> $DIR/suggestions.rs:16:14
    |
-14 | #[no_mangle] static SHENZHOU: usize = 1; // should suggest `pub`
+16 | #[no_mangle] static SHENZHOU: usize = 1; // should suggest `pub`
    |              -^^^^^^^^^^^^^^^^^^^^^^^^^^
    |              |
    |              help: try making it public: `pub`
@@ -43,9 +55,9 @@ warning: static is marked #[no_mangle], but not exported
    = note: #[warn(private_no_mangle_statics)] on by default
 
 error: const items should never be #[no_mangle]
-  --> $DIR/suggestions.rs:16:14
+  --> $DIR/suggestions.rs:18:14
    |
-16 | #[no_mangle] const DISCOVERY: usize = 1; // should suggest `pub static` rather than `const`
+18 | #[no_mangle] const DISCOVERY: usize = 1; // should suggest `pub static` rather than `const`
    |              -----^^^^^^^^^^^^^^^^^^^^^^
    |              |
    |              help: try a static value: `pub static`
@@ -53,19 +65,19 @@ error: const items should never be #[no_mangle]
    = note: #[deny(no_mangle_const_items)] on by default
 
 warning: functions generic over types must be mangled
-  --> $DIR/suggestions.rs:20:1
+  --> $DIR/suggestions.rs:22:1
    |
-19 | #[no_mangle] // should suggest removal (generics can't be no-mangle)
+21 | #[no_mangle] // should suggest removal (generics can't be no-mangle)
    | ------------ help: remove this attribute
-20 | pub fn defiant<T>(_t: T) {}
+22 | pub fn defiant<T>(_t: T) {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: #[warn(no_mangle_generic_items)] on by default
 
 warning: function is marked #[no_mangle], but not exported
-  --> $DIR/suggestions.rs:24:1
+  --> $DIR/suggestions.rs:26:1
    |
-24 | fn rio_grande() {} // should suggest `pub`
+26 | fn rio_grande() {} // should suggest `pub`
    | -^^^^^^^^^^^^^^^^^
    | |
    | help: try making it public: `pub`
@@ -73,29 +85,29 @@ warning: function is marked #[no_mangle], but not exported
    = note: #[warn(private_no_mangle_fns)] on by default
 
 warning: static is marked #[no_mangle], but not exported
-  --> $DIR/suggestions.rs:31:18
+  --> $DIR/suggestions.rs:33:18
    |
-31 |     #[no_mangle] pub static DAUNTLESS: bool = true;
+33 |     #[no_mangle] pub static DAUNTLESS: bool = true;
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: function is marked #[no_mangle], but not exported
-  --> $DIR/suggestions.rs:33:18
+  --> $DIR/suggestions.rs:35:18
    |
-33 |     #[no_mangle] pub fn val_jean() {}
+35 |     #[no_mangle] pub fn val_jean() {}
    |                  ^^^^^^^^^^^^^^^^^^^^
 
 warning: denote infinite loops with `loop { ... }`
-  --> $DIR/suggestions.rs:44:5
+  --> $DIR/suggestions.rs:46:5
    |
-44 |     while true { // should suggest `loop`
+46 |     while true { // should suggest `loop`
    |     ^^^^^^^^^^ help: use `loop`
    |
    = note: #[warn(while_true)] on by default
 
 warning: the `warp_factor:` in this pattern is redundant
-  --> $DIR/suggestions.rs:51:23
+  --> $DIR/suggestions.rs:57:23
    |
-51 |             Equinox { warp_factor: warp_factor } => {} // should suggest shorthand
+57 |             Equinox { warp_factor: warp_factor } => {} // should suggest shorthand
    |                       ------------^^^^^^^^^^^^
    |                       |
    |                       help: remove this
index 296b3b191e319e93ec0ddbf5c8ee7219401fcdee..982de00b4fa7c37ea89f6f4a500d3eb176423b98 100644 (file)
@@ -3,6 +3,10 @@ error[E0571]: `break` with value from a `for` loop
    |
 22 |         break 22 //~ ERROR `break` with value from a `for` loop
    |         ^^^^^^^^ can only break with a value inside `loop`
+help: instead, use `break` on its own without a value inside this `for` loop
+   |
+22 |         break //~ ERROR `break` with value from a `for` loop
+   |         ^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/macros/span-covering-argument-1.rs b/src/test/ui/macros/span-covering-argument-1.rs
new file mode 100644 (file)
index 0000000..bfc137f
--- /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.
+
+macro_rules! bad {
+    ($s:ident whatever) => {
+        {
+            let $s = 0;
+            *&mut $s = 0;
+            //~^ ERROR cannot borrow immutable local variable `foo` as mutable [E0596]
+        }
+    }
+}
+
+fn main() {
+    bad!(foo whatever);
+}
diff --git a/src/test/ui/macros/span-covering-argument-1.stderr b/src/test/ui/macros/span-covering-argument-1.stderr
new file mode 100644 (file)
index 0000000..677d2f1
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0596]: cannot borrow immutable local variable `foo` as mutable
+  --> $DIR/span-covering-argument-1.rs:15:19
+   |
+14 |             let $s = 0;
+   |                 -- consider changing this to `mut $s`
+15 |             *&mut $s = 0;
+   |                   ^^ cannot borrow mutably
+...
+22 |     bad!(foo whatever);
+   |     ------------------- in this macro invocation
+
+error: aborting due to previous error
+
index 03ef66681e4404f35980d00429d34fccc3f241a5..e2245b8a8b10a7b39bdb0827fc04123f9f055441 100644 (file)
@@ -10,8 +10,8 @@ error[E0255]: the name `transmute` is defined multiple times
    = note: `transmute` must be defined only once in the value namespace of this module
 help: You can use `as` to change the binding name of the import
    |
-11 | use std::mem::transmute as Othertransmute;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+11 | use std::mem::transmute as other_transmute;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
index 2a0e71e192c621cd64c228768e93ae9125da46a4..728cd12e2c6855c8648e8592244db856a4ffc5f7 100644 (file)
@@ -1,8 +1,8 @@
 warning: struct is never used: `S`
-  --> $DIR/macro-span-replacement.rs:17:9
+  --> $DIR/macro-span-replacement.rs:17:14
    |
 17 |         $b $a; //~ WARN struct is never used
-   |         ^^^^^^
+   |              ^
 ...
 22 |     m!(S struct);
    |     ------------- in this macro invocation
index a99dbf21e54e20e27c903da045de13d8de243094..24ba27b27ad368623eab3eeaa7398348fa4c6589 100644 (file)
@@ -8,7 +8,7 @@ note: lifetime parameter instantiated with the lifetime 'a as defined on the imp
   --> $DIR/static-lifetime.rs:13:1
    |
 13 | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {} //~ ERROR lifetime bound
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: but lifetime parameter must outlive the static lifetime
 
 error: aborting due to previous error
index d2ac15f7ffcb3542db461a5bb79e9c25078ffc92..01dba62a8511d17462ac1bff8b9367be1bf0b2d4 100644 (file)
@@ -7,7 +7,7 @@ error[E0259]: the name `std` is defined multiple times
    = note: `std` must be defined only once in the type namespace of this module
 help: You can use `as` to change the binding name of the import
    |
-11 | extern crate std as Otherstd;
+11 | extern crate std as other_std;
    |
 
 error: aborting due to previous error
index bb64909e64a0c5b67b780c2f9dbfee59205b5be5..1c9f306f493db9b5c357b3e84abcc583041668a5 100644 (file)
@@ -25,7 +25,7 @@ error[E0252]: the name `bar` is defined multiple times
    = note: `bar` must be defined only once in the type namespace of this module
 help: You can use `as` to change the binding name of the import
    |
-15 |     self as Otherbar
+15 |     self as other_bar
    |
 
 error: aborting due to 3 previous errors
index ff662736bdd1b7f004a5a178587cf4167243edc4..80750f9a3fee08081a8392829887462a6badc20c 100644 (file)
@@ -167,7 +167,7 @@ fn ignore_llvm(config: &Config, line: &str) -> bool {
                         .expect("Malformed llvm version directive");
                     // Ignore if using system LLVM and actual version
                     // is smaller the minimum required version
-                    !(config.system_llvm && &actual_version[..] < min_version)
+                    config.system_llvm && &actual_version[..] < min_version
                 } else {
                     false
                 }
index 511321ae1c2fa3f0e334885fecf406dd6c882836..dee42bda8156a28ead609080e27b02173bb9c29e 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 511321ae1c2fa3f0e334885fecf406dd6c882836
+Subproject commit dee42bda8156a28ead609080e27b02173bb9c29e
index e0e3e22248cd14ebbe0253e9720261a0328bfc59..346238f49740d6c98102a6a59811b1625c73a9d7 160000 (submodule)
@@ -1 +1 @@
-Subproject commit e0e3e22248cd14ebbe0253e9720261a0328bfc59
+Subproject commit 346238f49740d6c98102a6a59811b1625c73a9d7