]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #50670 - alexcrichton:remove-extern-crate-correct-span, r=Manishearth
authorkennytm <kennytm@gmail.com>
Sun, 13 May 2018 08:15:49 +0000 (16:15 +0800)
committerkennytm <kennytm@gmail.com>
Sun, 13 May 2018 09:20:31 +0000 (17:20 +0800)
rustc: Include semicolon when removing `extern crate`

Currently the lint for removing `extern crate` suggests removing `extern crate`
most of the time, but the rest of the time it suggest replacing it with `use
crate_name`. Unfortunately though when spliced into the original code you're
replacing

    extern crate foo;

with

    use foo

which is syntactically invalid! This commit ensure that the trailing semicolon
is included in rustc's suggestion to ensure that the code continues to compile
afterwards.

151 files changed:
appveyor.yml
src/Cargo.lock
src/bootstrap/bin/rustc.rs
src/bootstrap/bootstrap.py
src/bootstrap/builder.rs
src/ci/docker/x86_64-gnu-tools/checktools.sh
src/liballoc/btree/map.rs
src/liballoc/btree/node.rs
src/libcore/tests/time.rs
src/libcore/time.rs
src/librustc/dep_graph/dep_node.rs
src/librustc/dep_graph/graph.rs
src/librustc/hir/itemlikevisit.rs
src/librustc/hir/mod.rs
src/librustc/ich/fingerprint.rs
src/librustc/ich/impls_ty.rs
src/librustc/middle/const_val.rs
src/librustc/middle/cstore.rs
src/librustc/middle/mem_categorization.rs
src/librustc/middle/stability.rs
src/librustc/mir/interpret/mod.rs
src/librustc/mir/interpret/value.rs
src/librustc/mir/mod.rs
src/librustc/mir/tcx.rs
src/librustc/session/mod.rs
src/librustc/traits/mod.rs
src/librustc/traits/specialize/mod.rs
src/librustc/ty/codec.rs
src/librustc/ty/context.rs
src/librustc/ty/error.rs
src/librustc/ty/inhabitedness/mod.rs
src/librustc/ty/layout.rs
src/librustc/ty/maps/config.rs
src/librustc/ty/maps/keys.rs
src/librustc/ty/maps/mod.rs
src/librustc/ty/maps/plumbing.rs
src/librustc/ty/mod.rs
src/librustc/ty/relate.rs
src/librustc/ty/sty.rs
src/librustc/ty/util.rs
src/librustc/util/ppaux.rs
src/librustc_data_structures/Cargo.toml
src/librustc_data_structures/control_flow_graph/dominators/mod.rs
src/librustc_data_structures/lib.rs
src/librustc_data_structures/owning_ref/mod.rs
src/librustc_data_structures/sync.rs
src/librustc_driver/Cargo.toml
src/librustc_driver/driver.rs
src/librustc_driver/lib.rs
src/librustc_driver/pretty.rs
src/librustc_driver/test.rs
src/librustc_errors/lib.rs
src/librustc_incremental/lib.rs
src/librustc_incremental/persist/mod.rs
src/librustc_incremental/persist/save.rs
src/librustc_incremental/persist/work_product.rs
src/librustc_lint/builtin.rs
src/librustc_llvm/ffi.rs
src/librustc_mir/borrow_check/nll/region_infer/mod.rs
src/librustc_mir/borrow_check/nll/type_check/mod.rs
src/librustc_mir/build/expr/as_rvalue.rs
src/librustc_mir/build/matches/test.rs
src/librustc_mir/build/misc.rs
src/librustc_mir/hair/cx/expr.rs
src/librustc_mir/hair/cx/mod.rs
src/librustc_mir/hair/pattern/_match.rs
src/librustc_mir/hair/pattern/mod.rs
src/librustc_mir/interpret/const_eval.rs
src/librustc_mir/interpret/eval_context.rs
src/librustc_mir/interpret/memory.rs
src/librustc_mir/interpret/mod.rs
src/librustc_mir/interpret/place.rs
src/librustc_mir/lib.rs
src/librustc_mir/monomorphize/collector.rs
src/librustc_mir/monomorphize/item.rs
src/librustc_mir/shim.rs
src/librustc_mir/transform/const_prop.rs
src/librustc_mir/transform/elaborate_drops.rs
src/librustc_mir/transform/generator.rs
src/librustc_mir/transform/qualify_consts.rs
src/librustc_mir/transform/simplify_branches.rs
src/librustc_mir/transform/uniform_array_move_out.rs
src/librustc_mir/util/elaborate_drops.rs
src/librustc_mir/util/pretty.rs
src/librustc_target/spec/linux_musl_base.rs
src/librustc_target/spec/mod.rs
src/librustc_trans/back/link.rs
src/librustc_trans/back/lto.rs
src/librustc_trans/back/write.rs
src/librustc_trans/base.rs
src/librustc_trans/debuginfo/metadata.rs
src/librustc_trans/debuginfo/type_names.rs
src/librustc_trans/lib.rs
src/librustc_trans/mir/constant.rs
src/librustc_trans/mir/operand.rs
src/librustc_trans/mir/rvalue.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/op.rs
src/librustc_typeck/coherence/builtin.rs
src/librustdoc/clean/mod.rs
src/librustdoc/core.rs
src/librustdoc/html/render.rs
src/librustdoc/lib.rs
src/librustdoc/passes/propagate_doc_cfg.rs
src/librustdoc/test.rs
src/libstd/fs.rs
src/libstd/path.rs
src/libstd/sys/redox/syscall/error.rs
src/libstd/sys/unix/fd.rs
src/libstd/sys_common/wtf8.rs
src/libsyntax/feature_gate.rs
src/libsyntax/lib.rs
src/libsyntax_ext/format_foreign.rs
src/libsyntax_pos/Cargo.toml
src/libsyntax_pos/lib.rs
src/libsyntax_pos/symbol.rs
src/rustllvm/PassWrapper.cpp
src/test/codegen/link_section.rs
src/test/compile-fail/auxiliary/edition-extern-crate-allowed.rs [new file with mode: 0644]
src/test/compile-fail/edition-extern-crate-allowed.rs [new file with mode: 0644]
src/test/compile-fail/edition-feature-ok.rs [new file with mode: 0644]
src/test/run-make-fulldeps/issue-36710/Makefile [new file with mode: 0644]
src/test/run-make-fulldeps/issue-36710/foo.cpp [new file with mode: 0644]
src/test/run-make-fulldeps/issue-36710/foo.rs [new file with mode: 0644]
src/test/run-make-fulldeps/tools.mk
src/test/run-pass/atomic-print.rs
src/test/run-pass/union/union-trait-impl.rs
src/test/ui-fulldeps/unnecessary-extern-crate.rs
src/test/ui-fulldeps/unnecessary-extern-crate.stderr
src/test/ui/binary-op-on-double-ref.stderr
src/test/ui/codemap_tests/issue-28308.stderr
src/test/ui/const-eval/duration_conversion.rs [new file with mode: 0644]
src/test/ui/error-codes/E0067.stderr
src/test/ui/error-codes/E0600.stderr
src/test/ui/error-festival.stderr
src/test/ui/feature-gate-negate-unsigned.stderr
src/test/ui/issue-50480.rs [new file with mode: 0644]
src/test/ui/issue-50480.stderr [new file with mode: 0644]
src/test/ui/issue-5239-1.stderr
src/test/ui/lint/unreachable_pub-pub_crate.rs
src/test/ui/lint/unreachable_pub-pub_crate.stderr
src/test/ui/lint/unreachable_pub.rs
src/test/ui/lint/unreachable_pub.stderr
src/test/ui/reachable/expr_unary.stderr
src/test/ui/type-check/missing_trait_impl.rs
src/test/ui/type-check/missing_trait_impl.stderr
src/tools/compiletest/src/runtest.rs
src/tools/tidy/src/deps.rs
src/tools/tidy/src/libcoretest.rs

index a92f4a17811814a95f07f2a7b55efd0578804bf5..60f5b4be8def87b736c930bf7dafc996c428f1c4 100644 (file)
@@ -211,6 +211,11 @@ test_script:
   - set NO_CCACHE=1
   - sh src/ci/run.sh
 
+on_failure:
+  # Dump crash log
+  - set PATH=%PATH%;"C:\Program Files (x86)\Windows Kits\10\Debuggers\X64"
+  - if exist %LOCALAPPDATA%\CrashDumps for %%f in (%LOCALAPPDATA%\CrashDumps\*) do cdb -c "k;q" -G -z "%%f"
+
 branches:
   only:
     - auto
index 8add503bd7dfa999e1756f833a050d9358b297fb..4cb82f94251ff62ab3a94082220fbebb0d899478 100644 (file)
@@ -79,15 +79,15 @@ dependencies = [
 
 [[package]]
 name = "assert_cli"
-version = "0.5.4"
+version = "0.5.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "difference 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "environment 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "skeptic 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -183,11 +183,6 @@ dependencies = [
 name = "build_helper"
 version = "0.1.0"
 
-[[package]]
-name = "bytecount"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
 [[package]]
 name = "byteorder"
 version = "1.2.2"
@@ -240,18 +235,6 @@ dependencies = [
  "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "cargo_metadata"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "cargo_metadata"
 version = "0.5.4"
@@ -312,7 +295,7 @@ dependencies = [
  "clippy-mini-macro-test 0.2.0",
  "clippy_lints 0.0.198",
  "compiletest_rs 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "derive-new 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -574,12 +557,12 @@ version = "0.1.0"
 
 [[package]]
 name = "derive-new"
-version = "0.5.2"
+version = "0.5.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.12.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -587,11 +570,6 @@ name = "diff"
 version = "0.1.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "difference"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
 [[package]]
 name = "difference"
 version = "2.0.0"
@@ -1452,14 +1430,6 @@ dependencies = [
  "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "proc-macro2"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "proc-macro2"
 version = "0.3.6"
@@ -1511,14 +1481,6 @@ name = "quote"
 version = "0.3.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "quote"
-version = "0.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "quote"
 version = "0.5.1"
@@ -1588,7 +1550,7 @@ dependencies = [
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1703,7 +1665,7 @@ name = "rls-analysis"
 version = "0.12.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "derive-new 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "radix_trie 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-data 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1882,6 +1844,27 @@ dependencies = [
  "rustc_target 0.0.0",
 ]
 
+[[package]]
+name = "rustc-rayon"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-rayon-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rustc-rayon-core"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "rustc-serialize"
 version = "0.3.24"
@@ -1949,6 +1932,7 @@ dependencies = [
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-rayon 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_cratesio_shim 0.0.0",
  "serialize 0.0.0",
  "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1964,6 +1948,7 @@ dependencies = [
  "graphviz 0.0.0",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
+ "rustc-rayon 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_allocator 0.0.0",
  "rustc_borrowck 0.0.0",
  "rustc_data_structures 0.0.0",
@@ -1981,6 +1966,7 @@ dependencies = [
  "rustc_traits 0.0.0",
  "rustc_trans_utils 0.0.0",
  "rustc_typeck 0.0.0",
+ "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serialize 0.0.0",
  "syntax 0.0.0",
  "syntax_ext 0.0.0",
@@ -2303,9 +2289,9 @@ dependencies = [
 name = "rustfmt-nightly"
 version = "0.6.1"
 dependencies = [
- "assert_cli 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "assert_cli 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "derive-new 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2326,15 +2312,6 @@ dependencies = [
  "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "same-file"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "same-file"
 version = "1.0.2"
@@ -2362,15 +2339,6 @@ name = "scopeguard"
 version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "semver"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "semver"
 version = "0.9.0"
@@ -2448,21 +2416,6 @@ name = "siphasher"
 version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "skeptic"
-version = "0.13.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "bytecount 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "cargo_metadata 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
- "walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "smallvec"
 version = "0.6.0"
@@ -2573,16 +2526,6 @@ dependencies = [
  "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "syn"
-version = "0.12.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "syn"
 version = "0.13.1"
@@ -2641,6 +2584,7 @@ dependencies = [
 name = "syntax_pos"
 version = "0.0.0"
 dependencies = [
+ "arena 0.0.0",
  "rustc_data_structures 0.0.0",
  "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serialize 0.0.0",
@@ -2966,16 +2910,6 @@ name = "void"
 version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "walkdir"
-version = "1.0.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "walkdir"
 version = "2.1.4"
@@ -3053,7 +2987,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
 "checksum ar 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "35c7a5669cb64f085739387e1308b74e6d44022464b7f1b63bbd4ceb6379ec31"
 "checksum arrayvec 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a1e964f9e24d588183fcb43503abda40d288c8657dfc27311516ce2f05675aef"
-"checksum assert_cli 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "72342c21057a3cb5f7c2d849bf7999a83795434dd36d74fa8c24680581bd1930"
+"checksum assert_cli 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4c8ca6beaa44a3520407b28a4a779a19b1364fcadcb2f258c41a7baf3102ced0"
 "checksum atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "af80143d6f7608d746df1520709e5d141c96f240b0e62b0aa41bdfb53374d9d4"
 "checksum backtrace 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbe525f66f42d207968308ee86bc2dd60aa5fab535b22e616323a173d097d8e"
 "checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661"
@@ -3061,9 +2995,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
 "checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf"
 "checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32"
-"checksum bytecount 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "af27422163679dea46a1a7239dffff64d3dcdc3ba5fe9c49c789fbfe0eb949de"
 "checksum byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "73b5bdfe7ee3ad0b99c9801d58807a9dbc9e09196365b0203853b99889ab3c87"
-"checksum cargo_metadata 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1f56ec3e469bca7c276f2eea015aa05c5e381356febdbb0683c2580189604537"
 "checksum cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6ebd6272a2ca4fd39dbabbd6611eb03df45c2259b3b80b39a9ff8fbdcf42a4b3"
 "checksum cc 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "0ebb87d1116151416c0cf66a0e3fb6430cccd120fd6300794b4dfaa050ac40ba"
 "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
@@ -3085,9 +3017,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum curl 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "aaf20bbe084f285f215eef2165feed70d6b75ba29cad24469badb853a4a287d0"
 "checksum curl-sys 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "71c63a540a9ee4e15e56c3ed9b11a2f121239b9f6d7b7fe30f616e048148df9a"
 "checksum debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9a032eac705ca39214d169f83e3d3da290af06d8d1d344d1baad2fd002dca4b3"
-"checksum derive-new 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6fcb923bab47a948f1b01cec2f758fdebba95c9ebc255458654b2b88efe59d71"
+"checksum derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ceed73957c449214f8440eec8ad7fa282b67dc9eacbb24a3085b15d60397a17a"
 "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a"
-"checksum difference 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3304d19798a8e067e48d8e69b2c37f0b5e9b4e462504ad9e27e9f3fce02bba8"
 "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
 "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab"
 "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0"
@@ -3178,13 +3109,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
 "checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
 "checksum pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6"
-"checksum proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cd07deb3c6d1d9ff827999c7f9b04cdfd66b1b17ae508e14fe47b620f2282ae0"
 "checksum proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "49b6a521dc81b643e9a51e0d1cf05df46d5a2f3c0280ea72bcb68276ba64a118"
 "checksum pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdf85cda6cadfae5428a54661d431330b312bc767ddbc57adbedc24da66e32"
 "checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4"
 "checksum quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45"
 "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
-"checksum quote 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1eca14c727ad12702eb4b6bfb5a232287dcf8385cb8ca83a3eeaf6519c44c408"
 "checksum quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7b0ff51282f28dc1b53fd154298feaa2e77c5ea0dba68e1fd8b03b72fbe13d2a"
 "checksum racer 2.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "40d44bc30fc8d403b665286b2c9a83466ddbf69297668fb02b785c3e58eb8e0d"
 "checksum radix_trie 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "03d0d770481e8af620ca61d3d304bf014f965d7f78e923dc58545e6a545070a9"
@@ -3213,15 +3142,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum rustc-ap-syntax 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b50671adb9b0a7c57a4690ac6a40cb614879f543b64aada42f55b66212492323"
 "checksum rustc-ap-syntax_pos 113.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "55793c2a775230c42661194c48d44b35d4c8439d79ad8528e56651e854c48c63"
 "checksum rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11fb43a206a04116ffd7cfcf9bcb941f8eb6cc7ff667272246b0a1c74259a3cb"
+"checksum rustc-rayon 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1aa5cd8c3a706edb19b6ec6aa7b056bdc635b6e99c5cf7014f9af9d92f15e99"
+"checksum rustc-rayon-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d69983f8613a9c3ba1a3bbf5e8bdf2fd5c42317b1d8dd8623ca8030173bf8a6b"
 "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
 "checksum rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a54aa04a10c68c1c4eacb4337fd883b435997ede17a9385784b990777686b09a"
 "checksum rustfix 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "165a212dd11124d7070892da20f71d82970ef1d1dd41cd804b70f39740a21c85"
-"checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7"
 "checksum same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cfb6eded0b06a0b512c8ddbcf04089138c9b4362c2f696f3c3d76039d68f3637"
 "checksum schannel 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "85fd9df495640643ad2d00443b3d78aae69802ad488debab4f1dd52fc1806ade"
 "checksum scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8674d439c964889e2476f474a3bf198cc9e199e77499960893bac5de7e9218a4"
 "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
-"checksum semver 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bee2bc909ab2d8d60dab26e8cad85b25d795b14603a0dcb627b78b9d30b6454b"
 "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
 "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
 "checksum serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "29465552c9b767d0cb44be3ddf4c3214be15d34975a7750f6cf4f409835f0248"
@@ -3232,7 +3161,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum shell-escape 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "170a13e64f2a51b77a45702ba77287f5c6829375b04a69cf2222acd17d0cfab9"
 "checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
 "checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537"
-"checksum skeptic 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c8431f8fca168e2db4be547bd8329eac70d095dff1444fee4b0fa0fabc7df75a"
 "checksum smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44db0ecb22921ef790d17ae13a3f6d15784183ff5f2a01aa32098c7498d2b4b9"
 "checksum socket2 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ff606e0486e88f5fc6cfeb3966e434fb409abbc7a3ab495238f70a1ca97f789d"
 "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b"
@@ -3243,7 +3171,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum strum 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "099e21b5dd6dd07b5adcf8c4b723a7c0b7efd7a9359bf963d58c0caae8532545"
 "checksum strum_macros 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0dd9bd569e88028750e3ae5c25616b8278ac16a8e61aba4339195c72396d49e1"
 "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
-"checksum syn 0.12.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c97c05b8ebc34ddd6b967994d5c6e9852fa92f8b82b3858c39451f97346dcce5"
 "checksum syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "91b52877572087400e83d24b9178488541e3d535259e04ff17a63df1e5ceff59"
 "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
 "checksum synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a761d12e6d8dcb4dcf952a7a89b475e3a9d69e4a69307e01a470977642914bd"
@@ -3282,7 +3209,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum vcpkg 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7ed0f6789c8a85ca41bbc1c9d175422116a9869bd1cf31bb08e1493ecce60380"
 "checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c"
 "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
-"checksum walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "bb08f9e670fab86099470b97cd2b252d6527f0b3cc1401acdb595ffc9dd288ff"
 "checksum walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "63636bd0eb3d00ccb8b9036381b526efac53caf112b7783b730ab3f8e44da369"
 "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
 "checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3"
index 3f97accaa4d84088ecbd8524e359d653dda4aa6c..76d0e6e28aeda75e779ea703e8563dc01e2b4004 100644 (file)
@@ -268,6 +268,15 @@ fn main() {
         if let Ok(host_linker) = env::var("RUSTC_HOST_LINKER") {
             cmd.arg(format!("-Clinker={}", host_linker));
         }
+
+        if let Ok(s) = env::var("RUSTC_HOST_CRT_STATIC") {
+            if s == "true" {
+                cmd.arg("-C").arg("target-feature=+crt-static");
+            }
+            if s == "false" {
+                cmd.arg("-C").arg("target-feature=-crt-static");
+            }
+        }
     }
 
     if env::var_os("RUSTC_PARALLEL_QUERIES").is_some() {
index 487440becf630de7471c0228bab09c014e33d2ac..28f5192f2cdf455d9e6730f64ce324ab679a8af5 100644 (file)
@@ -489,7 +489,7 @@ class RustBuild(object):
         """
         return os.path.join(self.build_dir, self.build, "stage0")
 
-    def get_toml(self, key):
+    def get_toml(self, key, section=None):
         """Returns the value of the given key in config.toml, otherwise returns None
 
         >>> rb = RustBuild()
@@ -501,12 +501,29 @@ class RustBuild(object):
 
         >>> rb.get_toml("key3") is None
         True
+
+        Optionally also matches the section the key appears in
+
+        >>> rb.config_toml = '[a]\\nkey = "value1"\\n[b]\\nkey = "value2"'
+        >>> rb.get_toml('key', 'a')
+        'value1'
+        >>> rb.get_toml('key', 'b')
+        'value2'
+        >>> rb.get_toml('key', 'c') is None
+        True
         """
+
+        cur_section = None
         for line in self.config_toml.splitlines():
+            section_match = re.match(r'^\s*\[(.*)\]\s*$', line)
+            if section_match is not None:
+                cur_section = section_match.group(1)
+
             match = re.match(r'^{}\s*=(.*)$'.format(key), line)
             if match is not None:
                 value = match.group(1)
-                return self.get_string(value) or value.strip()
+                if section is None or section == cur_section:
+                    return self.get_string(value) or value.strip()
         return None
 
     def cargo(self):
@@ -589,7 +606,17 @@ class RustBuild(object):
         env["LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib") + \
             (os.pathsep + env["LIBRARY_PATH"]) \
             if "LIBRARY_PATH" in env else ""
-        env["RUSTFLAGS"] = "-Cdebuginfo=2"
+        env["RUSTFLAGS"] = "-Cdebuginfo=2 "
+
+        build_section = "target.{}".format(self.build_triple())
+        target_features = []
+        if self.get_toml("crt-static", build_section) == "true":
+            target_features += ["+crt-static"]
+        elif self.get_toml("crt-static", build_section) == "false":
+            target_features += ["-crt-static"]
+        if target_features:
+            env["RUSTFLAGS"] += "-C target-feature=" + (",".join(target_features)) + " "
+
         env["PATH"] = os.path.join(self.bin_root(), "bin") + \
             os.pathsep + env["PATH"]
         if not os.path.isfile(self.cargo()):
index f87436504c6c62a03cab9a5705fb989f82bdf255..17f19222e6ea65637828e5cae38dbb0ab8e604d2 100644 (file)
@@ -690,6 +690,10 @@ pub fn cargo(&self,
             cargo.env("RUSTC_CRT_STATIC", x.to_string());
         }
 
+        if let Some(x) = self.crt_static(compiler.host) {
+            cargo.env("RUSTC_HOST_CRT_STATIC", x.to_string());
+        }
+
         // Enable usage of unstable features
         cargo.env("RUSTC_BOOTSTRAP", "1");
         self.add_rust_test_threads(&mut cargo);
index 3fed0175371a7d494ec1d1bdaf790a7e73b4588d..d71d5daf8113bf4abb59d51101467e85985fc250 100755 (executable)
@@ -23,6 +23,8 @@ SIX_WEEK_CYCLE="$(( ($(date +%s) / 604800 - 3) % 6 ))"
 
 touch "$TOOLSTATE_FILE"
 
+# Try to test all the tools and store the build/test success in the TOOLSTATE_FILE
+
 set +e
 python2.7 "$X_PY" test --no-fail-fast \
     src/doc/book \
@@ -38,6 +40,7 @@ set -e
 cat "$TOOLSTATE_FILE"
 echo
 
+# This function checks that if a tool's submodule changed, the tool's state must improve
 verify_status() {
     echo "Verifying status of $1..."
     if echo "$CHANGED_FILES" | grep -q "^M[[:blank:]]$2$"; then
@@ -57,17 +60,36 @@ verify_status() {
     fi
 }
 
+# deduplicates the submodule check and the assertion that on beta some tools MUST be passing
+check_dispatch() {
+    if [ "$1" = submodule_changed ]; then
+        # ignore $2 (branch id)
+        verify_status $3 $4
+    elif [ "$2" = beta ]; then
+        echo "Requiring test passing for $3..."
+        if grep -q '"'"$3"'":"\(test\|build\)-fail"' "$TOOLSTATE_FILE"; then
+            exit 4
+        fi
+    fi
+}
+
+# list all tools here
+status_check() {
+    check_dispatch $1 beta book src/doc/book
+    check_dispatch $1 beta nomicon src/doc/nomicon
+    check_dispatch $1 beta reference src/doc/reference
+    check_dispatch $1 beta rust-by-example src/doc/rust-by-example
+    check_dispatch $1 beta rls src/tool/rls
+    check_dispatch $1 beta rustfmt src/tool/rustfmt
+    # these tools are not required for beta to successfully branch
+    check_dispatch $1 nightly clippy-driver src/tool/clippy
+    check_dispatch $1 nightly miri src/tool/miri
+}
+
 # If this PR is intended to update one of these tools, do not let the build pass
 # when they do not test-pass.
 
-verify_status book src/doc/book
-verify_status nomicon src/doc/nomicon
-verify_status reference src/doc/reference
-verify_status rust-by-example src/doc/rust-by-example
-verify_status rls src/tool/rls
-verify_status rustfmt src/tool/rustfmt
-verify_status clippy-driver src/tool/clippy
-verify_status miri src/tool/miri
+status_check "submodule_changed"
 
 if [ "$RUST_RELEASE_CHANNEL" = nightly -a -n "${TOOLSTATE_REPO_ACCESS_TOKEN+is_set}" ]; then
     . "$(dirname $0)/repo.sh"
@@ -86,6 +108,6 @@ $COMMIT\t$(cat "$TOOLSTATE_FILE")
     exit 0
 fi
 
-if grep -q fail "$TOOLSTATE_FILE"; then
-    exit 4
-fi
+# abort compilation if an important tool doesn't build
+# (this code is reachable if not on the nightly channel)
+status_check "beta_required"
index 3984379ea860dd3eabbb099da3c691cb78fcab61..bb2c68a27ba308f3ba1e825d57bbabd678e20cc4 100644 (file)
@@ -246,6 +246,7 @@ fn take(&mut self, key: &Q) -> Option<K> {
     }
 
     fn replace(&mut self, key: K) -> Option<K> {
+        self.ensure_root_is_owned();
         match search::search_tree::<marker::Mut, K, (), K>(self.root.as_mut(), &key) {
             Found(handle) => Some(mem::replace(handle.into_kv_mut().0, key)),
             GoDown(handle) => {
@@ -523,7 +524,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new() -> BTreeMap<K, V> {
         BTreeMap {
-            root: node::Root::new_leaf(),
+            root: node::Root::shared_empty_root(),
             length: 0,
         }
     }
@@ -544,7 +545,6 @@ pub fn new() -> BTreeMap<K, V> {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn clear(&mut self) {
-        // FIXME(gereeter) .clear() allocates
         *self = BTreeMap::new();
     }
 
@@ -890,6 +890,8 @@ pub fn range_mut<T: ?Sized, R>(&mut self, range: R) -> RangeMut<K, V>
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn entry(&mut self, key: K) -> Entry<K, V> {
+        // FIXME(@porglezomp) Avoid allocating if we don't insert
+        self.ensure_root_is_owned();
         match search::search_tree(self.root.as_mut(), &key) {
             Found(handle) => {
                 Occupied(OccupiedEntry {
@@ -910,6 +912,7 @@ pub fn entry(&mut self, key: K) -> Entry<K, V> {
     }
 
     fn from_sorted_iter<I: Iterator<Item = (K, V)>>(&mut self, iter: I) {
+        self.ensure_root_is_owned();
         let mut cur_node = last_leaf_edge(self.root.as_mut()).into_node();
         // Iterate through all key-value pairs, pushing them into nodes at the right level.
         for (key, value) in iter {
@@ -1019,6 +1022,7 @@ pub fn split_off<Q: ?Sized + Ord>(&mut self, key: &Q) -> Self
         let total_num = self.len();
 
         let mut right = Self::new();
+        right.root = node::Root::new_leaf();
         for _ in 0..(self.root.as_ref().height()) {
             right.root.push_level();
         }
@@ -1153,6 +1157,13 @@ fn fix_left_border(&mut self) {
 
         self.fix_top();
     }
+
+    /// If the root node is the shared root node, allocate our own node.
+    fn ensure_root_is_owned(&mut self) {
+        if self.root.is_shared_root() {
+            self.root = node::Root::new_leaf();
+        }
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1290,6 +1301,10 @@ fn drop(&mut self) {
         self.for_each(drop);
         unsafe {
             let leaf_node = ptr::read(&self.front).into_node();
+            if leaf_node.is_shared_root() {
+                return;
+            }
+
             if let Some(first_parent) = leaf_node.deallocate_and_ascend() {
                 let mut cur_node = first_parent.into_node();
                 while let Some(parent) = cur_node.deallocate_and_ascend() {
index d6346662314e65ae993a498ff4ffba1fb9579f30..431695c32ab68f8f9d35bef16a9442cb6a35d5cb 100644 (file)
 ///
 /// See also rust-lang/rfcs#197, which would make this structure significantly more safe by
 /// avoiding accidentally dropping unused and uninitialized keys and values.
+///
+/// We put the metadata first so that its position is the same for every `K` and `V`, in order
+/// to statically allocate a single dummy node to avoid allocations. This struct is `repr(C)` to
+/// prevent them from being reordered.
+#[repr(C)]
 struct LeafNode<K, V> {
-    /// The arrays storing the actual data of the node. Only the first `len` elements of each
-    /// array are initialized and valid.
-    keys: [K; CAPACITY],
-    vals: [V; CAPACITY],
-
     /// We use `*const` as opposed to `*mut` so as to be covariant in `K` and `V`.
     /// This either points to an actual node or is null.
     parent: *const InternalNode<K, V>,
@@ -77,10 +77,14 @@ struct LeafNode<K, V> {
 
     /// The number of keys and values this node stores.
     ///
-    /// This is at the end of the node's representation and next to `parent_idx` to encourage
-    /// the compiler to join `len` and `parent_idx` into the same 32-bit word, reducing space
-    /// overhead.
+    /// This next to `parent_idx` to encourage the compiler to join `len` and
+    /// `parent_idx` into the same 32-bit word, reducing space overhead.
     len: u16,
+
+    /// The arrays storing the actual data of the node. Only the first `len` elements of each
+    /// array are initialized and valid.
+    keys: [K; CAPACITY],
+    vals: [V; CAPACITY],
 }
 
 impl<K, V> LeafNode<K, V> {
@@ -97,8 +101,26 @@ unsafe fn new() -> Self {
             len: 0
         }
     }
+
+    fn is_shared_root(&self) -> bool {
+        self as *const _ == &EMPTY_ROOT_NODE as *const _ as *const LeafNode<K, V>
+    }
 }
 
+// We need to implement Sync here in order to make a static instance.
+unsafe impl Sync for LeafNode<(), ()> {}
+
+// An empty node used as a placeholder for the root node, to avoid allocations.
+// We use () in order to save space, since no operation on an empty tree will
+// ever take a pointer past the first key.
+static EMPTY_ROOT_NODE: LeafNode<(), ()> = LeafNode {
+    parent: ptr::null(),
+    parent_idx: 0,
+    len: 0,
+    keys: [(); CAPACITY],
+    vals: [(); CAPACITY],
+};
+
 /// The underlying representation of internal nodes. As with `LeafNode`s, these should be hidden
 /// behind `BoxedNode`s to prevent dropping uninitialized keys and values. Any pointer to an
 /// `InternalNode` can be directly casted to a pointer to the underlying `LeafNode` portion of the
@@ -168,6 +190,21 @@ unsafe impl<K: Sync, V: Sync> Sync for Root<K, V> { }
 unsafe impl<K: Send, V: Send> Send for Root<K, V> { }
 
 impl<K, V> Root<K, V> {
+    pub fn is_shared_root(&self) -> bool {
+        self.as_ref().is_shared_root()
+    }
+
+    pub fn shared_empty_root() -> Self {
+        Root {
+            node: unsafe {
+                BoxedNode::from_ptr(NonNull::new_unchecked(
+                    &EMPTY_ROOT_NODE as *const _ as *const LeafNode<K, V> as *mut _
+                ))
+            },
+            height: 0,
+        }
+    }
+
     pub fn new_leaf() -> Self {
         Root {
             node: BoxedNode::from_leaf(Box::new(unsafe { LeafNode::new() })),
@@ -209,6 +246,7 @@ pub fn into_ref(self)
     /// new node the root. This increases the height by 1 and is the opposite of `pop_level`.
     pub fn push_level(&mut self)
             -> NodeRef<marker::Mut, K, V, marker::Internal> {
+        debug_assert!(!self.is_shared_root());
         let mut new_node = Box::new(unsafe { InternalNode::new() });
         new_node.edges[0] = unsafe { BoxedNode::from_ptr(self.node.as_ptr()) };
 
@@ -353,12 +391,16 @@ fn as_leaf(&self) -> &LeafNode<K, V> {
         }
     }
 
+    pub fn is_shared_root(&self) -> bool {
+        self.as_leaf().is_shared_root()
+    }
+
     pub fn keys(&self) -> &[K] {
-        self.reborrow().into_slices().0
+        self.reborrow().into_key_slice()
     }
 
-    pub fn vals(&self) -> &[V] {
-        self.reborrow().into_slices().1
+    fn vals(&self) -> &[V] {
+        self.reborrow().into_val_slice()
     }
 
     /// Finds the parent of the current node. Returns `Ok(handle)` if the current
@@ -433,6 +475,7 @@ pub unsafe fn deallocate_and_ascend(self) -> Option<
             marker::Edge
         >
     > {
+        debug_assert!(!self.is_shared_root());
         let node = self.node;
         let ret = self.ascend().ok();
         Global.dealloc(node.as_opaque(), Layout::new::<LeafNode<K, V>>());
@@ -500,30 +543,51 @@ fn as_leaf_mut(&mut self) -> &mut LeafNode<K, V> {
         }
     }
 
-    pub fn keys_mut(&mut self) -> &mut [K] {
-        unsafe { self.reborrow_mut().into_slices_mut().0 }
+    fn keys_mut(&mut self) -> &mut [K] {
+        unsafe { self.reborrow_mut().into_key_slice_mut() }
     }
 
-    pub fn vals_mut(&mut self) -> &mut [V] {
-        unsafe { self.reborrow_mut().into_slices_mut().1 }
+    fn vals_mut(&mut self) -> &mut [V] {
+        unsafe { self.reborrow_mut().into_val_slice_mut() }
     }
 }
 
 impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Immut<'a>, K, V, Type> {
-    pub fn into_slices(self) -> (&'a [K], &'a [V]) {
-        unsafe {
-            (
+    fn into_key_slice(self) -> &'a [K] {
+        // When taking a pointer to the keys, if our key has a stricter
+        // alignment requirement than the shared root does, then the pointer
+        // would be out of bounds, which LLVM assumes will not happen. If the
+        // alignment is more strict, we need to make an empty slice that doesn't
+        // use an out of bounds pointer.
+        if mem::align_of::<K>() > mem::align_of::<LeafNode<(), ()>>() && self.is_shared_root() {
+            &[]
+        } else {
+            // Here either it's not the root, or the alignment is less strict,
+            // in which case the keys pointer will point "one-past-the-end" of
+            // the node, which is allowed by LLVM.
+            unsafe {
                 slice::from_raw_parts(
                     self.as_leaf().keys.as_ptr(),
                     self.len()
-                ),
-                slice::from_raw_parts(
-                    self.as_leaf().vals.as_ptr(),
-                    self.len()
                 )
+            }
+        }
+    }
+
+    fn into_val_slice(self) -> &'a [V] {
+        debug_assert!(!self.is_shared_root());
+        unsafe {
+            slice::from_raw_parts(
+                self.as_leaf().vals.as_ptr(),
+                self.len()
             )
         }
     }
+
+    fn into_slices(self) -> (&'a [K], &'a [V]) {
+        let k = unsafe { ptr::read(&self) };
+        (k.into_key_slice(), self.into_val_slice())
+    }
 }
 
 impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
@@ -535,20 +599,33 @@ pub fn into_root_mut(self) -> &'a mut Root<K, V> {
         }
     }
 
-    pub fn into_slices_mut(mut self) -> (&'a mut [K], &'a mut [V]) {
-        unsafe {
-            (
+    fn into_key_slice_mut(mut self) -> &'a mut [K] {
+        if mem::align_of::<K>() > mem::align_of::<LeafNode<(), ()>>() && self.is_shared_root() {
+            &mut []
+        } else {
+            unsafe {
                 slice::from_raw_parts_mut(
                     &mut self.as_leaf_mut().keys as *mut [K] as *mut K,
                     self.len()
-                ),
-                slice::from_raw_parts_mut(
-                    &mut self.as_leaf_mut().vals as *mut [V] as *mut V,
-                    self.len()
                 )
+            }
+        }
+    }
+
+    fn into_val_slice_mut(mut self) -> &'a mut [V] {
+        debug_assert!(!self.is_shared_root());
+        unsafe {
+            slice::from_raw_parts_mut(
+                &mut self.as_leaf_mut().vals as *mut [V] as *mut V,
+                self.len()
             )
         }
     }
+
+    fn into_slices_mut(self) -> (&'a mut [K], &'a mut [V]) {
+        let k = unsafe { ptr::read(&self) };
+        (k.into_key_slice_mut(), self.into_val_slice_mut())
+    }
 }
 
 impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Leaf> {
@@ -556,6 +633,7 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Leaf> {
     pub fn push(&mut self, key: K, val: V) {
         // Necessary for correctness, but this is an internal module
         debug_assert!(self.len() < CAPACITY);
+        debug_assert!(!self.is_shared_root());
 
         let idx = self.len();
 
@@ -571,6 +649,7 @@ pub fn push(&mut self, key: K, val: V) {
     pub fn push_front(&mut self, key: K, val: V) {
         // Necessary for correctness, but this is an internal module
         debug_assert!(self.len() < CAPACITY);
+        debug_assert!(!self.is_shared_root());
 
         unsafe {
             slice_insert(self.keys_mut(), 0, key);
@@ -884,6 +963,7 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge
     fn insert_fit(&mut self, key: K, val: V) -> *mut V {
         // Necessary for correctness, but in a private module
         debug_assert!(self.node.len() < CAPACITY);
+        debug_assert!(!self.node.is_shared_root());
 
         unsafe {
             slice_insert(self.node.keys_mut(), self.idx, key);
@@ -1061,6 +1141,7 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::KV>
     ///   allocated node.
     pub fn split(mut self)
             -> (NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, K, V, Root<K, V>) {
+        debug_assert!(!self.node.is_shared_root());
         unsafe {
             let mut new_node = Box::new(LeafNode::new());
 
@@ -1098,6 +1179,7 @@ pub fn split(mut self)
     /// now adjacent key/value pairs to the left and right of this handle.
     pub fn remove(mut self)
             -> (Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>, K, V) {
+        debug_assert!(!self.node.is_shared_root());
         unsafe {
             let k = slice_remove(self.node.keys_mut(), self.idx);
             let v = slice_remove(self.node.vals_mut(), self.idx);
index 042c523f25f25badec26e7737654afeb65de94ee..0f3b95236f069a5432daaf029dcec5d5a61af1f8 100644 (file)
@@ -23,9 +23,43 @@ fn creation() {
 #[test]
 fn secs() {
     assert_eq!(Duration::new(0, 0).as_secs(), 0);
+    assert_eq!(Duration::new(0, 500_000_005).as_secs(), 0);
+    assert_eq!(Duration::new(0, 1_050_000_001).as_secs(), 1);
     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);
+    assert_eq!(Duration::from_micros(999_999).as_secs(), 0);
+    assert_eq!(Duration::from_micros(1_000_001).as_secs(), 1);
+    assert_eq!(Duration::from_nanos(999_999_999).as_secs(), 0);
+    assert_eq!(Duration::from_nanos(1_000_000_001).as_secs(), 1);
+}
+
+#[test]
+fn millis() {
+    assert_eq!(Duration::new(0, 0).subsec_millis(), 0);
+    assert_eq!(Duration::new(0, 500_000_005).subsec_millis(), 500);
+    assert_eq!(Duration::new(0, 1_050_000_001).subsec_millis(), 50);
+    assert_eq!(Duration::from_secs(1).subsec_millis(), 0);
+    assert_eq!(Duration::from_millis(999).subsec_millis(), 999);
+    assert_eq!(Duration::from_millis(1001).subsec_millis(), 1);
+    assert_eq!(Duration::from_micros(999_999).subsec_millis(), 999);
+    assert_eq!(Duration::from_micros(1_001_000).subsec_millis(), 1);
+    assert_eq!(Duration::from_nanos(999_999_999).subsec_millis(), 999);
+    assert_eq!(Duration::from_nanos(1_001_000_000).subsec_millis(), 1);
+}
+
+#[test]
+fn micros() {
+    assert_eq!(Duration::new(0, 0).subsec_micros(), 0);
+    assert_eq!(Duration::new(0, 500_000_005).subsec_micros(), 500_000);
+    assert_eq!(Duration::new(0, 1_050_000_001).subsec_micros(), 50_000);
+    assert_eq!(Duration::from_secs(1).subsec_micros(), 0);
+    assert_eq!(Duration::from_millis(999).subsec_micros(), 999_000);
+    assert_eq!(Duration::from_millis(1001).subsec_micros(), 1_000);
+    assert_eq!(Duration::from_micros(999_999).subsec_micros(), 999_999);
+    assert_eq!(Duration::from_micros(1_000_001).subsec_micros(), 1);
+    assert_eq!(Duration::from_nanos(999_999_999).subsec_micros(), 999_999);
+    assert_eq!(Duration::from_nanos(1_000_001_000).subsec_micros(), 1);
 }
 
 #[test]
@@ -34,8 +68,12 @@ fn nanos() {
     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);
+    assert_eq!(Duration::from_millis(999).subsec_nanos(), 999_000_000);
+    assert_eq!(Duration::from_millis(1001).subsec_nanos(), 1_000_000);
+    assert_eq!(Duration::from_micros(999_999).subsec_nanos(), 999_999_000);
+    assert_eq!(Duration::from_micros(1_000_001).subsec_nanos(), 1000);
+    assert_eq!(Duration::from_nanos(999_999_999).subsec_nanos(), 999_999_999);
+    assert_eq!(Duration::from_nanos(1_000_000_001).subsec_nanos(), 1);
 }
 
 #[test]
index 8e8b1691c657a3bc0edaa12e336332e82f55a3db..c0b2b2a0bc682abf3fbe56df4108fef764b1fcdd 100644 (file)
@@ -203,8 +203,9 @@ pub const fn from_nanos(nanos: u64) -> Duration {
     ///
     /// [`subsec_nanos`]: #method.subsec_nanos
     #[stable(feature = "duration", since = "1.3.0")]
+    #[rustc_const_unstable(feature="duration_getters")]
     #[inline]
-    pub fn as_secs(&self) -> u64 { self.secs }
+    pub const fn as_secs(&self) -> u64 { self.secs }
 
     /// Returns the fractional part of this `Duration`, in milliseconds.
     ///
@@ -222,8 +223,9 @@ pub fn as_secs(&self) -> u64 { self.secs }
     /// assert_eq!(duration.subsec_millis(), 432);
     /// ```
     #[stable(feature = "duration_extras", since = "1.27.0")]
+    #[rustc_const_unstable(feature="duration_getters")]
     #[inline]
-    pub fn subsec_millis(&self) -> u32 { self.nanos / NANOS_PER_MILLI }
+    pub const fn subsec_millis(&self) -> u32 { self.nanos / NANOS_PER_MILLI }
 
     /// Returns the fractional part of this `Duration`, in microseconds.
     ///
@@ -241,8 +243,9 @@ pub fn subsec_millis(&self) -> u32 { self.nanos / NANOS_PER_MILLI }
     /// assert_eq!(duration.subsec_micros(), 234_567);
     /// ```
     #[stable(feature = "duration_extras", since = "1.27.0")]
+    #[rustc_const_unstable(feature="duration_getters")]
     #[inline]
-    pub fn subsec_micros(&self) -> u32 { self.nanos / NANOS_PER_MICRO }
+    pub const fn subsec_micros(&self) -> u32 { self.nanos / NANOS_PER_MICRO }
 
     /// Returns the fractional part of this `Duration`, in nanoseconds.
     ///
@@ -260,8 +263,9 @@ pub fn subsec_micros(&self) -> u32 { self.nanos / NANOS_PER_MICRO }
     /// assert_eq!(duration.subsec_nanos(), 10_000_000);
     /// ```
     #[stable(feature = "duration", since = "1.3.0")]
+    #[rustc_const_unstable(feature="duration_getters")]
     #[inline]
-    pub fn subsec_nanos(&self) -> u32 { self.nanos }
+    pub const fn subsec_nanos(&self) -> u32 { self.nanos }
 
     /// Checked `Duration` addition. Computes `self + other`, returning [`None`]
     /// if overflow occurred.
index e4f432e7caf494d789bd520299e6774db9cb22bd..4847a7f4ddbec4e6b5f98f9c0e58f6bf44704523 100644 (file)
@@ -60,7 +60,7 @@
 //! user of the `DepNode` API of having to know how to compute the expected
 //! fingerprint for a given set of node parameters.
 
-use mir::interpret::{GlobalId};
+use mir::interpret::{GlobalId, ConstValue};
 use hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX};
 use hir::map::DefPathHash;
 use hir::{HirId, ItemLocalId};
@@ -621,13 +621,14 @@ pub fn fingerprint_needed_for_crate_hash(self) -> bool {
     [input] UsedCrateSource(CrateNum),
     [input] PostorderCnums,
 
-    // This query is not expected to have inputs -- as a result, it's
-    // not a good candidate for "replay" because it's essentially a
-    // pure function of its input (and hence the expectation is that
-    // no caller would be green **apart** from just this
-    // query). Making it anonymous avoids hashing the result, which
+    // These queries are not expected to have inputs -- as a result, they
+    // are not good candidates for "replay" because they are essentially
+    // pure functions of their input (and hence the expectation is that
+    // no caller would be green **apart** from just these
+    // queries). Making them anonymous avoids hashing the result, which
     // may save a bit of time.
     [anon] EraseRegionsTy { ty: Ty<'tcx> },
+    [anon] ConstValueToAllocation { val: ConstValue<'tcx>, ty: Ty<'tcx> },
 
     [input] Freevars(DefId),
     [input] MaybeUnusedTraitImport(DefId),
index 03aff6410055815a27c1d63bd1b43a8e92b6fe2e..797332e699d4b99705cdaf4b9ce446b3cf728f0d 100644 (file)
@@ -13,7 +13,7 @@
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use rustc_data_structures::small_vec::SmallVec;
-use rustc_data_structures::sync::{Lrc, RwLock, ReadGuard, Lock};
+use rustc_data_structures::sync::{Lrc, Lock};
 use std::env;
 use std::hash::Hash;
 use ty::{self, TyCtxt};
@@ -80,9 +80,6 @@ struct DepGraphData {
     /// this map. We can later look for and extract that data.
     previous_work_products: FxHashMap<WorkProductId, WorkProduct>,
 
-    /// Work-products that we generate in this run.
-    work_products: RwLock<FxHashMap<WorkProductId, WorkProduct>>,
-
     dep_node_debug: Lock<FxHashMap<DepNode, String>>,
 
     // Used for testing, only populated when -Zquery-dep-graph is specified.
@@ -103,7 +100,6 @@ pub fn new(prev_graph: PreviousDepGraph,
         DepGraph {
             data: Some(Lrc::new(DepGraphData {
                 previous_work_products: prev_work_products,
-                work_products: RwLock::new(FxHashMap()),
                 dep_node_debug: Lock::new(FxHashMap()),
                 current: Lock::new(CurrentDepGraph::new()),
                 previous: prev_graph,
@@ -462,19 +458,6 @@ pub fn prev_dep_node_index_of(&self, dep_node: &DepNode) -> SerializedDepNodeInd
         self.data.as_ref().unwrap().previous.node_to_index(dep_node)
     }
 
-    /// Indicates that we created the given work-product in this run
-    /// for `v`. This record will be preserved and loaded in the next
-    /// run.
-    pub fn insert_work_product(&self, v: &WorkProductId, data: WorkProduct) {
-        debug!("insert_work_product({:?}, {:?})", v, data);
-        self.data
-            .as_ref()
-            .unwrap()
-            .work_products
-            .borrow_mut()
-            .insert(v.clone(), data);
-    }
-
     /// Check whether a previous work product exists for `v` and, if
     /// so, return the path that leads to it. Used to skip doing work.
     pub fn previous_work_product(&self, v: &WorkProductId) -> Option<WorkProduct> {
@@ -485,12 +468,6 @@ pub fn previous_work_product(&self, v: &WorkProductId) -> Option<WorkProduct> {
             })
     }
 
-    /// Access the map of work-products created during this run. Only
-    /// used during saving of the dep-graph.
-    pub fn work_products(&self) -> ReadGuard<FxHashMap<WorkProductId, WorkProduct>> {
-        self.data.as_ref().unwrap().work_products.borrow()
-    }
-
     /// Access the map of work-products created during the cached run. Only
     /// used during saving of the dep-graph.
     pub fn previous_work_products(&self) -> &FxHashMap<WorkProductId, WorkProduct> {
index 2221ecf07b434913b079643d283b48afeeed7d5f..a62000e10c79f8374116269b5eeb45c534307cea 100644 (file)
@@ -88,3 +88,33 @@ fn visit_impl_item(&mut self, impl_item: &'hir ImplItem) {
         self.visitor.visit_impl_item(impl_item);
     }
 }
+
+/// A parallel variant of ItemLikeVisitor
+pub trait ParItemLikeVisitor<'hir> {
+    fn visit_item(&self, item: &'hir Item);
+    fn visit_trait_item(&self, trait_item: &'hir TraitItem);
+    fn visit_impl_item(&self, impl_item: &'hir ImplItem);
+}
+
+pub trait IntoVisitor<'hir> {
+    type Visitor: Visitor<'hir>;
+    fn into_visitor(&self) -> Self::Visitor;
+}
+
+pub struct ParDeepVisitor<V>(pub V);
+
+impl<'hir, V> ParItemLikeVisitor<'hir> for ParDeepVisitor<V>
+    where V: IntoVisitor<'hir>
+{
+    fn visit_item(&self, item: &'hir Item) {
+        self.0.into_visitor().visit_item(item);
+    }
+
+    fn visit_trait_item(&self, trait_item: &'hir TraitItem) {
+        self.0.into_visitor().visit_trait_item(trait_item);
+    }
+
+    fn visit_impl_item(&self, impl_item: &'hir ImplItem) {
+        self.0.into_visitor().visit_impl_item(impl_item);
+    }
+}
index 0dc89d64bd50116b02d71039e34e6e32c05eb4d3..33076267dbc9d427009475ef677d8c99b3966b36 100644 (file)
@@ -48,6 +48,7 @@
 use ty::maps::Providers;
 
 use rustc_data_structures::indexed_vec;
+use rustc_data_structures::sync::{ParallelIterator, par_iter, Send, Sync, scope};
 
 use serialize::{self, Encoder, Encodable, Decoder, Decodable};
 use std::collections::BTreeMap;
@@ -720,6 +721,31 @@ pub fn visit_all_item_likes<'hir, V>(&'hir self, visitor: &mut V)
         }
     }
 
+    /// A parallel version of visit_all_item_likes
+    pub fn par_visit_all_item_likes<'hir, V>(&'hir self, visitor: &V)
+        where V: itemlikevisit::ParItemLikeVisitor<'hir> + Sync + Send
+    {
+        scope(|s| {
+            s.spawn(|_| {
+                par_iter(&self.items).for_each(|(_, item)| {
+                    visitor.visit_item(item);
+                });
+            });
+
+            s.spawn(|_| {
+                par_iter(&self.trait_items).for_each(|(_, trait_item)| {
+                    visitor.visit_trait_item(trait_item);
+                });
+            });
+
+            s.spawn(|_| {
+                par_iter(&self.impl_items).for_each(|(_, impl_item)| {
+                    visitor.visit_impl_item(impl_item);
+                });
+            });
+        });
+    }
+
     pub fn body(&self, id: BodyId) -> &Body {
         &self.bodies[&id]
     }
index a7adf28c481b95c3fa352aa6345254df6f6a15be..f56f4e12e7a02b9b16ffa34c2f9119ad0c492235 100644 (file)
@@ -67,7 +67,7 @@ pub fn decode_opaque<'a>(decoder: &mut Decoder<'a>) -> Result<Fingerprint, Strin
 }
 
 impl ::std::fmt::Display for Fingerprint {
-    fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
+    fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
         write!(formatter, "{:x}-{:x}", self.0, self.1)
     }
 }
index d0d0ab093c87ffbd976c77489d6beebc9a7f89da..1036eae9b856b0092ec949d94aa3655a33dcfb17 100644 (file)
@@ -384,6 +384,30 @@ fn hash_stable<W: StableHasherResult>(&self,
     }
 }
 
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
+for ::mir::interpret::ConstValue<'gcx> {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a>,
+                                          hasher: &mut StableHasher<W>) {
+        use mir::interpret::ConstValue::*;
+
+        mem::discriminant(self).hash_stable(hcx, hasher);
+
+        match *self {
+            ByVal(val) => {
+                val.hash_stable(hcx, hasher);
+            }
+            ByValPair(a, b) => {
+                a.hash_stable(hcx, hasher);
+                b.hash_stable(hcx, hasher);
+            }
+            ByRef(alloc) => {
+                alloc.hash_stable(hcx, hasher);
+            }
+        }
+    }
+}
+
 impl_stable_hash_for!(enum mir::interpret::Value {
     ByVal(v),
     ByValPair(a, b),
index 0ecab50dda22989faeb57d53f0bc642ff068e37d..3a76f75d01833a8dbb9ad6cf0653d2e8fd0c7b10 100644 (file)
@@ -11,7 +11,7 @@
 use hir::def_id::DefId;
 use ty::{self, TyCtxt, layout};
 use ty::subst::Substs;
-use mir::interpret::{Value, PrimVal};
+use mir::interpret::ConstValue;
 use errors::DiagnosticBuilder;
 
 use graphviz::IntoCow;
 #[derive(Copy, Clone, Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq)]
 pub enum ConstVal<'tcx> {
     Unevaluated(DefId, &'tcx Substs<'tcx>),
-    Value(Value),
-}
-
-impl<'tcx> ConstVal<'tcx> {
-    pub fn to_raw_bits(&self) -> Option<u128> {
-        match *self {
-            ConstVal::Value(Value::ByVal(PrimVal::Bytes(b))) => {
-                Some(b)
-            },
-            _ => None,
-        }
-    }
-    pub fn unwrap_u64(&self) -> u64 {
-        match self.to_raw_bits() {
-            Some(val) => {
-                assert_eq!(val as u64 as u128, val);
-                val as u64
-            },
-            None => bug!("expected constant u64, got {:#?}", self),
-        }
-    }
+    Value(ConstValue<'tcx>),
 }
 
 #[derive(Clone, Debug)]
index 4400ebc294fd89f4afd114926bb98e17198c6dbf..61c8470b616f833f2284fede138d1002232b44c2 100644 (file)
@@ -38,7 +38,7 @@
 use syntax::symbol::Symbol;
 use syntax_pos::Span;
 use rustc_target::spec::Target;
-use rustc_data_structures::sync::{MetadataRef, Lrc};
+use rustc_data_structures::sync::{self, MetadataRef, Lrc};
 
 pub use self::NativeLibraryKind::*;
 
@@ -255,6 +255,8 @@ fn encode_metadata<'a, 'tcx>(&self,
     fn metadata_encoding_version(&self) -> &[u8];
 }
 
+pub type CrateStoreDyn = CrateStore + sync::Sync;
+
 // FIXME: find a better place for this?
 pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option<Span>) {
     let mut err_count = 0;
index 3875770a5ff5c50298de2c1154e0d2be4d243241..a4c38333da19e8343550ba11ee954756ecb9333a 100644 (file)
@@ -945,7 +945,7 @@ pub fn cat_rvalue_node(&self,
 
         // Always promote `[T; 0]` (even when e.g. borrowed mutably).
         let promotable = match expr_ty.sty {
-            ty::TyArray(_, len) if len.val.to_raw_bits() == Some(0) => true,
+            ty::TyArray(_, len) if len.assert_usize(self.tcx) == Some(0) => true,
             _ => promotable,
         };
 
index 279908d2b675fae372bbb13780bf293d39fc7220..d6a7d5e8472ac086dab3b6dec23b6cc37664f8cd 100644 (file)
@@ -764,7 +764,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
                                      "unions with `Drop` implementations are unstable");
                 } else {
                     let param_env = self.tcx.param_env(def_id);
-                    if !param_env.can_type_implement_copy(self.tcx, ty, item.span).is_ok() {
+                    if !param_env.can_type_implement_copy(self.tcx, ty).is_ok() {
                         emit_feature_err(&self.tcx.sess.parse_sess,
                                         "untagged_unions", item.span, GateIssue::Language,
                                         "unions with non-`Copy` fields are unstable");
index 546c7a920d538fd6d12a653ea0c41ccf9f510088..afdd1c167c6dc781b488a0c06d55be60e757952b 100644 (file)
@@ -10,7 +10,7 @@ macro_rules! err {
 
 pub use self::error::{EvalError, EvalResult, EvalErrorKind, AssertMessage};
 
-pub use self::value::{PrimVal, PrimValKind, Value, Pointer};
+pub use self::value::{PrimVal, PrimValKind, Value, Pointer, ConstValue};
 
 use std::collections::BTreeMap;
 use std::fmt;
@@ -20,8 +20,10 @@ macro_rules! err {
 use ty::layout::{self, Align, HasDataLayout};
 use middle::region;
 use std::iter;
+use std::io;
 use syntax::ast::Mutability;
 use rustc_serialize::{Encoder, Decoder, Decodable, Encodable};
+use byteorder::{WriteBytesExt, ReadBytesExt, LittleEndian, BigEndian};
 
 #[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
 pub enum Lock {
@@ -235,7 +237,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-#[derive(Debug, Eq, PartialEq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, Eq, PartialEq, Hash, RustcEncodable, RustcDecodable)]
 pub struct Allocation {
     /// The actual bytes of the allocation.
     /// Note that the bytes of a pointer represent the offset of the pointer
@@ -254,17 +256,69 @@ pub struct Allocation {
 }
 
 impl Allocation {
-    pub fn from_bytes(slice: &[u8]) -> Self {
+    pub fn from_bytes(slice: &[u8], align: Align) -> Self {
         let mut undef_mask = UndefMask::new(0);
         undef_mask.grow(slice.len() as u64, true);
         Self {
             bytes: slice.to_owned(),
             relocations: BTreeMap::new(),
             undef_mask,
-            align: Align::from_bytes(1, 1).unwrap(),
+            align,
             runtime_mutability: Mutability::Immutable,
         }
     }
+
+    pub fn from_byte_aligned_bytes(slice: &[u8]) -> Self {
+        Allocation::from_bytes(slice, Align::from_bytes(1, 1).unwrap())
+    }
+
+    pub fn undef(size: u64, align: Align) -> Self {
+        assert_eq!(size as usize as u64, size);
+        Allocation {
+            bytes: vec![0; size as usize],
+            relocations: BTreeMap::new(),
+            undef_mask: UndefMask::new(size),
+            align,
+            runtime_mutability: Mutability::Immutable,
+        }
+    }
+}
+
+impl<'tcx> ::serialize::UseSpecializedDecodable for &'tcx Allocation {}
+
+////////////////////////////////////////////////////////////////////////////////
+// Methods to access integers in the target endianness
+////////////////////////////////////////////////////////////////////////////////
+
+pub fn write_target_uint(
+    endianness: layout::Endian,
+    mut target: &mut [u8],
+    data: u128,
+) -> Result<(), io::Error> {
+    let len = target.len();
+    match endianness {
+        layout::Endian::Little => target.write_uint128::<LittleEndian>(data, len),
+        layout::Endian::Big => target.write_uint128::<BigEndian>(data, len),
+    }
+}
+
+pub fn write_target_int(
+    endianness: layout::Endian,
+    mut target: &mut [u8],
+    data: i128,
+) -> Result<(), io::Error> {
+    let len = target.len();
+    match endianness {
+        layout::Endian::Little => target.write_int128::<LittleEndian>(data, len),
+        layout::Endian::Big => target.write_int128::<BigEndian>(data, len),
+    }
+}
+
+pub fn read_target_uint(endianness: layout::Endian, mut source: &[u8]) -> Result<u128, io::Error> {
+    match endianness {
+        layout::Endian::Little => source.read_uint128::<LittleEndian>(source.len()),
+        layout::Endian::Big => source.read_uint128::<BigEndian>(source.len()),
+    }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
index 7289d74bfbb1bd653fa529cd7951ff7da8a11bb6..2cd4bf9d18ca55ef3b3aad375bf292561f818f86 100644 (file)
@@ -3,7 +3,69 @@
 use ty::layout::{Align, HasDataLayout};
 use ty;
 
-use super::{EvalResult, MemoryPointer, PointerArithmetic};
+use super::{EvalResult, MemoryPointer, PointerArithmetic, Allocation};
+
+/// Represents a constant value in Rust. ByVal and ByValPair are optimizations which
+/// matches Value's optimizations for easy conversions between these two types
+#[derive(Clone, Copy, Debug, Eq, PartialEq, RustcEncodable, RustcDecodable, Hash)]
+pub enum ConstValue<'tcx> {
+    // Used only for types with layout::abi::Scalar ABI and ZSTs which use PrimVal::Undef
+    ByVal(PrimVal),
+    // Used only for types with layout::abi::ScalarPair
+    ByValPair(PrimVal, PrimVal),
+    // Used only for the remaining cases
+    ByRef(&'tcx Allocation),
+}
+
+impl<'tcx> ConstValue<'tcx> {
+    #[inline]
+    pub fn from_byval_value(val: Value) -> Self {
+        match val {
+            Value::ByRef(..) => bug!(),
+            Value::ByValPair(a, b) => ConstValue::ByValPair(a, b),
+            Value::ByVal(val) => ConstValue::ByVal(val),
+        }
+    }
+
+    #[inline]
+    pub fn to_byval_value(&self) -> Option<Value> {
+        match *self {
+            ConstValue::ByRef(..) => None,
+            ConstValue::ByValPair(a, b) => Some(Value::ByValPair(a, b)),
+            ConstValue::ByVal(val) => Some(Value::ByVal(val)),
+        }
+    }
+
+    #[inline]
+    pub fn from_primval(val: PrimVal) -> Self {
+        ConstValue::ByVal(val)
+    }
+
+    #[inline]
+    pub fn to_primval(&self) -> Option<PrimVal> {
+        match *self {
+            ConstValue::ByRef(..) => None,
+            ConstValue::ByValPair(..) => None,
+            ConstValue::ByVal(val) => Some(val),
+        }
+    }
+
+    #[inline]
+    pub fn to_bits(&self) -> Option<u128> {
+        match self.to_primval() {
+            Some(PrimVal::Bytes(val)) => Some(val),
+            _ => None,
+        }
+    }
+
+    #[inline]
+    pub fn to_ptr(&self) -> Option<MemoryPointer> {
+        match self.to_primval() {
+            Some(PrimVal::Ptr(ptr)) => Some(ptr),
+            _ => None,
+        }
+    }
+}
 
 /// A `Value` represents a single self-contained Rust value.
 ///
index 11e25322f00726b2e2226f7ae09bfed9f81cf96b..eb12444bcb4c92cc7279bd59a22efcdff47add05 100644 (file)
@@ -13,7 +13,6 @@
 //! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir.html
 
 use graphviz::IntoCow;
-use middle::const_val::ConstVal;
 use middle::region;
 use rustc_data_structures::sync::{Lrc};
 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
@@ -1549,11 +1548,7 @@ pub fn function_handle<'a>(
             span,
             ty,
             literal: Literal::Value {
-                value: tcx.mk_const(ty::Const {
-                    // ZST function type
-                    val: ConstVal::Value(Value::ByVal(PrimVal::Undef)),
-                    ty
-                })
+                value: ty::Const::zero_sized(tcx, ty),
             },
         })
     }
@@ -1881,11 +1876,17 @@ fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
 }
 
 /// Write a `ConstVal` in a way closer to the original source code than the `Debug` output.
-fn fmt_const_val<W: Write>(fmt: &mut W, const_val: &ty::Const) -> fmt::Result {
-    use middle::const_val::ConstVal::*;
+pub fn fmt_const_val<W: Write>(fmt: &mut W, const_val: &ty::Const) -> fmt::Result {
+    use middle::const_val::ConstVal;
     match const_val.val {
-        Unevaluated(..) => write!(fmt, "{:?}", const_val),
-        Value(val) => print_miri_value(val, const_val.ty, fmt),
+        ConstVal::Unevaluated(..) => write!(fmt, "{:?}", const_val),
+        ConstVal::Value(val) => {
+            if let Some(value) = val.to_byval_value() {
+                print_miri_value(value, const_val.ty, fmt)
+            } else {
+                write!(fmt, "{:?}:{}", val, const_val.ty)
+            }
+        },
     }
 }
 
index 6a9ff39c5f56b191163d8e59256b10a020501ade..67dfad50f4435ee0c67890e913c1517f2ddd9ca1 100644 (file)
@@ -69,7 +69,7 @@ pub fn projection_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
                 PlaceTy::Ty {
                     ty: match ty.sty {
                         ty::TyArray(inner, size) => {
-                            let size = size.val.unwrap_u64();
+                            let size = size.unwrap_usize(tcx);
                             let len = size - (from as u64) - (to as u64);
                             tcx.mk_array(inner, len)
                         }
index 23f84881c798098355513316001a1cb34bee001c..bbf873290a928f76a277fb5ef8213fc7b8adb831 100644 (file)
@@ -869,10 +869,16 @@ pub fn consider_optimizing<T: Fn() -> String>(&self, crate_name: &str, msg: T) -
         ret
     }
 
+    /// Returns the number of query threads that should be used for this
+    /// compilation
+    pub fn query_threads_from_opts(opts: &config::Options) -> usize {
+        opts.debugging_opts.query_threads.unwrap_or(1)
+    }
+
     /// Returns the number of query threads that should be used for this
     /// compilation
     pub fn query_threads(&self) -> usize {
-        self.opts.debugging_opts.query_threads.unwrap_or(1)
+        Self::query_threads_from_opts(&self.opts)
     }
 
     /// Returns the number of codegen units that should be used for this
index 10d88063ac35faea1c358253ffb82fbb42207169..a765ffe2396bf471db0e385e17a0bc36286bd5a6 100644 (file)
@@ -674,7 +674,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // we move over to lazy normalization *anyway*.
         let fulfill_cx = FulfillmentContext::new_ignoring_regions();
 
-        let predicates = match fully_normalize_with_fulfillcx(
+        let predicates = match fully_normalize(
             &infcx,
             fulfill_cx,
             cause,
@@ -734,31 +734,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     })
 }
 
-pub fn fully_normalize<'a, 'gcx, 'tcx, T>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
-                                          cause: ObligationCause<'tcx>,
-                                          param_env: ty::ParamEnv<'tcx>,
-                                          value: &T)
-                                          -> Result<T, Vec<FulfillmentError<'tcx>>>
-    where T : TypeFoldable<'tcx>
-{
-    // FIXME (@jroesch) ISSUE 26721
-    // I'm not sure if this is a bug or not, needs further investigation.
-    // It appears that by reusing the fulfillment_cx here we incur more
-    // obligations and later trip an assertion on regionck.rs line 337.
-    //
-    // The two possibilities I see is:
-    //      - normalization is not actually fully happening and we
-    //        have a bug else where
-    //      - we are adding a duplicate bound into the list causing
-    //        its size to change.
-    //
-    // I think we should probably land this refactor and then come
-    // back to this is a follow-up patch.
-    let fulfillcx = FulfillmentContext::new();
-    fully_normalize_with_fulfillcx(infcx, fulfillcx, cause, param_env, value)
-}
-
-pub fn fully_normalize_with_fulfillcx<'a, 'gcx, 'tcx, T>(
+pub fn fully_normalize<'a, 'gcx, 'tcx, T>(
     infcx: &InferCtxt<'a, 'gcx, 'tcx>,
     mut fulfill_cx: FulfillmentContext<'tcx>,
     cause: ObligationCause<'tcx>,
@@ -779,13 +755,7 @@ pub fn fully_normalize_with_fulfillcx<'a, 'gcx, 'tcx, T>(
     }
 
     debug!("fully_normalize: select_all_or_error start");
-    match fulfill_cx.select_all_or_error(infcx) {
-        Ok(()) => { }
-        Err(e) => {
-            debug!("fully_normalize: error={:?}", e);
-            return Err(e);
-        }
-    }
+    fulfill_cx.select_all_or_error(infcx)?;
     debug!("fully_normalize: select_all_or_error complete");
     let resolved_value = infcx.resolve_type_vars_if_possible(&normalized_value);
     debug!("fully_normalize: resolved_value={:?}", resolved_value);
index 30b2c55afa1948c5c9f24277655d78d5d15fae8e..d33806285142e4ba90de19eeac6cf240684892f0 100644 (file)
@@ -196,6 +196,7 @@ pub(super) fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // that this always succeeds.
         let impl1_trait_ref =
             match traits::fully_normalize(&infcx,
+                                          FulfillmentContext::new(),
                                           ObligationCause::dummy(),
                                           penv,
                                           &impl1_trait_ref) {
index 4e15f0711a5aa2a6b88bc71cde1635b801215117..d911f32ed3f1f7bc227d5f08ab4854de38011233 100644 (file)
@@ -24,6 +24,7 @@
 use std::intrinsics;
 use ty::{self, Ty, TyCtxt};
 use ty::subst::Substs;
+use mir::interpret::Allocation;
 
 /// The shorthand encoding uses an enum's variant index `usize`
 /// and is offset by this value so it never matches a real variant.
@@ -262,6 +263,15 @@ pub fn decode_const<'a, 'tcx, D>(decoder: &mut D)
     Ok(decoder.tcx().mk_const(Decodable::decode(decoder)?))
 }
 
+#[inline]
+pub fn decode_allocation<'a, 'tcx, D>(decoder: &mut D)
+                                 -> Result<&'tcx Allocation, D::Error>
+    where D: TyDecoder<'a, 'tcx>,
+          'tcx: 'a,
+{
+    Ok(decoder.tcx().intern_const_alloc(Decodable::decode(decoder)?))
+}
+
 #[macro_export]
 macro_rules! __impl_decoder_methods {
     ($($name:ident -> $ty:ty;)*) => {
@@ -393,6 +403,15 @@ fn specialized_decode(&mut self) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
                     decode_const(self)
                 }
             }
+
+            impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::mir::interpret::Allocation>
+            for $DecoderName<$($typaram),*> {
+                fn specialized_decode(
+                    &mut self
+                ) -> Result<&'tcx $crate::mir::interpret::Allocation, Self::Error> {
+                    decode_allocation(self)
+                }
+            }
         }
     }
 }
index a18103aaee54a8103cb075492556d2a977b833df..dcd20465fbb9a1537954f701501564de942c0a43 100644 (file)
 use ich::{StableHashingContext, NodeIdHashingMode};
 use infer::canonical::{CanonicalVarInfo, CanonicalVarInfos};
 use infer::outlives::free_region_map::FreeRegionMap;
-use middle::const_val::ConstVal;
-use middle::cstore::{CrateStore, LinkMeta};
+use middle::cstore::{CrateStoreDyn, LinkMeta};
 use middle::cstore::EncodedMetadata;
 use middle::lang_items;
 use middle::resolve_lifetime::{self, ObjectLifetimeDefault};
 use middle::stability;
 use mir::{self, Mir, interpret};
-use mir::interpret::{Value, PrimVal};
 use ty::subst::{Kind, Substs, Subst};
 use ty::ReprOptions;
 use ty::Instance;
@@ -854,7 +852,7 @@ pub struct GlobalCtxt<'tcx> {
     global_arenas: &'tcx GlobalArenas<'tcx>,
     global_interners: CtxtInterners<'tcx>,
 
-    cstore: &'tcx dyn CrateStore,
+    cstore: &'tcx CrateStoreDyn,
 
     pub sess: &'tcx Session,
 
@@ -1131,7 +1129,7 @@ pub fn allocate_cached(self, bytes: &[u8]) -> interpret::AllocId {
             return alloc_id;
         }
         // create an allocation that just contains these bytes
-        let alloc = interpret::Allocation::from_bytes(bytes);
+        let alloc = interpret::Allocation::from_byte_aligned_bytes(bytes);
         let alloc = self.intern_const_alloc(alloc);
 
         // the next unique id
@@ -1190,7 +1188,7 @@ fn is_global(self) -> bool {
     /// value (types, substs, etc.) can only be used while `ty::tls` has a valid
     /// reference to the context, to allow formatting values that need it.
     pub fn create_and_enter<F, R>(s: &'tcx Session,
-                                  cstore: &'tcx dyn CrateStore,
+                                  cstore: &'tcx CrateStoreDyn,
                                   local_providers: ty::maps::Providers<'tcx>,
                                   extern_providers: ty::maps::Providers<'tcx>,
                                   arenas: &'tcx AllArenas<'tcx>,
@@ -1802,9 +1800,11 @@ fn span_debug(span: syntax_pos::Span, f: &mut fmt::Formatter) -> fmt::Result {
     /// in librustc otherwise. It is used to when diagnostic messages are
     /// emitted and stores them in the current query, if there is one.
     fn track_diagnostic(diagnostic: &Diagnostic) {
-        with_context(|context| {
-            if let Some(ref query) = context.query {
-                query.diagnostics.lock().push(diagnostic.clone());
+        with_context_opt(|icx| {
+            if let Some(icx) = icx {
+                if let Some(ref query) = icx.query {
+                    query.diagnostics.lock().push(diagnostic.clone());
+                }
             }
         })
     }
@@ -2366,10 +2366,7 @@ pub fn mk_nil_ptr(self) -> Ty<'tcx> {
     }
 
     pub fn mk_array(self, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> {
-        self.mk_ty(TyArray(ty, self.mk_const(ty::Const {
-            val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(n.into()))),
-            ty: self.types.usize
-        })))
+        self.mk_ty(TyArray(ty, ty::Const::from_usize(self, n)))
     }
 
     pub fn mk_slice(self, ty: Ty<'tcx>) -> Ty<'tcx> {
index cfde35de93c3b1ac2963dd0186bb2b628d74f93a..7dfdc592647dbafaa7cdd610c1dcbf60abc5983d 100644 (file)
@@ -182,7 +182,7 @@ pub fn sort_string(&self, tcx: TyCtxt<'a, 'gcx, 'lcx>) -> String {
             ty::TyAdt(def, _) => format!("{} `{}`", def.descr(), tcx.item_path_str(def.did)),
             ty::TyForeign(def_id) => format!("extern type `{}`", tcx.item_path_str(def_id)),
             ty::TyArray(_, n) => {
-                match n.val.to_raw_bits() {
+                match n.assert_usize(tcx) {
                     Some(n) => format!("array of {} elements", n),
                     None => "array".to_string(),
                 }
index 17a3d0011eddfe5276eadb910ff9dc214583568f..19e5406cd0d0a0aadf1d14224914d7280cac8dcb 100644 (file)
@@ -262,7 +262,7 @@ fn uninhabited_from(
                 }))
             },
             TyArray(ty, len) => {
-                match len.val.to_raw_bits() {
+                match len.assert_usize(tcx) {
                     // If the array is definitely non-empty, it's uninhabited if
                     // the type of its elements is uninhabited.
                     Some(n) if n != 0 => ty.uninhabited_from(visited, tcx),
index 0688dcabe5585db0d83089b372f918c30b07dbb3..9cbee143990791d7cca7e799f1f4a8eb6d4d70ba 100644 (file)
@@ -543,7 +543,7 @@ enum StructKind {
                 }
 
                 let element = self.layout_of(element)?;
-                let count = count.val.unwrap_u64();
+                let count = count.unwrap_usize(tcx);
                 let size = element.size.checked_mul(count, dl)
                     .ok_or(LayoutError::SizeOverflow(ty))?;
 
index 57c8c4f34e70e66c72ad4a8724972d8a989d6f74..4e104692d859b78f75a0efd5a30ae0e13a847f23 100644 (file)
@@ -11,7 +11,7 @@
 use dep_graph::SerializedDepNodeIndex;
 use dep_graph::DepNode;
 use hir::def_id::{CrateNum, DefId, DefIndex};
-use mir::interpret::{GlobalId};
+use mir::interpret::{GlobalId, ConstValue};
 use traits::query::{CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal};
 use ty::{self, ParamEnvAnd, Ty, TyCtxt};
 use ty::subst::Substs;
@@ -137,6 +137,12 @@ fn describe(tcx: TyCtxt, def_id: DefId) -> String {
     }
 }
 
+impl<'tcx> QueryDescription<'tcx> for queries::const_value_to_allocation<'tcx> {
+    fn describe(_tcx: TyCtxt, (val, ty): (ConstValue<'tcx>, Ty<'tcx>)) -> String {
+        format!("converting value `{:?}` ({}) to an allocation", val, ty)
+    }
+}
+
 impl<'tcx> QueryDescription<'tcx> for queries::erase_regions_ty<'tcx> {
     fn describe(_tcx: TyCtxt, ty: Ty<'tcx>) -> String {
         format!("erasing regions from `{:?}`", ty)
index da29f23589e85e7a5f464cc5d325d1fbc8b49787..3510a1b7a028f55a04d4ded97028b1a8fe47bde1 100644 (file)
@@ -145,6 +145,15 @@ fn default_span(&self, tcx: TyCtxt) -> Span {
     }
 }
 
+impl<'tcx> Key for (mir::interpret::ConstValue<'tcx>, Ty<'tcx>) {
+    fn map_crate(&self) -> CrateNum {
+        LOCAL_CRATE
+    }
+    fn default_span(&self, _: TyCtxt) -> Span {
+        DUMMY_SP
+    }
+}
+
 impl<'tcx> Key for Ty<'tcx> {
     fn map_crate(&self) -> CrateNum {
         LOCAL_CRATE
index d89846a75ef51a8050c0af043e60045f2830666f..6e419627dd8b5bfe6ed04ecd6fac754fdb18c0f4 100644 (file)
@@ -28,7 +28,7 @@
 use middle::const_val::EvalResult;
 use mir::mono::{CodegenUnit, Stats};
 use mir;
-use mir::interpret::{GlobalId};
+use mir::interpret::{GlobalId, Allocation, ConstValue};
 use session::{CompileResult, CrateDisambiguator};
 use session::config::OutputFilenames;
 use traits::{self, Vtable};
     [] fn const_eval: const_eval_dep_node(ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
         -> EvalResult<'tcx>,
 
+    /// Converts a constant value to an constant allocation
+    [] fn const_value_to_allocation: const_value_to_allocation(
+        (ConstValue<'tcx>, Ty<'tcx>)
+    ) -> &'tcx Allocation,
+
     [] fn check_match: CheckMatch(DefId)
         -> Result<(), ErrorReported>,
 
@@ -478,6 +483,12 @@ fn erase_regions_ty<'tcx>(ty: Ty<'tcx>) -> DepConstructor<'tcx> {
     DepConstructor::EraseRegionsTy { ty }
 }
 
+fn const_value_to_allocation<'tcx>(
+    (val, ty): (ConstValue<'tcx>, Ty<'tcx>)
+) -> DepConstructor<'tcx> {
+    DepConstructor::ConstValueToAllocation { val, ty }
+}
+
 fn type_param_predicates<'tcx>((item_id, param_id): (DefId, DefId)) -> DepConstructor<'tcx> {
     DepConstructor::TypeParamPredicates {
         item_id,
index 37950463f74446d1f9b486224e416832a04e8f9b..65dcb7311d336fd76885afc62aa53c50be118b50 100644 (file)
@@ -956,6 +956,7 @@ macro_rules! force {
         DepKind::FulfillObligation |
         DepKind::VtableMethods |
         DepKind::EraseRegionsTy |
+        DepKind::ConstValueToAllocation |
         DepKind::NormalizeProjectionTy |
         DepKind::NormalizeTyAfterErasingRegions |
         DepKind::DropckOutlives |
index 7076112e3715a285b6377140e3319d40332fcff3..eede7bd2ea619ac230f5a63aa0371c1879cafbeb 100644 (file)
 use ich::Fingerprint;
 use ich::StableHashingContext;
 use infer::canonical::{Canonical, Canonicalize};
-use middle::const_val::ConstVal;
 use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
 use middle::privacy::AccessLevels;
 use middle::resolve_lifetime::ObjectLifetimeDefault;
 use mir::Mir;
-use mir::interpret::{GlobalId, Value, PrimVal};
+use mir::interpret::GlobalId;
 use mir::GeneratorLayout;
 use session::CrateDisambiguator;
 use traits::{self, Reveal};
@@ -1933,27 +1932,23 @@ pub fn eval_explicit_discr(
             promoted: None
         };
         match tcx.const_eval(param_env.and(cid)) {
-            Ok(&ty::Const {
-                val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(b))),
-                ty,
-            }) => {
-                trace!("discriminants: {} ({:?})", b, repr_type);
-                Some(Discr {
-                    val: b,
-                    ty,
-                })
-            },
-            Ok(&ty::Const {
-                val: ConstVal::Value(other),
-                ..
-            }) => {
-                info!("invalid enum discriminant: {:#?}", other);
-                ::middle::const_val::struct_error(
-                    tcx,
-                    tcx.def_span(expr_did),
-                    "constant evaluation of enum discriminant resulted in non-integer",
-                ).emit();
-                None
+            Ok(val) => {
+                // FIXME: Find the right type and use it instead of `val.ty` here
+                if let Some(b) = val.assert_bits(val.ty) {
+                    trace!("discriminants: {} ({:?})", b, repr_type);
+                    Some(Discr {
+                        val: b,
+                        ty: val.ty,
+                    })
+                } else {
+                    info!("invalid enum discriminant: {:#?}", val);
+                    ::middle::const_val::struct_error(
+                        tcx,
+                        tcx.def_span(expr_did),
+                        "constant evaluation of enum discriminant resulted in non-integer",
+                    ).emit();
+                    None
+                }
             }
             Err(err) => {
                 err.report(tcx, tcx.def_span(expr_did), "enum discriminant");
@@ -1964,7 +1959,6 @@ pub fn eval_explicit_discr(
                 }
                 None
             }
-            _ => span_bug!(tcx.def_span(expr_did), "const eval "),
         }
     }
 
index 109dfebf154de67730d3e0294d5cf092af1dee30..4a33f1a1f54d2d268bfa3c2319e28fa0aa46780f 100644 (file)
@@ -18,7 +18,7 @@
 use ty::subst::{Kind, UnpackedKind, Substs};
 use ty::{self, Ty, TyCtxt, TypeFoldable};
 use ty::error::{ExpectedFound, TypeError};
-use mir::interpret::{GlobalId, Value, PrimVal};
+use mir::interpret::GlobalId;
 use util::common::ErrorReported;
 use std::rc::Rc;
 use std::iter;
@@ -469,8 +469,10 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
             assert_eq!(sz_a.ty, tcx.types.usize);
             assert_eq!(sz_b.ty, tcx.types.usize);
             let to_u64 = |x: &'tcx ty::Const<'tcx>| -> Result<u64, ErrorReported> {
+                if let Some(s) = x.assert_usize(tcx) {
+                    return Ok(s);
+                }
                 match x.val {
-                    ConstVal::Value(Value::ByVal(prim)) => Ok(prim.to_u64().unwrap()),
                     ConstVal::Unevaluated(def_id, substs) => {
                         // FIXME(eddyb) get the right param_env.
                         let param_env = ty::ParamEnv::empty();
@@ -487,15 +489,10 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
                                         instance,
                                         promoted: None
                                     };
-                                    match tcx.const_eval(param_env.and(cid)) {
-                                        Ok(&ty::Const {
-                                            val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(b))),
-                                            ..
-                                        }) => {
-                                            assert_eq!(b as u64 as u128, b);
-                                            return Ok(b as u64);
-                                        }
-                                        _ => {}
+                                    if let Some(s) = tcx.const_eval(param_env.and(cid))
+                                                        .ok()
+                                                        .map(|c| c.unwrap_usize(tcx)) {
+                                        return Ok(s)
                                     }
                                 }
                             },
index 7518f008fb316515be6f8b4ce65e1f2ffe442b6d..f0a7ce54971661db1768ba9e0d71467addb88bfc 100644 (file)
@@ -19,6 +19,7 @@
 use ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable};
 use ty::{Slice, TyS};
 use util::captures::Captures;
+use mir::interpret::{Allocation, PrimVal, MemoryPointer, Value, ConstValue};
 
 use std::iter;
 use std::cmp::Ordering;
@@ -1730,4 +1731,156 @@ pub struct Const<'tcx> {
     pub val: ConstVal<'tcx>,
 }
 
+impl<'tcx> Const<'tcx> {
+    pub fn unevaluated(
+        tcx: TyCtxt<'_, '_, 'tcx>,
+        def_id: DefId,
+        substs: &'tcx Substs<'tcx>,
+        ty: Ty<'tcx>,
+    ) -> &'tcx Self {
+        tcx.mk_const(Const {
+            val: ConstVal::Unevaluated(def_id, substs),
+            ty,
+        })
+    }
+
+    #[inline]
+    pub fn from_const_val(
+        tcx: TyCtxt<'_, '_, 'tcx>,
+        val: ConstVal<'tcx>,
+        ty: Ty<'tcx>,
+    ) -> &'tcx Self {
+        tcx.mk_const(Const {
+            val,
+            ty,
+        })
+    }
+
+    #[inline]
+    pub fn from_const_value(
+        tcx: TyCtxt<'_, '_, 'tcx>,
+        val: ConstValue<'tcx>,
+        ty: Ty<'tcx>,
+    ) -> &'tcx Self {
+        Self::from_const_val(tcx, ConstVal::Value(val), ty)
+    }
+
+    #[inline]
+    pub fn from_alloc(
+        tcx: TyCtxt<'_, '_, 'tcx>,
+        alloc: &'tcx Allocation,
+        ty: Ty<'tcx>,
+    ) -> &'tcx Self {
+        Self::from_const_value(tcx, ConstValue::ByRef(alloc), ty)
+    }
+
+    #[inline]
+    pub fn from_byval_value(
+        tcx: TyCtxt<'_, '_, 'tcx>,
+        val: Value,
+        ty: Ty<'tcx>,
+    ) -> &'tcx Self {
+        Self::from_const_value(tcx, ConstValue::from_byval_value(val), ty)
+    }
+
+    #[inline]
+    pub fn from_primval(
+        tcx: TyCtxt<'_, '_, 'tcx>,
+        val: PrimVal,
+        ty: Ty<'tcx>,
+    ) -> &'tcx Self {
+        Self::from_const_value(tcx, ConstValue::from_primval(val), ty)
+    }
+
+    #[inline]
+    pub fn from_bits(
+        tcx: TyCtxt<'_, '_, 'tcx>,
+        val: u128,
+        ty: Ty<'tcx>,
+    ) -> &'tcx Self {
+        Self::from_primval(tcx, PrimVal::Bytes(val), ty)
+    }
+
+    #[inline]
+    pub fn zero_sized(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) -> &'tcx Self {
+        Self::from_primval(tcx, PrimVal::Undef, ty)
+    }
+
+    #[inline]
+    pub fn from_bool(tcx: TyCtxt<'_, '_, 'tcx>, v: bool) -> &'tcx Self {
+        Self::from_bits(tcx, v as u128, tcx.types.bool)
+    }
+
+    #[inline]
+    pub fn from_usize(tcx: TyCtxt<'_, '_, 'tcx>, n: u64) -> &'tcx Self {
+        Self::from_bits(tcx, n as u128, tcx.types.usize)
+    }
+
+    #[inline]
+    pub fn to_bits(&self, ty: Ty<'_>) -> Option<u128> {
+        if self.ty != ty {
+            return None;
+        }
+        match self.val {
+            ConstVal::Value(val) => val.to_bits(),
+            _ => None,
+        }
+    }
+
+    #[inline]
+    pub fn to_ptr(&self) -> Option<MemoryPointer> {
+        match self.val {
+            ConstVal::Value(val) => val.to_ptr(),
+            _ => None,
+        }
+    }
+
+    #[inline]
+    pub fn to_primval(&self) -> Option<PrimVal> {
+        match self.val {
+            ConstVal::Value(val) => val.to_primval(),
+            _ => None,
+        }
+    }
+
+    #[inline]
+    pub fn assert_bits(&self, ty: Ty<'_>) -> Option<u128> {
+        assert_eq!(self.ty, ty);
+        match self.val {
+            ConstVal::Value(val) => val.to_bits(),
+            _ => None,
+        }
+    }
+
+    #[inline]
+    pub fn assert_bool(&self, tcx: TyCtxt<'_, '_, '_>) -> Option<bool> {
+        self.assert_bits(tcx.types.bool).and_then(|v| match v {
+            0 => Some(false),
+            1 => Some(true),
+            _ => None,
+        })
+    }
+
+    #[inline]
+    pub fn assert_usize(&self, tcx: TyCtxt<'_, '_, '_>) -> Option<u64> {
+        self.assert_bits(tcx.types.usize).map(|v| v as u64)
+    }
+
+    #[inline]
+    pub fn unwrap_bits(&self, ty: Ty<'_>) -> u128 {
+        match self.assert_bits(ty) {
+            Some(val) => val,
+            None => bug!("expected bits of {}, got {:#?}", ty, self),
+        }
+    }
+
+    #[inline]
+    pub fn unwrap_usize(&self, tcx: TyCtxt<'_, '_, '_>) -> u64 {
+        match self.assert_usize(tcx) {
+            Some(val) => val,
+            None => bug!("expected constant usize, got {:#?}", self),
+        }
+    }
+}
+
 impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Const<'tcx> {}
index 80dc3b2b452ce4047370fcf5683b9da55872d8fa..fdd0754730febb72bf0d37a73f73d95bf00c864f 100644 (file)
@@ -16,7 +16,7 @@
 use hir;
 use ich::NodeIdHashingMode;
 use middle::const_val::ConstVal;
-use traits;
+use traits::{self, ObligationCause};
 use ty::{self, Ty, TyCtxt, TypeFoldable};
 use ty::fold::TypeVisitor;
 use ty::subst::UnpackedKind;
@@ -25,7 +25,6 @@
 use ty::layout::{Integer, IntegerExt};
 use util::common::ErrorReported;
 use middle::lang_items;
-use mir::interpret::{Value, PrimVal};
 
 use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
                                            HashStable};
@@ -167,9 +166,9 @@ fn disr_incr<'a, 'tcx>(
 }
 
 
-#[derive(Copy, Clone)]
+#[derive(Clone)]
 pub enum CopyImplementationError<'tcx> {
-    InfrigingField(&'tcx ty::FieldDef),
+    InfrigingFields(Vec<&'tcx ty::FieldDef>),
     NotAnAdt,
     HasDestructor,
 }
@@ -192,7 +191,7 @@ pub enum Representability {
 impl<'tcx> ty::ParamEnv<'tcx> {
     pub fn can_type_implement_copy<'a>(self,
                                        tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                       self_type: Ty<'tcx>, span: Span)
+                                       self_type: Ty<'tcx>)
                                        -> Result<(), CopyImplementationError<'tcx>> {
         // FIXME: (@jroesch) float this code up
         tcx.infer_ctxt().enter(|infcx| {
@@ -208,22 +207,29 @@ pub fn can_type_implement_copy<'a>(self,
                 _ => return Err(CopyImplementationError::NotAnAdt),
             };
 
-            let field_implements_copy = |field: &ty::FieldDef| {
-                let cause = traits::ObligationCause::dummy();
-                match traits::fully_normalize(&infcx, cause, self, &field.ty(tcx, substs)) {
-                    Ok(ty) => !infcx.type_moves_by_default(self, ty, span),
-                    Err(..) => false,
-                }
-            };
-
+            let mut infringing = Vec::new();
             for variant in &adt.variants {
                 for field in &variant.fields {
-                    if !field_implements_copy(field) {
-                        return Err(CopyImplementationError::InfrigingField(field));
+                    let span = tcx.def_span(field.did);
+                    let ty = field.ty(tcx, substs);
+                    if ty.references_error() {
+                        continue;
                     }
+                    let cause = ObligationCause { span, ..ObligationCause::dummy() };
+                    let ctx = traits::FulfillmentContext::new();
+                    match traits::fully_normalize(&infcx, ctx, cause, self, &ty) {
+                        Ok(ty) => if infcx.type_moves_by_default(self, ty, span) {
+                            infringing.push(field);
+                        }
+                        Err(errors) => {
+                            infcx.report_fulfillment_errors(&errors, None, false);
+                        }
+                    };
                 }
             }
-
+            if !infringing.is_empty() {
+                return Err(CopyImplementationError::InfrigingFields(infringing));
+            }
             if adt.has_dtor(tcx) {
                 return Err(CopyImplementationError::HasDestructor);
             }
@@ -659,9 +665,8 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool {
             TyArray(_, n) => {
                 self.hash_discriminant_u8(&n.val);
                 match n.val {
-                    ConstVal::Value(Value::ByVal(PrimVal::Bytes(b))) => self.hash(b),
+                    ConstVal::Value(alloc) => self.hash(alloc),
                     ConstVal::Unevaluated(def_id, _) => self.def_id(def_id),
-                    _ => bug!("arrays should not have {:?} as length", n)
                 }
             }
             TyRawPtr(m) => self.hash(m.mutbl),
index 4fb1017035168497b5d42b9534251e736a9e2e43..a6eb468e33836fc43fcddf6ae9e209a95b174c82 100644 (file)
@@ -21,7 +21,6 @@
 use ty::{TyDynamic, TyInt, TyUint, TyInfer};
 use ty::{self, Ty, TyCtxt, TypeFoldable};
 use util::nodemap::FxHashSet;
-use mir::interpret::{Value, PrimVal};
 
 use std::cell::Cell;
 use std::fmt;
@@ -1183,15 +1182,12 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                 TyArray(ty, sz) => {
                     print!(f, cx, write("["), print(ty), write("; "))?;
                     match sz.val {
-                        ConstVal::Value(Value::ByVal(PrimVal::Bytes(sz))) => {
-                            write!(f, "{}", sz)?;
-                        }
+                        ConstVal::Value(..) => ty::tls::with(|tcx| {
+                            write!(f, "{}", sz.unwrap_usize(tcx))
+                        })?,
                         ConstVal::Unevaluated(_def_id, _substs) => {
                             write!(f, "_")?;
                         }
-                        _ => {
-                            write!(f, "{:?}", sz)?;
-                        }
                     }
                     write!(f, "]")
                 }
index 9178d0d00faa49ae0c34f68e9d2a214b32ae047c..6f1cbcad2f46c3bec9f83df0dd1614a4548d612c 100644 (file)
@@ -16,6 +16,7 @@ serialize = { path = "../libserialize" }
 cfg-if = "0.1.2"
 stable_deref_trait = "1.0.0"
 parking_lot_core = "0.2.8"
+rustc-rayon = "0.1.0"
 
 [dependencies.parking_lot]
 version = "0.5"
index dc487f1162ca9d074b8735937e069b846a7dbc60..54407658e6ccc85f77e27682800529d98db3fba0 100644 (file)
@@ -175,7 +175,7 @@ pub fn children(&self, node: Node) -> &[Node] {
 }
 
 impl<Node: Idx> fmt::Debug for DominatorTree<Node> {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         fmt::Debug::fmt(&DominatorTreeNode {
                             tree: self,
                             node: self.root,
@@ -190,7 +190,7 @@ struct DominatorTreeNode<'tree, Node: Idx> {
 }
 
 impl<'tree, Node: Idx> fmt::Debug for DominatorTreeNode<'tree, Node> {
-    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         let subtrees: Vec<_> = self.tree
             .children(self.node)
             .iter()
index 597d1627ada03da578556f761897937181a063c7..b2e7450e76cdf4a9063e4dbb9e5bf6c147d9165d 100644 (file)
@@ -44,6 +44,7 @@
 #[macro_use]
 extern crate cfg_if;
 extern crate stable_deref_trait;
+extern crate rustc_rayon as rayon;
 
 // See librustc_cratesio_shim/Cargo.toml for a comment explaining this.
 #[allow(unused_extern_crates)]
index c466b8f8ad1b5acb716db8b2720dd2cadb25c08f..aa113fac9fb7dff28baa92dfba7bfe5f0b80b50b 100644 (file)
@@ -1002,7 +1002,7 @@ impl<O, T: ?Sized> Debug for OwningRef<O, T>
     where O: Debug,
           T: Debug,
 {
-    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f,
                "OwningRef {{ owner: {:?}, reference: {:?} }}",
                self.owner(),
@@ -1014,7 +1014,7 @@ impl<O, T: ?Sized> Debug for OwningRefMut<O, T>
     where O: Debug,
           T: Debug,
 {
-    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f,
                "OwningRefMut {{ owner: {:?}, reference: {:?} }}",
                self.owner(),
@@ -1047,7 +1047,7 @@ unsafe impl<O, T: ?Sized> Sync for OwningRefMut<O, T>
     where O: Sync, for<'a> (&'a mut T): Sync {}
 
 impl Debug for Erased {
-    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "<Erased>",)
     }
 }
index 3b7d6efbdae1e760694fced946ac9031bd2db2ec..3661763133014b593f42fd30f0bc1bbd345f3c44 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! This mdoule defines types which are thread safe if cfg!(parallel_queries) is true.
+//! This module defines types which are thread safe if cfg!(parallel_queries) is true.
 //!
 //! `Lrc` is an alias of either Rc or Arc.
 //!
 use std::ops::{Deref, DerefMut};
 use owning_ref::{Erased, OwningRef};
 
+pub fn serial_join<A, B, RA, RB>(oper_a: A, oper_b: B) -> (RA, RB)
+    where A: FnOnce() -> RA,
+          B: FnOnce() -> RB
+{
+    (oper_a(), oper_b())
+}
+
+pub struct SerialScope;
+
+impl SerialScope {
+    pub fn spawn<F>(&self, f: F)
+        where F: FnOnce(&SerialScope)
+    {
+        f(self)
+    }
+}
+
+pub fn serial_scope<F, R>(f: F) -> R
+    where F: FnOnce(&SerialScope) -> R
+{
+    f(&SerialScope)
+}
+
 cfg_if! {
     if #[cfg(not(parallel_queries))] {
         pub auto trait Send {}
@@ -55,9 +78,19 @@ macro_rules! rustc_erase_owner {
             }
         }
 
+        pub use self::serial_join as join;
+        pub use self::serial_scope as scope;
+
+        pub use std::iter::Iterator as ParallelIterator;
+
+        pub fn par_iter<T: IntoIterator>(t: T) -> T::IntoIter {
+            t.into_iter()
+        }
+
         pub type MetadataRef = OwningRef<Box<Erased>, [u8]>;
 
         pub use std::rc::Rc as Lrc;
+        pub use std::rc::Weak as Weak;
         pub use std::cell::Ref as ReadGuard;
         pub use std::cell::RefMut as WriteGuard;
         pub use std::cell::RefMut as LockGuard;
@@ -160,6 +193,7 @@ pub fn take(&self) -> Option<T> {
         pub use parking_lot::MutexGuard as LockGuard;
 
         pub use std::sync::Arc as Lrc;
+        pub use std::sync::Weak as Weak;
 
         pub use self::Lock as MTLock;
 
@@ -167,6 +201,14 @@ pub fn take(&self) -> Option<T> {
         use parking_lot::RwLock as InnerRwLock;
 
         use std::thread;
+        pub use rayon::{join, scope};
+
+        pub use rayon::iter::ParallelIterator;
+        use rayon::iter::IntoParallelIterator;
+
+        pub fn par_iter<T: IntoParallelIterator>(t: T) -> T::Iter {
+            t.into_par_iter()
+        }
 
         pub type MetadataRef = OwningRef<Box<Erased + Send + Sync>, [u8]>;
 
index 5aae1bcad896f18fdee8a2d9ac60f8e7d27ab865..1827533f0acb5977be80b10f24c89e85f7291980 100644 (file)
@@ -13,6 +13,8 @@ arena = { path = "../libarena" }
 graphviz = { path = "../libgraphviz" }
 log = "0.4"
 env_logger = { version = "0.5", default-features = false }
+rustc-rayon = "0.1.0"
+scoped-tls = { version = "0.1.1", features = ["nightly"] }
 rustc = { path = "../librustc" }
 rustc_allocator = { path = "../librustc_allocator" }
 rustc_target = { path = "../librustc_target" }
index 1e74039503d51c5760498d1fd3f8de3f75e7b5d5..62b3accc46f18e6bfc85600df45e1def21ef59c2 100644 (file)
@@ -20,7 +20,7 @@
 use rustc::session::search_paths::PathKind;
 use rustc::lint;
 use rustc::middle::{self, reachable, resolve_lifetime, stability};
-use rustc::middle::cstore::CrateStore;
+use rustc::middle::cstore::CrateStoreDyn;
 use rustc::middle::privacy::AccessLevels;
 use rustc::ty::{self, AllArenas, Resolutions, TyCtxt};
 use rustc::traits;
@@ -49,7 +49,7 @@
 use std::io::{self, Write};
 use std::iter;
 use std::path::{Path, PathBuf};
-use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::{self, Lrc};
 use std::sync::mpsc;
 use syntax::{self, ast, attr, diagnostics, visit};
 use syntax::ext::base::ExtCtxt;
 
 use profile;
 
+#[cfg(not(parallel_queries))]
+pub fn spawn_thread_pool<F: FnOnce(config::Options) -> R + sync::Send, R: sync::Send>(
+    opts: config::Options,
+    f: F
+) -> R {
+    f(opts)
+}
+
+#[cfg(parallel_queries)]
+pub fn spawn_thread_pool<F: FnOnce(config::Options) -> R + sync::Send, R: sync::Send>(
+    opts: config::Options,
+    f: F
+) -> R {
+    use syntax;
+    use syntax_pos;
+    use rayon::{ThreadPoolBuilder, ThreadPool};
+
+    let config = ThreadPoolBuilder::new().num_threads(Session::query_threads_from_opts(&opts))
+                                         .stack_size(16 * 1024 * 1024);
+
+    let with_pool = move |pool: &ThreadPool| {
+        pool.install(move || f(opts))
+    };
+
+    syntax::GLOBALS.with(|syntax_globals| {
+        syntax_pos::GLOBALS.with(|syntax_pos_globals| {
+            // The main handler run for each Rayon worker thread and sets up
+            // the thread local rustc uses. syntax_globals and syntax_pos_globals are
+            // captured and set on the new threads. ty::tls::with_thread_locals sets up
+            // thread local callbacks from libsyntax
+            let main_handler = move |worker: &mut FnMut()| {
+                syntax::GLOBALS.set(syntax_globals, || {
+                    syntax_pos::GLOBALS.set(syntax_pos_globals, || {
+                        ty::tls::with_thread_locals(|| {
+                            worker()
+                        })
+                    })
+                })
+            };
+
+            ThreadPool::scoped_pool(config, main_handler, with_pool).unwrap()
+        })
+    })
+}
+
 pub fn compile_input(
     trans: Box<TransCrate>,
     sess: &Session,
@@ -1047,7 +1092,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(
     trans: &TransCrate,
     control: &CompileController,
     sess: &'tcx Session,
-    cstore: &'tcx CrateStore,
+    cstore: &'tcx CrateStoreDyn,
     hir_map: hir_map::Map<'tcx>,
     mut analysis: ty::CrateAnalysis,
     resolutions: Resolutions,
index a1052ca6c3ca9520fc7cf8f4e38ebc106f8263a7..148fbd73e9bd8ffc7d1e9cafea1c8cf684c0b684 100644 (file)
 #![feature(rustc_stack_internals)]
 #![feature(no_debug)]
 
+#![recursion_limit="256"]
+
 extern crate arena;
 extern crate getopts;
 extern crate graphviz;
 extern crate env_logger;
 #[cfg(unix)]
 extern crate libc;
+extern crate rustc_rayon as rayon;
 extern crate rustc;
 extern crate rustc_allocator;
 extern crate rustc_target;
@@ -51,6 +54,7 @@
 extern crate rustc_traits;
 extern crate rustc_trans_utils;
 extern crate rustc_typeck;
+extern crate scoped_tls;
 extern crate serialize;
 #[macro_use]
 extern crate log;
@@ -64,7 +68,7 @@
 use rustc_resolve as resolve;
 use rustc_save_analysis as save;
 use rustc_save_analysis::DumpHandler;
-use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::{self, Lrc};
 use rustc_data_structures::OnDrop;
 use rustc::session::{self, config, Session, build_session, CompileResult};
 use rustc::session::CompileIncomplete;
@@ -448,22 +452,33 @@ fn GetModuleFileNameW(hModule: usize,
 // See comments on CompilerCalls below for details about the callbacks argument.
 // The FileLoader provides a way to load files from sources other than the file system.
 pub fn run_compiler<'a>(args: &[String],
-                        callbacks: &mut CompilerCalls<'a>,
+                        callbacks: &mut (CompilerCalls<'a> + sync::Send),
                         file_loader: Option<Box<FileLoader + Send + Sync + 'static>>,
                         emitter_dest: Option<Box<Write + Send>>)
                         -> (CompileResult, Option<Session>)
 {
     syntax::with_globals(|| {
-        run_compiler_impl(args, callbacks, file_loader, emitter_dest)
+        let matches = match handle_options(args) {
+            Some(matches) => matches,
+            None => return (Ok(()), None),
+        };
+
+        let (sopts, cfg) = config::build_session_options_and_crate_config(&matches);
+
+        driver::spawn_thread_pool(sopts, |sopts| {
+            run_compiler_with_pool(matches, sopts, cfg, callbacks, file_loader, emitter_dest)
+        })
     })
 }
 
-fn run_compiler_impl<'a>(args: &[String],
-                         callbacks: &mut CompilerCalls<'a>,
-                         file_loader: Option<Box<FileLoader + Send + Sync + 'static>>,
-                         emitter_dest: Option<Box<Write + Send>>)
-                         -> (CompileResult, Option<Session>)
-{
+fn run_compiler_with_pool<'a>(
+    matches: getopts::Matches,
+    sopts: config::Options,
+    cfg: ast::CrateConfig,
+    callbacks: &mut (CompilerCalls<'a> + sync::Send),
+    file_loader: Option<Box<FileLoader + Send + Sync + 'static>>,
+    emitter_dest: Option<Box<Write + Send>>
+) -> (CompileResult, Option<Session>) {
     macro_rules! do_or_return {($expr: expr, $sess: expr) => {
         match $expr {
             Compilation::Stop => return (Ok(()), $sess),
@@ -471,13 +486,6 @@ macro_rules! do_or_return {($expr: expr, $sess: expr) => {
         }
     }}
 
-    let matches = match handle_options(args) {
-        Some(matches) => matches,
-        None => return (Ok(()), None),
-    };
-
-    let (sopts, cfg) = config::build_session_options_and_crate_config(&matches);
-
     let descriptions = diagnostics_registry();
 
     do_or_return!(callbacks.early_callback(&matches,
index 70b73ebb8cdeb476f5b978bdf9579a8e017542a7..108b47623383c0e3e27755fca3c4dd01f4bbd1d0 100644 (file)
@@ -20,7 +20,7 @@
 use rustc::ty::{self, TyCtxt, Resolutions, AllArenas};
 use rustc::cfg;
 use rustc::cfg::graphviz::LabelledCFG;
-use rustc::middle::cstore::CrateStore;
+use rustc::middle::cstore::CrateStoreDyn;
 use rustc::session::Session;
 use rustc::session::config::{Input, OutputFilenames};
 use rustc_borrowck as borrowck;
@@ -199,7 +199,7 @@ fn call_with_pp_support<'tcx, A, F>(&self,
     }
     fn call_with_pp_support_hir<'tcx, A, F>(&self,
                                                sess: &'tcx Session,
-                                               cstore: &'tcx CrateStore,
+                                               cstore: &'tcx CrateStoreDyn,
                                                hir_map: &hir_map::Map<'tcx>,
                                                analysis: &ty::CrateAnalysis,
                                                resolutions: &Resolutions,
@@ -912,7 +912,7 @@ pub fn print_after_parsing(sess: &Session,
 }
 
 pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session,
-                                                cstore: &'tcx CrateStore,
+                                                cstore: &'tcx CrateStoreDyn,
                                                 hir_map: &hir_map::Map<'tcx>,
                                                 analysis: &ty::CrateAnalysis,
                                                 resolutions: &Resolutions,
@@ -1068,7 +1068,7 @@ pub fn print_after_hir_lowering<'tcx, 'a: 'tcx>(sess: &'a Session,
 // with a different callback than the standard driver, so that isn't easy.
 // Instead, we call that function ourselves.
 fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session,
-                                       cstore: &'a CrateStore,
+                                       cstore: &'a CrateStoreDyn,
                                        hir_map: &hir_map::Map<'tcx>,
                                        analysis: &ty::CrateAnalysis,
                                        resolutions: &Resolutions,
index d2ee3d8743c2cd74886d8e3b3a5d18098c5d22e7..7ae26e9e9798e72c15b8f64e70d1459c0b90e6c5 100644 (file)
@@ -99,20 +99,25 @@ fn test_env<F>(source_string: &str,
     where F: FnOnce(Env)
 {
     syntax::with_globals(|| {
-        test_env_impl(source_string, args, body)
+        let mut options = config::basic_options();
+        options.debugging_opts.verbose = true;
+        options.unstable_features = UnstableFeatures::Allow;
+
+        driver::spawn_thread_pool(options, |options| {
+            test_env_with_pool(options, source_string, args, body)
+        })
     });
 }
 
-fn test_env_impl<F>(source_string: &str,
-                    (emitter, expected_err_count): (Box<Emitter + sync::Send>, usize),
-                    body: F)
+fn test_env_with_pool<F>(
+    options: config::Options,
+    source_string: &str,
+    (emitter, expected_err_count): (Box<Emitter + sync::Send>, usize),
+    body: F
+)
     where F: FnOnce(Env)
 {
-    let mut options = config::basic_options();
-    options.debugging_opts.verbose = true;
-    options.unstable_features = UnstableFeatures::Allow;
     let diagnostic_handler = errors::Handler::with_emitter(true, false, emitter);
-
     let sess = session::build_session_(options,
                                        None,
                                        diagnostic_handler,
index c2b442e949758a19c64f4b2aa73dc8d7264f6282..fd90e1cbe0866b16bdbfaefb2dfd20c4e6055a20 100644 (file)
@@ -232,7 +232,7 @@ pub fn raise(self) -> ! {
 }
 
 impl fmt::Display for FatalError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "parser fatal error")
     }
 }
@@ -249,7 +249,7 @@ fn description(&self) -> &str {
 pub struct ExplicitBug;
 
 impl fmt::Display for ExplicitBug {
-    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "parser internal bug")
     }
 }
index a5e07bcec24bb65c242de5765c68c6ad9c3792a9..ababce69e3170d850e939df33dfefdc3b4039ad6 100644 (file)
@@ -36,9 +36,9 @@
 pub use persist::load_dep_graph;
 pub use persist::load_query_result_cache;
 pub use persist::LoadResult;
+pub use persist::copy_cgu_workproducts_to_incr_comp_cache_dir;
 pub use persist::save_dep_graph;
-pub use persist::save_trans_partition;
-pub use persist::save_work_products;
+pub use persist::save_work_product_index;
 pub use persist::in_incr_comp_dir;
 pub use persist::prepare_session_directory;
 pub use persist::finalize_session_directory;
index 755a550b5bca31e4af3a120cd56d4b6ce22dd204..e1f00db56d5cbc0572214a3a15d94941e7a8b09e 100644 (file)
@@ -29,6 +29,6 @@
 pub use self::load::load_query_result_cache;
 pub use self::load::LoadResult;
 pub use self::save::save_dep_graph;
-pub use self::save::save_work_products;
-pub use self::work_product::save_trans_partition;
+pub use self::save::save_work_product_index;
+pub use self::work_product::copy_cgu_workproducts_to_incr_comp_cache_dir;
 pub use self::work_product::delete_workproduct_files;
index e524fcecf9094a3edce0a932d97ee83f2878272c..be725b17933215661af70724ba01e6b4c432a7b7 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use rustc::dep_graph::{DepGraph, DepKind};
+use rustc::dep_graph::{DepGraph, DepKind, WorkProduct, WorkProductId};
 use rustc::session::Session;
 use rustc::ty::TyCtxt;
 use rustc::util::common::time;
@@ -55,22 +55,22 @@ pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     })
 }
 
-pub fn save_work_products(sess: &Session, dep_graph: &DepGraph) {
+pub fn save_work_product_index(sess: &Session,
+                               dep_graph: &DepGraph,
+                               new_work_products: FxHashMap<WorkProductId, WorkProduct>) {
     if sess.opts.incremental.is_none() {
         return;
     }
 
-    debug!("save_work_products()");
+    debug!("save_work_product_index()");
     dep_graph.assert_ignored();
     let path = work_products_path(sess);
-    save_in(sess, path, |e| encode_work_products(dep_graph, e));
+    save_in(sess, path, |e| encode_work_product_index(&new_work_products, e));
 
     // We also need to clean out old work-products, as not all of them are
     // deleted during invalidation. Some object files don't change their
     // content, they are just not needed anymore.
-    let new_work_products = dep_graph.work_products();
     let previous_work_products = dep_graph.previous_work_products();
-
     for (id, wp) in previous_work_products.iter() {
         if !new_work_products.contains_key(id) {
             work_product::delete_workproduct_files(sess, wp);
@@ -234,10 +234,9 @@ struct Stat {
     Ok(())
 }
 
-fn encode_work_products(dep_graph: &DepGraph,
-                        encoder: &mut Encoder) -> io::Result<()> {
-    let work_products: Vec<_> = dep_graph
-        .work_products()
+fn encode_work_product_index(work_products: &FxHashMap<WorkProductId, WorkProduct>,
+                             encoder: &mut Encoder) -> io::Result<()> {
+    let serialized_products: Vec<_> = work_products
         .iter()
         .map(|(id, work_product)| {
             SerializedWorkProduct {
@@ -247,7 +246,7 @@ fn encode_work_products(dep_graph: &DepGraph,
         })
         .collect();
 
-    work_products.encode(encoder)
+    serialized_products.encode(encoder)
 }
 
 fn encode_query_cache(tcx: TyCtxt,
index 879132bcacfcfcd86a3c6426152e7fc95d016e75..d0c7766cbae08bd3338ba2db91baa965c359ec1a 100644 (file)
 //! This module contains files for saving intermediate work-products.
 
 use persist::fs::*;
-use rustc::dep_graph::{WorkProduct, WorkProductId, DepGraph, WorkProductFileKind};
+use rustc::dep_graph::{WorkProduct, WorkProductId, WorkProductFileKind};
 use rustc::session::Session;
 use rustc::util::fs::link_or_copy;
 use std::path::PathBuf;
 use std::fs as std_fs;
 
-pub fn save_trans_partition(sess: &Session,
-                            dep_graph: &DepGraph,
-                            cgu_name: &str,
-                            files: &[(WorkProductFileKind, PathBuf)]) {
-    debug!("save_trans_partition({:?},{:?})",
+pub fn copy_cgu_workproducts_to_incr_comp_cache_dir(
+    sess: &Session,
+    cgu_name: &str,
+    files: &[(WorkProductFileKind, PathBuf)]
+) -> Option<(WorkProductId, WorkProduct)> {
+    debug!("copy_cgu_workproducts_to_incr_comp_cache_dir({:?},{:?})",
            cgu_name,
            files);
     if sess.opts.incremental.is_none() {
-        return
+        return None
     }
     let work_product_id = WorkProductId::from_cgu_name(cgu_name);
 
@@ -53,8 +54,8 @@ pub fn save_trans_partition(sess: &Session,
              })
              .collect();
     let saved_files = match saved_files {
+        None => return None,
         Some(v) => v,
-        None => return,
     };
 
     let work_product = WorkProduct {
@@ -62,7 +63,7 @@ pub fn save_trans_partition(sess: &Session,
         saved_files,
     };
 
-    dep_graph.insert_work_product(&work_product_id, work_product);
+    Some((work_product_id, work_product))
 }
 
 pub fn delete_workproduct_files(sess: &Session, work_product: &WorkProduct) {
index a12b28ee8883dcfb9be8d22356f5d91c9d04a4b3..c2dcbad8d24519fc1b1d23f5c78362185827fc51 100644 (file)
@@ -541,7 +541,7 @@ fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
         if !ty.moves_by_default(cx.tcx, param_env, item.span) {
             return;
         }
-        if param_env.can_type_implement_copy(cx.tcx, ty, item.span).is_ok() {
+        if param_env.can_type_implement_copy(cx.tcx, ty).is_ok() {
             cx.span_lint(MISSING_COPY_IMPLEMENTATIONS,
                          item.span,
                          "type could implement `Copy`; consider adding `impl \
@@ -1287,32 +1287,27 @@ fn get_lints(&self) -> LintArray {
 
 impl UnreachablePub {
     fn perform_lint(&self, cx: &LateContext, what: &str, id: ast::NodeId,
-                    vis: &hir::Visibility, span: Span, exportable: bool) {
+                    vis: &hir::Visibility, span: Span, exportable: bool,
+                    mut applicability: Applicability) {
         if !cx.access_levels.is_reachable(id) && *vis == hir::Visibility::Public {
+            if span.ctxt().outer().expn_info().is_some() {
+                applicability = Applicability::MaybeIncorrect;
+            }
             let def_span = cx.tcx.sess.codemap().def_span(span);
             let mut err = cx.struct_span_lint(UNREACHABLE_PUB, def_span,
                                               &format!("unreachable `pub` {}", what));
-            // visibility is token at start of declaration (can be macro
-            // variable rather than literal `pub`)
+            // We are presuming that visibility is token at start of
+            // declaration (can be macro variable rather than literal `pub`)
             let pub_span = cx.tcx.sess.codemap().span_until_char(def_span, ' ');
             let replacement = if cx.tcx.features().crate_visibility_modifier {
                 "crate"
             } else {
                 "pub(crate)"
             }.to_owned();
-            let app = if span.ctxt().outer().expn_info().is_none() {
-                // even if macros aren't involved the suggestion
-                // may be incorrect -- the user may have mistakenly
-                // hidden it behind a private module and this lint is
-                // a helpful way to catch that. However, we're trying
-                // not to change the nature of the code with this lint
-                // so it's marked as machine applicable.
-                Applicability::MachineApplicable
-            } else {
-                Applicability::MaybeIncorrect
-            };
-            err.span_suggestion_with_applicability(pub_span, "consider restricting its visibility",
-                                                   replacement, app);
+            err.span_suggestion_with_applicability(pub_span,
+                                                   "consider restricting its visibility",
+                                                   replacement,
+                                                   applicability);
             if exportable {
                 err.help("or consider exporting it for use by other crates");
             }
@@ -1321,21 +1316,31 @@ fn perform_lint(&self, cx: &LateContext, what: &str, id: ast::NodeId,
     }
 }
 
+
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnreachablePub {
     fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
-        self.perform_lint(cx, "item", item.id, &item.vis, item.span, true);
+        let applicability = match item.node {
+            // suggestion span-manipulation is inadequate for `pub use
+            // module::{item}` (Issue #50455)
+            hir::ItemUse(..) => Applicability::MaybeIncorrect,
+            _ => Applicability::MachineApplicable,
+        };
+        self.perform_lint(cx, "item", item.id, &item.vis, item.span, true, applicability);
     }
 
     fn check_foreign_item(&mut self, cx: &LateContext, foreign_item: &hir::ForeignItem) {
-        self.perform_lint(cx, "item", foreign_item.id, &foreign_item.vis, foreign_item.span, true);
+        self.perform_lint(cx, "item", foreign_item.id, &foreign_item.vis,
+                          foreign_item.span, true, Applicability::MachineApplicable);
     }
 
     fn check_struct_field(&mut self, cx: &LateContext, field: &hir::StructField) {
-        self.perform_lint(cx, "field", field.id, &field.vis, field.span, false);
+        self.perform_lint(cx, "field", field.id, &field.vis, field.span, false,
+                          Applicability::MachineApplicable);
     }
 
     fn check_impl_item(&mut self, cx: &LateContext, impl_item: &hir::ImplItem) {
-        self.perform_lint(cx, "item", impl_item.id, &impl_item.vis, impl_item.span, false);
+        self.perform_lint(cx, "item", impl_item.id, &impl_item.vis, impl_item.span, false,
+                          Applicability::MachineApplicable);
     }
 }
 
@@ -1543,6 +1548,9 @@ fn get_lints(&self) -> LintArray {
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ExternCrate {
     fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
+        if !cx.tcx.features().extern_absolute_paths {
+            return
+        }
         if let hir::ItemExternCrate(ref orig) =  it.node {
             if it.attrs.iter().any(|a| a.check_name("macro_use")) {
                 return
index dba2e918f6f3a10a3fb44618bfcd55d6909de825..c1e32c7c0226ed94898566f5e3423e9579563392 100644 (file)
@@ -1651,6 +1651,7 @@ pub fn LLVMRustConfigurePassManagerBuilder(PMB: PassManagerBuilderRef,
                                                MergeFunctions: bool,
                                                SLPVectorize: bool,
                                                LoopVectorize: bool,
+                                               PrepareForThinLTO: bool,
                                                PGOGenPath: *const c_char,
                                                PGOUsePath: *const c_char);
     pub fn LLVMRustAddLibraryInfo(PM: PassManagerRef,
index 4d1f3e2b4300ab30a8ed6927cfe0029b6f78bca9..57b8824191f7b86ab50e1e02148e1eb35c129fcc 100644 (file)
@@ -1185,7 +1185,7 @@ fn new(origin: RegionVariableOrigin) -> Self {
 }
 
 impl fmt::Debug for Constraint {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
         write!(
             formatter,
             "({:?}: {:?} @ {:?}) due to {:?}",
index 42a1745addff75de36333f0f7047e59e2af05aea..1014299c708ddbcb4eb33d6ccda25cef9e0c71c6 100644 (file)
@@ -425,7 +425,7 @@ fn sanitize_projection(
             ProjectionElem::Subslice { from, to } => PlaceTy::Ty {
                 ty: match base_ty.sty {
                     ty::TyArray(inner, size) => {
-                        let size = size.val.unwrap_u64();
+                        let size = size.unwrap_usize(tcx);
                         let min_size = (from as u64) + (to as u64);
                         if let Some(rest_size) = size.checked_sub(min_size) {
                             tcx.mk_array(inner, rest_size)
index 648746b6e9047d9e21978a1940990ff77c0a9187..20e11abca9fa0cf9eff30aa1ac1c92453151d7df 100644 (file)
 use build::{BlockAnd, BlockAndExtension, Builder};
 use build::expr::category::{Category, RvalueFunc};
 use hair::*;
-use rustc::middle::const_val::ConstVal;
 use rustc::middle::region;
 use rustc::ty::{self, Ty, UpvarSubsts};
 use rustc::mir::*;
-use rustc::mir::interpret::{Value, PrimVal, EvalErrorKind};
+use rustc::mir::interpret::EvalErrorKind;
 use syntax_pos::Span;
 
 impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
@@ -200,10 +199,10 @@ fn expr_as_rvalue(&mut self,
                             span: expr_span,
                             ty: this.hir.tcx().types.u32,
                             literal: Literal::Value {
-                                value: this.hir.tcx().mk_const(ty::Const {
-                                    val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(0))),
-                                    ty: this.hir.tcx().types.u32
-                                }),
+                                value: ty::Const::from_bits(
+                                    this.hir.tcx(),
+                                    0,
+                                    this.hir.tcx().types.u32),
                             },
                         }));
                         box AggregateKind::Generator(closure_id, substs, movability)
@@ -378,10 +377,7 @@ fn neg_1_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
         let bits = self.hir.integer_bit_width(ty);
         let n = (!0u128) >> (128 - bits);
         let literal = Literal::Value {
-            value: self.hir.tcx().mk_const(ty::Const {
-                val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(n))),
-                ty
-            })
+            value: ty::Const::from_bits(self.hir.tcx(), n, ty)
         };
 
         self.literal_operand(span, ty, literal)
@@ -393,10 +389,7 @@ fn minval_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
         let bits = self.hir.integer_bit_width(ty);
         let n = 1 << (bits - 1);
         let literal = Literal::Value {
-            value: self.hir.tcx().mk_const(ty::Const {
-                val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(n))),
-                ty
-            })
+            value: ty::Const::from_bits(self.hir.tcx(), n, ty)
         };
 
         self.literal_operand(span, ty, literal)
index d6ddfea1f19fb7dfd137360f0dcbd7a700f2b58b..913cb944835550be0e97234721aa643bcc5607ed 100644 (file)
@@ -122,12 +122,9 @@ pub fn add_cases_to_switch<'pat>(&mut self,
 
         match *match_pair.pattern.kind {
             PatternKind::Constant { value } => {
-                // if the places match, the type should match
-                assert_eq!(match_pair.pattern.ty, switch_ty);
-
                 indices.entry(value)
                        .or_insert_with(|| {
-                           options.push(value.val.to_raw_bits().expect("switching on int"));
+                           options.push(value.unwrap_bits(switch_ty));
                            options.len() - 1
                        });
                 true
index 6e10c2307c8e6879e29bf8b2e74ff7e6e1d6db07..6501dd00fe817493cf4fe50064ad697b7e0ea566 100644 (file)
@@ -13,9 +13,7 @@
 
 use build::Builder;
 
-use rustc::middle::const_val::ConstVal;
 use rustc::ty::{self, Ty};
-use rustc::mir::interpret::{Value, PrimVal};
 
 use rustc::mir::*;
 use syntax_pos::{Span, DUMMY_SP};
@@ -64,10 +62,7 @@ pub fn zero_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> {
             }
         }
         let literal = Literal::Value {
-            value: self.hir.tcx().mk_const(ty::Const {
-                val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(0))),
-                ty
-            })
+            value: ty::Const::from_bits(self.hir.tcx(), 0, ty)
         };
 
         self.literal_operand(span, ty, literal)
index 76605a7aa04840a05aac63af6f619f3a5a5883b8..e3ff67703bd4ed2fd440dc5065b2d99316fa8b42 100644 (file)
@@ -14,8 +14,7 @@
 use hair::cx::block;
 use hair::cx::to_ref::ToRef;
 use rustc::hir::def::{Def, CtorKind};
-use rustc::middle::const_val::ConstVal;
-use rustc::mir::interpret::{GlobalId, Value, PrimVal};
+use rustc::mir::interpret::GlobalId;
 use rustc::ty::{self, AdtKind, Ty};
 use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability};
 use rustc::ty::cast::CastKind as TyCastKind;
@@ -522,7 +521,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                 promoted: None
             };
             let count = match cx.tcx.at(c.span).const_eval(cx.param_env.and(global_id)) {
-                Ok(cv) => cv.val.unwrap_u64(),
+                Ok(cv) => cv.unwrap_usize(cx.tcx),
                 Err(e) => {
                     e.report(cx.tcx, cx.tcx.def_span(def_id), "array length");
                     0
@@ -635,22 +634,17 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                         span: expr.span,
                         kind: ExprKind::Literal {
                             literal: Literal::Value {
-                                value: cx.tcx().mk_const(ty::Const {
-                                    val,
-                                    ty,
-                                }),
+                                value: val,
                             },
                         },
                     }.to_ref();
-                    let offset = mk_const(
-                        ConstVal::Value(Value::ByVal(PrimVal::Bytes(offset as u128))),
-                    );
+                    let offset = mk_const(ty::Const::from_bits(cx.tcx, offset as u128, ty));
                     match did {
                         Some(did) => {
                             // in case we are offsetting from a computed discriminant
                             // and not the beginning of discriminants (which is always `0`)
                             let substs = Substs::identity_for_item(cx.tcx(), did);
-                            let lhs = mk_const(ConstVal::Unevaluated(did, substs));
+                            let lhs = mk_const(ty::Const::unevaluated(cx.tcx(), did, substs, ty));
                             let bin = ExprKind::Binary {
                                 op: BinOp::Add,
                                 lhs,
@@ -707,10 +701,7 @@ fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
         span: expr.span,
         kind: ExprKind::Literal {
             literal: Literal::Value {
-                value: cx.tcx().mk_const(ty::Const {
-                    val: ConstVal::Value(Value::ByVal(PrimVal::Undef)),
-                    ty
-                }),
+                value: ty::Const::zero_sized(cx.tcx(), ty),
             },
         },
     }
@@ -764,20 +755,20 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
         Def::StructCtor(_, CtorKind::Fn) |
         Def::VariantCtor(_, CtorKind::Fn) => ExprKind::Literal {
             literal: Literal::Value {
-                value: cx.tcx.mk_const(ty::Const {
-                    val: ConstVal::Value(Value::ByVal(PrimVal::Undef)),
-                    ty: cx.tables().node_id_to_type(expr.hir_id)
-                }),
+                value: ty::Const::zero_sized(
+                    cx.tcx,
+                    cx.tables().node_id_to_type(expr.hir_id)),
             },
         },
 
         Def::Const(def_id) |
         Def::AssociatedConst(def_id) => ExprKind::Literal {
             literal: Literal::Value {
-                value: cx.tcx.mk_const(ty::Const {
-                    val: ConstVal::Unevaluated(def_id, substs),
-                    ty: cx.tables().node_id_to_type(expr.hir_id)
-                }),
+                value: ty::Const::unevaluated(
+                    cx.tcx,
+                    def_id,
+                    substs,
+                    cx.tables().node_id_to_type(expr.hir_id))
             },
         },
 
index 5890ea5c9d0c653cc8d186986dbb1c4dd303ade1..4765a82d85b6c1bae1eeb5272e7a4b3badb3131f 100644 (file)
@@ -16,7 +16,6 @@
 
 use hair::*;
 
-use rustc::middle::const_val::ConstVal;
 use rustc_data_structures::indexed_vec::Idx;
 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::hir::map::blocks::FnLikeNode;
@@ -31,7 +30,6 @@
 use syntax::symbol::Symbol;
 use rustc::hir;
 use rustc_data_structures::sync::Lrc;
-use rustc::mir::interpret::{Value, PrimVal};
 use hair::pattern::parse_float;
 
 #[derive(Clone)]
@@ -117,10 +115,7 @@ pub fn usize_ty(&mut self) -> Ty<'tcx> {
 
     pub fn usize_literal(&mut self, value: u64) -> Literal<'tcx> {
         Literal::Value {
-            value: self.tcx.mk_const(ty::Const {
-                val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(value as u128))),
-                ty: self.tcx.types.usize
-            })
+            value: ty::Const::from_usize(self.tcx, value),
         }
     }
 
@@ -134,19 +129,13 @@ pub fn unit_ty(&mut self) -> Ty<'tcx> {
 
     pub fn true_literal(&mut self) -> Literal<'tcx> {
         Literal::Value {
-            value: self.tcx.mk_const(ty::Const {
-                val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(1))),
-                ty: self.tcx.types.bool
-            })
+            value: ty::Const::from_bool(self.tcx, true),
         }
     }
 
     pub fn false_literal(&mut self) -> Literal<'tcx> {
         Literal::Value {
-            value: self.tcx.mk_const(ty::Const {
-                val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(0))),
-                ty: self.tcx.types.bool
-            })
+            value: ty::Const::from_bool(self.tcx, false),
         }
     }
 
@@ -162,6 +151,7 @@ pub fn integer_bit_width(
         layout::Integer::from_attr(self.tcx, ty).size().bits()
     }
 
+    // FIXME: Combine with rustc_mir::hair::pattern::lit_to_const
     pub fn const_eval_literal(
         &mut self,
         lit: &'tcx ast::LitKind,
@@ -171,7 +161,7 @@ pub fn const_eval_literal(
     ) -> Literal<'tcx> {
         trace!("const_eval_literal: {:#?}, {:?}, {:?}, {:?}", lit, ty, sp, neg);
 
-        let parse_float = |num, fty| -> Value {
+        let parse_float = |num, fty| -> ConstValue<'tcx> {
             parse_float(num, fty, neg).unwrap_or_else(|_| {
                 // FIXME(#31407) this is only necessary because float parsing is buggy
                 self.tcx.sess.span_fatal(sp, "could not evaluate float literal (see issue #31407)");
@@ -193,7 +183,7 @@ pub fn const_eval_literal(
                 let s = s.as_str();
                 let id = self.tcx.allocate_cached(s.as_bytes());
                 let ptr = MemoryPointer::new(id, 0);
-                Value::ByValPair(
+                ConstValue::ByValPair(
                     PrimVal::Ptr(ptr),
                     PrimVal::from_u128(s.len() as u128),
                 )
@@ -201,16 +191,16 @@ pub fn const_eval_literal(
             LitKind::ByteStr(ref data) => {
                 let id = self.tcx.allocate_cached(data);
                 let ptr = MemoryPointer::new(id, 0);
-                Value::ByVal(PrimVal::Ptr(ptr))
+                ConstValue::ByVal(PrimVal::Ptr(ptr))
             },
-            LitKind::Byte(n) => Value::ByVal(PrimVal::Bytes(n as u128)),
+            LitKind::Byte(n) => ConstValue::ByVal(PrimVal::Bytes(n as u128)),
             LitKind::Int(n, _) if neg => {
                 let n = n as i128;
                 let n = n.overflowing_neg().0;
                 let n = clamp(n as u128);
-                Value::ByVal(PrimVal::Bytes(n))
+                ConstValue::ByVal(PrimVal::Bytes(n))
             },
-            LitKind::Int(n, _) => Value::ByVal(PrimVal::Bytes(clamp(n))),
+            LitKind::Int(n, _) => ConstValue::ByVal(PrimVal::Bytes(clamp(n))),
             LitKind::Float(n, fty) => {
                 parse_float(n, fty)
             }
@@ -221,14 +211,11 @@ pub fn const_eval_literal(
                 };
                 parse_float(n, fty)
             }
-            LitKind::Bool(b) => Value::ByVal(PrimVal::Bytes(b as u128)),
-            LitKind::Char(c) => Value::ByVal(PrimVal::Bytes(c as u128)),
+            LitKind::Bool(b) => ConstValue::ByVal(PrimVal::Bytes(b as u128)),
+            LitKind::Char(c) => ConstValue::ByVal(PrimVal::Bytes(c as u128)),
         };
         Literal::Value {
-            value: self.tcx.mk_const(ty::Const {
-                val: ConstVal::Value(lit),
-                ty,
-            }),
+            value: ty::Const::from_const_value(self.tcx, lit, ty)
         }
     }
 
@@ -258,11 +245,7 @@ pub fn trait_method(&mut self,
                 let method_ty = method_ty.subst(self.tcx, substs);
                 return (method_ty,
                         Literal::Value {
-                            value: self.tcx.mk_const(ty::Const {
-                                // ZST function type
-                                val: ConstVal::Value(Value::ByVal(PrimVal::Undef)),
-                                ty: method_ty
-                            }),
+                            value: ty::Const::zero_sized(self.tcx, method_ty)
                         });
             }
         }
index 1245f506955c133a4ebc2f51fc3d44b9850797bb..f930d47dc0bd37e3658f71c8a43bf35eabae4e73 100644 (file)
@@ -25,7 +25,6 @@
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
 
 use rustc::mir::Field;
-use rustc::mir::interpret::{Value, PrimVal};
 use rustc::util::common::ErrorReported;
 
 use syntax_pos::{Span, DUMMY_SP};
@@ -180,37 +179,34 @@ fn lower_byte_str_pattern<'p>(&mut self, pat: &'p Pattern<'tcx>) -> Vec<&'p Patt
         self.byte_array_map.entry(pat).or_insert_with(|| {
             match pat.kind {
                 box PatternKind::Constant {
-                    value: &ty::Const { val: ConstVal::Value(b), ty }
+                    value: const_val
                 } => {
-                    match b {
-                        Value::ByVal(PrimVal::Ptr(ptr)) => {
-                            let is_array_ptr = ty
-                                .builtin_deref(true)
-                                .and_then(|t| t.ty.builtin_index())
-                                .map_or(false, |t| t == tcx.types.u8);
-                            assert!(is_array_ptr);
-                            let alloc = tcx
-                                .interpret_interner
-                                .get_alloc(ptr.alloc_id)
-                                .unwrap();
-                            assert_eq!(ptr.offset, 0);
-                            // FIXME: check length
-                            alloc.bytes.iter().map(|b| {
-                                &*pattern_arena.alloc(Pattern {
-                                    ty: tcx.types.u8,
-                                    span: pat.span,
-                                    kind: box PatternKind::Constant {
-                                        value: tcx.mk_const(ty::Const {
-                                            val: ConstVal::Value(Value::ByVal(
-                                                PrimVal::Bytes(*b as u128),
-                                            )),
-                                            ty: tcx.types.u8
-                                        })
-                                    }
-                                })
-                            }).collect()
-                        },
-                        _ => bug!("not a byte str: {:?}", b),
+                    if let Some(ptr) = const_val.to_ptr() {
+                        let is_array_ptr = const_val.ty
+                            .builtin_deref(true)
+                            .and_then(|t| t.ty.builtin_index())
+                            .map_or(false, |t| t == tcx.types.u8);
+                        assert!(is_array_ptr);
+                        let alloc = tcx
+                            .interpret_interner
+                            .get_alloc(ptr.alloc_id)
+                            .unwrap();
+                        assert_eq!(ptr.offset, 0);
+                        // FIXME: check length
+                        alloc.bytes.iter().map(|b| {
+                            &*pattern_arena.alloc(Pattern {
+                                ty: tcx.types.u8,
+                                span: pat.span,
+                                kind: box PatternKind::Constant {
+                                    value: ty::Const::from_bits(
+                                        tcx,
+                                        *b as u128,
+                                        tcx.types.u8)
+                                }
+                            })
+                        }).collect()
+                    } else {
+                        bug!("not a byte str: {:?}", const_val)
                     }
                 }
                 _ => span_bug!(pat.span, "unexpected byte array pattern {:?}", pat)
@@ -439,14 +435,11 @@ fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
     match pcx.ty.sty {
         ty::TyBool => {
             [true, false].iter().map(|&b| {
-                ConstantValue(cx.tcx.mk_const(ty::Const {
-                    val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(b as u128))),
-                    ty: cx.tcx.types.bool
-                }))
+                ConstantValue(ty::Const::from_bool(cx.tcx, b))
             }).collect()
         }
-        ty::TyArray(ref sub_ty, len) if len.val.to_raw_bits().is_some() => {
-            let len = len.val.unwrap_u64();
+        ty::TyArray(ref sub_ty, len) if len.assert_usize(cx.tcx).is_some() => {
+            let len = len.unwrap_usize(cx.tcx);
             if len != 0 && cx.is_uninhabited(sub_ty) {
                 vec![]
             } else {
@@ -554,21 +547,23 @@ fn max_slice_length<'p, 'a: 'p, 'tcx: 'a, I>(
     for row in patterns {
         match *row.kind {
             PatternKind::Constant {
-                value: &ty::Const {
-                    val: ConstVal::Value(Value::ByVal(PrimVal::Ptr(ptr))),
-                    ty,
+                value: const_val @ &ty::Const {
+                    val: ConstVal::Value(..),
+                    ..
                 }
             } => {
-                let is_array_ptr = ty
-                    .builtin_deref(true)
-                    .and_then(|t| t.ty.builtin_index())
-                    .map_or(false, |t| t == cx.tcx.types.u8);
-                if is_array_ptr {
-                    let alloc = cx.tcx
-                        .interpret_interner
-                        .get_alloc(ptr.alloc_id)
-                        .unwrap();
-                    max_fixed_len = cmp::max(max_fixed_len, alloc.bytes.len() as u64);
+                if let Some(ptr) = const_val.to_ptr() {
+                    let is_array_ptr = const_val.ty
+                        .builtin_deref(true)
+                        .and_then(|t| t.ty.builtin_index())
+                        .map_or(false, |t| t == cx.tcx.types.u8);
+                    if is_array_ptr {
+                        let alloc = cx.tcx
+                            .interpret_interner
+                            .get_alloc(ptr.alloc_id)
+                            .unwrap();
+                        max_fixed_len = cmp::max(max_fixed_len, alloc.bytes.len() as u64);
+                    }
                 }
             }
             PatternKind::Slice { ref prefix, slice: None, ref suffix } => {
@@ -836,7 +831,7 @@ fn is_useful_specialized<'p, 'a:'p, 'tcx: 'a>(
 /// `[a, b, ..tail]` can match a slice of length 2, 3, 4 and so on.
 ///
 /// Returns None in case of a catch-all, which can't be specialized.
-fn pat_constructors<'tcx>(_cx: &mut MatchCheckCtxt,
+fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt,
                           pat: &Pattern<'tcx>,
                           pcx: PatternContext)
                           -> Option<Vec<Constructor<'tcx>>>
@@ -854,7 +849,7 @@ fn pat_constructors<'tcx>(_cx: &mut MatchCheckCtxt,
             Some(vec![ConstantRange(lo, hi, end)]),
         PatternKind::Array { .. } => match pcx.ty.sty {
             ty::TyArray(_, length) => Some(vec![
-                Slice(length.val.unwrap_u64())
+                Slice(length.unwrap_usize(cx.tcx))
             ]),
             _ => span_bug!(pat.span, "bad ty {:?} for array pattern", pcx.ty)
         },
@@ -934,27 +929,31 @@ fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>,
     }
 }
 
-fn slice_pat_covered_by_constructor(tcx: TyCtxt, _span: Span,
-                                    ctor: &Constructor,
-                                    prefix: &[Pattern],
-                                    slice: &Option<Pattern>,
-                                    suffix: &[Pattern])
-                                    -> Result<bool, ErrorReported> {
+fn slice_pat_covered_by_constructor<'tcx>(
+    tcx: TyCtxt<'_, 'tcx, '_>,
+    _span: Span,
+    ctor: &Constructor,
+    prefix: &[Pattern<'tcx>],
+    slice: &Option<Pattern<'tcx>>,
+    suffix: &[Pattern<'tcx>]
+) -> Result<bool, ErrorReported> {
     let data: &[u8] = match *ctor {
-        ConstantValue(&ty::Const { val: ConstVal::Value(
-            Value::ByVal(PrimVal::Ptr(ptr))
-        ), ty }) => {
-            let is_array_ptr = ty
-                .builtin_deref(true)
-                .and_then(|t| t.ty.builtin_index())
-                .map_or(false, |t| t == tcx.types.u8);
-            assert!(is_array_ptr);
-            tcx
-                .interpret_interner
-                .get_alloc(ptr.alloc_id)
-                .unwrap()
-                .bytes
-                .as_ref()
+        ConstantValue(const_val @ &ty::Const { val: ConstVal::Value(..), .. }) => {
+            if let Some(ptr) = const_val.to_ptr() {
+                let is_array_ptr = const_val.ty
+                    .builtin_deref(true)
+                    .and_then(|t| t.ty.builtin_index())
+                    .map_or(false, |t| t == tcx.types.u8);
+                assert!(is_array_ptr);
+                tcx
+                    .interpret_interner
+                    .get_alloc(ptr.alloc_id)
+                    .unwrap()
+                    .bytes
+                    .as_ref()
+            } else {
+                bug!()
+            }
         }
         _ => bug!()
     };
@@ -969,15 +968,13 @@ fn slice_pat_covered_by_constructor(tcx: TyCtxt, _span: Span,
             data[data.len()-suffix.len()..].iter().zip(suffix))
     {
         match pat.kind {
-            box PatternKind::Constant { value } => match value.val {
-                ConstVal::Value(Value::ByVal(PrimVal::Bytes(b))) => {
-                    assert_eq!(b as u8 as u128, b);
-                    if b as u8 != *ch {
-                        return Ok(false);
-                    }
+            box PatternKind::Constant { value } => {
+                let b = value.unwrap_bits(pat.ty);
+                assert_eq!(b as u8 as u128, b);
+                if b as u8 != *ch {
+                    return Ok(false);
                 }
-                _ => span_bug!(pat.span, "bad const u8 {:?}", value)
-            },
+            }
             _ => {}
         }
     }
@@ -987,8 +984,8 @@ fn slice_pat_covered_by_constructor(tcx: TyCtxt, _span: Span,
 
 fn constructor_covered_by_range<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    ctor: &Constructor,
-    from: &ConstVal, to: &ConstVal,
+    ctor: &Constructor<'tcx>,
+    from: &'tcx ty::Const<'tcx>, to: &'tcx ty::Const<'tcx>,
     end: RangeEnd,
     ty: Ty<'tcx>,
 ) -> Result<bool, ErrorReported> {
@@ -1006,22 +1003,22 @@ macro_rules! some_or_ok {
     }
     match *ctor {
         ConstantValue(value) => {
-            let to = some_or_ok!(cmp_to(&value.val));
+            let to = some_or_ok!(cmp_to(value));
             let end = (to == Ordering::Less) ||
                       (end == RangeEnd::Included && to == Ordering::Equal);
-            Ok(some_or_ok!(cmp_from(&value.val)) && end)
+            Ok(some_or_ok!(cmp_from(value)) && end)
         },
         ConstantRange(from, to, RangeEnd::Included) => {
-            let to = some_or_ok!(cmp_to(&to.val));
+            let to = some_or_ok!(cmp_to(to));
             let end = (to == Ordering::Less) ||
                       (end == RangeEnd::Included && to == Ordering::Equal);
-            Ok(some_or_ok!(cmp_from(&from.val)) && end)
+            Ok(some_or_ok!(cmp_from(from)) && end)
         },
         ConstantRange(from, to, RangeEnd::Excluded) => {
-            let to = some_or_ok!(cmp_to(&to.val));
+            let to = some_or_ok!(cmp_to(to));
             let end = (to == Ordering::Less) ||
                       (end == RangeEnd::Excluded && to == Ordering::Equal);
-            Ok(some_or_ok!(cmp_from(&from.val)) && end)
+            Ok(some_or_ok!(cmp_from(from)) && end)
         }
         Single => Ok(true),
         _ => bug!(),
@@ -1083,8 +1080,8 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
 
         PatternKind::Constant { value } => {
             match *constructor {
-                Slice(..) => match value.val {
-                    ConstVal::Value(Value::ByVal(PrimVal::Ptr(ptr))) => {
+                Slice(..) => {
+                    if let Some(ptr) = value.to_ptr() {
                         let is_array_ptr = value.ty
                             .builtin_deref(true)
                             .and_then(|t| t.ty.builtin_index())
@@ -1101,14 +1098,15 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
                         } else {
                             None
                         }
-                    }
-                    _ => span_bug!(pat.span,
+                    } else {
+                        span_bug!(pat.span,
                         "unexpected const-val {:?} with ctor {:?}", value, constructor)
+                    }
                 },
                 _ => {
                     match constructor_covered_by_range(
                         cx.tcx,
-                        constructor, &value.val, &value.val, RangeEnd::Included,
+                        constructor, value, value, RangeEnd::Included,
                         value.ty,
                             ) {
                         Ok(true) => Some(vec![]),
@@ -1122,7 +1120,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
         PatternKind::Range { lo, hi, ref end } => {
             match constructor_covered_by_range(
                 cx.tcx,
-                constructor, &lo.val, &hi.val, end.clone(), lo.ty,
+                constructor, lo, hi, end.clone(), lo.ty,
             ) {
                 Ok(true) => Some(vec![]),
                 Ok(false) => None,
index 2585447fa0a04f6cdecfe14bb2777a7a04fb4d31..749e574ff7ad41ca5bfa7420f2ded0f12825491f 100644 (file)
@@ -19,8 +19,8 @@
 use interpret::{const_val_field, const_variant_index, self};
 
 use rustc::middle::const_val::ConstVal;
-use rustc::mir::{Field, BorrowKind, Mutability};
-use rustc::mir::interpret::{GlobalId, Value, PrimVal};
+use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability};
+use rustc::mir::interpret::{PrimVal, GlobalId, ConstValue};
 use rustc::ty::{self, TyCtxt, AdtDef, Ty, Region};
 use rustc::ty::subst::{Substs, Kind};
 use rustc::hir::{self, PatKind, RangeEnd};
@@ -124,24 +124,11 @@ pub enum PatternKind<'tcx> {
 
 fn print_const_val(value: &ty::Const, f: &mut fmt::Formatter) -> fmt::Result {
     match value.val {
-        ConstVal::Value(v) => print_miri_value(v, value.ty, f),
+        ConstVal::Value(..) => fmt_const_val(f, value),
         ConstVal::Unevaluated(..) => bug!("{:?} not printable in a pattern", value)
     }
 }
 
-fn print_miri_value(value: Value, ty: Ty, f: &mut fmt::Formatter) -> fmt::Result {
-    use rustc::ty::TypeVariants::*;
-    match (value, &ty.sty) {
-        (Value::ByVal(PrimVal::Bytes(0)), &TyBool) => write!(f, "false"),
-        (Value::ByVal(PrimVal::Bytes(1)), &TyBool) => write!(f, "true"),
-        (Value::ByVal(PrimVal::Bytes(n)), &TyUint(..)) => write!(f, "{:?}", n),
-        (Value::ByVal(PrimVal::Bytes(n)), &TyInt(..)) => write!(f, "{:?}", n as i128),
-        (Value::ByVal(PrimVal::Bytes(n)), &TyChar) =>
-            write!(f, "{:?}", ::std::char::from_u32(n as u32).unwrap()),
-        _ => bug!("{:?}: {} not printable in a pattern", value, ty),
-    }
-}
-
 impl<'tcx> fmt::Display for Pattern<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self.kind {
@@ -372,7 +359,7 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat) -> Pattern<'tcx> {
                     (PatternKind::Constant { value: lo },
                      PatternKind::Constant { value: hi }) => {
                         use std::cmp::Ordering;
-                        match (end, compare_const_vals(self.tcx, &lo.val, &hi.val, ty).unwrap()) {
+                        match (end, compare_const_vals(self.tcx, lo, hi, ty).unwrap()) {
                             (RangeEnd::Excluded, Ordering::Less) =>
                                 PatternKind::Range { lo, hi, end },
                             (RangeEnd::Excluded, _) => {
@@ -616,7 +603,7 @@ fn slice_or_array_pattern(
 
             ty::TyArray(_, len) => {
                 // fixed-length array
-                let len = len.val.unwrap_u64();
+                let len = len.unwrap_usize(self.tcx);
                 assert!(len >= prefix.len() as u64 + suffix.len() as u64);
                 PatternKind::Array { prefix: prefix, slice: slice, suffix: suffix }
             }
@@ -740,8 +727,7 @@ fn lower_lit(&mut self, expr: &'tcx hir::Expr) -> PatternKind<'tcx> {
                             self.tables.local_id_root.expect("literal outside any scope"),
                             self.substs,
                         );
-                        let cv = self.tcx.mk_const(ty::Const { val, ty });
-                        *self.const_to_pat(instance, cv, expr.hir_id, lit.span).kind
+                        *self.const_to_pat(instance, val, expr.hir_id, lit.span).kind
                     },
                     Err(()) => {
                         self.errors.push(PatternError::FloatBug);
@@ -762,8 +748,7 @@ fn lower_lit(&mut self, expr: &'tcx hir::Expr) -> PatternKind<'tcx> {
                             self.tables.local_id_root.expect("literal outside any scope"),
                             self.substs,
                         );
-                        let cv = self.tcx.mk_const(ty::Const { val, ty });
-                        *self.const_to_pat(instance, cv, expr.hir_id, lit.span).kind
+                        *self.const_to_pat(instance, val, expr.hir_id, lit.span).kind
                     },
                     Err(()) => {
                         self.errors.push(PatternError::FloatBug);
@@ -866,7 +851,7 @@ fn const_to_pat(
             }
             ty::TyArray(_, n) => {
                 PatternKind::Array {
-                    prefix: (0..n.val.unwrap_u64())
+                    prefix: (0..n.unwrap_usize(self.tcx))
                         .map(|i| adt_subpattern(i as usize, None))
                         .collect(),
                     slice: None,
@@ -1049,45 +1034,48 @@ fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
 
 pub fn compare_const_vals<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    a: &ConstVal,
-    b: &ConstVal,
+    a: &'tcx ty::Const<'tcx>,
+    b: &'tcx ty::Const<'tcx>,
     ty: Ty<'tcx>,
 ) -> Option<Ordering> {
     trace!("compare_const_vals: {:?}, {:?}", a, b);
-    use rustc::mir::interpret::{Value, PrimVal};
-    match (a, b) {
-        (&ConstVal::Value(Value::ByVal(PrimVal::Bytes(a))),
-         &ConstVal::Value(Value::ByVal(PrimVal::Bytes(b)))) => {
-            use ::rustc_apfloat::Float;
-            match ty.sty {
-                ty::TyFloat(ast::FloatTy::F32) => {
-                    let l = ::rustc_apfloat::ieee::Single::from_bits(a);
-                    let r = ::rustc_apfloat::ieee::Single::from_bits(b);
-                    l.partial_cmp(&r)
-                },
-                ty::TyFloat(ast::FloatTy::F64) => {
-                    let l = ::rustc_apfloat::ieee::Double::from_bits(a);
-                    let r = ::rustc_apfloat::ieee::Double::from_bits(b);
-                    l.partial_cmp(&r)
-                },
-                ty::TyInt(_) => {
-                    let a = interpret::sign_extend(tcx, a, ty).expect("layout error for TyInt");
-                    let b = interpret::sign_extend(tcx, b, ty).expect("layout error for TyInt");
-                    Some((a as i128).cmp(&(b as i128)))
-                },
-                _ => Some(a.cmp(&b)),
-            }
-        },
-        _ if a == b => Some(Ordering::Equal),
-        _ => None,
+    // FIXME: This should use assert_bits(ty) instead of use_bits
+    // but triggers possibly bugs due to mismatching of arrays and slices
+    if let (Some(a), Some(b)) = (a.to_bits(ty), b.to_bits(ty)) {
+        use ::rustc_apfloat::Float;
+        match ty.sty {
+            ty::TyFloat(ast::FloatTy::F32) => {
+                let l = ::rustc_apfloat::ieee::Single::from_bits(a);
+                let r = ::rustc_apfloat::ieee::Single::from_bits(b);
+                l.partial_cmp(&r)
+            },
+            ty::TyFloat(ast::FloatTy::F64) => {
+                let l = ::rustc_apfloat::ieee::Double::from_bits(a);
+                let r = ::rustc_apfloat::ieee::Double::from_bits(b);
+                l.partial_cmp(&r)
+            },
+            ty::TyInt(_) => {
+                let a = interpret::sign_extend(tcx, a, ty).expect("layout error for TyInt");
+                let b = interpret::sign_extend(tcx, b, ty).expect("layout error for TyInt");
+                Some((a as i128).cmp(&(b as i128)))
+            },
+            _ => Some(a.cmp(&b)),
+        }
+    } else {
+        if a == b {
+            Some(Ordering::Equal)
+        } else {
+            None
+        }
     }
 }
 
+// FIXME: Combine with rustc_mir::hair::cx::const_eval_literal
 fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind,
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           ty: Ty<'tcx>,
                           neg: bool)
-                          -> Result<ConstVal<'tcx>, ()> {
+                          -> Result<&'tcx ty::Const<'tcx>, ()> {
     use syntax::ast::*;
 
     use rustc::mir::interpret::*;
@@ -1096,7 +1084,7 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind,
             let s = s.as_str();
             let id = tcx.allocate_cached(s.as_bytes());
             let ptr = MemoryPointer::new(id, 0);
-            Value::ByValPair(
+            ConstValue::ByValPair(
                 PrimVal::Ptr(ptr),
                 PrimVal::from_u128(s.len() as u128),
             )
@@ -1104,9 +1092,9 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind,
         LitKind::ByteStr(ref data) => {
             let id = tcx.allocate_cached(data);
             let ptr = MemoryPointer::new(id, 0);
-            Value::ByVal(PrimVal::Ptr(ptr))
+            ConstValue::ByVal(PrimVal::Ptr(ptr))
         },
-        LitKind::Byte(n) => Value::ByVal(PrimVal::Bytes(n as u128)),
+        LitKind::Byte(n) => ConstValue::ByVal(PrimVal::Bytes(n as u128)),
         LitKind::Int(n, _) => {
             enum Int {
                 Signed(IntTy),
@@ -1119,31 +1107,28 @@ enum Int {
                 ty::TyUint(other) => Int::Unsigned(other),
                 _ => bug!(),
             };
+            // This converts from LitKind::Int (which is sign extended) to
+            // PrimVal::Bytes (which is zero extended)
             let n = match ty {
                 // FIXME(oli-obk): are these casts correct?
                 Int::Signed(IntTy::I8) if neg =>
-                    (n as i128 as i8).overflowing_neg().0 as i128 as u128,
+                    (n as i8).overflowing_neg().0 as u8 as u128,
                 Int::Signed(IntTy::I16) if neg =>
-                    (n as i128 as i16).overflowing_neg().0 as i128 as u128,
+                    (n as i16).overflowing_neg().0 as u16 as u128,
                 Int::Signed(IntTy::I32) if neg =>
-                    (n as i128 as i32).overflowing_neg().0 as i128 as u128,
+                    (n as i32).overflowing_neg().0 as u32 as u128,
                 Int::Signed(IntTy::I64) if neg =>
-                    (n as i128 as i64).overflowing_neg().0 as i128 as u128,
+                    (n as i64).overflowing_neg().0 as u64 as u128,
                 Int::Signed(IntTy::I128) if neg =>
                     (n as i128).overflowing_neg().0 as u128,
-                Int::Signed(IntTy::I8) => n as i128 as i8 as i128 as u128,
-                Int::Signed(IntTy::I16) => n as i128 as i16 as i128 as u128,
-                Int::Signed(IntTy::I32) => n as i128 as i32 as i128 as u128,
-                Int::Signed(IntTy::I64) => n as i128 as i64 as i128 as u128,
-                Int::Signed(IntTy::I128) => n,
-                Int::Unsigned(UintTy::U8) => n as u8 as u128,
-                Int::Unsigned(UintTy::U16) => n as u16 as u128,
-                Int::Unsigned(UintTy::U32) => n as u32 as u128,
-                Int::Unsigned(UintTy::U64) => n as u64 as u128,
-                Int::Unsigned(UintTy::U128) => n,
+                Int::Signed(IntTy::I8) | Int::Unsigned(UintTy::U8) => n as u8 as u128,
+                Int::Signed(IntTy::I16) | Int::Unsigned(UintTy::U16) => n as u16 as u128,
+                Int::Signed(IntTy::I32) | Int::Unsigned(UintTy::U32) => n as u32 as u128,
+                Int::Signed(IntTy::I64) | Int::Unsigned(UintTy::U64) => n as u64 as u128,
+                Int::Signed(IntTy::I128)| Int::Unsigned(UintTy::U128) => n,
                 _ => bug!(),
             };
-            Value::ByVal(PrimVal::Bytes(n))
+            ConstValue::ByVal(PrimVal::Bytes(n))
         },
         LitKind::Float(n, fty) => {
             parse_float(n, fty, neg)?
@@ -1155,17 +1140,17 @@ enum Int {
             };
             parse_float(n, fty, neg)?
         }
-        LitKind::Bool(b) => Value::ByVal(PrimVal::Bytes(b as u128)),
-        LitKind::Char(c) => Value::ByVal(PrimVal::Bytes(c as u128)),
+        LitKind::Bool(b) => ConstValue::ByVal(PrimVal::Bytes(b as u128)),
+        LitKind::Char(c) => ConstValue::ByVal(PrimVal::Bytes(c as u128)),
     };
-    Ok(ConstVal::Value(lit))
+    Ok(ty::Const::from_const_value(tcx, lit, ty))
 }
 
-pub fn parse_float(
+pub fn parse_float<'tcx>(
     num: Symbol,
     fty: ast::FloatTy,
     neg: bool,
-) -> Result<Value, ()> {
+) -> Result<ConstValue<'tcx>, ()> {
     let num = num.as_str();
     use rustc_apfloat::ieee::{Single, Double};
     use rustc_apfloat::Float;
@@ -1192,5 +1177,5 @@ pub fn parse_float(
         }
     };
 
-    Ok(Value::ByVal(PrimVal::Bytes(bits)))
+    Ok(ConstValue::ByVal(PrimVal::Bytes(bits)))
 }
index dff9fa271aba52f99b6b03c7ad54dbc03889bbd0..6bf965aaf44630079178dd4536be7f565a31782c 100644 (file)
@@ -1,5 +1,5 @@
 use rustc::hir;
-use rustc::middle::const_val::{ConstEvalErr, ConstVal, ErrKind};
+use rustc::middle::const_val::{ConstEvalErr, ErrKind};
 use rustc::middle::const_val::ErrKind::{TypeckError, CheckMatchError};
 use rustc::mir;
 use rustc::ty::{self, TyCtxt, Ty, Instance};
@@ -8,9 +8,13 @@
 
 use syntax::ast::Mutability;
 use syntax::codemap::Span;
+use syntax::codemap::DUMMY_SP;
 
-use rustc::mir::interpret::{EvalResult, EvalError, EvalErrorKind, GlobalId, Value, MemoryPointer, Pointer, PrimVal, AllocId};
-use super::{Place, EvalContext, StackPopCleanup, ValTy, PlaceExtra, Memory};
+use rustc::mir::interpret::{
+    EvalResult, EvalError, EvalErrorKind, GlobalId,
+    Value, Pointer, PrimVal, AllocId, Allocation, ConstValue,
+};
+use super::{Place, EvalContext, StackPopCleanup, ValTy, PlaceExtra, Memory, MemoryKind};
 
 use std::fmt;
 use std::error::Error;
@@ -57,19 +61,21 @@ pub fn mk_eval_cx<'a, 'tcx>(
 }
 
 pub fn eval_promoted<'a, 'mir, 'tcx>(
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    ecx: &mut EvalContext<'a, 'mir, 'tcx, CompileTimeEvaluator>,
     cid: GlobalId<'tcx>,
     mir: &'mir mir::Mir<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
 ) -> Option<(Value, Pointer, Ty<'tcx>)> {
-    let (res, ecx) = eval_body_and_ecx(tcx, cid, Some(mir), param_env);
-    match res {
-        Ok(val) => Some(val),
-        Err(mut err) => {
-            ecx.report(&mut err, false, None);
-            None
+    ecx.with_fresh_body(|ecx| {
+        let res = eval_body_using_ecx(ecx, cid, Some(mir), param_env);
+        match res {
+            Ok(val) => Some(val),
+            Err(mut err) => {
+                ecx.report(&mut err, false, None);
+                None
+            }
         }
-    }
+    })
 }
 
 pub fn eval_body<'a, 'tcx>(
@@ -87,19 +93,76 @@ pub fn eval_body<'a, 'tcx>(
     }
 }
 
+pub fn value_to_const_value<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    val: Value,
+    ty: Ty<'tcx>,
+) -> &'tcx ty::Const<'tcx> {
+    let layout = tcx.layout_of(ty::ParamEnv::reveal_all().and(ty)).unwrap();
+
+    if layout.is_zst() {
+        return ty::Const::from_const_value(
+            tcx,
+            ConstValue::ByVal(PrimVal::Undef),
+            ty);
+    }
+
+    let val = match layout.abi {
+        layout::Abi::Scalar(..) => {
+            if let Value::ByVal(val) = val {
+                ConstValue::ByVal(val)
+            } else {
+                bug!("expected ByVal value, got {:?}", val);
+            }
+        }
+        layout::Abi::ScalarPair(..) => {
+            if let Value::ByValPair(a, b) = val {
+                ConstValue::ByValPair(a, b)
+            } else {
+                bug!("expected ByValPair value, got {:?}", val);
+            }
+        }
+        _ => {
+            if let Value::ByRef(ptr, align) = val {
+                let ptr = ptr.primval.to_ptr().unwrap();
+                assert_eq!(ptr.offset, 0);
+                let alloc = tcx.interpret_interner
+                               .get_alloc(ptr.alloc_id)
+                               .expect("miri allocation never successfully created");
+                assert_eq!(align, alloc.align);
+                ConstValue::ByRef(alloc)
+            } else {
+                bug!("expected ByRef value, got {:?}", val);
+            }
+        },
+    };
+    ty::Const::from_const_value(tcx, val, ty)
+}
+
 fn eval_body_and_ecx<'a, 'mir, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     cid: GlobalId<'tcx>,
     mir: Option<&'mir mir::Mir<'tcx>>,
     param_env: ty::ParamEnv<'tcx>,
 ) -> (EvalResult<'tcx, (Value, Pointer, Ty<'tcx>)>, EvalContext<'a, 'mir, 'tcx, CompileTimeEvaluator>) {
-    debug!("eval_body: {:?}, {:?}", cid, param_env);
+    debug!("eval_body_and_ecx: {:?}, {:?}", cid, param_env);
     // we start out with the best span we have
     // and try improving it down the road when more information is available
     let span = tcx.def_span(cid.instance.def_id());
-    let mut span = mir.map(|mir| mir.span).unwrap_or(span);
+    let span = mir.map(|mir| mir.span).unwrap_or(span);
     let mut ecx = EvalContext::new(tcx.at(span), param_env, CompileTimeEvaluator, ());
-    let res = (|| {
+    let r = eval_body_using_ecx(&mut ecx, cid, mir, param_env);
+    (r, ecx)
+}
+
+fn eval_body_using_ecx<'a, 'mir, 'tcx>(
+    ecx: &mut EvalContext<'a, 'mir, 'tcx, CompileTimeEvaluator>,
+    cid: GlobalId<'tcx>,
+    mir: Option<&'mir mir::Mir<'tcx>>,
+    param_env: ty::ParamEnv<'tcx>,
+) -> EvalResult<'tcx, (Value, Pointer, Ty<'tcx>)> {
+    debug!("eval_body: {:?}, {:?}", cid, param_env);
+    let tcx = ecx.tcx.tcx;
         let mut mir = match mir {
             Some(mir) => mir,
             None => ecx.load_mir(cid.instance.def)?,
@@ -107,7 +170,6 @@ fn eval_body_and_ecx<'a, 'mir, 'tcx>(
         if let Some(index) = cid.promoted {
             mir = &mir.promoted[index];
         }
-        span = mir.span;
         let layout = ecx.layout_of(mir.return_ty().subst(tcx, cid.instance.substs))?;
         assert!(!layout.is_unsized());
         let ptr = ecx.memory.allocate(
@@ -139,14 +201,11 @@ fn eval_body_and_ecx<'a, 'mir, 'tcx>(
         let ptr = ptr.into();
         // always try to read the value and report errors
         let value = match ecx.try_read_value(ptr, layout.align, layout.ty)? {
-            // if it's a constant (so it needs no address, directly compute its value)
-            Some(val) if tcx.is_static(cid.instance.def_id()).is_none() => val,
+            Some(val) => val,
             // point at the allocation
             _ => Value::ByRef(ptr, layout.align),
         };
         Ok((value, ptr, layout.ty))
-    })();
-    (res, ecx)
 }
 
 pub struct CompileTimeEvaluator;
@@ -357,14 +416,16 @@ pub fn const_val_field<'a, 'tcx>(
     instance: ty::Instance<'tcx>,
     variant: Option<usize>,
     field: mir::Field,
-    value: Value,
+    value: ConstValue<'tcx>,
     ty: Ty<'tcx>,
 ) -> ::rustc::middle::const_val::EvalResult<'tcx> {
     trace!("const_val_field: {:?}, {:?}, {:?}, {:?}", instance, field, value, ty);
     let mut ecx = mk_eval_cx(tcx, instance, param_env).unwrap();
     let result = (|| {
+        let value = ecx.const_value_to_value(value, ty)?;
         let (mut field, ty) = match value {
-            Value::ByValPair(..) | Value::ByVal(_) => ecx.read_field(value, variant, field, ty)?.expect("const_val_field on non-field"),
+            Value::ByValPair(..) | Value::ByVal(_) => 
+                ecx.read_field(value, variant, field, ty)?.expect("const_val_field on non-field"),
             Value::ByRef(ptr, align) => {
                 let place = Place::Ptr {
                     ptr,
@@ -385,10 +446,7 @@ pub fn const_val_field<'a, 'tcx>(
         Ok((field, ty))
     })();
     match result {
-        Ok((field, ty)) => Ok(tcx.mk_const(ty::Const {
-            val: ConstVal::Value(field),
-            ty,
-        })),
+        Ok((field, ty)) => Ok(value_to_const_value(tcx, field, ty)),
         Err(err) => {
             let (trace, span) = ecx.generate_stacktrace(None);
             let err = ErrKind::Miri(err, trace);
@@ -404,15 +462,15 @@ pub fn const_variant_index<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     instance: ty::Instance<'tcx>,
-    value: Value,
+    val: ConstValue<'tcx>,
     ty: Ty<'tcx>,
 ) -> EvalResult<'tcx, usize> {
-    trace!("const_variant_index: {:?}, {:?}, {:?}", instance, value, ty);
+    trace!("const_variant_index: {:?}, {:?}, {:?}", instance, val, ty);
     let mut ecx = mk_eval_cx(tcx, instance, param_env).unwrap();
+    let value = ecx.const_value_to_value(val, ty)?;
     let (ptr, align) = match value {
         Value::ByValPair(..) | Value::ByVal(_) => {
             let layout = ecx.layout_of(ty)?;
-            use super::MemoryKind;
             let ptr = ecx.memory.allocate(layout.size.bytes(), layout.align, Some(MemoryKind::Stack))?;
             let ptr: Pointer = ptr.into();
             ecx.write_value_to_ptr(value, ptr, layout.align, ty)?;
@@ -424,6 +482,30 @@ pub fn const_variant_index<'a, 'tcx>(
     ecx.read_discriminant_as_variant_index(place, ty)
 }
 
+pub fn const_value_to_allocation_provider<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    (val, ty): (ConstValue<'tcx>, Ty<'tcx>),
+) -> &'tcx Allocation {
+    match val {
+        ConstValue::ByRef(alloc) => return alloc,
+        _ => ()
+    }
+    let result = || -> EvalResult<'tcx, &'tcx Allocation> {
+        let mut ecx = EvalContext::new(
+            tcx.at(DUMMY_SP),
+            ty::ParamEnv::reveal_all(),
+            CompileTimeEvaluator,
+            ());
+        let value = ecx.const_value_to_value(val, ty)?;
+        let layout = ecx.layout_of(ty)?;
+        let ptr = ecx.memory.allocate(layout.size.bytes(), layout.align, Some(MemoryKind::Stack))?;
+        ecx.write_value_to_ptr(value, ptr.into(), layout.align, ty)?;
+        let alloc = ecx.memory.get(ptr.alloc_id)?;
+        Ok(tcx.intern_const_alloc(alloc.clone()))
+    };
+    result().expect("unable to convert ConstVal to Allocation")
+}
+
 pub fn const_eval_provider<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
@@ -432,17 +514,6 @@ pub fn const_eval_provider<'a, 'tcx>(
     let cid = key.value;
     let def_id = cid.instance.def.def_id();
 
-    if tcx.is_foreign_item(def_id) {
-        let id = tcx.interpret_interner.cache_static(def_id);
-        let ty = tcx.type_of(def_id);
-        let layout = tcx.layout_of(key.param_env.and(ty)).unwrap();
-        let ptr = MemoryPointer::new(id, 0);
-        return Ok(tcx.mk_const(ty::Const {
-            val: ConstVal::Value(Value::ByRef(ptr.into(), layout.align)),
-            ty,
-        }))
-    }
-
     if let Some(id) = tcx.hir.as_local_node_id(def_id) {
         let tables = tcx.typeck_tables_of(def_id);
         let span = tcx.def_span(def_id);
@@ -469,11 +540,8 @@ pub fn const_eval_provider<'a, 'tcx>(
     };
 
     let (res, ecx) = eval_body_and_ecx(tcx, cid, None, key.param_env);
-    res.map(|(miri_value, _, miri_ty)| {
-        tcx.mk_const(ty::Const {
-            val: ConstVal::Value(miri_value),
-            ty: miri_ty,
-        })
+    res.map(|(val, _, miri_ty)| {
+        value_to_const_value(tcx, val, miri_ty)
     }).map_err(|mut err| {
         if tcx.is_static(def_id).is_some() {
             ecx.report(&mut err, true, None);
index 3d670acf98cb2d3f20993f9fc7f8f96268613625..03137619edaf48d72a0780b073a6446cc575ec53 100644 (file)
@@ -15,7 +15,7 @@
 use syntax::ast::Mutability;
 use rustc::mir::interpret::{
     GlobalId, Value, Pointer, PrimVal, PrimValKind,
-    EvalError, EvalResult, EvalErrorKind, MemoryPointer,
+    EvalError, EvalResult, EvalErrorKind, MemoryPointer, ConstValue,
 };
 use std::mem;
 
@@ -116,15 +116,6 @@ pub struct ValTy<'tcx> {
     pub ty: Ty<'tcx>,
 }
 
-impl<'tcx> ValTy<'tcx> {
-    pub fn from(val: &ty::Const<'tcx>) -> Option<Self> {
-        match val.val {
-            ConstVal::Value(value) => Some(ValTy { value, ty: val.ty }),
-            ConstVal::Unevaluated { .. } => None,
-        }
-    }
-}
-
 impl<'tcx> ::std::ops::Deref for ValTy<'tcx> {
     type Target = Value;
     fn deref(&self) -> &Value {
@@ -183,6 +174,8 @@ fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
     }
 }
 
+const MAX_TERMINATORS: usize = 1_000_000;
+
 impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
     pub fn new(
         tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
@@ -197,10 +190,19 @@ pub fn new(
             memory: Memory::new(tcx, memory_data),
             stack: Vec::new(),
             stack_limit: tcx.sess.const_eval_stack_frame_limit,
-            terminators_remaining: 1_000_000,
+            terminators_remaining: MAX_TERMINATORS,
         }
     }
 
+    pub(crate) fn with_fresh_body<F: FnOnce(&mut Self) -> R, R>(&mut self, f: F) -> R {
+        let stack = mem::replace(&mut self.stack, Vec::new());
+        let terminators_remaining = mem::replace(&mut self.terminators_remaining, MAX_TERMINATORS);
+        let r = f(self);
+        self.stack = stack;
+        self.terminators_remaining = terminators_remaining;
+        r
+    }
+
     pub fn alloc_ptr(&mut self, ty: Ty<'tcx>) -> EvalResult<'tcx, MemoryPointer> {
         let layout = self.layout_of(ty)?;
         assert!(!layout.is_unsized(), "cannot alloc memory for unsized type");
@@ -235,7 +237,27 @@ pub fn str_to_value(&mut self, s: &str) -> EvalResult<'tcx, Value> {
         ))
     }
 
-    pub(super) fn const_to_value(&self, const_val: &ConstVal<'tcx>, ty: Ty<'tcx>) -> EvalResult<'tcx, Value> {
+    pub fn const_value_to_value(
+        &mut self,
+        val: ConstValue<'tcx>,
+        _ty: Ty<'tcx>,
+    ) -> EvalResult<'tcx, Value> {
+        match val {
+            ConstValue::ByRef(alloc) => {
+                // FIXME: Allocate new AllocId for all constants inside
+                let id = self.memory.allocate_value(alloc.clone(), Some(MemoryKind::Stack))?;
+                Ok(Value::ByRef(MemoryPointer::new(id, 0).into(), alloc.align))
+            },
+            ConstValue::ByValPair(a, b) => Ok(Value::ByValPair(a, b)),
+            ConstValue::ByVal(val) => Ok(Value::ByVal(val)),
+        }
+    }
+
+    pub(super) fn const_to_value(
+        &mut self,
+        const_val: &ConstVal<'tcx>,
+        ty: Ty<'tcx>
+    ) -> EvalResult<'tcx, Value> {
         match *const_val {
             ConstVal::Unevaluated(def_id, substs) => {
                 let instance = self.resolve(def_id, substs)?;
@@ -244,7 +266,7 @@ pub(super) fn const_to_value(&self, const_val: &ConstVal<'tcx>, ty: Ty<'tcx>) ->
                     promoted: None,
                 }, ty)
             }
-            ConstVal::Value(val) => Ok(val),
+            ConstVal::Value(val) => self.const_value_to_value(val, ty)
         }
     }
 
@@ -568,7 +590,7 @@ pub(super) fn eval_rvalue_into_place(
 
             Repeat(ref operand, _) => {
                 let (elem_ty, length) = match dest_ty.sty {
-                    ty::TyArray(elem_ty, n) => (elem_ty, n.val.unwrap_u64()),
+                    ty::TyArray(elem_ty, n) => (elem_ty, n.unwrap_usize(self.tcx.tcx)),
                     _ => {
                         bug!(
                             "tried to assign array-repeat to non-array type {:?}",
@@ -592,7 +614,7 @@ pub(super) fn eval_rvalue_into_place(
                 // FIXME(CTFE): don't allow computing the length of arrays in const eval
                 let src = self.eval_place(place)?;
                 let ty = self.place_ty(place);
-                let (_, len) = src.elem_ty_and_len(ty);
+                let (_, len) = src.elem_ty_and_len(ty, self.tcx.tcx);
                 self.write_primval(
                     dest,
                     PrimVal::from_u128(len as u128),
@@ -822,8 +844,9 @@ pub fn eval_operand(&mut self, op: &mir::Operand<'tcx>) -> EvalResult<'tcx, ValT
                     Literal::Value { ref value } => self.const_to_value(&value.val, ty)?,
 
                     Literal::Promoted { index } => {
+                        let instance = self.frame().instance;
                         self.read_global_as_value(GlobalId {
-                            instance: self.frame().instance,
+                            instance,
                             promoted: Some(index),
                         }, ty)?
                     }
@@ -997,7 +1020,7 @@ pub fn write_discriminant_value(
         Ok(())
     }
 
-    pub fn read_global_as_value(&self, gid: GlobalId<'tcx>, ty: Ty<'tcx>) -> EvalResult<'tcx, Value> {
+    pub fn read_global_as_value(&mut self, gid: GlobalId<'tcx>, ty: Ty<'tcx>) -> EvalResult<'tcx, Value> {
         if self.tcx.is_static(gid.instance.def_id()).is_some() {
             let alloc_id = self
                 .tcx
@@ -1341,92 +1364,84 @@ pub(crate) fn read_ptr(
         }
     }
 
-    pub fn try_read_value(&self, ptr: Pointer, ptr_align: Align, ty: Ty<'tcx>) -> EvalResult<'tcx, Option<Value>> {
-        use syntax::ast::FloatTy;
-
-        let layout = self.layout_of(ty)?;
-        self.memory.check_align(ptr, ptr_align)?;
-
-        if layout.size.bytes() == 0 {
-            return Ok(Some(Value::ByVal(PrimVal::Undef)));
-        }
-
-        let ptr = ptr.to_ptr()?;
-        let val = match ty.sty {
+    pub fn validate_ptr_target(
+        &self,
+        ptr: MemoryPointer,
+        ptr_align: Align,
+        ty: Ty<'tcx>
+    ) -> EvalResult<'tcx> {
+        match ty.sty {
             ty::TyBool => {
                 let val = self.memory.read_primval(ptr, ptr_align, 1)?;
-                let val = match val {
-                    PrimVal::Bytes(0) => false,
-                    PrimVal::Bytes(1) => true,
+                match val {
+                    PrimVal::Bytes(0) | PrimVal::Bytes(1) => (),
                     // TODO: This seems a little overeager, should reading at bool type already be insta-UB?
                     _ => return err!(InvalidBool),
-                };
-                PrimVal::from_bool(val)
+                }
             }
             ty::TyChar => {
                 let c = self.memory.read_primval(ptr, ptr_align, 4)?.to_bytes()? as u32;
                 match ::std::char::from_u32(c) {
-                    Some(ch) => PrimVal::from_char(ch),
+                    Some(..) => (),
                     None => return err!(InvalidChar(c as u128)),
                 }
             }
 
-            ty::TyInt(int_ty) => {
-                use syntax::ast::IntTy::*;
-                let size = match int_ty {
-                    I8 => 1,
-                    I16 => 2,
-                    I32 => 4,
-                    I64 => 8,
-                    I128 => 16,
-                    Isize => self.memory.pointer_size(),
-                };
-                self.memory.read_primval(ptr, ptr_align, size)?
-            }
-
-            ty::TyUint(uint_ty) => {
-                use syntax::ast::UintTy::*;
-                let size = match uint_ty {
-                    U8 => 1,
-                    U16 => 2,
-                    U32 => 4,
-                    U64 => 8,
-                    U128 => 16,
-                    Usize => self.memory.pointer_size(),
-                };
-                self.memory.read_primval(ptr, ptr_align, size)?
-            }
-
-            ty::TyFloat(FloatTy::F32) => {
-                PrimVal::Bytes(self.memory.read_primval(ptr, ptr_align, 4)?.to_bytes()?)
-            }
-            ty::TyFloat(FloatTy::F64) => {
-                PrimVal::Bytes(self.memory.read_primval(ptr, ptr_align, 8)?.to_bytes()?)
-            }
-
-            ty::TyFnPtr(_) => self.memory.read_ptr_sized(ptr, ptr_align)?,
+            ty::TyFnPtr(_) => {
+                self.memory.read_ptr_sized(ptr, ptr_align)?;
+            },
             ty::TyRef(_, rty, _) |
             ty::TyRawPtr(ty::TypeAndMut { ty: rty, .. }) => {
-                return self.read_ptr(ptr, ptr_align, rty).map(Some)
+                self.read_ptr(ptr, ptr_align, rty)?;
             }
 
             ty::TyAdt(def, _) => {
                 if def.is_box() {
-                    return self.read_ptr(ptr, ptr_align, ty.boxed_ty()).map(Some);
+                    self.read_ptr(ptr, ptr_align, ty.boxed_ty())?;
+                    return Ok(());
                 }
 
                 if let layout::Abi::Scalar(ref scalar) = self.layout_of(ty)?.abi {
                     let size = scalar.value.size(self).bytes();
-                    self.memory.read_primval(ptr, ptr_align, size)?
-                } else {
-                    return Ok(None);
+                    self.memory.read_primval(ptr, ptr_align, size)?;
                 }
             }
 
-            _ => return Ok(None),
-        };
+            _ => (),
+        }
+        Ok(())
+    }
+
+    pub fn try_read_value(&self, ptr: Pointer, ptr_align: Align, ty: Ty<'tcx>) -> EvalResult<'tcx, Option<Value>> {
+        let layout = self.layout_of(ty)?;
+        self.memory.check_align(ptr, ptr_align)?;
 
-        Ok(Some(Value::ByVal(val)))
+        if layout.size.bytes() == 0 {
+            return Ok(Some(Value::ByVal(PrimVal::Undef)));
+        }
+
+        let ptr = ptr.to_ptr()?;
+
+        // Not the right place to do this
+        //self.validate_ptr_target(ptr, ptr_align, ty)?;
+
+        match layout.abi {
+            layout::Abi::Scalar(..) => {
+                let primval = self.memory.read_primval(ptr, ptr_align, layout.size.bytes())?;
+                Ok(Some(Value::ByVal(primval)))
+            }
+            layout::Abi::ScalarPair(ref a, ref b) => {
+                let (a, b) = (&a.value, &b.value);
+                let (a_size, b_size) = (a.size(self), b.size(self));
+                let a_ptr = ptr;
+                let b_offset = a_size.abi_align(b.align(self));
+                let b_ptr = ptr.offset(b_offset.bytes(), self)?.into();
+                let a_val = self.memory.read_primval(a_ptr, ptr_align, a_size.bytes())?;
+                let b_val = self.memory.read_primval(b_ptr, ptr_align, b_size.bytes())?;
+                Ok(Some(Value::ByValPair(a_val, b_val)))
+            }
+            _ => Ok(None),
+        }
     }
 
     pub fn frame(&self) -> &Frame<'mir, 'tcx> {
@@ -1466,7 +1481,7 @@ fn unsize_into_ptr(
                 let ptr = self.into_ptr(src)?;
                 // u64 cast is from usize to u64, which is always good
                 let valty = ValTy {
-                    value: ptr.to_value_with_len(length.val.unwrap_u64() ),
+                    value: ptr.to_value_with_len(length.unwrap_usize(self.tcx.tcx)),
                     ty: dest_ty,
                 };
                 self.write_value(valty, dest)
index 7f8205b8327face1250c757888a8dbfaaf8039d7..ba1c05deef1b42e8a0264c5ef4d7dc34223d14ce 100644 (file)
@@ -1,15 +1,18 @@
-use byteorder::{ReadBytesExt, WriteBytesExt, LittleEndian, BigEndian};
-use std::collections::{btree_map, BTreeMap, VecDeque};
-use std::{ptr, io};
+use std::collections::{btree_map, VecDeque};
+use std::ptr;
 
+use rustc::hir::def_id::DefId;
 use rustc::ty::Instance;
+use rustc::ty::ParamEnv;
 use rustc::ty::maps::TyCtxtAt;
 use rustc::ty::layout::{self, Align, TargetDataLayout};
 use syntax::ast::Mutability;
+use rustc::middle::const_val::{ConstVal, ErrKind};
 
 use rustc_data_structures::fx::{FxHashSet, FxHashMap};
-use rustc::mir::interpret::{MemoryPointer, AllocId, Allocation, AccessKind, UndefMask, Value, Pointer,
-                            EvalResult, PrimVal, EvalErrorKind};
+use rustc::mir::interpret::{MemoryPointer, AllocId, Allocation, AccessKind, Value, Pointer,
+                            EvalResult, PrimVal, EvalErrorKind, GlobalId};
+pub use rustc::mir::interpret::{write_target_uint, write_target_int, read_target_uint};
 
 use super::{EvalContext, Machine};
 
@@ -79,20 +82,11 @@ pub fn allocate_cached(&mut self, bytes: &[u8]) -> MemoryPointer {
     }
 
     /// kind is `None` for statics
-    pub fn allocate(
+    pub fn allocate_value(
         &mut self,
-        size: u64,
-        align: Align,
+        alloc: Allocation,
         kind: Option<MemoryKind<M::MemoryKinds>>,
-    ) -> EvalResult<'tcx, MemoryPointer> {
-        assert_eq!(size as usize as u64, size);
-        let alloc = Allocation {
-            bytes: vec![0; size as usize],
-            relocations: BTreeMap::new(),
-            undef_mask: UndefMask::new(size),
-            align,
-            runtime_mutability: Mutability::Immutable,
-        };
+    ) -> EvalResult<'tcx, AllocId> {
         let id = self.tcx.interpret_interner.reserve();
         M::add_lock(self, id);
         match kind {
@@ -105,6 +99,17 @@ pub fn allocate(
                 self.uninitialized_statics.insert(id, alloc);
             },
         }
+        Ok(id)
+    }
+
+    /// kind is `None` for statics
+    pub fn allocate(
+        &mut self,
+        size: u64,
+        align: Align,
+        kind: Option<MemoryKind<M::MemoryKinds>>,
+    ) -> EvalResult<'tcx, MemoryPointer> {
+        let id = self.allocate_value(Allocation::undef(size, align), kind)?;
         Ok(MemoryPointer::new(id, 0))
     }
 
@@ -272,6 +277,31 @@ pub fn check_bounds(&self, ptr: MemoryPointer, access: bool) -> EvalResult<'tcx>
 
 /// Allocation accessors
 impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
+    fn const_eval_static(&self, def_id: DefId) -> EvalResult<'tcx, &'tcx Allocation> {
+        let instance = Instance::mono(self.tcx.tcx, def_id);
+        let gid = GlobalId {
+            instance,
+            promoted: None,
+        };
+        self.tcx.const_eval(ParamEnv::reveal_all().and(gid)).map_err(|err| {
+            match *err.kind {
+                ErrKind::Miri(ref err, _) => match err.kind {
+                    EvalErrorKind::TypeckError |
+                    EvalErrorKind::Layout(_) => EvalErrorKind::TypeckError.into(),
+                    _ => EvalErrorKind::ReferencedConstant.into(),
+                },
+                ErrKind::TypeckError => EvalErrorKind::TypeckError.into(),
+                ref other => bug!("const eval returned {:?}", other),
+            }
+        }).map(|val| {
+            let const_val = match val.val {
+                ConstVal::Value(val) => val,
+                ConstVal::Unevaluated(..) => bug!("should be evaluated"),
+            };
+            self.tcx.const_value_to_allocation((const_val, val.ty))
+        })
+    }
+
     pub fn get(&self, id: AllocId) -> EvalResult<'tcx, &Allocation> {
         // normal alloc?
         match self.alloc_map.get(&id) {
@@ -281,13 +311,19 @@ pub fn get(&self, id: AllocId) -> EvalResult<'tcx, &Allocation> {
                 Some(alloc) => Ok(alloc),
                 None => {
                     // static alloc?
-                    self.tcx.interpret_interner.get_alloc(id)
-                        // no alloc? produce an error
-                        .ok_or_else(|| if self.tcx.interpret_interner.get_fn(id).is_some() {
-                            EvalErrorKind::DerefFunctionPointer.into()
-                        } else {
-                            EvalErrorKind::DanglingPointerDeref.into()
-                        })
+                    if let Some(a) = self.tcx.interpret_interner.get_alloc(id) {
+                        return Ok(a);
+                    }
+                    // static variable?
+                    if let Some(did) = self.tcx.interpret_interner.get_static(id) {
+                        return self.const_eval_static(did);
+                    }
+                    // otherwise return an error
+                    Err(if self.tcx.interpret_interner.get_fn(id).is_some() {
+                        EvalErrorKind::DerefFunctionPointer.into()
+                    } else {
+                        EvalErrorKind::DanglingPointerDeref.into()
+                    })
                 },
             },
         }
@@ -873,41 +909,6 @@ pub fn mark_definedness(
     }
 }
 
-////////////////////////////////////////////////////////////////////////////////
-// Methods to access integers in the target endianness
-////////////////////////////////////////////////////////////////////////////////
-
-pub fn write_target_uint(
-    endianness: layout::Endian,
-    mut target: &mut [u8],
-    data: u128,
-) -> Result<(), io::Error> {
-    let len = target.len();
-    match endianness {
-        layout::Endian::Little => target.write_uint128::<LittleEndian>(data, len),
-        layout::Endian::Big => target.write_uint128::<BigEndian>(data, len),
-    }
-}
-
-pub fn write_target_int(
-    endianness: layout::Endian,
-    mut target: &mut [u8],
-    data: i128,
-) -> Result<(), io::Error> {
-    let len = target.len();
-    match endianness {
-        layout::Endian::Little => target.write_int128::<LittleEndian>(data, len),
-        layout::Endian::Big => target.write_int128::<BigEndian>(data, len),
-    }
-}
-
-pub fn read_target_uint(endianness: layout::Endian, mut source: &[u8]) -> Result<u128, io::Error> {
-    match endianness {
-        layout::Endian::Little => source.read_uint128::<LittleEndian>(source.len()),
-        layout::Endian::Big => source.read_uint128::<BigEndian>(source.len()),
-    }
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // Unaligned accesses
 ////////////////////////////////////////////////////////////////////////////////
index 1eb131810bdf38d9404a60a6fa16f61c4c3a9c17..d39bae5e8dbbaa1ca4ecc17539f5b6039af025a3 100644 (file)
     mk_borrowck_eval_cx,
     eval_body,
     CompileTimeEvaluator,
+    const_value_to_allocation_provider,
     const_eval_provider,
     const_val_field,
     const_variant_index,
+    value_to_const_value,
 };
 
 pub use self::machine::Machine;
index b5a06286e4eed18430d12f9460043b0ecd27d4aa..883b17b8584fb010ff322449d6262a5e4cced110 100644 (file)
@@ -1,5 +1,5 @@
 use rustc::mir;
-use rustc::ty::{self, Ty};
+use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::layout::{self, Align, LayoutOf, TyLayout};
 use rustc_data_structures::indexed_vec::Idx;
 
@@ -69,9 +69,13 @@ pub fn to_ptr(self) -> EvalResult<'tcx, MemoryPointer> {
         self.to_ptr_align().0.to_ptr()
     }
 
-    pub(super) fn elem_ty_and_len(self, ty: Ty<'tcx>) -> (Ty<'tcx>, u64) {
+    pub(super) fn elem_ty_and_len(
+        self,
+        ty: Ty<'tcx>,
+        tcx: TyCtxt<'_, 'tcx, '_>
+    ) -> (Ty<'tcx>, u64) {
         match ty.sty {
-            ty::TyArray(elem, n) => (elem, n.val.unwrap_u64() as u64),
+            ty::TyArray(elem, n) => (elem, n.unwrap_usize(tcx)),
 
             ty::TySlice(elem) => {
                 match self {
@@ -320,7 +324,7 @@ pub fn place_index(
         let base = self.force_allocation(base)?;
         let (base_ptr, align) = base.to_ptr_align();
 
-        let (elem_ty, len) = base.elem_ty_and_len(outer_ty);
+        let (elem_ty, len) = base.elem_ty_and_len(outer_ty, self.tcx.tcx);
         let elem_size = self.layout_of(elem_ty)?.size.bytes();
         assert!(
             n < len,
@@ -396,7 +400,7 @@ pub fn eval_place_projection(
                 let base = self.force_allocation(base)?;
                 let (base_ptr, align) = base.to_ptr_align();
 
-                let (elem_ty, n) = base.elem_ty_and_len(base_ty);
+                let (elem_ty, n) = base.elem_ty_and_len(base_ty, self.tcx.tcx);
                 let elem_size = self.layout_of(elem_ty)?.size.bytes();
                 assert!(n >= min_length as u64);
 
@@ -415,7 +419,7 @@ pub fn eval_place_projection(
                 let base = self.force_allocation(base)?;
                 let (base_ptr, align) = base.to_ptr_align();
 
-                let (elem_ty, n) = base.elem_ty_and_len(base_ty);
+                let (elem_ty, n) = base.elem_ty_and_len(base_ty, self.tcx.tcx);
                 let elem_size = self.layout_of(elem_ty)?.size.bytes();
                 assert!(u64::from(from) <= n - u64::from(to));
                 let ptr = base_ptr.offset(u64::from(from) * elem_size, &self)?;
index 2545ba3a94af12215c6a4a15437304944a2ee358..fbc0facbc49670ca94fedbeef383d422780c83be 100644 (file)
@@ -85,6 +85,7 @@ pub fn provide(providers: &mut Providers) {
     shim::provide(providers);
     transform::provide(providers);
     providers.const_eval = interpret::const_eval_provider;
+    providers.const_value_to_allocation = interpret::const_value_to_allocation_provider;
     providers.check_match = hair::pattern::check_match;
 }
 
index e051b848c011fe21a193cfc193fbf88719413b34..e690e8ee88066cc9b9f99efaaea7d758529175b0 100644 (file)
 use rustc::hir::map as hir_map;
 use rustc::hir::def_id::DefId;
 use rustc::middle::const_val::ConstVal;
-use rustc::mir::interpret::{Value, PrimVal, AllocId, Pointer};
+use rustc::mir::interpret::{AllocId, ConstValue};
 use rustc::middle::lang_items::{ExchangeMallocFnLangItem, StartFnLangItem};
 use rustc::ty::subst::{Substs, Kind};
 use rustc::ty::{self, TypeFoldable, Ty, TyCtxt};
 use rustc::mir::{self, Location, Promoted};
 use rustc::mir::visit::Visitor as MirVisitor;
 use rustc::mir::mono::MonoItem;
-use rustc::mir::interpret::GlobalId;
+use rustc::mir::interpret::{PrimVal, GlobalId};
 
 use monomorphize::{self, Instance};
 use rustc::util::nodemap::{FxHashSet, FxHashMap, DefIdMap};
@@ -1237,22 +1237,17 @@ fn collect_const<'a, 'tcx>(
     };
     match val {
         ConstVal::Unevaluated(..) => bug!("const eval yielded unevaluated const"),
-        ConstVal::Value(Value::ByValPair(PrimVal::Ptr(a), PrimVal::Ptr(b))) => {
+        ConstVal::Value(ConstValue::ByValPair(PrimVal::Ptr(a), PrimVal::Ptr(b))) => {
             collect_miri(tcx, a.alloc_id, output);
             collect_miri(tcx, b.alloc_id, output);
         }
-        ConstVal::Value(Value::ByValPair(_, PrimVal::Ptr(ptr))) |
-        ConstVal::Value(Value::ByValPair(PrimVal::Ptr(ptr), _)) |
-        ConstVal::Value(Value::ByVal(PrimVal::Ptr(ptr))) =>
+        ConstVal::Value(ConstValue::ByValPair(_, PrimVal::Ptr(ptr))) |
+        ConstVal::Value(ConstValue::ByValPair(PrimVal::Ptr(ptr), _)) |
+        ConstVal::Value(ConstValue::ByVal(PrimVal::Ptr(ptr))) =>
             collect_miri(tcx, ptr.alloc_id, output),
-        ConstVal::Value(Value::ByRef(Pointer { primval: PrimVal::Ptr(ptr) }, _)) => {
-            // by ref should only collect the inner allocation, not the value itself
-            let alloc = tcx
-                .interpret_interner
-                .get_alloc(ptr.alloc_id)
-                .expect("ByRef to extern static is not allowed");
-            for &inner in alloc.relocations.values() {
-                collect_miri(tcx, inner, output);
+        ConstVal::Value(ConstValue::ByRef(alloc)) => {
+            for &id in alloc.relocations.values() {
+                collect_miri(tcx, id, output);
             }
         }
         _ => {},
index 176ed8c5bca745c53e4c8f0cf2c7f80f9ba86bd7..a569ad00d0c65a6a3dcb211ef677964cc2dbbb86 100644 (file)
@@ -313,8 +313,7 @@ pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String) {
             ty::TyArray(inner_type, len) => {
                 output.push('[');
                 self.push_type_name(inner_type, output);
-                write!(output, "; {}",
-                    len.val.unwrap_u64()).unwrap();
+                write!(output, "; {}", len.unwrap_usize(self.tcx)).unwrap();
                 output.push(']');
             },
             ty::TySlice(inner_type) => {
index 699a5b17435bd2c4161d8033eee349992cfc0d9f..5b2f3a8b8aac7ee01237d4ee84e572f28e090e74 100644 (file)
 use rustc::hir;
 use rustc::hir::def_id::DefId;
 use rustc::infer;
-use rustc::middle::const_val::ConstVal;
 use rustc::mir::*;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::subst::{Kind, Subst, Substs};
 use rustc::ty::maps::Providers;
-use rustc::mir::interpret::{Value, PrimVal};
 
 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
 
@@ -303,7 +301,7 @@ fn build_clone_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     match self_ty.sty {
         _ if is_copy => builder.copy_shim(),
         ty::TyArray(ty, len) => {
-            let len = len.val.unwrap_u64();
+            let len = len.unwrap_usize(tcx);
             builder.array_shim(dest, src, ty, len)
         }
         ty::TyClosure(def_id, substs) => {
@@ -442,11 +440,7 @@ fn make_clone_call(
             span: self.span,
             ty: func_ty,
             literal: Literal::Value {
-                value: tcx.mk_const(ty::Const {
-                    // ZST function type
-                    val: ConstVal::Value(Value::ByVal(PrimVal::Undef)),
-                    ty: func_ty
-                }),
+                value: ty::Const::zero_sized(self.tcx, func_ty)
             },
         });
 
@@ -506,10 +500,7 @@ fn make_usize(&self, value: u64) -> Box<Constant<'tcx>> {
             span: self.span,
             ty: self.tcx.types.usize,
             literal: Literal::Value {
-                value: self.tcx.mk_const(ty::Const {
-                    val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(value.into()))),
-                    ty: self.tcx.types.usize,
-                })
+                value: ty::Const::from_usize(self.tcx, value),
             }
         }
     }
@@ -738,11 +729,7 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 span,
                 ty,
                 literal: Literal::Value {
-                    value: tcx.mk_const(ty::Const {
-                        // ZST function type
-                        val: ConstVal::Value(Value::ByVal(PrimVal::Undef)),
-                        ty
-                    }),
+                    value: ty::Const::zero_sized(tcx, ty)
                 },
              }),
              vec![rcvr])
index e1db216b6bbbcfad1b1d15a9a696d79cc3325674..6b0217c8f7cbc17b48687f4d94a1e83286df3d2c 100644 (file)
 use rustc::mir::visit::{Visitor, PlaceContext};
 use rustc::middle::const_val::ConstVal;
 use rustc::ty::{TyCtxt, self, Instance};
-use rustc::mir::interpret::{Value, PrimVal, GlobalId};
+use rustc::mir::interpret::{Value, PrimVal, GlobalId, EvalResult};
+use interpret::EvalContext;
+use interpret::CompileTimeEvaluator;
 use interpret::{eval_promoted, mk_borrowck_eval_cx, ValTy};
 use transform::{MirPass, MirSource};
-use syntax::codemap::Span;
+use syntax::codemap::{Span, DUMMY_SP};
 use rustc::ty::subst::Substs;
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc::ty::ParamEnv;
 use rustc::ty::layout::{
-    LayoutOf, TyLayout, LayoutError,
+    LayoutOf, TyLayout, LayoutError, LayoutCx,
     HasTyCtxt, TargetDataLayout, HasDataLayout,
 };
 
@@ -64,6 +66,7 @@ fn run_pass<'a, 'tcx>(&self,
 
 /// Finds optimization opportunities on the MIR.
 struct ConstPropagator<'b, 'a, 'tcx:'a+'b> {
+    ecx: EvalContext<'a, 'b, 'tcx, CompileTimeEvaluator>,
     mir: &'b Mir<'tcx>,
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     source: MirSource,
@@ -102,7 +105,11 @@ fn new(
         source: MirSource,
     ) -> ConstPropagator<'b, 'a, 'tcx> {
         let param_env = tcx.param_env(source.def_id);
+        let substs = Substs::identity_for_item(tcx, source.def_id);
+        let instance = Instance::new(source.def_id, substs);
+        let ecx = mk_borrowck_eval_cx(tcx, instance, mir, DUMMY_SP).unwrap();
         ConstPropagator {
+            ecx,
             mir,
             tcx,
             source,
@@ -112,7 +119,27 @@ fn new(
         }
     }
 
-    fn const_eval(&self, cid: GlobalId<'tcx>, span: Span) -> Option<Const<'tcx>> {
+    fn use_ecx<F, T>(
+        &mut self,
+        span: Span,
+        f: F
+    ) -> Option<T>
+    where
+        F: FnOnce(&mut Self) -> EvalResult<'tcx, T>,
+    {
+        self.ecx.tcx.span = span;
+        let r = match f(self) {
+            Ok(val) => Some(val),
+            Err(mut err) => {
+                self.ecx.report(&mut err, false, Some(span));
+                None
+            },
+        };
+        self.ecx.tcx.span = DUMMY_SP;
+        r
+    }
+
+    fn const_eval(&mut self, cid: GlobalId<'tcx>, span: Span) -> Option<Const<'tcx>> {
         let value = match self.tcx.const_eval(self.param_env.and(cid)) {
             Ok(val) => val,
             Err(err) => {
@@ -121,7 +148,9 @@ fn const_eval(&self, cid: GlobalId<'tcx>, span: Span) -> Option<Const<'tcx>> {
             },
         };
         let val = match value.val {
-            ConstVal::Value(v) => v,
+            ConstVal::Value(v) => {
+                self.use_ecx(span, |this| this.ecx.const_value_to_value(v, value.ty))?
+            },
             _ => bug!("eval produced: {:?}", value),
         };
         let val = (val, value.ty, span);
@@ -132,7 +161,12 @@ fn const_eval(&self, cid: GlobalId<'tcx>, span: Span) -> Option<Const<'tcx>> {
     fn eval_constant(&mut self, c: &Constant<'tcx>) -> Option<Const<'tcx>> {
         match c.literal {
             Literal::Value { value } => match value.val {
-                ConstVal::Value(v) => Some((v, value.ty, c.span)),
+                ConstVal::Value(v) => {
+                    let v = self.use_ecx(c.span, |this| {
+                        this.ecx.const_value_to_value(v, value.ty)
+                    })?;
+                    Some((v, value.ty, c.span))
+                },
                 ConstVal::Unevaluated(did, substs) => {
                     let instance = Instance::resolve(
                         self.tcx,
@@ -162,7 +196,10 @@ fn eval_constant(&mut self, c: &Constant<'tcx>) -> Option<Const<'tcx>> {
                 };
                 // cannot use `const_eval` here, because that would require having the MIR
                 // for the current function available, but we're producing said MIR right now
-                let (value, _, ty) = eval_promoted(self.tcx, cid, self.mir, self.param_env)?;
+                let span = self.mir.span;
+                let (value, _, ty) = self.use_ecx(span, |this| {
+                    Ok(eval_promoted(&mut this.ecx, cid, this.mir, this.param_env))
+                })??;
                 let val = (value, ty, c.span);
                 trace!("evaluated {:?} to {:?}", c, val);
                 Some(val)
@@ -185,7 +222,11 @@ fn eval_place(&mut self, place: &Place<'tcx>) -> Option<Const<'tcx>> {
                             use rustc_data_structures::indexed_vec::Idx;
                             let field_index = field.index();
                             let val = [a, b][field_index];
-                            let field = base_layout.field(&*self, field_index).ok()?;
+                            let cx = LayoutCx {
+                                tcx: self.tcx,
+                                param_env: self.param_env,
+                            };
+                            let field = base_layout.field(cx, field_index).ok()?;
                             trace!("projection resulted in: {:?}", val);
                             Some((Value::ByVal(val), field.ty, span))
                         },
@@ -258,19 +299,13 @@ fn const_prop(
                     // FIXME: can't handle code with generics
                     return None;
                 }
-                let substs = Substs::identity_for_item(self.tcx, self.source.def_id);
-                let instance = Instance::new(self.source.def_id, substs);
-                let ecx = mk_borrowck_eval_cx(self.tcx, instance, self.mir, span).unwrap();
 
                 let val = self.eval_operand(arg)?;
-                let prim = ecx.value_to_primval(ValTy { value: val.0, ty: val.1 }).ok()?;
-                match ecx.unary_op(op, prim, val.1) {
-                    Ok(val) => Some((Value::ByVal(val), place_ty, span)),
-                    Err(mut err) => {
-                        ecx.report(&mut err, false, Some(span));
-                        None
-                    },
-                }
+                let prim = self.use_ecx(span, |this| {
+                    this.ecx.value_to_primval(ValTy { value: val.0, ty: val.1 })
+                })?;
+                let val = self.use_ecx(span, |this| this.ecx.unary_op(op, prim, val.1))?;
+                Some((Value::ByVal(val), place_ty, span))
             }
             Rvalue::CheckedBinaryOp(op, ref left, ref right) |
             Rvalue::BinaryOp(op, ref left, ref right) => {
@@ -287,11 +322,10 @@ fn const_prop(
                     // FIXME: can't handle code with generics
                     return None;
                 }
-                let substs = Substs::identity_for_item(self.tcx, self.source.def_id);
-                let instance = Instance::new(self.source.def_id, substs);
-                let ecx = mk_borrowck_eval_cx(self.tcx, instance, self.mir, span).unwrap();
 
-                let r = ecx.value_to_primval(ValTy { value: right.0, ty: right.1 }).ok()?;
+                let r = self.use_ecx(span, |this| {
+                    this.ecx.value_to_primval(ValTy { value: right.0, ty: right.1 })
+                })?;
                 if op == BinOp::Shr || op == BinOp::Shl {
                     let param_env = self.tcx.param_env(self.source.def_id);
                     let left_ty = left.ty(self.mir, self.tcx);
@@ -316,31 +350,31 @@ fn const_prop(
                     }
                 }
                 let left = self.eval_operand(left)?;
-                let l = ecx.value_to_primval(ValTy { value: left.0, ty: left.1 }).ok()?;
+                let l = self.use_ecx(span, |this| {
+                    this.ecx.value_to_primval(ValTy { value: left.0, ty: left.1 })
+                })?;
                 trace!("const evaluating {:?} for {:?} and {:?}", op, left, right);
-                match ecx.binary_op(op, l, left.1, r, right.1) {
-                    Ok((val, overflow)) => {
-                        let val = if let Rvalue::CheckedBinaryOp(..) = *rvalue {
-                            Value::ByValPair(
-                                val,
-                                PrimVal::from_bool(overflow),
-                            )
-                        } else {
-                            if overflow {
-                                use rustc::mir::interpret::EvalErrorKind;
-                                let mut err = EvalErrorKind::Overflow(op).into();
-                                ecx.report(&mut err, false, Some(span));
-                                return None;
-                            }
-                            Value::ByVal(val)
-                        };
-                        Some((val, place_ty, span))
-                    },
-                    Err(mut err) => {
-                        ecx.report(&mut err, false, Some(span));
-                        None
-                    },
-                }
+                let (val, overflow) = self.use_ecx(span, |this| {
+                    this.ecx.binary_op(op, l, left.1, r, right.1)
+                })?;
+                let val = if let Rvalue::CheckedBinaryOp(..) = *rvalue {
+                    Value::ByValPair(
+                        val,
+                        PrimVal::from_bool(overflow),
+                    )
+                } else {
+                    if overflow {
+                        use rustc::mir::interpret::EvalErrorKind;
+                        let mut err = EvalErrorKind::Overflow(op).into();
+                        self.use_ecx(span, |this| {
+                            this.ecx.report(&mut err, false, Some(span));
+                            Ok(())
+                        });
+                        return None;
+                    }
+                    Value::ByVal(val)
+                };
+                Some((val, place_ty, span))
             },
         }
     }
index 5397d18cdd720be1b0d185fe4359e88d10bb07d3..56050318ca7faf808687a0dd313110f83d996ded 100644 (file)
@@ -17,8 +17,6 @@
 use dataflow::{self, do_dataflow, DebugFormatted};
 use rustc::ty::{self, TyCtxt};
 use rustc::mir::*;
-use rustc::middle::const_val::ConstVal;
-use rustc::mir::interpret::{Value, PrimVal};
 use rustc::util::nodemap::FxHashMap;
 use rustc_data_structures::indexed_set::IdxSetBuf;
 use rustc_data_structures::indexed_vec::Idx;
@@ -174,7 +172,7 @@ struct Elaborator<'a, 'b: 'a, 'tcx: 'b> {
 }
 
 impl<'a, 'b, 'tcx> fmt::Debug for Elaborator<'a, 'b, 'tcx> {
-    fn fmt(&self, _f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+    fn fmt(&self, _f: &mut fmt::Formatter) -> fmt::Result {
         Ok(())
     }
 }
@@ -533,10 +531,7 @@ fn constant_bool(&self, span: Span, val: bool) -> Rvalue<'tcx> {
             span,
             ty: self.tcx.types.bool,
             literal: Literal::Value {
-                value: self.tcx.mk_const(ty::Const {
-                    val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(val as u128))),
-                    ty: self.tcx.types.bool
-                })
+                value: ty::Const::from_bool(self.tcx, val)
             }
         })))
     }
index c4e700cdd1f41aa2d62c720dc0a2d0ef5b2f9a72..5da40d04b337399b6526b5bcf64b43c4267bd098 100644 (file)
@@ -61,7 +61,6 @@
 
 use rustc::hir;
 use rustc::hir::def_id::DefId;
-use rustc::middle::const_val::ConstVal;
 use rustc::mir::*;
 use rustc::mir::visit::{PlaceContext, Visitor, MutVisitor};
 use rustc::ty::{self, TyCtxt, AdtDef, Ty};
@@ -79,7 +78,6 @@
 use transform::no_landing_pads::no_landing_pads;
 use dataflow::{do_dataflow, DebugFormatted, state_for_location};
 use dataflow::{MaybeStorageLive, HaveBeenBorrowedLocals};
-use rustc::mir::interpret::{Value, PrimVal};
 
 pub struct StateTransform;
 
@@ -180,10 +178,10 @@ fn set_state(&self, state_disc: u32, source_info: SourceInfo) -> Statement<'tcx>
             span: source_info.span,
             ty: self.tcx.types.u32,
             literal: Literal::Value {
-                value: self.tcx.mk_const(ty::Const {
-                    val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(state_disc.into()))),
-                    ty: self.tcx.types.u32
-                }),
+                value: ty::Const::from_bits(
+                    self.tcx,
+                    state_disc.into(),
+                    self.tcx.types.u32),
             },
         });
         Statement {
@@ -698,10 +696,7 @@ fn insert_panic_block<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             span: mir.span,
             ty: tcx.types.bool,
             literal: Literal::Value {
-                value: tcx.mk_const(ty::Const {
-                    val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(0))),
-                    ty: tcx.types.bool
-                }),
+                value: ty::Const::from_bool(tcx, false),
             },
         }),
         expected: true,
index 4762c6aaa27cc8143e78f65ffe3058c493a67d62..28ab3d6a8574fb3543cf27bc40e15f42192cb97d 100644 (file)
@@ -595,7 +595,7 @@ fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
             }
             Operand::Constant(ref constant) => {
                 if let Literal::Value {
-                    value: &ty::Const { val: ConstVal::Unevaluated(def_id, _), ty }
+                    value: &ty::Const { val: ConstVal::Unevaluated(def_id, _), ty, .. }
                 } = constant.literal {
                     // Don't peek inside trait associated constants.
                     if self.tcx.trait_of_item(def_id).is_some() {
@@ -690,7 +690,7 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
                             _ => false
                         }
                     } else if let ty::TyArray(_, len) = ty.sty {
-                        len.val.unwrap_u64() == 0 &&
+                        len.unwrap_usize(self.tcx) == 0 &&
                             self.mode == Mode::Fn
                     } else {
                         false
index 9dd48952208a9bed86565fb603ffdbaca8bf1927..72bee040c06a9a676f5b5b3c5fcad9fc00511acc 100644 (file)
 
 //! A pass that simplifies branches when their condition is known.
 
-use rustc::ty::{self, TyCtxt};
-use rustc::middle::const_val::ConstVal;
+use rustc::ty::TyCtxt;
 use rustc::mir::*;
-use rustc::mir::interpret::{Value, PrimVal};
 use transform::{MirPass, MirSource};
 
 use std::borrow::Cow;
@@ -32,7 +30,7 @@ fn name<'a>(&'a self) -> Cow<'a, str> {
     }
 
     fn run_pass<'a, 'tcx>(&self,
-                          _tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                          tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           _src: MirSource,
                           mir: &mut Mir<'tcx>) {
         for block in mir.basic_blocks_mut() {
@@ -40,8 +38,8 @@ fn run_pass<'a, 'tcx>(&self,
             terminator.kind = match terminator.kind {
                 TerminatorKind::SwitchInt { discr: Operand::Constant(box Constant {
                     literal: Literal::Value { ref value }, ..
-                }), ref values, ref targets, .. } => {
-                    if let Some(constint) = value.val.to_raw_bits() {
+                }), switch_ty, ref values, ref targets, .. } => {
+                    if let Some(constint) = value.assert_bits(switch_ty) {
                         let (otherwise, targets) = targets.split_last().unwrap();
                         let mut ret = TerminatorKind::Goto { target: *otherwise };
                         for (&v, t) in values.iter().zip(targets.iter()) {
@@ -57,12 +55,9 @@ fn run_pass<'a, 'tcx>(&self,
                 },
                 TerminatorKind::Assert { target, cond: Operand::Constant(box Constant {
                     literal: Literal::Value {
-                        value: &ty::Const {
-                            val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(cond))),
-                        .. }
+                        value
                     }, ..
-                }), expected, .. } if (cond == 1) == expected => {
-                    assert!(cond <= 1);
+                }), expected, .. } if (value.assert_bool(tcx) == Some(true)) == expected => {
                     TerminatorKind::Goto { target: target }
                 },
                 TerminatorKind::FalseEdges { real_target, .. } => {
index 9cc3ffb30638fe78945d485a482235b0ee7e0f92..5019c74742a2b3ff31ddc087b85883ae5a1de196 100644 (file)
@@ -81,9 +81,9 @@ fn visit_assign(&mut self,
                 } else {
                     let place_ty = proj.base.ty(self.mir, self.tcx).to_ty(self.tcx);
                     if let ty::TyArray(item_ty, const_size) = place_ty.sty {
-                        if let Some(size) = const_size.val.to_raw_bits() {
-                            assert!(size <= (u32::max_value() as u128),
-                                    "unform array move out doesn't supported
+                        if let Some(size) = const_size.assert_usize(self.tcx) {
+                            assert!(size <= u32::max_value() as u64,
+                                    "uniform array move out doesn't supported
                                      for array bigger then u32");
                             self.uniform(location, dst_place, proj, item_ty, size as u32);
                         }
@@ -203,7 +203,7 @@ fn run_pass<'a, 'tcx>(&self,
                         let opt_size = opt_src_place.and_then(|src_place| {
                             let src_ty = src_place.ty(mir, tcx).to_ty(tcx);
                             if let ty::TyArray(_, ref size_o) = src_ty.sty {
-                                size_o.val.to_raw_bits().map(|n| n as u64)
+                                size_o.assert_usize(tcx)
                             } else {
                                 None
                             }
index a641cf3d93ecfeff5dab38d05389ee2c448a5761..9fc04dc7d24914a3c66fca69418aeaa2cf984799 100644 (file)
@@ -11,7 +11,6 @@
 use std::fmt;
 use rustc::hir;
 use rustc::mir::*;
-use rustc::middle::const_val::ConstVal;
 use rustc::middle::lang_items;
 use rustc::traits::Reveal;
 use rustc::ty::{self, Ty, TyCtxt};
@@ -19,7 +18,6 @@
 use rustc::ty::util::IntTypeExt;
 use rustc_data_structures::indexed_vec::Idx;
 use util::patch::MirPatch;
-use rustc::mir::interpret::{Value, PrimVal};
 
 use std::{iter, u32};
 
@@ -809,8 +807,10 @@ fn open_drop<'a>(&mut self) -> BasicBlock {
                 let succ = self.succ;
                 self.complete_drop(Some(DropFlagMode::Deep), succ, unwind)
             }
-            ty::TyArray(ety, size) => self.open_drop_for_array(
-                ety, size.val.to_raw_bits().map(|i| i as u64)),
+            ty::TyArray(ety, size) => {
+                let size = size.assert_usize(self.tcx());
+                self.open_drop_for_array(ety, size)
+            },
             ty::TySlice(ety) => self.open_drop_for_array(ety, None),
 
             _ => bug!("open drop from non-ADT `{:?}`", ty)
@@ -961,10 +961,7 @@ fn constant_usize(&self, val: u16) -> Operand<'tcx> {
             span: self.source_info.span,
             ty: self.tcx().types.usize,
             literal: Literal::Value {
-                value: self.tcx().mk_const(ty::Const {
-                    val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(val.into()))),
-                    ty: self.tcx().types.usize
-                })
+                value: ty::Const::from_usize(self.tcx(), val.into())
             }
         })
     }
index 71012ca6d5f7992045124a4af6997ed39a65351d..9d74ad0830f0c236178cc1227b48e0a81ac1fa45 100644 (file)
@@ -402,7 +402,7 @@ fn visit_constant(&mut self, constant: &Constant<'tcx>, location: Location) {
 
     fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, _: Location) {
         self.super_const(constant);
-        let ty::Const { ty, val } = constant;
+        let ty::Const { ty, val, .. } = constant;
         self.push(&format!("ty::Const"));
         self.push(&format!("+ ty: {:?}", ty));
         self.push(&format!("+ val: {:?}", val));
index 293f23eab388317c4b5a5d0bdbd8f50ca3d2426a..4594d450c1507f7a05dbd9078d0f3c9d90dab2c4 100644 (file)
@@ -15,7 +15,8 @@ pub fn opts() -> TargetOptions {
 
     // Make sure that the linker/gcc really don't pull in anything, including
     // default objects, libs, etc.
-    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-nostdlib".to_string());
+    base.pre_link_args_crt.insert(LinkerFlavor::Gcc, Vec::new());
+    base.pre_link_args_crt.get_mut(&LinkerFlavor::Gcc).unwrap().push("-nostdlib".to_string());
 
     // At least when this was tested, the linker would not add the
     // `GNU_EH_FRAME` program header to executables generated, which is required
@@ -55,9 +56,11 @@ pub fn opts() -> TargetOptions {
     //
     // Each target directory for musl has these object files included in it so
     // they'll be included from there.
-    base.pre_link_objects_exe.push("crt1.o".to_string());
-    base.pre_link_objects_exe.push("crti.o".to_string());
-    base.post_link_objects.push("crtn.o".to_string());
+    base.pre_link_objects_exe_crt.push("crt1.o".to_string());
+    base.pre_link_objects_exe_crt.push("crti.o".to_string());
+    base.pre_link_objects_exe_crt_sys.push("crtbegin.o".to_string());
+    base.post_link_objects_crt_sys.push("crtend.o".to_string());
+    base.post_link_objects_crt.push("crtn.o".to_string());
 
     // These targets statically link libc by default
     base.crt_static_default = true;
index 48e771e0aafab3c942cf8922825cc28cc4276be9..708a3865b23b910fa88920f25044b18287686f69 100644 (file)
@@ -421,20 +421,26 @@ pub struct TargetOptions {
     /// Linker to invoke
     pub linker: Option<String>,
 
-    /// Linker arguments that are unconditionally passed *before* any
-    /// user-defined libraries.
-    pub pre_link_args: LinkArgs,
-    /// Objects to link before all others, always found within the
+    /// Linker arguments that are passed *before* any user-defined libraries.
+    pub pre_link_args: LinkArgs, // ... unconditionally
+    pub pre_link_args_crt: LinkArgs, // ... when linking with a bundled crt
+    /// Objects to link before all others, all except *_sys found within the
     /// sysroot folder.
-    pub pre_link_objects_exe: Vec<String>, // ... when linking an executable
+    pub pre_link_objects_exe: Vec<String>, // ... when linking an executable, unconditionally
+    pub pre_link_objects_exe_crt: Vec<String>, // ... when linking an executable with a bundled crt
+    pub pre_link_objects_exe_crt_sys: Vec<String>, // ... when linking an executable with a bundled
+                                                   //  crt, from the system library search path
     pub pre_link_objects_dll: Vec<String>, // ... when linking a dylib
     /// Linker arguments that are unconditionally passed after any
     /// user-defined but before post_link_objects.  Standard platform
     /// libraries that should be always be linked to, usually go here.
     pub late_link_args: LinkArgs,
-    /// Objects to link after all others, always found within the
+    /// Objects to link after all others, all except *_sys found within the
     /// sysroot folder.
-    pub post_link_objects: Vec<String>,
+    pub post_link_objects: Vec<String>, // ... unconditionally
+    pub post_link_objects_crt: Vec<String>, // ... when linking with a bundled crt
+    pub post_link_objects_crt_sys: Vec<String>, // ... when linking with a bundled crt, from the
+                                                //  system library search path
     /// Linker arguments that are unconditionally passed *after* any
     /// user-defined libraries.
     pub post_link_args: LinkArgs,
@@ -634,6 +640,7 @@ fn default() -> TargetOptions {
             is_builtin: false,
             linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.to_string()),
             pre_link_args: LinkArgs::new(),
+            pre_link_args_crt: LinkArgs::new(),
             post_link_args: LinkArgs::new(),
             asm_args: Vec::new(),
             cpu: "generic".to_string(),
@@ -667,8 +674,12 @@ fn default() -> TargetOptions {
             position_independent_executables: false,
             relro_level: RelroLevel::None,
             pre_link_objects_exe: Vec::new(),
+            pre_link_objects_exe_crt: Vec::new(),
+            pre_link_objects_exe_crt_sys: Vec::new(),
             pre_link_objects_dll: Vec::new(),
             post_link_objects: Vec::new(),
+            post_link_objects_crt: Vec::new(),
+            post_link_objects_crt_sys: Vec::new(),
             late_link_args: LinkArgs::new(),
             link_env: Vec::new(),
             archive_format: "gnu".to_string(),
@@ -887,10 +898,15 @@ macro_rules! key {
         key!(is_builtin, bool);
         key!(linker, optional);
         key!(pre_link_args, link_args);
+        key!(pre_link_args_crt, link_args);
         key!(pre_link_objects_exe, list);
+        key!(pre_link_objects_exe_crt, list);
+        key!(pre_link_objects_exe_crt_sys, list);
         key!(pre_link_objects_dll, list);
         key!(late_link_args, link_args);
         key!(post_link_objects, list);
+        key!(post_link_objects_crt, list);
+        key!(post_link_objects_crt_sys, list);
         key!(post_link_args, link_args);
         key!(link_env, env);
         key!(asm_args, list);
@@ -1092,10 +1108,15 @@ macro_rules! target_option_val {
         target_option_val!(is_builtin);
         target_option_val!(linker);
         target_option_val!(link_args - pre_link_args);
+        target_option_val!(link_args - pre_link_args_crt);
         target_option_val!(pre_link_objects_exe);
+        target_option_val!(pre_link_objects_exe_crt);
+        target_option_val!(pre_link_objects_exe_crt_sys);
         target_option_val!(pre_link_objects_dll);
         target_option_val!(link_args - late_link_args);
         target_option_val!(post_link_objects);
+        target_option_val!(post_link_objects_crt);
+        target_option_val!(post_link_objects_crt_sys);
         target_option_val!(link_args - post_link_args);
         target_option_val!(env - link_env);
         target_option_val!(asm_args);
index d39556e9bb197e6ff91aaef9fad166ee04bd3268..299075ed03ad9ec0cfbc922c89f624227f8048fb 100644 (file)
@@ -621,6 +621,11 @@ fn link_natively(sess: &Session,
     if let Some(args) = sess.target.target.options.pre_link_args.get(&flavor) {
         cmd.args(args);
     }
+    if let Some(args) = sess.target.target.options.pre_link_args_crt.get(&flavor) {
+        if sess.crt_static() {
+            cmd.args(args);
+        }
+    }
     if let Some(ref args) = sess.opts.debugging_opts.pre_link_args {
         cmd.args(args);
     }
@@ -635,6 +640,18 @@ fn link_natively(sess: &Session,
         cmd.arg(root.join(obj));
     }
 
+    if crate_type == config::CrateTypeExecutable && sess.crt_static() {
+        for obj in &sess.target.target.options.pre_link_objects_exe_crt {
+            cmd.arg(root.join(obj));
+        }
+
+        for obj in &sess.target.target.options.pre_link_objects_exe_crt_sys {
+            if flavor == LinkerFlavor::Gcc {
+                cmd.arg(format!("-l:{}", obj));
+            }
+        }
+    }
+
     if sess.target.target.options.is_like_emscripten {
         cmd.arg("-s");
         cmd.arg(if sess.panic_strategy() == PanicStrategy::Abort {
@@ -656,6 +673,16 @@ fn link_natively(sess: &Session,
     for obj in &sess.target.target.options.post_link_objects {
         cmd.arg(root.join(obj));
     }
+    if sess.crt_static() {
+        for obj in &sess.target.target.options.post_link_objects_crt_sys {
+            if flavor == LinkerFlavor::Gcc {
+                cmd.arg(format!("-l:{}", obj));
+            }
+        }
+        for obj in &sess.target.target.options.post_link_objects_crt {
+            cmd.arg(root.join(obj));
+        }
+    }
     if let Some(args) = sess.target.target.options.post_link_args.get(&flavor) {
         cmd.args(args);
     }
index 2a473f1ecbcc5efcff393a10b751c22a0ae96998..bbb5f7eecc82c28223cd4e6edad47cca48769d17 100644 (file)
@@ -482,7 +482,7 @@ fn run_pass_manager(cgcx: &CodegenContext,
             llvm::CodeGenOptLevel::None => llvm::CodeGenOptLevel::Less,
             level => level,
         };
-        with_llvm_pmb(llmod, config, opt_level, &mut |b| {
+        with_llvm_pmb(llmod, config, opt_level, false, &mut |b| {
             if thin {
                 if !llvm::LLVMRustPassManagerBuilderPopulateThinLTOPassManager(b, pm) {
                     panic!("this version of LLVM does not support ThinLTO");
index 64876e82309f05182f6fba788b23b39b39047540..acfe7c33028274a1be426816e9dd3f19f2545693 100644 (file)
@@ -17,8 +17,8 @@
 use back::symbol_export::ExportedSymbols;
 use base;
 use consts;
-use rustc_incremental::{save_trans_partition, in_incr_comp_dir};
-use rustc::dep_graph::{DepGraph, WorkProductFileKind};
+use rustc_incremental::{copy_cgu_workproducts_to_incr_comp_cache_dir, in_incr_comp_dir};
+use rustc::dep_graph::{WorkProduct, WorkProductId, WorkProductFileKind};
 use rustc::middle::cstore::{LinkMeta, EncodedMetadata};
 use rustc::session::config::{self, OutputFilenames, OutputType, Passes, SomePasses,
                              AllPasses, Sanitizer, Lto};
@@ -547,7 +547,8 @@ unsafe fn optimize(cgcx: &CodegenContext,
             llvm::LLVMRustAddAnalysisPasses(tm, fpm, llmod);
             llvm::LLVMRustAddAnalysisPasses(tm, mpm, llmod);
             let opt_level = config.opt_level.unwrap_or(llvm::CodeGenOptLevel::None);
-            with_llvm_pmb(llmod, &config, opt_level, &mut |b| {
+            let prepare_for_thin_lto = cgcx.lto == Lto::Thin || cgcx.lto == Lto::ThinLocal;
+            with_llvm_pmb(llmod, &config, opt_level, prepare_for_thin_lto, &mut |b| {
                 llvm::LLVMPassManagerBuilderPopulateFunctionPassManager(b, fpm);
                 llvm::LLVMPassManagerBuilderPopulateModulePassManager(b, mpm);
             })
@@ -1021,11 +1022,14 @@ pub fn start_async_translation(tcx: TyCtxt,
     }
 }
 
-fn copy_module_artifacts_into_incr_comp_cache(sess: &Session,
-                                              dep_graph: &DepGraph,
-                                              compiled_modules: &CompiledModules) {
+fn copy_all_cgu_workproducts_to_incr_comp_cache_dir(
+    sess: &Session,
+    compiled_modules: &CompiledModules
+) -> FxHashMap<WorkProductId, WorkProduct> {
+    let mut work_products = FxHashMap::default();
+
     if sess.opts.incremental.is_none() {
-        return;
+        return work_products;
     }
 
     for module in compiled_modules.modules.iter() {
@@ -1041,8 +1045,13 @@ fn copy_module_artifacts_into_incr_comp_cache(sess: &Session,
             files.push((WorkProductFileKind::BytecodeCompressed, path.clone()));
         }
 
-        save_trans_partition(sess, dep_graph, &module.name, &files);
+        if let Some((id, product)) =
+                copy_cgu_workproducts_to_incr_comp_cache_dir(sess, &module.name, &files) {
+            work_products.insert(id, product);
+        }
     }
+
+    work_products
 }
 
 fn produce_final_output_artifacts(sess: &Session,
@@ -2042,6 +2051,7 @@ pub fn run_assembler(cgcx: &CodegenContext, handler: &Handler, assembly: &Path,
 pub unsafe fn with_llvm_pmb(llmod: ModuleRef,
                             config: &ModuleConfig,
                             opt_level: llvm::CodeGenOptLevel,
+                            prepare_for_thin_lto: bool,
                             f: &mut FnMut(llvm::PassManagerBuilderRef)) {
     use std::ptr;
 
@@ -2069,6 +2079,7 @@ pub unsafe fn with_llvm_pmb(llmod: ModuleRef,
         config.merge_functions,
         config.vectorize_slp,
         config.vectorize_loop,
+        prepare_for_thin_lto,
         pgo_gen_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
         pgo_use_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
     );
@@ -2236,7 +2247,10 @@ pub struct OngoingCrateTranslation {
 }
 
 impl OngoingCrateTranslation {
-    pub(crate) fn join(self, sess: &Session, dep_graph: &DepGraph) -> CrateTranslation {
+    pub(crate) fn join(
+        self,
+        sess: &Session
+    ) -> (CrateTranslation, FxHashMap<WorkProductId, WorkProduct>) {
         self.shared_emitter_main.check(sess, true);
         let compiled_modules = match self.future.join() {
             Ok(Ok(compiled_modules)) => compiled_modules,
@@ -2255,9 +2269,9 @@ pub(crate) fn join(self, sess: &Session, dep_graph: &DepGraph) -> CrateTranslati
             time_graph.dump(&format!("{}-timings", self.crate_name));
         }
 
-        copy_module_artifacts_into_incr_comp_cache(sess,
-                                                   dep_graph,
-                                                   &compiled_modules);
+        let work_products = copy_all_cgu_workproducts_to_incr_comp_cache_dir(sess,
+                                                                             &compiled_modules);
+
         produce_final_output_artifacts(sess,
                                        &compiled_modules,
                                        &self.output_filenames);
@@ -2281,7 +2295,7 @@ pub(crate) fn join(self, sess: &Session, dep_graph: &DepGraph) -> CrateTranslati
             metadata_module: compiled_modules.metadata_module,
         };
 
-        trans
+        (trans, work_products)
     }
 
     pub(crate) fn submit_pre_translated_module_to_llvm(&self,
index 33dc9b3b7ab90087caf3291f7c1ae6aabe53115d..0dd1adbff86e0daf7f616c646dcee11b3748c856 100644 (file)
@@ -199,7 +199,7 @@ pub fn unsized_info<'cx, 'tcx>(cx: &CodegenCx<'cx, 'tcx>,
     let (source, target) = cx.tcx.struct_lockstep_tails(source, target);
     match (&source.sty, &target.sty) {
         (&ty::TyArray(_, len), &ty::TySlice(_)) => {
-            C_usize(cx, len.val.unwrap_u64())
+            C_usize(cx, len.unwrap_usize(cx.tcx))
         }
         (&ty::TyDynamic(..), &ty::TyDynamic(..)) => {
             // For now, upcasts are limited to changes in marker
@@ -1372,7 +1372,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 }
 
 fn fetch_wasm_section(tcx: TyCtxt, id: DefId) -> (String, Vec<u8>) {
-    use rustc::mir::interpret::{GlobalId, Value, PrimVal};
+    use rustc::mir::interpret::GlobalId;
     use rustc::middle::const_val::ConstVal;
 
     info!("loading wasm section {:?}", id);
@@ -1392,22 +1392,11 @@ fn fetch_wasm_section(tcx: TyCtxt, id: DefId) -> (String, Vec<u8>) {
     let param_env = ty::ParamEnv::reveal_all();
     let val = tcx.const_eval(param_env.and(cid)).unwrap();
 
-    let val = match val.val {
+    let const_val = match val.val {
         ConstVal::Value(val) => val,
         ConstVal::Unevaluated(..) => bug!("should be evaluated"),
     };
-    let val = match val {
-        Value::ByRef(ptr, _align) => ptr.into_inner_primval(),
-        ref v => bug!("should be ByRef, was {:?}", v),
-    };
-    let mem = match val {
-        PrimVal::Ptr(mem) => mem,
-        ref v => bug!("should be Ptr, was {:?}", v),
-    };
-    assert_eq!(mem.offset, 0);
-    let alloc = tcx
-        .interpret_interner
-        .get_alloc(mem.alloc_id)
-        .expect("miri allocation never successfully created");
+
+    let alloc = tcx.const_value_to_allocation((const_val, val.ty));
     (section.to_string(), alloc.bytes.clone())
 }
index ae23b523cbfaebcb68fa9dc4e56e44a2a5d2a297..4e77c0df65ef4eeeb6569d2d67b0f237c1d4ca8d 100644 (file)
@@ -277,7 +277,7 @@ fn fixed_vec_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
 
     let upper_bound = match array_or_slice_type.sty {
         ty::TyArray(_, len) => {
-            len.val.unwrap_u64() as c_longlong
+            len.unwrap_usize(cx.tcx) as c_longlong
         }
         _ => -1
     };
index 565a9bedef0f51d724bf78e044bcb1e7c66891b0..05a74db3a6ca9842470d51991fc589dc5998c88a 100644 (file)
@@ -97,7 +97,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
         ty::TyArray(inner_type, len) => {
             output.push('[');
             push_debuginfo_type_name(cx, inner_type, true, output);
-            output.push_str(&format!("; {}", len.val.unwrap_u64()));
+            output.push_str(&format!("; {}", len.unwrap_usize(cx.tcx)));
             output.push(']');
         },
         ty::TySlice(inner_type) => {
index 7a152d6ded4c56ecc957f4d6ce7c40d5a1a31c31..30780b8c965637704a683b5e16552ecd4e8bc0d6 100644 (file)
@@ -212,16 +212,16 @@ fn join_trans_and_link(
         outputs: &OutputFilenames,
     ) -> Result<(), CompileIncomplete>{
         use rustc::util::common::time;
-        let trans = trans.downcast::<::back::write::OngoingCrateTranslation>()
+        let (trans, work_products) = trans.downcast::<::back::write::OngoingCrateTranslation>()
             .expect("Expected LlvmTransCrate's OngoingCrateTranslation, found Box<Any>")
-            .join(sess, dep_graph);
+            .join(sess);
         if sess.opts.debugging_opts.incremental_info {
             back::write::dump_incremental_data(&trans);
         }
 
         time(sess,
              "serialize work products",
-             move || rustc_incremental::save_work_products(sess, &dep_graph));
+             move || rustc_incremental::save_work_product_index(sess, &dep_graph, work_products));
 
         sess.compile_status()?;
 
index 6e07b8e73ef22c329ea9c8749ede3d649ae14667..a10b7c9c9f10f23a818d98dd2b8ead0e96fd3fb5 100644 (file)
@@ -14,7 +14,7 @@
 use rustc::hir::def_id::DefId;
 use rustc::mir;
 use rustc_data_structures::indexed_vec::Idx;
-use rustc::mir::interpret::{Allocation, GlobalId, MemoryPointer, PrimVal, Value as MiriValue};
+use rustc::mir::interpret::{GlobalId, MemoryPointer, PrimVal, Allocation, ConstValue};
 use rustc::ty::{self, Ty};
 use rustc::ty::layout::{self, HasDataLayout, LayoutOf, Scalar};
 use builder::Builder;
@@ -56,7 +56,7 @@ pub fn primval_to_llvm(cx: &CodegenCx,
                     consts::get_static(cx, def_id)
                 } else if let Some(alloc) = cx.tcx.interpret_interner
                                               .get_alloc(ptr.alloc_id) {
-                    let init = global_initializer(cx, alloc);
+                    let init = const_alloc_to_llvm(cx, alloc);
                     if alloc.runtime_mutability == Mutability::Mutable {
                         consts::addr_of_mut(cx, init, alloc.align, "byte_str")
                     } else {
@@ -81,7 +81,50 @@ pub fn primval_to_llvm(cx: &CodegenCx,
     }
 }
 
-pub fn global_initializer(cx: &CodegenCx, alloc: &Allocation) -> ValueRef {
+fn const_value_to_llvm<'tcx>(cx: &CodegenCx<'_, 'tcx>, val: ConstValue, ty: Ty<'tcx>) -> ValueRef {
+    let layout = cx.layout_of(ty);
+
+    if layout.is_zst() {
+        return C_undef(layout.immediate_llvm_type(cx));
+    }
+
+    match val {
+        ConstValue::ByVal(x) => {
+            let scalar = match layout.abi {
+                layout::Abi::Scalar(ref x) => x,
+                _ => bug!("const_value_to_llvm: invalid ByVal layout: {:#?}", layout)
+            };
+            primval_to_llvm(
+                cx,
+                x,
+                scalar,
+                layout.immediate_llvm_type(cx),
+            )
+        },
+        ConstValue::ByValPair(a, b) => {
+            let (a_scalar, b_scalar) = match layout.abi {
+                layout::Abi::ScalarPair(ref a, ref b) => (a, b),
+                _ => bug!("const_value_to_llvm: invalid ByValPair layout: {:#?}", layout)
+            };
+            let a_llval = primval_to_llvm(
+                cx,
+                a,
+                a_scalar,
+                layout.scalar_pair_element_llvm_type(cx, 0),
+            );
+            let b_llval = primval_to_llvm(
+                cx,
+                b,
+                b_scalar,
+                layout.scalar_pair_element_llvm_type(cx, 1),
+            );
+            C_struct(cx, &[a_llval, b_llval], false)
+        },
+        ConstValue::ByRef(alloc) => const_alloc_to_llvm(cx, alloc),
+    }
+}
+
+pub fn const_alloc_to_llvm(cx: &CodegenCx, alloc: &Allocation) -> ValueRef {
     let mut llvals = Vec::with_capacity(alloc.relocations.len() + 1);
     let layout = cx.data_layout();
     let pointer_size = layout.pointer_size.bytes() as usize;
@@ -96,7 +139,7 @@ pub fn global_initializer(cx: &CodegenCx, alloc: &Allocation) -> ValueRef {
         let ptr_offset = read_target_uint(
             layout.endian,
             &alloc.bytes[offset..(offset + pointer_size)],
-        ).expect("global_initializer: could not read relocation pointer") as u64;
+        ).expect("const_alloc_to_llvm: could not read relocation pointer") as u64;
         llvals.push(primval_to_llvm(
             cx,
             PrimVal::Ptr(MemoryPointer { alloc_id, offset: ptr_offset }),
@@ -128,25 +171,19 @@ pub fn trans_static_initializer<'a, 'tcx>(
     let param_env = ty::ParamEnv::reveal_all();
     let static_ = cx.tcx.const_eval(param_env.and(cid))?;
 
-    let ptr = match static_.val {
-        ConstVal::Value(MiriValue::ByRef(ptr, _)) => ptr,
+    let val = match static_.val {
+        ConstVal::Value(val) => val,
         _ => bug!("static const eval returned {:#?}", static_),
     };
-
-    let alloc = cx
-        .tcx
-        .interpret_interner
-        .get_alloc(ptr.primval.to_ptr().expect("static has integer pointer").alloc_id)
-        .expect("miri allocation never successfully created");
-    Ok(global_initializer(cx, alloc))
+    Ok(const_value_to_llvm(cx, val, static_.ty))
 }
 
 impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
-    fn const_to_miri_value(
+    fn const_to_const_value(
         &mut self,
         bx: &Builder<'a, 'tcx>,
         constant: &'tcx ty::Const<'tcx>,
-    ) -> Result<MiriValue, ConstEvalErr<'tcx>> {
+    ) -> Result<ConstValue<'tcx>, ConstEvalErr<'tcx>> {
         match constant.val {
             ConstVal::Unevaluated(def_id, ref substs) => {
                 let tcx = bx.tcx();
@@ -157,17 +194,17 @@ fn const_to_miri_value(
                     promoted: None,
                 };
                 let c = tcx.const_eval(param_env.and(cid))?;
-                self.const_to_miri_value(bx, c)
+                self.const_to_const_value(bx, c)
             },
-            ConstVal::Value(miri_val) => Ok(miri_val),
+            ConstVal::Value(val) => Ok(val),
         }
     }
 
-    pub fn mir_constant_to_miri_value(
+    pub fn mir_constant_to_const_value(
         &mut self,
         bx: &Builder<'a, 'tcx>,
         constant: &mir::Constant<'tcx>,
-    ) -> Result<MiriValue, ConstEvalErr<'tcx>> {
+    ) -> Result<ConstValue<'tcx>, ConstEvalErr<'tcx>> {
         match constant.literal {
             mir::Literal::Promoted { index } => {
                 let param_env = ty::ParamEnv::reveal_all();
@@ -180,7 +217,7 @@ pub fn mir_constant_to_miri_value(
             mir::Literal::Value { value } => {
                 Ok(self.monomorphize(&value))
             }
-        }.and_then(|c| self.const_to_miri_value(bx, c))
+        }.and_then(|c| self.const_to_const_value(bx, c))
     }
 
     /// process constant containing SIMD shuffle indices
@@ -189,11 +226,11 @@ pub fn simd_shuffle_indices(
         bx: &Builder<'a, 'tcx>,
         constant: &mir::Constant<'tcx>,
     ) -> (ValueRef, Ty<'tcx>) {
-        self.mir_constant_to_miri_value(bx, constant)
+        self.mir_constant_to_const_value(bx, constant)
             .and_then(|c| {
                 let field_ty = constant.ty.builtin_index().unwrap();
                 let fields = match constant.ty.sty {
-                    ty::TyArray(_, n) => n.val.unwrap_u64(),
+                    ty::TyArray(_, n) => n.unwrap_usize(bx.tcx()),
                     ref other => bug!("invalid simd shuffle type: {}", other),
                 };
                 let values: Result<Vec<ValueRef>, _> = (0..fields).map(|field| {
@@ -206,19 +243,18 @@ pub fn simd_shuffle_indices(
                         c,
                         constant.ty,
                     )?;
-                    match field.val {
-                        ConstVal::Value(MiriValue::ByVal(prim)) => {
-                            let layout = bx.cx.layout_of(field_ty);
-                            let scalar = match layout.abi {
-                                layout::Abi::Scalar(ref x) => x,
-                                _ => bug!("from_const: invalid ByVal layout: {:#?}", layout)
-                            };
-                            Ok(primval_to_llvm(
-                                bx.cx, prim, scalar,
-                                layout.immediate_llvm_type(bx.cx),
-                            ))
-                        },
-                        other => bug!("simd shuffle field {:?}, {}", other, constant.ty),
+                    if let Some(prim) = field.to_primval() {
+                        let layout = bx.cx.layout_of(field_ty);
+                        let scalar = match layout.abi {
+                            layout::Abi::Scalar(ref x) => x,
+                            _ => bug!("from_const: invalid ByVal layout: {:#?}", layout)
+                        };
+                        Ok(primval_to_llvm(
+                            bx.cx, prim, scalar,
+                            layout.immediate_llvm_type(bx.cx),
+                        ))
+                    } else {
+                        bug!("simd shuffle field {:?}", field)
                     }
                 }).collect();
                 let llval = C_struct(bx.cx, &values?, false);
index 656ab95a28cf3e1730c78092260dc9ec40e9fb90..432ac44e0a5660e2f33f90042b7912a065f4d3e0 100644 (file)
@@ -11,7 +11,7 @@
 use llvm::ValueRef;
 use rustc::middle::const_val::ConstEvalErr;
 use rustc::mir;
-use rustc::mir::interpret::Value as MiriValue;
+use rustc::mir::interpret::ConstValue;
 use rustc::ty;
 use rustc::ty::layout::{self, Align, LayoutOf, TyLayout};
 use rustc_data_structures::indexed_vec::Idx;
 use value::Value;
 use type_of::LayoutLlvmExt;
 use type_::Type;
+use consts;
 
 use std::fmt;
 use std::ptr;
 
 use super::{FunctionCx, LocalRef};
-use super::constant::{primval_to_llvm};
+use super::constant::{primval_to_llvm, const_alloc_to_llvm};
 use super::place::PlaceRef;
 
 /// The representation of a Rust value. The enum variant is in fact
@@ -94,7 +95,7 @@ pub fn new_zst(cx: &CodegenCx<'a, 'tcx>,
     }
 
     pub fn from_const(bx: &Builder<'a, 'tcx>,
-                      miri_val: MiriValue,
+                      val: ConstValue<'tcx>,
                       ty: ty::Ty<'tcx>)
                       -> Result<OperandRef<'tcx>, ConstEvalErr<'tcx>> {
         let layout = bx.cx.layout_of(ty);
@@ -103,8 +104,8 @@ pub fn from_const(bx: &Builder<'a, 'tcx>,
             return Ok(OperandRef::new_zst(bx.cx, layout));
         }
 
-        let val = match miri_val {
-            MiriValue::ByVal(x) => {
+        let val = match val {
+            ConstValue::ByVal(x) => {
                 let scalar = match layout.abi {
                     layout::Abi::Scalar(ref x) => x,
                     _ => bug!("from_const: invalid ByVal layout: {:#?}", layout)
@@ -117,7 +118,7 @@ pub fn from_const(bx: &Builder<'a, 'tcx>,
                 );
                 OperandValue::Immediate(llval)
             },
-            MiriValue::ByValPair(a, b) => {
+            ConstValue::ByValPair(a, b) => {
                 let (a_scalar, b_scalar) = match layout.abi {
                     layout::Abi::ScalarPair(ref a, ref b) => (a, b),
                     _ => bug!("from_const: invalid ByValPair layout: {:#?}", layout)
@@ -136,18 +137,11 @@ pub fn from_const(bx: &Builder<'a, 'tcx>,
                 );
                 OperandValue::Pair(a_llval, b_llval)
             },
-            MiriValue::ByRef(ptr, align) => {
-                let scalar = layout::Scalar {
-                    value: layout::Primitive::Pointer,
-                    valid_range: 0..=!0
-                };
-                let ptr = primval_to_llvm(
-                    bx.cx,
-                    ptr.into_inner_primval(),
-                    &scalar,
-                    layout.llvm_type(bx.cx).ptr_to(),
-                );
-                return Ok(PlaceRef::new_sized(ptr, layout, align).load(bx));
+            ConstValue::ByRef(alloc) => {
+                let init = const_alloc_to_llvm(bx.cx, alloc);
+                let llval = consts::addr_of(bx.cx, init, layout.align, "byte_str");
+                let llval = consts::bitcast(llval, layout.llvm_type(bx.cx).ptr_to());
+                return Ok(PlaceRef::new_sized(llval, layout, alloc.align).load(bx));
             },
         };
 
@@ -396,7 +390,7 @@ pub fn trans_operand(&mut self,
 
             mir::Operand::Constant(ref constant) => {
                 let ty = self.monomorphize(&constant.ty);
-                self.mir_constant_to_miri_value(bx, constant)
+                self.mir_constant_to_const_value(bx, constant)
                     .and_then(|c| OperandRef::from_const(bx, c, ty))
                     .unwrap_or_else(|err| {
                         match constant.literal {
index 0cd823391b9b66ed4dd6872afb2f56d6ce51f0bc..3b4477564502c4f11f17e8b6a26af70e5585c7f9 100644 (file)
@@ -516,7 +516,7 @@ fn evaluate_array_len(&mut self,
         if let mir::Place::Local(index) = *place {
             if let LocalRef::Operand(Some(op)) = self.locals[index] {
                 if let ty::TyArray(_, n) = op.layout.ty.sty {
-                    let n = n.val.unwrap_u64();
+                    let n = n.unwrap_usize(bx.cx.tcx);
                     return common::C_usize(bx.cx, n);
                 }
             }
index 93dbba6e873a9d4f807e906dfd8008c2f1335a93..d307ef30044e12f13d9faa92fc3059fe4265765f 100644 (file)
@@ -12,7 +12,6 @@
 //! representation.  The main routine here is `ast_ty_to_ty()`: each use
 //! is parameterized by an instance of `AstConv`.
 
-use rustc::middle::const_val::ConstVal;
 use rustc_data_structures::accumulate_vec::AccumulateVec;
 use hir;
 use hir::def::Def;
@@ -1087,10 +1086,7 @@ pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty) -> Ty<'tcx> {
             hir::TyArray(ref ty, length) => {
                 let length_def_id = tcx.hir.body_owner_def_id(length);
                 let substs = Substs::identity_for_item(tcx, length_def_id);
-                let length = tcx.mk_const(ty::Const {
-                    val: ConstVal::Unevaluated(length_def_id, substs),
-                    ty: tcx.types.usize
-                });
+                let length = ty::Const::unevaluated(tcx, length_def_id, substs, tcx.types.usize);
                 let array_ty = tcx.mk_ty(ty::TyArray(self.ast_ty_to_ty(&ty), length));
                 self.normalize_ty(ast_ty.span, array_ty)
             }
index c7585c827ce11eaf92b0f0cbf59cd5ec1b0ec7a3..2547952d1043cfc8805b3655a1d8b461c3c03ed0 100644 (file)
@@ -375,7 +375,7 @@ pub fn check_pat_walk(
                 let expected_ty = self.structurally_resolved_type(pat.span, expected);
                 let (inner_ty, slice_ty) = match expected_ty.sty {
                     ty::TyArray(inner_ty, size) => {
-                        let size = size.val.unwrap_u64();
+                        let size = size.unwrap_usize(tcx);
                         let min_len = before.len() as u64 + after.len() as u64;
                         if slice.is_none() {
                             if min_len != size {
index ef14fa9a12248eb5a49d189eda474601d617e778..7b859635f60df1f297a04df6c838db4b33106361 100644 (file)
@@ -4018,7 +4018,7 @@ fn check_expr_kind(&self,
             };
 
             if let Ok(count) = count {
-                let zero_or_one = count.val.to_raw_bits().map_or(false, |count| count <= 1);
+                let zero_or_one = count.assert_usize(tcx).map_or(false, |count| count <= 1);
                 if !zero_or_one {
                     // For [foo, ..n] where n > 1, `foo` must have
                     // Copy type:
index 9e8e00594e60afc9074322c7b080ac6c09294f7f..23081b87d2651e4f7ec1bfc1143d9b7d90f0aa7c 100644 (file)
@@ -12,8 +12,8 @@
 
 use super::{FnCtxt, Needs};
 use super::method::MethodCallee;
-use rustc::ty::{self, Ty, TypeFoldable, TypeVariants};
-use rustc::ty::TypeVariants::{TyStr, TyRef, TyAdt};
+use rustc::ty::{self, Ty, TypeFoldable};
+use rustc::ty::TypeVariants::{TyRef, TyAdt, TyStr, TyUint, TyNever, TyTuple, TyChar, TyArray};
 use rustc::ty::adjustment::{Adjustment, Adjust, AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
 use rustc::infer::type_variable::TypeVariableOrigin;
 use errors;
@@ -246,76 +246,151 @@ fn check_overloaded_binop(&self,
             Err(()) => {
                 // error types are considered "builtin"
                 if !lhs_ty.references_error() {
-                    if let IsAssign::Yes = is_assign {
-                        struct_span_err!(self.tcx.sess, expr.span, E0368,
-                                         "binary assignment operation `{}=` \
-                                          cannot be applied to type `{}`",
-                                         op.node.as_str(),
-                                         lhs_ty)
-                            .span_label(lhs_expr.span,
-                                        format!("cannot use `{}=` on type `{}`",
-                                        op.node.as_str(), lhs_ty))
-                            .emit();
-                    } else {
-                        let mut err = struct_span_err!(self.tcx.sess, expr.span, E0369,
-                            "binary operation `{}` cannot be applied to type `{}`",
-                            op.node.as_str(),
-                            lhs_ty);
-
-                        if let TypeVariants::TyRef(_, rty, _) = lhs_ty.sty {
-                            if {
-                                !self.infcx.type_moves_by_default(self.param_env,
-                                                                  rty,
-                                                                  lhs_expr.span) &&
-                                    self.lookup_op_method(rty,
-                                                          &[rhs_ty],
-                                                          Op::Binary(op, is_assign))
-                                        .is_ok()
-                            } {
-                                err.note(
-                                    &format!(
-                                        "this is a reference to a type that `{}` can be applied \
-                                        to; you need to dereference this variable once for this \
-                                        operation to work",
-                                    op.node.as_str()));
+                    let codemap = self.tcx.sess.codemap();
+                    match is_assign {
+                        IsAssign::Yes => {
+                            let mut err = struct_span_err!(self.tcx.sess, expr.span, E0368,
+                                                "binary assignment operation `{}=` \
+                                                cannot be applied to type `{}`",
+                                                op.node.as_str(),
+                                                lhs_ty);
+                            err.span_label(lhs_expr.span,
+                                    format!("cannot use `{}=` on type `{}`",
+                                    op.node.as_str(), lhs_ty));
+                            let mut suggested_deref = false;
+                            if let TyRef(_, mut rty, _) = lhs_ty.sty {
+                                if {
+                                    !self.infcx.type_moves_by_default(self.param_env,
+                                                                        rty,
+                                                                        lhs_expr.span) &&
+                                        self.lookup_op_method(rty,
+                                                              &[rhs_ty],
+                                                              Op::Binary(op, is_assign))
+                                            .is_ok()
+                                } {
+                                    if let Ok(lstring) = codemap.span_to_snippet(lhs_expr.span) {
+                                        while let TyRef(_, rty_inner, _) = rty.sty {
+                                            rty = rty_inner;
+                                        }
+                                        let msg = &format!(
+                                                "`{}=` can be used on '{}', you can \
+                                                dereference `{2}`: `*{2}`",
+                                                op.node.as_str(),
+                                                rty,
+                                                lstring
+                                        );
+                                        err.help(msg);
+                                        suggested_deref = true;
+                                    }
+                                }
                             }
+                            let missing_trait = match op.node {
+                                hir::BiAdd    => Some("std::ops::AddAssign"),
+                                hir::BiSub    => Some("std::ops::SubAssign"),
+                                hir::BiMul    => Some("std::ops::MulAssign"),
+                                hir::BiDiv    => Some("std::ops::DivAssign"),
+                                hir::BiRem    => Some("std::ops::RemAssign"),
+                                hir::BiBitAnd => Some("std::ops::BitAndAssign"),
+                                hir::BiBitXor => Some("std::ops::BitXorAssign"),
+                                hir::BiBitOr  => Some("std::ops::BitOrAssign"),
+                                hir::BiShl    => Some("std::ops::ShlAssign"),
+                                hir::BiShr    => Some("std::ops::ShrAssign"),
+                                _             => None
+                            };
+                            if let Some(missing_trait) = missing_trait {
+                                if op.node == hir::BiAdd &&
+                                    self.check_str_addition(expr, lhs_expr, rhs_expr, lhs_ty,
+                                                            rhs_ty, &mut err) {
+                                    // This has nothing here because it means we did string
+                                    // concatenation (e.g. "Hello " + "World!"). This means
+                                    // we don't want the note in the else clause to be emitted
+                                } else if let ty::TyParam(_) = lhs_ty.sty {
+                                    // FIXME: point to span of param
+                                    err.note(&format!(
+                                        "`{}` might need a bound for `{}`",
+                                        lhs_ty, missing_trait
+                                    ));
+                                } else if !suggested_deref {
+                                    err.note(&format!(
+                                        "an implementation of `{}` might \
+                                         be missing for `{}`",
+                                        missing_trait, lhs_ty
+                                    ));
+                                }
+                            }
+                            err.emit();
                         }
-
-                        let missing_trait = match op.node {
-                            hir::BiAdd    => Some("std::ops::Add"),
-                            hir::BiSub    => Some("std::ops::Sub"),
-                            hir::BiMul    => Some("std::ops::Mul"),
-                            hir::BiDiv    => Some("std::ops::Div"),
-                            hir::BiRem    => Some("std::ops::Rem"),
-                            hir::BiBitAnd => Some("std::ops::BitAnd"),
-                            hir::BiBitOr  => Some("std::ops::BitOr"),
-                            hir::BiShl    => Some("std::ops::Shl"),
-                            hir::BiShr    => Some("std::ops::Shr"),
-                            hir::BiEq | hir::BiNe => Some("std::cmp::PartialEq"),
-                            hir::BiLt | hir::BiLe | hir::BiGt | hir::BiGe =>
-                                Some("std::cmp::PartialOrd"),
-                            _             => None
-                        };
-
-                        if let Some(missing_trait) = missing_trait {
-                            if missing_trait == "std::ops::Add" &&
-                                self.check_str_addition(expr, lhs_expr, rhs_expr, lhs_ty,
-                                                        rhs_ty, &mut err) {
-                                // This has nothing here because it means we did string
-                                // concatenation (e.g. "Hello " + "World!"). This means
-                                // we don't want the note in the else clause to be emitted
-                            } else if let ty::TyParam(_) = lhs_ty.sty {
-                                // FIXME: point to span of param
-                                err.note(
-                                    &format!("`{}` might need a bound for `{}`",
-                                             lhs_ty, missing_trait));
-                            } else {
-                                err.note(
-                                    &format!("an implementation of `{}` might be missing for `{}`",
-                                             missing_trait, lhs_ty));
+                        IsAssign::No => {
+                            let mut err = struct_span_err!(self.tcx.sess, expr.span, E0369,
+                                            "binary operation `{}` cannot be applied to type `{}`",
+                                            op.node.as_str(),
+                                            lhs_ty);
+                            let mut suggested_deref = false;
+                            if let TyRef(_, mut rty, _) = lhs_ty.sty {
+                                if {
+                                    !self.infcx.type_moves_by_default(self.param_env,
+                                                                        rty,
+                                                                        lhs_expr.span) &&
+                                        self.lookup_op_method(rty,
+                                                              &[rhs_ty],
+                                                              Op::Binary(op, is_assign))
+                                            .is_ok()
+                                } {
+                                    if let Ok(lstring) = codemap.span_to_snippet(lhs_expr.span) {
+                                        while let TyRef(_, rty_inner, _) = rty.sty {
+                                            rty = rty_inner;
+                                        }
+                                        let msg = &format!(
+                                                "`{}` can be used on '{}', you can \
+                                                dereference `{2}`: `*{2}`",
+                                                op.node.as_str(),
+                                                rty,
+                                                lstring
+                                        );
+                                        err.help(msg);
+                                        suggested_deref = true;
+                                    }
+                                }
                             }
+                            let missing_trait = match op.node {
+                                hir::BiAdd    => Some("std::ops::Add"),
+                                hir::BiSub    => Some("std::ops::Sub"),
+                                hir::BiMul    => Some("std::ops::Mul"),
+                                hir::BiDiv    => Some("std::ops::Div"),
+                                hir::BiRem    => Some("std::ops::Rem"),
+                                hir::BiBitAnd => Some("std::ops::BitAnd"),
+                                hir::BiBitXor => Some("std::ops::BitXor"),
+                                hir::BiBitOr  => Some("std::ops::BitOr"),
+                                hir::BiShl    => Some("std::ops::Shl"),
+                                hir::BiShr    => Some("std::ops::Shr"),
+                                hir::BiEq | hir::BiNe => Some("std::cmp::PartialEq"),
+                                hir::BiLt | hir::BiLe | hir::BiGt | hir::BiGe =>
+                                    Some("std::cmp::PartialOrd"),
+                                _             => None
+                            };
+                            if let Some(missing_trait) = missing_trait {
+                                if op.node == hir::BiAdd &&
+                                    self.check_str_addition(expr, lhs_expr, rhs_expr, lhs_ty,
+                                                            rhs_ty, &mut err) {
+                                    // This has nothing here because it means we did string
+                                    // concatenation (e.g. "Hello " + "World!"). This means
+                                    // we don't want the note in the else clause to be emitted
+                                } else if let ty::TyParam(_) = lhs_ty.sty {
+                                    // FIXME: point to span of param
+                                    err.note(&format!(
+                                        "`{}` might need a bound for `{}`",
+                                        lhs_ty, missing_trait
+                                    ));
+                                } else if !suggested_deref {
+                                    err.note(&format!(
+                                        "an implementation of `{}` might \
+                                         be missing for `{}`",
+                                        missing_trait, lhs_ty
+                                    ));
+                                }
+                            }
+                            err.emit();
                         }
-                        err.emit();
                     }
                 }
                 self.tcx.types.err
@@ -393,9 +468,29 @@ pub fn check_user_unop(&self,
             Err(()) => {
                 let actual = self.resolve_type_vars_if_possible(&operand_ty);
                 if !actual.references_error() {
-                    struct_span_err!(self.tcx.sess, ex.span, E0600,
+                    let mut err = struct_span_err!(self.tcx.sess, ex.span, E0600,
                                      "cannot apply unary operator `{}` to type `{}`",
-                                     op.as_str(), actual).emit();
+                                     op.as_str(), actual);
+                    err.span_label(ex.span, format!("cannot apply unary \
+                                                    operator `{}`", op.as_str()));
+                    match actual.sty {
+                        TyUint(_) if op == hir::UnNeg => {
+                            err.note(&format!("unsigned values cannot be negated"));
+                        },
+                        TyStr | TyNever | TyChar | TyTuple(_) | TyArray(_,_) => {},
+                        TyRef(_, ref lty, _) if lty.sty == TyStr => {},
+                        _ => {
+                            let missing_trait = match op {
+                                hir::UnNeg => "std::ops::Neg",
+                                hir::UnNot => "std::ops::Not",
+                                hir::UnDeref => "std::ops::UnDerf"
+                            };
+                            err.note(&format!("an implementation of `{}` might \
+                                                be missing for `{}`",
+                                             missing_trait, operand_ty));
+                        }
+                    }
+                    err.emit();
                 }
                 self.tcx.types.err
             }
index 3424a31e09df09245058b1315be2b9c54450c6c2..2f08a54e10f08839b6cffbb4d58899f9d42af86f 100644 (file)
@@ -111,9 +111,9 @@ fn visit_implementation_of_copy<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     debug!("visit_implementation_of_copy: self_type={:?} (free)",
            self_type);
 
-    match param_env.can_type_implement_copy(tcx, self_type, span) {
+    match param_env.can_type_implement_copy(tcx, self_type) {
         Ok(()) => {}
-        Err(CopyImplementationError::InfrigingField(field)) => {
+        Err(CopyImplementationError::InfrigingFields(fields)) => {
             let item = tcx.hir.expect_item(impl_node_id);
             let span = if let ItemImpl(.., Some(ref tr), _, _) = item.node {
                 tr.path.span
@@ -121,14 +121,14 @@ fn visit_implementation_of_copy<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 span
             };
 
-            struct_span_err!(tcx.sess,
-                             span,
-                             E0204,
-                             "the trait `Copy` may not be implemented for this type")
-                .span_label(
-                    tcx.def_span(field.did),
-                    "this field does not implement `Copy`")
-                .emit()
+            let mut err = struct_span_err!(tcx.sess,
+                                          span,
+                                          E0204,
+                                          "the trait `Copy` may not be implemented for this type");
+            for span in fields.iter().map(|f| tcx.def_span(f.did)) {
+                    err.span_label(span, "this field does not implement `Copy`");
+            }
+            err.emit()
         }
         Err(CopyImplementationError::NotAnAdt) => {
             let item = tcx.hir.expect_item(impl_node_id);
index 007938e86ed9d9f37addd9624cd71b897b7c8c1a..7d3ba792829382c75d6f613225f906aa1882dc9a 100644 (file)
@@ -697,7 +697,7 @@ fn from_iter<T>(iter: T) -> Self
 pub struct Attributes {
     pub doc_strings: Vec<DocFragment>,
     pub other_attrs: Vec<ast::Attribute>,
-    pub cfg: Option<Rc<Cfg>>,
+    pub cfg: Option<Arc<Cfg>>,
     pub span: Option<syntax_pos::Span>,
     /// map from Rust paths to resolved defs and potential URL fragments
     pub links: Vec<(String, Option<DefId>, Option<String>)>,
@@ -848,7 +848,7 @@ pub fn from_ast(diagnostic: &::errors::Handler,
         Attributes {
             doc_strings,
             other_attrs,
-            cfg: if cfg == Cfg::True { None } else { Some(Rc::new(cfg)) },
+            cfg: if cfg == Cfg::True { None } else { Some(Arc::new(cfg)) },
             span: sp,
             links: vec![],
         }
@@ -2644,10 +2644,7 @@ fn clean(&self, cx: &DocContext) -> Type {
                     promoted: None
                 };
                 let n = cx.tcx.const_eval(param_env.and(cid)).unwrap_or_else(|_| {
-                    cx.tcx.mk_const(ty::Const {
-                        val: ConstVal::Unevaluated(def_id, substs),
-                        ty: cx.tcx.types.usize
-                    })
+                    ty::Const::unevaluated(cx.tcx, def_id, substs, cx.tcx.types.usize)
                 });
                 let n = print_const(cx, n);
                 Array(box ty.clean(cx), n)
@@ -3828,9 +3825,9 @@ fn print_const(cx: &DocContext, n: &ty::Const) -> String {
                 inline::print_inlined_const(cx, def_id)
             }
         },
-        ConstVal::Value(val) => {
+        ConstVal::Value(..) => {
             let mut s = String::new();
-            ::rustc::mir::print_miri_value(val, n.ty, &mut s).unwrap();
+            ::rustc::mir::fmt_const_val(&mut s, n).unwrap();
             // array lengths are obviously usize
             if s.ends_with("usize") {
                 let n = s.len() - "usize".len();
index 61fb0b40c231560b8005af5f1997b706a41f190e..6222edd5450f05cc1facd4fe4271816daab71d5a 100644 (file)
@@ -161,161 +161,162 @@ pub fn run_core(search_paths: SearchPaths,
         edition,
         ..config::basic_options().clone()
     };
-
-    let codemap = Lrc::new(codemap::CodeMap::new(sessopts.file_path_mapping()));
-    let emitter: Box<dyn Emitter + sync::Send> = match error_format {
-        ErrorOutputType::HumanReadable(color_config) => Box::new(
-            EmitterWriter::stderr(
-                color_config,
-                Some(codemap.clone()),
-                false,
-                sessopts.debugging_opts.teach,
-            ).ui_testing(sessopts.debugging_opts.ui_testing)
-        ),
-        ErrorOutputType::Json(pretty) => Box::new(
-            JsonEmitter::stderr(
-                None,
-                codemap.clone(),
-                pretty,
-                sessopts.debugging_opts.suggestion_applicability,
-            ).ui_testing(sessopts.debugging_opts.ui_testing)
-        ),
-        ErrorOutputType::Short(color_config) => Box::new(
-            EmitterWriter::stderr(color_config, Some(codemap.clone()), true, false)
-        ),
-    };
-
-    let diagnostic_handler = errors::Handler::with_emitter_and_flags(
-        emitter,
-        errors::HandlerFlags {
-            can_emit_warnings: true,
-            treat_err_as_bug: false,
-            external_macro_backtrace: false,
-            ..Default::default()
-        },
-    );
-
-    let mut sess = session::build_session_(
-        sessopts, cpath, diagnostic_handler, codemap,
-    );
-    let trans = rustc_driver::get_trans(&sess);
-    let cstore = Rc::new(CStore::new(trans.metadata_loader()));
-    rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
-
-    let mut cfg = config::build_configuration(&sess, config::parse_cfgspecs(cfgs));
-    target_features::add_configuration(&mut cfg, &sess, &*trans);
-    sess.parse_sess.config = cfg;
-
-    let control = &driver::CompileController::basic();
-
-    let krate = panictry!(driver::phase_1_parse_input(control, &sess, &input));
-
-    let name = ::rustc_trans_utils::link::find_crate_name(Some(&sess), &krate.attrs, &input);
-
-    let mut crate_loader = CrateLoader::new(&sess, &cstore, &name);
-
-    let resolver_arenas = resolve::Resolver::arenas();
-    let result = driver::phase_2_configure_and_expand_inner(&sess,
-                                                      &cstore,
-                                                      krate,
-                                                      None,
-                                                      &name,
-                                                      None,
-                                                      resolve::MakeGlobMap::No,
-                                                      &resolver_arenas,
-                                                      &mut crate_loader,
-                                                      |_| Ok(()));
-    let driver::InnerExpansionResult {
-        mut hir_forest,
-        resolver,
-        ..
-    } = abort_on_err(result, &sess);
-
-    // We need to hold on to the complete resolver, so we clone everything
-    // for the analysis passes to use. Suboptimal, but necessary in the
-    // current architecture.
-    let defs = resolver.definitions.clone();
-    let resolutions = ty::Resolutions {
-        freevars: resolver.freevars.clone(),
-        export_map: resolver.export_map.clone(),
-        trait_map: resolver.trait_map.clone(),
-        maybe_unused_trait_imports: resolver.maybe_unused_trait_imports.clone(),
-        maybe_unused_extern_crates: resolver.maybe_unused_extern_crates.clone(),
-    };
-    let analysis = ty::CrateAnalysis {
-        access_levels: Lrc::new(AccessLevels::default()),
-        name: name.to_string(),
-        glob_map: if resolver.make_glob_map { Some(resolver.glob_map.clone()) } else { None },
-    };
-
-    let arenas = AllArenas::new();
-    let hir_map = hir_map::map_crate(&sess, &*cstore, &mut hir_forest, &defs);
-    let output_filenames = driver::build_output_filenames(&input,
-                                                          &None,
-                                                          &None,
-                                                          &[],
-                                                          &sess);
-
-    let resolver = RefCell::new(resolver);
-
-    abort_on_err(driver::phase_3_run_analysis_passes(&*trans,
-                                                     control,
-                                                     &sess,
-                                                     &*cstore,
-                                                     hir_map,
-                                                     analysis,
-                                                     resolutions,
-                                                     &arenas,
-                                                     &name,
-                                                     &output_filenames,
-                                                     |tcx, analysis, _, result| {
-        if let Err(_) = result {
-            sess.fatal("Compilation failed, aborting rustdoc");
-        }
-
-        let ty::CrateAnalysis { access_levels, .. } = analysis;
-
-        // Convert from a NodeId set to a DefId set since we don't always have easy access
-        // to the map from defid -> nodeid
-        let access_levels = AccessLevels {
-            map: access_levels.map.iter()
-                                  .map(|(&k, &v)| (tcx.hir.local_def_id(k), v))
-                                  .collect()
+    driver::spawn_thread_pool(sessopts, move |sessopts| {
+        let codemap = Lrc::new(codemap::CodeMap::new(sessopts.file_path_mapping()));
+        let emitter: Box<dyn Emitter + sync::Send> = match error_format {
+            ErrorOutputType::HumanReadable(color_config) => Box::new(
+                EmitterWriter::stderr(
+                    color_config,
+                    Some(codemap.clone()),
+                    false,
+                    sessopts.debugging_opts.teach,
+                ).ui_testing(sessopts.debugging_opts.ui_testing)
+            ),
+            ErrorOutputType::Json(pretty) => Box::new(
+                JsonEmitter::stderr(
+                    None,
+                    codemap.clone(),
+                    pretty,
+                    sessopts.debugging_opts.suggestion_applicability,
+                ).ui_testing(sessopts.debugging_opts.ui_testing)
+            ),
+            ErrorOutputType::Short(color_config) => Box::new(
+                EmitterWriter::stderr(color_config, Some(codemap.clone()), true, false)
+            ),
         };
 
-        let send_trait = if crate_name == Some("core".to_string()) {
-            clean::get_trait_def_id(&tcx, &["marker", "Send"], true)
-        } else {
-            clean::get_trait_def_id(&tcx, &["core", "marker", "Send"], false)
+        let diagnostic_handler = errors::Handler::with_emitter_and_flags(
+            emitter,
+            errors::HandlerFlags {
+                can_emit_warnings: true,
+                treat_err_as_bug: false,
+                external_macro_backtrace: false,
+                ..Default::default()
+            },
+        );
+
+        let mut sess = session::build_session_(
+            sessopts, cpath, diagnostic_handler, codemap,
+        );
+        let trans = rustc_driver::get_trans(&sess);
+        let cstore = Rc::new(CStore::new(trans.metadata_loader()));
+        rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
+
+        let mut cfg = config::build_configuration(&sess, config::parse_cfgspecs(cfgs));
+        target_features::add_configuration(&mut cfg, &sess, &*trans);
+        sess.parse_sess.config = cfg;
+
+        let control = &driver::CompileController::basic();
+
+        let krate = panictry!(driver::phase_1_parse_input(control, &sess, &input));
+
+        let name = ::rustc_trans_utils::link::find_crate_name(Some(&sess), &krate.attrs, &input);
+
+        let mut crate_loader = CrateLoader::new(&sess, &cstore, &name);
+
+        let resolver_arenas = resolve::Resolver::arenas();
+        let result = driver::phase_2_configure_and_expand_inner(&sess,
+                                                        &cstore,
+                                                        krate,
+                                                        None,
+                                                        &name,
+                                                        None,
+                                                        resolve::MakeGlobMap::No,
+                                                        &resolver_arenas,
+                                                        &mut crate_loader,
+                                                        |_| Ok(()));
+        let driver::InnerExpansionResult {
+            mut hir_forest,
+            resolver,
+            ..
+        } = abort_on_err(result, &sess);
+
+        // We need to hold on to the complete resolver, so we clone everything
+        // for the analysis passes to use. Suboptimal, but necessary in the
+        // current architecture.
+        let defs = resolver.definitions.clone();
+        let resolutions = ty::Resolutions {
+            freevars: resolver.freevars.clone(),
+            export_map: resolver.export_map.clone(),
+            trait_map: resolver.trait_map.clone(),
+            maybe_unused_trait_imports: resolver.maybe_unused_trait_imports.clone(),
+            maybe_unused_extern_crates: resolver.maybe_unused_extern_crates.clone(),
         };
-
-        let ctxt = DocContext {
-            tcx,
-            resolver: &resolver,
-            crate_name,
-            cstore: cstore.clone(),
-            populated_all_crate_impls: Cell::new(false),
-            access_levels: RefCell::new(access_levels),
-            external_traits: Default::default(),
-            active_extern_traits: Default::default(),
-            renderinfo: Default::default(),
-            ty_substs: Default::default(),
-            lt_substs: Default::default(),
-            impl_trait_bounds: Default::default(),
-            mod_ids: Default::default(),
-            send_trait: send_trait,
-            fake_def_ids: RefCell::new(FxHashMap()),
-            all_fake_def_ids: RefCell::new(FxHashSet()),
-            generated_synthetics: RefCell::new(FxHashSet()),
-        };
-        debug!("crate: {:?}", tcx.hir.krate());
-
-        let krate = {
-            let mut v = RustdocVisitor::new(&*cstore, &ctxt);
-            v.visit(tcx.hir.krate());
-            v.clean(&ctxt)
+        let analysis = ty::CrateAnalysis {
+            access_levels: Lrc::new(AccessLevels::default()),
+            name: name.to_string(),
+            glob_map: if resolver.make_glob_map { Some(resolver.glob_map.clone()) } else { None },
         };
 
-        (krate, ctxt.renderinfo.into_inner())
-    }), &sess)
+        let arenas = AllArenas::new();
+        let hir_map = hir_map::map_crate(&sess, &*cstore, &mut hir_forest, &defs);
+        let output_filenames = driver::build_output_filenames(&input,
+                                                            &None,
+                                                            &None,
+                                                            &[],
+                                                            &sess);
+
+        let resolver = RefCell::new(resolver);
+
+        abort_on_err(driver::phase_3_run_analysis_passes(&*trans,
+                                                        control,
+                                                        &sess,
+                                                        &*cstore,
+                                                        hir_map,
+                                                        analysis,
+                                                        resolutions,
+                                                        &arenas,
+                                                        &name,
+                                                        &output_filenames,
+                                                        |tcx, analysis, _, result| {
+            if let Err(_) = result {
+                sess.fatal("Compilation failed, aborting rustdoc");
+            }
+
+            let ty::CrateAnalysis { access_levels, .. } = analysis;
+
+            // Convert from a NodeId set to a DefId set since we don't always have easy access
+            // to the map from defid -> nodeid
+            let access_levels = AccessLevels {
+                map: access_levels.map.iter()
+                                    .map(|(&k, &v)| (tcx.hir.local_def_id(k), v))
+                                    .collect()
+            };
+
+            let send_trait = if crate_name == Some("core".to_string()) {
+                clean::get_trait_def_id(&tcx, &["marker", "Send"], true)
+            } else {
+                clean::get_trait_def_id(&tcx, &["core", "marker", "Send"], false)
+            };
+
+            let ctxt = DocContext {
+                tcx,
+                resolver: &resolver,
+                crate_name,
+                cstore: cstore.clone(),
+                populated_all_crate_impls: Cell::new(false),
+                access_levels: RefCell::new(access_levels),
+                external_traits: Default::default(),
+                active_extern_traits: Default::default(),
+                renderinfo: Default::default(),
+                ty_substs: Default::default(),
+                lt_substs: Default::default(),
+                impl_trait_bounds: Default::default(),
+                mod_ids: Default::default(),
+                send_trait: send_trait,
+                fake_def_ids: RefCell::new(FxHashMap()),
+                all_fake_def_ids: RefCell::new(FxHashSet()),
+                generated_synthetics: RefCell::new(FxHashSet()),
+            };
+            debug!("crate: {:?}", tcx.hir.krate());
+
+            let krate = {
+                let mut v = RustdocVisitor::new(&*cstore, &ctxt);
+                v.visit(tcx.hir.krate());
+                v.clean(&ctxt)
+            };
+
+            (krate, ctxt.renderinfo.into_inner())
+        }), &sess)
+    })
 }
index 21de2db1dfe74fd7bf1930e06b38b3e20589b31b..fe9fc3ddd680ee5626cc42d67ae4b53daaf18c35 100644 (file)
@@ -2579,7 +2579,7 @@ fn item_function(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
 }
 
 fn render_implementor(cx: &Context, implementor: &Impl, w: &mut fmt::Formatter,
-                      implementor_dups: &FxHashMap<&str, (DefId, bool)>) -> Result<(), fmt::Error> {
+                      implementor_dups: &FxHashMap<&str, (DefId, bool)>) -> fmt::Result {
     write!(w, "<li><table class='table-display'><tbody><tr><td><code>")?;
     // If there's already another implementor that has the same abbridged name, use the
     // full path, for example in `std::iter::ExactSizeIterator`
@@ -2612,7 +2612,7 @@ fn render_implementor(cx: &Context, implementor: &Impl, w: &mut fmt::Formatter,
 
 fn render_impls(cx: &Context, w: &mut fmt::Formatter,
                 traits: &[&&Impl],
-                containing_item: &clean::Item) -> Result<(), fmt::Error> {
+                containing_item: &clean::Item) -> fmt::Result {
     for i in traits {
         let did = i.trait_did().unwrap();
         let assoc_link = AssocItemLink::GotoSource(did, &i.inner_impl().provided_trait_methods);
index 059d41698953d2a4fcb85e36b1e45fd7e264ffa8..f2da09e16036ea05f9b56ca87c2645de6fd95bbe 100644 (file)
@@ -26,6 +26,8 @@
 #![feature(vec_remove_item)]
 #![feature(entry_and_modify)]
 
+#![recursion_limit="256"]
+
 extern crate arena;
 extern crate getopts;
 extern crate env_logger;
index 9e65fff5e2ac6f3f65c04f9a3af106a9e708c65a..fc8abafd4d89b549cb71e4b139f1a8532abec4d0 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::rc::Rc;
+use std::sync::Arc;
 
 use clean::{Crate, Item};
 use clean::cfg::Cfg;
@@ -20,7 +20,7 @@ pub fn propagate_doc_cfg(cr: Crate) -> PluginResult {
 }
 
 struct CfgPropagator {
-    parent_cfg: Option<Rc<Cfg>>,
+    parent_cfg: Option<Arc<Cfg>>,
 }
 
 impl DocFolder for CfgPropagator {
@@ -31,8 +31,8 @@ fn fold_item(&mut self, mut item: Item) -> Option<Item> {
             (None, None) => None,
             (Some(rc), None) | (None, Some(rc)) => Some(rc),
             (Some(mut a), Some(b)) => {
-                let b = Rc::try_unwrap(b).unwrap_or_else(|rc| Cfg::clone(&rc));
-                *Rc::make_mut(&mut a) &= b;
+                let b = Arc::try_unwrap(b).unwrap_or_else(|rc| Cfg::clone(&rc));
+                *Arc::make_mut(&mut a) &= b;
                 Some(a)
             }
         };
index c4eaa48e49db62e47c6bb0bb3c4fc64b32f2871d..7be7ce313fcffcbc738bde5667ed6c7a1b31efdf 100644 (file)
@@ -85,77 +85,80 @@ pub fn run(input_path: &Path,
         edition,
         ..config::basic_options().clone()
     };
-
-    let codemap = Lrc::new(CodeMap::new(sessopts.file_path_mapping()));
-    let handler =
-        errors::Handler::with_tty_emitter(ColorConfig::Auto,
-                                          true, false,
-                                          Some(codemap.clone()));
-
-    let mut sess = session::build_session_(
-        sessopts, Some(input_path.to_owned()), handler, codemap.clone(),
-    );
-    let trans = rustc_driver::get_trans(&sess);
-    let cstore = CStore::new(trans.metadata_loader());
-    rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
-
-    let mut cfg = config::build_configuration(&sess, config::parse_cfgspecs(cfgs.clone()));
-    target_features::add_configuration(&mut cfg, &sess, &*trans);
-    sess.parse_sess.config = cfg;
-
-    let krate = panictry!(driver::phase_1_parse_input(&driver::CompileController::basic(),
-                                                      &sess,
-                                                      &input));
-    let driver::ExpansionResult { defs, mut hir_forest, .. } = {
-        phase_2_configure_and_expand(
-            &sess,
-            &cstore,
-            krate,
-            None,
-            "rustdoc-test",
-            None,
-            MakeGlobMap::No,
-            |_| Ok(()),
-        ).expect("phase_2_configure_and_expand aborted in rustdoc!")
-    };
-
-    let crate_name = crate_name.unwrap_or_else(|| {
-        ::rustc_trans_utils::link::find_crate_name(None, &hir_forest.krate().attrs, &input)
-    });
-    let mut opts = scrape_test_config(hir_forest.krate());
-    opts.display_warnings |= display_warnings;
-    let mut collector = Collector::new(crate_name,
-                                       cfgs,
-                                       libs,
-                                       cg,
-                                       externs,
-                                       false,
-                                       opts,
-                                       maybe_sysroot,
-                                       Some(codemap),
-                                       None,
-                                       linker,
-                                       edition);
-
-    {
-        let map = hir::map::map_crate(&sess, &cstore, &mut hir_forest, &defs);
-        let krate = map.krate();
-        let mut hir_collector = HirCollector {
-            sess: &sess,
-            collector: &mut collector,
-            map: &map
+    driver::spawn_thread_pool(sessopts, |sessopts| {
+        let codemap = Lrc::new(CodeMap::new(sessopts.file_path_mapping()));
+        let handler =
+            errors::Handler::with_tty_emitter(ColorConfig::Auto,
+                                            true, false,
+                                            Some(codemap.clone()));
+
+        let mut sess = session::build_session_(
+            sessopts, Some(input_path.to_owned()), handler, codemap.clone(),
+        );
+        let trans = rustc_driver::get_trans(&sess);
+        let cstore = CStore::new(trans.metadata_loader());
+        rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
+
+        let mut cfg = config::build_configuration(&sess, config::parse_cfgspecs(cfgs.clone()));
+        target_features::add_configuration(&mut cfg, &sess, &*trans);
+        sess.parse_sess.config = cfg;
+
+        let krate = panictry!(driver::phase_1_parse_input(&driver::CompileController::basic(),
+                                                        &sess,
+                                                        &input));
+        let driver::ExpansionResult { defs, mut hir_forest, .. } = {
+            phase_2_configure_and_expand(
+                &sess,
+                &cstore,
+                krate,
+                None,
+                "rustdoc-test",
+                None,
+                MakeGlobMap::No,
+                |_| Ok(()),
+            ).expect("phase_2_configure_and_expand aborted in rustdoc!")
         };
-        hir_collector.visit_testable("".to_string(), &krate.attrs, |this| {
-            intravisit::walk_crate(this, krate);
+
+        let crate_name = crate_name.unwrap_or_else(|| {
+            ::rustc_trans_utils::link::find_crate_name(None, &hir_forest.krate().attrs, &input)
         });
-    }
+        let mut opts = scrape_test_config(hir_forest.krate());
+        opts.display_warnings |= display_warnings;
+        let mut collector = Collector::new(
+            crate_name,
+            cfgs,
+            libs,
+            cg,
+            externs,
+            false,
+            opts,
+            maybe_sysroot,
+            Some(codemap),
+             None,
+            linker,
+            edition
+        );
+
+        {
+            let map = hir::map::map_crate(&sess, &cstore, &mut hir_forest, &defs);
+            let krate = map.krate();
+            let mut hir_collector = HirCollector {
+                sess: &sess,
+                collector: &mut collector,
+                map: &map
+            };
+            hir_collector.visit_testable("".to_string(), &krate.attrs, |this| {
+                intravisit::walk_crate(this, krate);
+            });
+        }
 
-    test_args.insert(0, "rustdoctest".to_string());
+        test_args.insert(0, "rustdoctest".to_string());
 
-    testing::test_main(&test_args,
-                       collector.tests.into_iter().collect(),
-                       testing::Options::new().display_output(display_warnings));
-    0
+        testing::test_main(&test_args,
+                        collector.tests.into_iter().collect(),
+                        testing::Options::new().display_output(display_warnings));
+        0
+    })
 }
 
 // Look for #![doc(test(no_crate_inject))], used by crates in the std facade
@@ -229,102 +232,106 @@ fn run_test(test: &str, cratename: &str, filename: &FileName, line: usize,
         ..config::basic_options().clone()
     };
 
-    // Shuffle around a few input and output handles here. We're going to pass
-    // an explicit handle into rustc to collect output messages, but we also
-    // want to catch the error message that rustc prints when it fails.
-    //
-    // We take our thread-local stderr (likely set by the test runner) and replace
-    // it with a sink that is also passed to rustc itself. When this function
-    // returns the output of the sink is copied onto the output of our own thread.
-    //
-    // The basic idea is to not use a default Handler for rustc, and then also
-    // not print things by default to the actual stderr.
-    struct Sink(Arc<Mutex<Vec<u8>>>);
-    impl Write for Sink {
-        fn write(&mut self, data: &[u8]) -> io::Result<usize> {
-            Write::write(&mut *self.0.lock().unwrap(), data)
+    let (libdir, outdir) = driver::spawn_thread_pool(sessopts, |sessopts| {
+        // Shuffle around a few input and output handles here. We're going to pass
+        // an explicit handle into rustc to collect output messages, but we also
+        // want to catch the error message that rustc prints when it fails.
+        //
+        // We take our thread-local stderr (likely set by the test runner) and replace
+        // it with a sink that is also passed to rustc itself. When this function
+        // returns the output of the sink is copied onto the output of our own thread.
+        //
+        // The basic idea is to not use a default Handler for rustc, and then also
+        // not print things by default to the actual stderr.
+        struct Sink(Arc<Mutex<Vec<u8>>>);
+        impl Write for Sink {
+            fn write(&mut self, data: &[u8]) -> io::Result<usize> {
+                Write::write(&mut *self.0.lock().unwrap(), data)
+            }
+            fn flush(&mut self) -> io::Result<()> { Ok(()) }
         }
-        fn flush(&mut self) -> io::Result<()> { Ok(()) }
-    }
-    struct Bomb(Arc<Mutex<Vec<u8>>>, Box<Write+Send>);
-    impl Drop for Bomb {
-        fn drop(&mut self) {
-            let _ = self.1.write_all(&self.0.lock().unwrap());
+        struct Bomb(Arc<Mutex<Vec<u8>>>, Box<Write+Send>);
+        impl Drop for Bomb {
+            fn drop(&mut self) {
+                let _ = self.1.write_all(&self.0.lock().unwrap());
+            }
         }
-    }
-    let data = Arc::new(Mutex::new(Vec::new()));
-    let codemap = Lrc::new(CodeMap::new_doctest(
-        sessopts.file_path_mapping(), filename.clone(), line as isize - line_offset as isize
-    ));
-    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()));
-
-    // Compile the code
-    let diagnostic_handler = errors::Handler::with_emitter(true, false, box emitter);
-
-    let mut sess = session::build_session_(
-        sessopts, None, diagnostic_handler, codemap,
-    );
-    let trans = rustc_driver::get_trans(&sess);
-    let cstore = CStore::new(trans.metadata_loader());
-    rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
-
-    let outdir = Mutex::new(TempDir::new("rustdoctest").ok().expect("rustdoc needs a tempdir"));
-    let libdir = sess.target_filesearch(PathKind::All).get_lib_path();
-    let mut control = driver::CompileController::basic();
-
-    let mut cfg = config::build_configuration(&sess, config::parse_cfgspecs(cfgs.clone()));
-    target_features::add_configuration(&mut cfg, &sess, &*trans);
-    sess.parse_sess.config = cfg;
-
-    let out = Some(outdir.lock().unwrap().path().to_path_buf());
-
-    if no_run {
-        control.after_analysis.stop = Compilation::Stop;
-    }
-
-    let res = panic::catch_unwind(AssertUnwindSafe(|| {
-        driver::compile_input(
-            trans,
-            &sess,
-            &cstore,
-            &None,
-            &input,
-            &out,
-            &None,
-            None,
-            &control
-        )
-    }));
-
-    let compile_result = match res {
-        Ok(Ok(())) | Ok(Err(CompileIncomplete::Stopped)) => Ok(()),
-        Err(_) | Ok(Err(CompileIncomplete::Errored(_))) => Err(())
-    };
-
-    match (compile_result, compile_fail) {
-        (Ok(()), true) => {
-            panic!("test compiled while it wasn't supposed to")
+        let data = Arc::new(Mutex::new(Vec::new()));
+        let codemap = Lrc::new(CodeMap::new_doctest(
+            sessopts.file_path_mapping(), filename.clone(), line as isize - line_offset as isize
+        ));
+        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()));
+
+        // Compile the code
+        let diagnostic_handler = errors::Handler::with_emitter(true, false, box emitter);
+
+        let mut sess = session::build_session_(
+            sessopts, None, diagnostic_handler, codemap,
+        );
+        let trans = rustc_driver::get_trans(&sess);
+        let cstore = CStore::new(trans.metadata_loader());
+        rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
+
+        let outdir = Mutex::new(TempDir::new("rustdoctest").ok().expect("rustdoc needs a tempdir"));
+        let libdir = sess.target_filesearch(PathKind::All).get_lib_path();
+        let mut control = driver::CompileController::basic();
+
+        let mut cfg = config::build_configuration(&sess, config::parse_cfgspecs(cfgs.clone()));
+        target_features::add_configuration(&mut cfg, &sess, &*trans);
+        sess.parse_sess.config = cfg;
+
+        let out = Some(outdir.lock().unwrap().path().to_path_buf());
+
+        if no_run {
+            control.after_analysis.stop = Compilation::Stop;
         }
-        (Ok(()), false) => {}
-        (Err(()), true) => {
-            if error_codes.len() > 0 {
-                let out = String::from_utf8(data.lock().unwrap().to_vec()).unwrap();
-                error_codes.retain(|err| !out.contains(err));
+
+        let res = panic::catch_unwind(AssertUnwindSafe(|| {
+            driver::compile_input(
+                trans,
+                &sess,
+                &cstore,
+                &None,
+                &input,
+                &out,
+                &None,
+                None,
+                &control
+            )
+        }));
+
+        let compile_result = match res {
+            Ok(Ok(())) | Ok(Err(CompileIncomplete::Stopped)) => Ok(()),
+            Err(_) | Ok(Err(CompileIncomplete::Errored(_))) => Err(())
+        };
+
+        match (compile_result, compile_fail) {
+            (Ok(()), true) => {
+                panic!("test compiled while it wasn't supposed to")
+            }
+            (Ok(()), false) => {}
+            (Err(()), true) => {
+                if error_codes.len() > 0 {
+                    let out = String::from_utf8(data.lock().unwrap().to_vec()).unwrap();
+                    error_codes.retain(|err| !out.contains(err));
+                }
+            }
+            (Err(()), false) => {
+                panic!("couldn't compile the test")
             }
         }
-        (Err(()), false) => {
-            panic!("couldn't compile the test")
+
+        if error_codes.len() > 0 {
+            panic!("Some expected error codes were not found: {:?}", error_codes);
         }
-    }
 
-    if error_codes.len() > 0 {
-        panic!("Some expected error codes were not found: {:?}", error_codes);
-    }
+        (libdir, outdir)
+    });
 
     if no_run { return }
 
index 7bd1adc411ae4b1c0f19009c51f0faf1ff046643..442a0873ae075ad550e983747d6d91a06ecab75a 100644 (file)
@@ -331,6 +331,7 @@ pub fn read_to_string<P: AsRef<Path>>(path: P) -> io::Result<String> {
 ///
 /// fn main() -> std::io::Result<()> {
 ///     fs::write("foo.txt", b"Lorem ipsum")?;
+///     fs::write("bar.txt", "dolor sit")?;
 ///     Ok(())
 /// }
 /// ```
@@ -1699,8 +1700,8 @@ pub fn read_link<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
     fs_imp::readlink(path.as_ref())
 }
 
-/// Returns the canonical form of a path with all intermediate components
-/// normalized and symbolic links resolved.
+/// Returns the canonical, absolute form of a path with all intermediate
+/// components normalized and symbolic links resolved.
 ///
 /// # Platform-specific behavior
 ///
@@ -1708,7 +1709,14 @@ pub fn read_link<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
 /// and the `CreateFile` and `GetFinalPathNameByHandle` functions on Windows.
 /// Note that, this [may change in the future][changes].
 ///
+/// On Windows, this converts the path to use [extended length path][path]
+/// syntax, which allows your program to use longer path names, but means you
+/// can only join backslash-delimited paths to it, and it may be incompatible
+/// with other applications (if passed to the application on the command-line,
+/// or written to a file another application may read).
+///
 /// [changes]: ../io/index.html#platform-specific-behavior
+/// [path]: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx#maxpath
 ///
 /// # Errors
 ///
index 696711a70d4f6408cc773abf87d04ed932e64b02..86478f0a523190fc6abc64772241f2c555d7fd4a 100644 (file)
@@ -1460,7 +1460,7 @@ fn extend<I: IntoIterator<Item = P>>(&mut self, iter: I) {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Debug for PathBuf {
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
         fmt::Debug::fmt(&**self, formatter)
     }
 }
@@ -2284,8 +2284,8 @@ pub fn symlink_metadata(&self) -> io::Result<fs::Metadata> {
         fs::symlink_metadata(self)
     }
 
-    /// Returns the canonical form of the path with all intermediate components
-    /// normalized and symbolic links resolved.
+    /// Returns the canonical, absolute form of the path with all intermediate
+    /// components normalized and symbolic links resolved.
     ///
     /// This is an alias to [`fs::canonicalize`].
     ///
index d8d78d550162ae3ef0f6750b8b82d39b3095bec1..1ef79547431f8ac0a23d9e3a85d92c288da346fa 100644 (file)
@@ -48,13 +48,13 @@ pub fn text(&self) -> &str {
 }
 
 impl fmt::Debug for Error {
-    fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.write_str(self.text())
     }
 }
 
 impl fmt::Display for Error {
-    fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.write_str(self.text())
     }
 }
index 5dafc3251e7551e10f6c68573b479a16cd2efbf6..67546d06b4e55055d98b767d0cd1b6a4fec43b5a 100644 (file)
@@ -75,8 +75,15 @@ pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
         unsafe fn cvt_pread64(fd: c_int, buf: *mut c_void, count: usize, offset: i64)
             -> io::Result<isize>
         {
+            use convert::TryInto;
             use libc::pread64;
-            cvt(pread64(fd, buf, count, offset as i32))
+            // pread64 on emscripten actually takes a 32 bit offset
+            if let Ok(o) = offset.try_into() {
+                cvt(pread64(fd, buf, count, o))
+            } else {
+                Err(io::Error::new(io::ErrorKind::InvalidInput,
+                                   "cannot pread >2GB"))
+            }
         }
 
         #[cfg(not(any(target_os = "android", target_os = "emscripten")))]
@@ -116,8 +123,15 @@ pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
         unsafe fn cvt_pwrite64(fd: c_int, buf: *const c_void, count: usize, offset: i64)
             -> io::Result<isize>
         {
+            use convert::TryInto;
             use libc::pwrite64;
-            cvt(pwrite64(fd, buf, count, offset as i32))
+            // pwrite64 on emscripten actually takes a 32 bit offset
+            if let Ok(o) = offset.try_into() {
+                cvt(pwrite64(fd, buf, count, o))
+            } else {
+                Err(io::Error::new(io::ErrorKind::InvalidInput,
+                                   "cannot pwrite >2GB"))
+            }
         }
 
         #[cfg(not(any(target_os = "android", target_os = "emscripten")))]
index fe7e058091ed5fe1c6cf871817f879892f5ead2d..14a2555adf9baa109e7d7afe08bbea07e685826a 100644 (file)
@@ -56,7 +56,7 @@ pub struct CodePoint {
 /// Example: `U+1F4A9`
 impl fmt::Debug for CodePoint {
     #[inline]
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
         write!(formatter, "U+{:04X}", self.value)
     }
 }
@@ -144,7 +144,7 @@ fn deref_mut(&mut self) -> &mut Wtf8 {
 /// Example: `"a\u{D800}"` for a string with code points [U+0061, U+D800]
 impl fmt::Debug for Wtf8Buf {
     #[inline]
-    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
         fmt::Debug::fmt(&**self, formatter)
     }
 }
index a137faf689fb71a27a61ee8f589ce0163ebba723..b27568a61f85cfb16390130cf07086787abd047a 100644 (file)
@@ -1861,56 +1861,61 @@ fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) {
             continue
         }
 
-        match attr.meta_item_list() {
+        let list = match attr.meta_item_list() {
+            Some(list) => list,
             None => {
                 span_err!(span_handler, attr.span, E0555,
                           "malformed feature attribute, expected #![feature(...)]");
+                continue
+            }
+        };
+
+        for mi in list {
+            let name = if let Some(word) = mi.word() {
+                word.name()
+            } else {
+                span_err!(span_handler, mi.span, E0556,
+                          "malformed feature, expected just one word");
+                continue
+            };
+
+            if let Some((.., set)) = ACTIVE_FEATURES.iter().find(|f| name == f.0) {
+                set(&mut features, mi.span);
+                feature_checker.collect(&features, mi.span);
+                continue
             }
-            Some(list) => {
-                for mi in list {
 
-                    let name = if let Some(word) = mi.word() {
-                        word.name()
-                    } else {
-                        span_err!(span_handler, mi.span, E0556,
-                                  "malformed feature, expected just one word");
-                        continue
-                    };
-
-                    if let Some(&(_, _, _, _, set)) = ACTIVE_FEATURES.iter()
-                        .find(|& &(n, ..)| name == n) {
-                        set(&mut features, mi.span);
-                        feature_checker.collect(&features, mi.span);
-                    }
-                    else if let Some(&(.., reason)) = REMOVED_FEATURES.iter()
-                            .find(|& &(n, ..)| name == n)
-                        .or_else(|| STABLE_REMOVED_FEATURES.iter()
-                            .find(|& &(n, ..)| name == n)) {
-                        feature_removed(span_handler, mi.span, reason);
-                    }
-                    else if let Some(&(..)) = ACCEPTED_FEATURES.iter()
-                        .find(|& &(n, ..)| name == n) {
-                        features.declared_stable_lang_features.push((name, mi.span));
-                    } else if let Some(&edition) = ALL_EDITIONS.iter()
-                                                              .find(|e| name == e.feature_name()) {
-                        if edition <= crate_edition {
-                            feature_removed(span_handler, mi.span, None);
-                        } else {
-                            for &(.., f_edition, set) in ACTIVE_FEATURES.iter() {
-                                if let Some(f_edition) = f_edition {
-                                    if edition >= f_edition {
-                                        // FIXME(Manishearth) there is currently no way to set
-                                        // lib features by edition
-                                        set(&mut features, DUMMY_SP);
-                                    }
-                                }
-                            }
+            let removed = REMOVED_FEATURES.iter().find(|f| name == f.0);
+            let stable_removed = STABLE_REMOVED_FEATURES.iter().find(|f| name == f.0);
+            if let Some((.., reason)) = removed.or(stable_removed) {
+                feature_removed(span_handler, mi.span, *reason);
+                continue
+            }
+
+            if ACCEPTED_FEATURES.iter().any(|f| name == f.0) {
+                features.declared_stable_lang_features.push((name, mi.span));
+                continue
+            }
+
+            if let Some(edition) = ALL_EDITIONS.iter().find(|e| name == e.feature_name()) {
+                if *edition <= crate_edition {
+                    continue
+                }
+
+                for &(.., f_edition, set) in ACTIVE_FEATURES.iter() {
+                    if let Some(f_edition) = f_edition {
+                        if *edition >= f_edition {
+                            // FIXME(Manishearth) there is currently no way to set
+                            // lib features by edition
+                            set(&mut features, DUMMY_SP);
                         }
-                    } else {
-                        features.declared_lib_features.push((name, mi.span));
                     }
                 }
+
+                continue
             }
+
+            features.declared_lib_features.push((name, mi.span));
         }
     }
 
index f148aaf7267eec9dc581fdfc025d8f2884df44b6..90af3ba51ecadcff1a3d7fdf58c90099df2c14b4 100644 (file)
@@ -73,7 +73,7 @@ macro_rules! unwrap_or {
     }
 }
 
-struct Globals {
+pub struct Globals {
     used_attrs: Lock<Vec<u64>>,
     known_attrs: Lock<Vec<u64>>,
     syntax_pos_globals: syntax_pos::Globals,
@@ -98,7 +98,7 @@ pub fn with_globals<F, R>(f: F) -> R
     })
 }
 
-scoped_thread_local!(static GLOBALS: Globals);
+scoped_thread_local!(pub static GLOBALS: Globals);
 
 #[macro_use]
 pub mod diagnostics {
index e95c6f2e1243fe7f5a2556d64d243eb3c30e12b4..2b8603c75a57b50733b0ac0ec611b8fd438b93d4 100644 (file)
@@ -989,7 +989,7 @@ fn clone(&self) -> StrCursor<'a> {
     }
 
     impl<'a> std::fmt::Debug for StrCursor<'a> {
-        fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
+        fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
             write!(fmt, "StrCursor({:?} | {:?})", self.slice_before(), self.slice_after())
         }
     }
index b9637b1855ef08760a3ed96b6afdedd1aae4ecb5..a9147b394f7a498406baec5c22449ed2943c1c16 100644 (file)
@@ -11,5 +11,6 @@ crate-type = ["dylib"]
 [dependencies]
 serialize = { path = "../libserialize" }
 rustc_data_structures = { path = "../librustc_data_structures" }
+arena = { path = "../libarena" }
 scoped-tls = { version = "0.1.1", features = ["nightly"] }
 unicode-width = "0.1.4"
index 8b4a3ea26a1ef7dca52f5a179e2f0110c7ea5f3f..d30d3d78ca5404dbea9f10b29f81f272b6c5af35 100644 (file)
@@ -35,6 +35,7 @@
 use rustc_data_structures::stable_hasher::StableHasher;
 use rustc_data_structures::sync::{Lrc, Lock};
 
+extern crate arena;
 extern crate rustc_data_structures;
 
 #[macro_use]
index 4a8b1e8b1c1e46edb8569c04006a1258a9be7b0a..2258ed12779e4ce7792a195d9cfaa234db812bac 100644 (file)
 use {Span, DUMMY_SP, GLOBALS};
 
 use rustc_data_structures::fx::FxHashMap;
+use arena::DroplessArena;
 use serialize::{Decodable, Decoder, Encodable, Encoder};
 use std::fmt;
+use std::str;
 use std::cmp::{PartialEq, Ordering, PartialOrd, Ord};
 use std::hash::{Hash, Hasher};
 
@@ -198,22 +200,35 @@ fn eq(&self, other: &T) -> bool {
     }
 }
 
-#[derive(Default)]
+// The &'static strs in this type actually point into the arena
 pub struct Interner {
-    names: FxHashMap<Box<str>, Symbol>,
-    strings: Vec<Box<str>>,
+    arena: DroplessArena,
+    names: FxHashMap<&'static str, Symbol>,
+    strings: Vec<&'static str>,
     gensyms: Vec<Symbol>,
 }
 
 impl Interner {
     pub fn new() -> Self {
-        Interner::default()
+        Interner {
+            arena: DroplessArena::new(),
+            names: Default::default(),
+            strings: Default::default(),
+            gensyms: Default::default(),
+        }
     }
 
     fn prefill(init: &[&str]) -> Self {
         let mut this = Interner::new();
         for &string in init {
-            this.intern(string);
+            if string == "" {
+                // We can't allocate empty strings in the arena, so handle this here
+                let name = Symbol(this.strings.len() as u32);
+                this.names.insert("", name);
+                this.strings.push("");
+            } else {
+                this.intern(string);
+            }
         }
         this
     }
@@ -224,8 +239,17 @@ pub fn intern(&mut self, string: &str) -> Symbol {
         }
 
         let name = Symbol(self.strings.len() as u32);
-        let string = string.to_string().into_boxed_str();
-        self.strings.push(string.clone());
+
+        // from_utf8_unchecked is safe since we just allocated a &str which is known to be utf8
+        let string: &str = unsafe {
+            str::from_utf8_unchecked(self.arena.alloc_slice(string.as_bytes()))
+        };
+        // It is safe to extend the arena allocation to 'static because we only access
+        // these while the arena is still alive
+        let string: &'static str =  unsafe {
+            &*(string as *const str)
+        };
+        self.strings.push(string);
         self.names.insert(string, name);
         name
     }
@@ -254,7 +278,7 @@ fn is_gensymed(&mut self, symbol: Symbol) -> bool {
 
     pub fn get(&self, symbol: Symbol) -> &str {
         match self.strings.get(symbol.0 as usize) {
-            Some(ref string) => string,
+            Some(string) => string,
             None => self.get(self.gensyms[(!0 - symbol.0) as usize]),
         }
     }
@@ -503,7 +527,7 @@ fn partial_cmp(&self, other: &InternedString) -> Option<Ordering> {
         if self.symbol == other.symbol {
             return Some(Ordering::Equal);
         }
-        self.with(|self_str| other.with(|other_str| self_str.partial_cmp(&other_str)))
+        self.with(|self_str| other.with(|other_str| self_str.partial_cmp(other_str)))
     }
 }
 
index 382ef2cc407dd93ba704457c5fee7a58073fde86..8593f543619a59ba5aa1b4e0db00bfaa9e20e3b2 100644 (file)
@@ -428,13 +428,16 @@ extern "C" void LLVMRustAddAnalysisPasses(LLVMTargetMachineRef TM,
 
 extern "C" void LLVMRustConfigurePassManagerBuilder(
     LLVMPassManagerBuilderRef PMBR, LLVMRustCodeGenOptLevel OptLevel,
-    bool MergeFunctions, bool SLPVectorize, bool LoopVectorize,
+    bool MergeFunctions, bool SLPVectorize, bool LoopVectorize, bool PrepareForThinLTO,
     const char* PGOGenPath, const char* PGOUsePath) {
   // Ignore mergefunc for now as enabling it causes crashes.
   // unwrap(PMBR)->MergeFunctions = MergeFunctions;
   unwrap(PMBR)->SLPVectorize = SLPVectorize;
   unwrap(PMBR)->OptLevel = fromRust(OptLevel);
   unwrap(PMBR)->LoopVectorize = LoopVectorize;
+#if LLVM_VERSION_GE(4, 0)
+  unwrap(PMBR)->PrepareForThinLTO = PrepareForThinLTO;
+#endif
 
 #ifdef PGO_AVAILABLE
   if (PGOGenPath) {
index 415ee6eb7eab8754834de460088b0ac260935313..1879002e7f3d7cb2750ca73b9aad7aedda4a8347 100644 (file)
 
 #![crate_type = "lib"]
 
-// CHECK: @VAR1 = constant <{ [4 x i8] }> <{ [4 x i8] c"\01\00\00\00" }>, section ".test_one"
+// CHECK: @VAR1 = constant i32 1, section ".test_one"
 #[no_mangle]
 #[link_section = ".test_one"]
-#[cfg(target_endian = "little")]
 pub static VAR1: u32 = 1;
 
-#[no_mangle]
-#[link_section = ".test_one"]
-#[cfg(target_endian = "big")]
-pub static VAR1: u32 = 0x01000000;
-
 pub enum E {
     A(u32),
     B(f32)
diff --git a/src/test/compile-fail/auxiliary/edition-extern-crate-allowed.rs b/src/test/compile-fail/auxiliary/edition-extern-crate-allowed.rs
new file mode 100644 (file)
index 0000000..d26ab6d
--- /dev/null
@@ -0,0 +1,11 @@
+// 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.
+
+// intentionally empty
diff --git a/src/test/compile-fail/edition-extern-crate-allowed.rs b/src/test/compile-fail/edition-extern-crate-allowed.rs
new file mode 100644 (file)
index 0000000..286ee89
--- /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.
+
+// aux-build:edition-extern-crate-allowed.rs
+// compile-flags: --edition 2015
+// compile-pass
+
+#![deny(rust_2018_idioms)]
+
+extern crate edition_extern_crate_allowed;
+
+fn main() {}
diff --git a/src/test/compile-fail/edition-feature-ok.rs b/src/test/compile-fail/edition-feature-ok.rs
new file mode 100644 (file)
index 0000000..3a3a6ff
--- /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.
+
+// compile-flags:--edition 2018
+// compile-pass
+
+#![feature(rust_2018_preview)]
+
+fn main() {}
diff --git a/src/test/run-make-fulldeps/issue-36710/Makefile b/src/test/run-make-fulldeps/issue-36710/Makefile
new file mode 100644 (file)
index 0000000..2cb0b4c
--- /dev/null
@@ -0,0 +1,12 @@
+-include ../tools.mk
+
+all: foo
+       $(call RUN,foo)
+
+foo: foo.rs $(call NATIVE_STATICLIB,foo)
+       $(RUSTC) $< -lfoo $(EXTRACXXFLAGS)
+
+$(TMPDIR)/libfoo.o: foo.cpp
+       $(call COMPILE_OBJ_CXX,$@,$<)
+
+.PHONY: all
diff --git a/src/test/run-make-fulldeps/issue-36710/foo.cpp b/src/test/run-make-fulldeps/issue-36710/foo.cpp
new file mode 100644 (file)
index 0000000..fbd0ead
--- /dev/null
@@ -0,0 +1,25 @@
+// 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.
+
+#include <stdint.h>
+
+struct A {
+    A() { v = 1234; }
+    ~A() { v = 1; }
+    uint32_t v;
+};
+
+A a;
+
+extern "C" {
+    uint32_t get() {
+        return a.v;
+    }
+}
diff --git a/src/test/run-make-fulldeps/issue-36710/foo.rs b/src/test/run-make-fulldeps/issue-36710/foo.rs
new file mode 100644 (file)
index 0000000..6e50566
--- /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.
+
+// Tests that linking to C++ code with global destructors works.
+
+extern { fn get() -> u32; }
+
+fn main() {
+    let i = unsafe { get() };
+    assert_eq!(i, 1234);
+}
index af1707de6c02f52432cfc241cca0df4f9e06ad70..3de358fa50007140e480d160ec4b66e01d70d08d 100644 (file)
@@ -59,12 +59,14 @@ endif
 
 ifdef IS_MSVC
 COMPILE_OBJ = $(CC) -c -Fo:`cygpath -w $(1)` $(2)
+COMPILE_OBJ_CXX = $(CXX) -c -Fo:`cygpath -w $(1)` $(2)
 NATIVE_STATICLIB_FILE = $(1).lib
 NATIVE_STATICLIB = $(TMPDIR)/$(call NATIVE_STATICLIB_FILE,$(1))
 OUT_EXE=-Fe:`cygpath -w $(TMPDIR)/$(call BIN,$(1))` \
        -Fo:`cygpath -w $(TMPDIR)/$(1).obj`
 else
 COMPILE_OBJ = $(CC) -c -o $(1) $(2)
+COMPILE_OBJ_CXX = $(CXX) -c -o $(1) $(2)
 NATIVE_STATICLIB_FILE = lib$(1).a
 NATIVE_STATICLIB = $(call STATICLIB,$(1))
 OUT_EXE=-o $(TMPDIR)/$(1)
index 914b89dfb4dc030ae81190b79d525f51eaed8b7e..2d478e954e7cb7cb493e98b9da4e2ad124f80b33 100644 (file)
@@ -15,7 +15,7 @@
 
 struct SlowFmt(u32);
 impl fmt::Debug for SlowFmt {
-    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         thread::sleep_ms(3);
         self.0.fmt(f)
     }
index 1cdaff2cab7c8c7e25efe55464f7744d03fdf8d3..c1e408cc02ac6764aa95fc848f28fe26ddcf4549 100644 (file)
@@ -15,7 +15,7 @@ union U {
 }
 
 impl fmt::Display for U {
-    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         unsafe { write!(f, "Oh hai {}", self.a) }
     }
 }
index 9d678d91578bc1027db26cba228d1a80489178ae..0f532d3da6a7307ad1f25993bb5705ee3be751c4 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// compile-flags: --edition 2018
+
 #![deny(unnecessary_extern_crate)]
 #![feature(alloc, test, libc)]
 
index e27ccaeba0c2be41724df6513b7fcafbb7407f59..ab5457018eda66d9e0a068faa17919396fd78062 100644 (file)
@@ -1,65 +1,65 @@
 error: `extern crate` is unnecessary in the new edition
-  --> $DIR/unnecessary-extern-crate.rs:14:1
+  --> $DIR/unnecessary-extern-crate.rs:16:1
    |
 LL | extern crate alloc;
    | ^^^^^^^^^^^^^^^^^^^ help: remove it
    |
 note: lint level defined here
-  --> $DIR/unnecessary-extern-crate.rs:11:9
+  --> $DIR/unnecessary-extern-crate.rs:13:9
    |
 LL | #![deny(unnecessary_extern_crate)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `extern crate` is unnecessary in the new edition
-  --> $DIR/unnecessary-extern-crate.rs:17:1
+  --> $DIR/unnecessary-extern-crate.rs:19:1
    |
 LL | extern crate alloc as x;
    | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `use`: `use alloc as x;`
 
 error: `extern crate` is unnecessary in the new edition
-  --> $DIR/unnecessary-extern-crate.rs:23:1
+  --> $DIR/unnecessary-extern-crate.rs:25:1
    |
 LL | pub extern crate test as y;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `pub use`: `pub use test as y;`
 
 error: `extern crate` is unnecessary in the new edition
-  --> $DIR/unnecessary-extern-crate.rs:26:1
+  --> $DIR/unnecessary-extern-crate.rs:28:1
    |
 LL | pub extern crate libc;
    | ^^^^^^^^^^^^^^^^^^^^^^ help: use `pub use`: `pub use libc;`
 
 error: `extern crate` is unnecessary in the new edition
-  --> $DIR/unnecessary-extern-crate.rs:32:5
+  --> $DIR/unnecessary-extern-crate.rs:34:5
    |
 LL |     extern crate alloc;
    |     ^^^^^^^^^^^^^^^^^^^ help: use `use`: `use alloc;`
 
 error: `extern crate` is unnecessary in the new edition
-  --> $DIR/unnecessary-extern-crate.rs:35:5
+  --> $DIR/unnecessary-extern-crate.rs:37:5
    |
 LL |     extern crate alloc as x;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `use`: `use alloc as x;`
 
 error: `extern crate` is unnecessary in the new edition
-  --> $DIR/unnecessary-extern-crate.rs:38:5
+  --> $DIR/unnecessary-extern-crate.rs:40:5
    |
 LL |     pub extern crate test;
    |     ^^^^^^^^^^^^^^^^^^^^^^ help: use `pub use`: `pub use test;`
 
 error: `extern crate` is unnecessary in the new edition
-  --> $DIR/unnecessary-extern-crate.rs:41:5
+  --> $DIR/unnecessary-extern-crate.rs:43:5
    |
 LL |     pub extern crate test as y;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `pub use`: `pub use test as y;`
 
 error: `extern crate` is unnecessary in the new edition
-  --> $DIR/unnecessary-extern-crate.rs:45:9
+  --> $DIR/unnecessary-extern-crate.rs:47:9
    |
 LL |         extern crate alloc;
    |         ^^^^^^^^^^^^^^^^^^^ help: use `use`: `use alloc;`
 
 error: `extern crate` is unnecessary in the new edition
-  --> $DIR/unnecessary-extern-crate.rs:48:9
+  --> $DIR/unnecessary-extern-crate.rs:50:9
    |
 LL |         extern crate alloc as x;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use `use`: `use alloc as x;`
index 07aa3bfe40dea06e94f2da26f0a40d493b70ed81..c89defa3dd196d97a4a8822a33b37b1a933b527a 100644 (file)
@@ -4,8 +4,7 @@ error[E0369]: binary operation `%` cannot be applied to type `&&{integer}`
 LL |         x % 2 == 0
    |         ^^^^^
    |
-   = note: this is a reference to a type that `%` can be applied to; you need to dereference this variable once for this operation to work
-   = note: an implementation of `std::ops::Rem` might be missing for `&&{integer}`
+   = help: `%` can be used on '{integer}', you can dereference `x`: `*x`
 
 error: aborting due to previous error
 
index 2c8a33d95c03a23e57839323ea4f1d5feb7afb90..15c159a3b153cf8f8cfcdc586eac03a2dce496ae 100644 (file)
@@ -2,7 +2,7 @@ error[E0600]: cannot apply unary operator `!` to type `&'static str`
   --> $DIR/issue-28308.rs:12:5
    |
 LL |     assert!("foo");
-   |     ^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^ cannot apply unary operator `!`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-eval/duration_conversion.rs b/src/test/ui/const-eval/duration_conversion.rs
new file mode 100644 (file)
index 0000000..4481b75
--- /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.
+
+// compile-pass
+
+#![feature(duration_getters)]
+
+use std::time::Duration;
+
+fn main() {
+    const _ONE_SECOND: Duration = Duration::from_nanos(1_000_000_000);
+    const _ONE_MILLISECOND: Duration = Duration::from_nanos(1_000_000);
+    const _ONE_MICROSECOND: Duration = Duration::from_nanos(1_000);
+    const _ONE_NANOSECOND: Duration = Duration::from_nanos(1);
+    const _ONE: usize = _ONE_SECOND.as_secs() as usize;
+    const _TWO: usize = _ONE_MILLISECOND.subsec_millis() as usize;
+    const _THREE: usize = _ONE_MICROSECOND.subsec_micros() as usize;
+    const _FOUR: usize = _ONE_NANOSECOND.subsec_nanos() as usize;
+    const _0: [[u8; _ONE]; _TWO] = [[1; _ONE]; _TWO];
+    const _1: [[u8; _THREE]; _FOUR] = [[3; _THREE]; _FOUR];
+}
index 76f06c7c46379476a0cc744d4e5f6d1b4c3d74b7..43e1ca4096cf69a37f9c90006a04ced496241fc9 100644 (file)
@@ -5,6 +5,8 @@ LL |     LinkedList::new() += 1; //~ ERROR E0368
    |     -----------------^^^^^
    |     |
    |     cannot use `+=` on type `std::collections::LinkedList<_>`
+   |
+   = note: an implementation of `std::ops::AddAssign` might be missing for `std::collections::LinkedList<_>`
 
 error[E0067]: invalid left-hand side expression
   --> $DIR/E0067.rs:14:5
index 500feb39f5e7421e9cafaa93fc2e3a717d65abc6..c29ec4fe6ae76e2f09e9ae53971e886b78deacc9 100644 (file)
@@ -2,7 +2,7 @@ error[E0600]: cannot apply unary operator `!` to type `&'static str`
   --> $DIR/E0600.rs:12:5
    |
 LL |     !"a"; //~ ERROR E0600
-   |     ^^^^
+   |     ^^^^ cannot apply unary operator `!`
 
 error: aborting due to previous error
 
index 345691352b407a7084cc0e38c890caad7712b1d6..69f11b4b7c08c33c74af00c7a73a05bd941ec0aa 100644 (file)
@@ -17,6 +17,8 @@ LL |     x += 2;
    |     -^^^^^
    |     |
    |     cannot use `+=` on type `&str`
+   |
+   = note: an implementation of `std::ops::AddAssign` might be missing for `&str`
 
 error[E0599]: no method named `z` found for type `&str` in the current scope
   --> $DIR/error-festival.rs:26:7
@@ -28,7 +30,9 @@ error[E0600]: cannot apply unary operator `!` to type `Question`
   --> $DIR/error-festival.rs:29:5
    |
 LL |     !Question::Yes;
-   |     ^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^ cannot apply unary operator `!`
+   |
+   = note: an implementation of `std::ops::Not` might be missing for `Question`
 
 error[E0604]: only `u8` can be cast as `char`, not `u32`
   --> $DIR/error-festival.rs:35:5
index 1025b56f55bc3cfc7dc505f6d845a09f452a3a2a..85e9b56e4af9db3f0caeee55d1621e7421599e08 100644 (file)
@@ -2,13 +2,17 @@ error[E0600]: cannot apply unary operator `-` to type `usize`
   --> $DIR/feature-gate-negate-unsigned.rs:20:23
    |
 LL |     let _max: usize = -1;
-   |                       ^^
+   |                       ^^ cannot apply unary operator `-`
+   |
+   = note: unsigned values cannot be negated
 
 error[E0600]: cannot apply unary operator `-` to type `u8`
   --> $DIR/feature-gate-negate-unsigned.rs:24:14
    |
 LL |     let _y = -x;
-   |              ^^
+   |              ^^ cannot apply unary operator `-`
+   |
+   = note: unsigned values cannot be negated
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issue-50480.rs b/src/test/ui/issue-50480.rs
new file mode 100644 (file)
index 0000000..3427cf6
--- /dev/null
@@ -0,0 +1,17 @@
+// 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.
+
+#[derive(Clone, Copy)]
+//~^ ERROR the trait `Copy` may not be implemented for this type
+struct Foo(NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+//~^ ERROR cannot find type `NotDefined` in this scope
+//~| ERROR the trait bound `i32: std::iter::Iterator` is not satisfied
+
+fn main() {}
diff --git a/src/test/ui/issue-50480.stderr b/src/test/ui/issue-50480.stderr
new file mode 100644 (file)
index 0000000..f5281fe
--- /dev/null
@@ -0,0 +1,29 @@
+error[E0412]: cannot find type `NotDefined` in this scope
+  --> $DIR/issue-50480.rs:13:12
+   |
+LL | struct Foo(NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+   |            ^^^^^^^^^^ not found in this scope
+
+error[E0277]: the trait bound `i32: std::iter::Iterator` is not satisfied
+  --> $DIR/issue-50480.rs:13:24
+   |
+LL | struct Foo(NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+   |                        ^^^^^^^^^^^^^^^^^^^^^^^ `i32` is not an iterator; maybe try calling `.iter()` or a similar method
+   |
+   = help: the trait `std::iter::Iterator` is not implemented for `i32`
+
+error[E0204]: the trait `Copy` may not be implemented for this type
+  --> $DIR/issue-50480.rs:11:17
+   |
+LL | #[derive(Clone, Copy)]
+   |                 ^^^^
+LL | //~^ ERROR the trait `Copy` may not be implemented for this type
+LL | struct Foo(NotDefined, <i32 as Iterator>::Item, Vec<i32>, String);
+   |                                                 --------  ------ this field does not implement `Copy`
+   |                                                 |
+   |                                                 this field does not implement `Copy`
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0204, E0277, E0412.
+For more information about an error, try `rustc --explain E0204`.
index 2f9204e72d3fb0e73ac3e673ca3c945c3ef1f012..7ae01fb7d6012996c1e80ebb82038431117b6aaa 100644 (file)
@@ -5,6 +5,8 @@ LL |     let x = |ref x: isize| { x += 1; };
    |                              -^^^^^
    |                              |
    |                              cannot use `+=` on type `&isize`
+   |
+   = help: `+=` can be used on 'isize', you can dereference `x`: `*x`
 
 error: aborting due to previous error
 
index f5e6b4d3b48622d2a30b591490f41c3407a6ea07..0a1926f8ae56a11dd9ad7f91881d37c3827cbbde 100644 (file)
@@ -24,6 +24,7 @@
 mod private_mod {
     // non-leaked `pub` items in private module should be linted
     pub use std::fmt;
+    pub use std::env::{Args}; // braced-use has different item spans than unbraced
 
     pub struct Hydrogen {
         // `pub` struct fields, too
index d1711be456bcc1667babc691e12d6ea7e376a4ed..2948deb23009c64b62b33b56fa7a380974aae3b3 100644 (file)
@@ -14,7 +14,15 @@ LL | #![warn(unreachable_pub)]
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub-pub_crate.rs:28:5
+  --> $DIR/unreachable_pub-pub_crate.rs:27:24
+   |
+LL |     pub use std::env::{Args}; // braced-use has different item spans than unbraced
+   |                        ^^^^ help: consider restricting its visibility: `pub(crate)`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub-pub_crate.rs:29:5
    |
 LL |     pub struct Hydrogen {
    |     ---^^^^^^^^^^^^^^^^
@@ -24,7 +32,7 @@ LL |     pub struct Hydrogen {
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` field
-  --> $DIR/unreachable_pub-pub_crate.rs:30:9
+  --> $DIR/unreachable_pub-pub_crate.rs:31:9
    |
 LL |         pub neutrons: usize,
    |         ---^^^^^^^^^^^^^^^^
@@ -32,7 +40,7 @@ LL |         pub neutrons: usize,
    |         help: consider restricting its visibility: `pub(crate)`
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub-pub_crate.rs:36:9
+  --> $DIR/unreachable_pub-pub_crate.rs:37:9
    |
 LL |         pub fn count_neutrons(&self) -> usize { self.neutrons }
    |         ---^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -40,7 +48,7 @@ LL |         pub fn count_neutrons(&self) -> usize { self.neutrons }
    |         help: consider restricting its visibility: `pub(crate)`
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub-pub_crate.rs:40:5
+  --> $DIR/unreachable_pub-pub_crate.rs:41:5
    |
 LL |     pub enum Helium {}
    |     ---^^^^^^^^^^^^
@@ -50,7 +58,7 @@ LL |     pub enum Helium {}
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub-pub_crate.rs:41:5
+  --> $DIR/unreachable_pub-pub_crate.rs:42:5
    |
 LL |     pub union Lithium { c1: usize, c2: u8 }
    |     ---^^^^^^^^^^^^^^
@@ -60,7 +68,7 @@ LL |     pub union Lithium { c1: usize, c2: u8 }
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub-pub_crate.rs:42:5
+  --> $DIR/unreachable_pub-pub_crate.rs:43:5
    |
 LL |     pub fn beryllium() {}
    |     ---^^^^^^^^^^^^^^^
@@ -70,7 +78,7 @@ LL |     pub fn beryllium() {}
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub-pub_crate.rs:43:5
+  --> $DIR/unreachable_pub-pub_crate.rs:44:5
    |
 LL |     pub trait Boron {}
    |     ---^^^^^^^^^^^^
@@ -80,7 +88,7 @@ LL |     pub trait Boron {}
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub-pub_crate.rs:44:5
+  --> $DIR/unreachable_pub-pub_crate.rs:45:5
    |
 LL |     pub const CARBON: usize = 1;
    |     ---^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -90,7 +98,7 @@ LL |     pub const CARBON: usize = 1;
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub-pub_crate.rs:45:5
+  --> $DIR/unreachable_pub-pub_crate.rs:46:5
    |
 LL |     pub static NITROGEN: usize = 2;
    |     ---^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -100,7 +108,7 @@ LL |     pub static NITROGEN: usize = 2;
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub-pub_crate.rs:46:5
+  --> $DIR/unreachable_pub-pub_crate.rs:47:5
    |
 LL |     pub type Oxygen = bool;
    |     ---^^^^^^^^^^^^^^^^^^^^
@@ -110,7 +118,7 @@ LL |     pub type Oxygen = bool;
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub-pub_crate.rs:49:47
+  --> $DIR/unreachable_pub-pub_crate.rs:50:47
    |
 LL |         ($visibility: vis, $name: ident) => { $visibility struct $name {} }
    |                                               -----------^^^^^^^^^^^^^
@@ -123,7 +131,7 @@ LL |     define_empty_struct_with_visibility!(pub, Fluorine);
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub-pub_crate.rs:54:9
+  --> $DIR/unreachable_pub-pub_crate.rs:55:9
    |
 LL |         pub fn catalyze() -> bool;
    |         ---^^^^^^^^^^^^^^^^^^^^^^^
index 347579c3e7bb93df13e9d262e7d6561241d1e9a1..5bb67670d85c2ae6f9bcfa708e28c944ed82f2c4 100644 (file)
@@ -19,6 +19,7 @@
 mod private_mod {
     // non-leaked `pub` items in private module should be linted
     pub use std::fmt;
+    pub use std::env::{Args}; // braced-use has different item spans than unbraced
 
     pub struct Hydrogen {
         // `pub` struct fields, too
index 1d693161108db03fe6d319e84de76c90d3c94d6e..ad88c55d54013a92c97697454bdfcfcac7ef4fb4 100644 (file)
@@ -14,7 +14,15 @@ LL | #![warn(unreachable_pub)]
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub.rs:23:5
+  --> $DIR/unreachable_pub.rs:22:24
+   |
+LL |     pub use std::env::{Args}; // braced-use has different item spans than unbraced
+   |                        ^^^^ help: consider restricting its visibility: `crate`
+   |
+   = help: or consider exporting it for use by other crates
+
+warning: unreachable `pub` item
+  --> $DIR/unreachable_pub.rs:24:5
    |
 LL |     pub struct Hydrogen {
    |     ---^^^^^^^^^^^^^^^^
@@ -24,7 +32,7 @@ LL |     pub struct Hydrogen {
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` field
-  --> $DIR/unreachable_pub.rs:25:9
+  --> $DIR/unreachable_pub.rs:26:9
    |
 LL |         pub neutrons: usize,
    |         ---^^^^^^^^^^^^^^^^
@@ -32,7 +40,7 @@ LL |         pub neutrons: usize,
    |         help: consider restricting its visibility: `crate`
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub.rs:31:9
+  --> $DIR/unreachable_pub.rs:32:9
    |
 LL |         pub fn count_neutrons(&self) -> usize { self.neutrons }
    |         ---^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -40,7 +48,7 @@ LL |         pub fn count_neutrons(&self) -> usize { self.neutrons }
    |         help: consider restricting its visibility: `crate`
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub.rs:35:5
+  --> $DIR/unreachable_pub.rs:36:5
    |
 LL |     pub enum Helium {}
    |     ---^^^^^^^^^^^^
@@ -50,7 +58,7 @@ LL |     pub enum Helium {}
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub.rs:36:5
+  --> $DIR/unreachable_pub.rs:37:5
    |
 LL |     pub union Lithium { c1: usize, c2: u8 }
    |     ---^^^^^^^^^^^^^^
@@ -60,7 +68,7 @@ LL |     pub union Lithium { c1: usize, c2: u8 }
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub.rs:37:5
+  --> $DIR/unreachable_pub.rs:38:5
    |
 LL |     pub fn beryllium() {}
    |     ---^^^^^^^^^^^^^^^
@@ -70,7 +78,7 @@ LL |     pub fn beryllium() {}
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub.rs:38:5
+  --> $DIR/unreachable_pub.rs:39:5
    |
 LL |     pub trait Boron {}
    |     ---^^^^^^^^^^^^
@@ -80,7 +88,7 @@ LL |     pub trait Boron {}
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub.rs:39:5
+  --> $DIR/unreachable_pub.rs:40:5
    |
 LL |     pub const CARBON: usize = 1;
    |     ---^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -90,7 +98,7 @@ LL |     pub const CARBON: usize = 1;
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub.rs:40:5
+  --> $DIR/unreachable_pub.rs:41:5
    |
 LL |     pub static NITROGEN: usize = 2;
    |     ---^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -100,7 +108,7 @@ LL |     pub static NITROGEN: usize = 2;
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub.rs:41:5
+  --> $DIR/unreachable_pub.rs:42:5
    |
 LL |     pub type Oxygen = bool;
    |     ---^^^^^^^^^^^^^^^^^^^^
@@ -110,7 +118,7 @@ LL |     pub type Oxygen = bool;
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub.rs:44:47
+  --> $DIR/unreachable_pub.rs:45:47
    |
 LL |         ($visibility: vis, $name: ident) => { $visibility struct $name {} }
    |                                               -----------^^^^^^^^^^^^^
@@ -123,7 +131,7 @@ LL |     define_empty_struct_with_visibility!(pub, Fluorine);
    = help: or consider exporting it for use by other crates
 
 warning: unreachable `pub` item
-  --> $DIR/unreachable_pub.rs:49:9
+  --> $DIR/unreachable_pub.rs:50:9
    |
 LL |         pub fn catalyze() -> bool;
    |         ---^^^^^^^^^^^^^^^^^^^^^^^
index 165eccd42396b2e8310ffcc4b6d6a734d44363ec..b889c884fcbb223f66e2eb574dc482cf6c06f908 100644 (file)
@@ -2,7 +2,7 @@ error[E0600]: cannot apply unary operator `!` to type `!`
   --> $DIR/expr_unary.rs:17:16
    |
 LL |     let x: ! = ! { return; }; //~ ERROR unreachable
-   |                ^^^^^^^^^^^^^
+   |                ^^^^^^^^^^^^^ cannot apply unary operator `!`
 
 error: unreachable expression
   --> $DIR/expr_unary.rs:17:16
index adf6b85b6429c57e02a8cdef8d49ef7ac03e9231..b3e79ce2447fb564838d82ea413716b8c7ec8e03 100644 (file)
@@ -14,3 +14,7 @@ fn main() {
 fn foo<T>(x: T, y: T) {
     let z = x + y; //~ ERROR binary operation `+` cannot be applied to type `T`
 }
+
+fn bar<T>(x: T) {
+    x += x; //~ ERROR binary assignment operation `+=` cannot be applied to type `T`
+}
index 777f16b12ce683a4466b607fb344a3035453ec7d..4b01a626814e555a5427e4a316b65d970ef12c8a 100644 (file)
@@ -6,6 +6,17 @@ LL |     let z = x + y; //~ ERROR binary operation `+` cannot be applied to type
    |
    = note: `T` might need a bound for `std::ops::Add`
 
-error: aborting due to previous error
+error[E0368]: binary assignment operation `+=` cannot be applied to type `T`
+  --> $DIR/missing_trait_impl.rs:19:5
+   |
+LL |     x += x; //~ ERROR binary assignment operation `+=` cannot be applied to type `T`
+   |     -^^^^^
+   |     |
+   |     cannot use `+=` on type `T`
+   |
+   = note: `T` might need a bound for `std::ops::AddAssign`
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0369`.
+Some errors occurred: E0368, E0369.
+For more information about an error, try `rustc --explain E0368`.
index 1bac9ef66bb81354e9b25f6e66ae05d916877ad1..4f18f238cab903af72e49191325c5c28ba385e1c 100644 (file)
@@ -2524,7 +2524,7 @@ fn run_rmake_test(&self) {
                 .env("IS_WINDOWS", "1")
                 .env("MSVC_LIB", format!("'{}' -nologo", lib.display()))
                 .env("CC", format!("'{}' {}", self.config.cc, cflags))
-                .env("CXX", &self.config.cxx);
+                .env("CXX", format!("'{}'", &self.config.cxx));
         } else {
             cmd.env("CC", format!("{} {}", self.config.cc, self.config.cflags))
                 .env("CXX", format!("{} {}", self.config.cxx, self.config.cflags))
index 9a87fcb00d526f4cc683cfbbf98b2bbc9446d0b7..c34cf1bd5ec09691c5993f0ae2facee2205c2eb0 100644 (file)
@@ -59,6 +59,7 @@
 static WHITELIST: &'static [Crate] = &[
     Crate("aho-corasick"),
     Crate("ar"),
+    Crate("arrayvec"),
     Crate("atty"),
     Crate("backtrace"),
     Crate("backtrace-sys"),
     Crate("cc"),
     Crate("cfg-if"),
     Crate("cmake"),
+    Crate("crossbeam-deque"),
+    Crate("crossbeam-epoch"),
+    Crate("crossbeam-utils"),
+    Crate("either"),
     Crate("ena"),
     Crate("env_logger"),
     Crate("filetime"),
@@ -82,7 +87,9 @@
     Crate("log"),
     Crate("log_settings"),
     Crate("memchr"),
+    Crate("memoffset"),
     Crate("miniz-sys"),
+    Crate("nodrop"),
     Crate("num_cpus"),
     Crate("owning_ref"),
     Crate("parking_lot"),
     Crate("regex-syntax"),
     Crate("remove_dir_all"),
     Crate("rustc-demangle"),
+    Crate("rustc-rayon"),
+    Crate("rustc-rayon-core"),
     Crate("scoped-tls"),
+    Crate("scopeguard"),
     Crate("smallvec"),
     Crate("stable_deref_trait"),
     Crate("tempdir"),
index ef8b55186b104e8c0ad67012bbc2cad53d455e91..363d01d964eb5da89624680234f263d03cfddf43 100644 (file)
@@ -22,12 +22,22 @@ pub fn check(path: &Path, bad: &mut bool) {
         &libcore_path,
         &mut |subpath| t!(subpath.strip_prefix(&libcore_path)).starts_with("tests"),
         &mut |subpath| {
-            if t!(read_to_string(subpath)).contains("#[test]") {
-                tidy_error!(
-                    bad,
-                    "{} contains #[test]; libcore tests must be placed inside `src/libcore/tests/`",
-                    subpath.display()
-                );
+            if let Some("rs") = subpath.extension().and_then(|e| e.to_str()) {
+                match read_to_string(subpath) {
+                    Ok(contents) => {
+                        if contents.contains("#[test]") {
+                            tidy_error!(
+                                bad,
+                                "{} contains #[test]; libcore tests must be placed inside \
+                                `src/libcore/tests/`",
+                                subpath.display()
+                            );
+                        }
+                    }
+                    Err(err) => {
+                        panic!("failed to read file {:?}: {}", subpath, err);
+                    }
+                }
             }
         },
     );