]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #55858 - GuillaumeGomez:fixes-rustdoc-codeblocks, r=QuietMisdreavus
authorkennytm <kennytm@gmail.com>
Tue, 13 Nov 2018 05:03:14 +0000 (13:03 +0800)
committerkennytm <kennytm@gmail.com>
Tue, 13 Nov 2018 11:20:37 +0000 (19:20 +0800)
Small fixes on code blocks in rustdoc

It currently has a little margin issue with the `i` and there were js errors.

r? @QuietMisdreavus

293 files changed:
src/Cargo.lock
src/bootstrap/bootstrap.py
src/bootstrap/compile.rs
src/bootstrap/dist.rs
src/ci/docker/asmjs/Dockerfile
src/ci/docker/disabled/wasm32/Dockerfile
src/ci/docker/scripts/emscripten.sh
src/ci/docker/wasm32-unknown/Dockerfile
src/doc/rustdoc/src/the-doc-attribute.md
src/liballoc/boxed.rs
src/liballoc/boxed_test.rs
src/liballoc/collections/btree/map.rs
src/liballoc/rc.rs
src/liballoc/sync.rs
src/liballoc/tests/heap.rs
src/liballoc/tests/lib.rs
src/liballoc_system/Cargo.toml [deleted file]
src/liballoc_system/lib.rs [deleted file]
src/libcore/alloc.rs
src/libcore/cell.rs
src/libcore/char/methods.rs
src/libcore/convert.rs
src/libcore/future/future.rs
src/libcore/intrinsics.rs
src/libcore/iter/sources.rs
src/libcore/lib.rs
src/libcore/macros.rs
src/libcore/marker.rs
src/libcore/mem.rs
src/libcore/num/flt2dec/estimator.rs
src/libcore/num/flt2dec/mod.rs
src/libcore/num/mod.rs
src/libcore/num/wrapping.rs
src/libcore/ops/range.rs
src/libcore/pin.rs
src/libcore/ptr.rs
src/libcore/slice/mod.rs
src/libcore/str/mod.rs
src/libcore/time.rs
src/libcore/unicode/tables.rs
src/libpanic_abort/lib.rs
src/librustc/diagnostics.rs
src/librustc/hir/lowering.rs
src/librustc/hir/mod.rs
src/librustc/infer/error_reporting/mod.rs
src/librustc/infer/opaque_types/mod.rs
src/librustc/infer/outlives/obligations.rs
src/librustc/infer/outlives/verify.rs
src/librustc/lint/builtin.rs
src/librustc/macros.rs
src/librustc/middle/dependency_format.rs
src/librustc/mir/interpret/allocation.rs [new file with mode: 0644]
src/librustc/mir/interpret/mod.rs
src/librustc/mir/interpret/pointer.rs [new file with mode: 0644]
src/librustc/mir/interpret/value.rs
src/librustc/mir/mod.rs
src/librustc/mir/tcx.rs
src/librustc/session/config.rs
src/librustc/session/mod.rs
src/librustc/traits/mod.rs
src/librustc/traits/project.rs
src/librustc/traits/specialize/mod.rs
src/librustc/traits/specialize/specialization_graph.rs
src/librustc/traits/util.rs
src/librustc/ty/context.rs
src/librustc/ty/mod.rs
src/librustc/ty/outlives.rs
src/librustc/ty/query/on_disk_cache.rs
src/librustc/ty/sty.rs
src/librustc/ty/subst.rs
src/librustc_apfloat/Cargo.toml
src/librustc_apfloat/ieee.rs
src/librustc_apfloat/lib.rs
src/librustc_asan/Cargo.toml
src/librustc_asan/lib.rs
src/librustc_codegen_llvm/abi.rs
src/librustc_codegen_llvm/back/archive.rs
src/librustc_codegen_llvm/back/bytecode.rs
src/librustc_codegen_llvm/back/link.rs
src/librustc_codegen_llvm/back/lto.rs
src/librustc_codegen_llvm/back/rpath.rs
src/librustc_codegen_llvm/back/wasm.rs
src/librustc_codegen_llvm/back/write.rs
src/librustc_codegen_llvm/base.rs
src/librustc_codegen_llvm/builder.rs
src/librustc_codegen_llvm/context.rs
src/librustc_codegen_llvm/debuginfo/metadata.rs
src/librustc_codegen_llvm/intrinsic.rs
src/librustc_codegen_llvm/llvm/ffi.rs
src/librustc_codegen_llvm/llvm_util.rs
src/librustc_codegen_llvm/meth.rs
src/librustc_codegen_llvm/mir/block.rs
src/librustc_codegen_llvm/mir/mod.rs
src/librustc_codegen_llvm/mir/operand.rs
src/librustc_codegen_llvm/type_.rs
src/librustc_codegen_llvm/type_of.rs
src/librustc_codegen_utils/linker.rs
src/librustc_codegen_utils/symbol_export.rs
src/librustc_data_structures/lib.rs
src/librustc_data_structures/macros.rs [new file with mode: 0644]
src/librustc_errors/emitter.rs
src/librustc_lint/lib.rs
src/librustc_lsan/Cargo.toml
src/librustc_lsan/lib.rs
src/librustc_metadata/creader.rs
src/librustc_mir/borrow_check/borrow_set.rs
src/librustc_mir/borrow_check/mod.rs
src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
src/librustc_mir/borrow_check/nll/type_check/mod.rs
src/librustc_mir/borrow_check/used_muts.rs
src/librustc_mir/dataflow/move_paths/builder.rs
src/librustc_mir/interpret/intrinsics.rs
src/librustc_mir/interpret/machine.rs
src/librustc_mir/interpret/memory.rs
src/librustc_mir/interpret/operand.rs
src/librustc_mir/interpret/place.rs
src/librustc_mir/interpret/snapshot.rs
src/librustc_mir/interpret/validity.rs
src/librustc_mir/shim.rs
src/librustc_mir/transform/cleanup_post_borrowck.rs
src/librustc_mir/transform/const_prop.rs
src/librustc_mir/transform/inline.rs
src/librustc_mir/transform/promote_consts.rs
src/librustc_mir/transform/qualify_consts.rs
src/librustc_msan/Cargo.toml
src/librustc_msan/lib.rs
src/librustc_resolve/macros.rs
src/librustc_target/abi/mod.rs
src/librustc_target/spec/aarch64_unknown_freebsd.rs
src/librustc_target/spec/aarch64_unknown_linux_gnu.rs
src/librustc_target/spec/aarch64_unknown_linux_musl.rs
src/librustc_target/spec/hermit_base.rs
src/librustc_target/spec/l4re_base.rs
src/librustc_target/spec/linux_musl_base.rs
src/librustc_target/spec/mips64_unknown_linux_gnuabi64.rs
src/librustc_target/spec/mips64el_unknown_linux_gnuabi64.rs
src/librustc_target/spec/mips_unknown_linux_gnu.rs
src/librustc_target/spec/mips_unknown_linux_musl.rs
src/librustc_target/spec/mips_unknown_linux_uclibc.rs
src/librustc_target/spec/mipsel_unknown_linux_gnu.rs
src/librustc_target/spec/mipsel_unknown_linux_musl.rs
src/librustc_target/spec/mipsel_unknown_linux_uclibc.rs
src/librustc_target/spec/mod.rs
src/librustc_target/spec/powerpc64_unknown_linux_gnu.rs
src/librustc_target/spec/powerpc64le_unknown_linux_gnu.rs
src/librustc_target/spec/powerpc64le_unknown_linux_musl.rs
src/librustc_target/spec/powerpc_unknown_linux_gnu.rs
src/librustc_target/spec/powerpc_unknown_linux_gnuspe.rs
src/librustc_target/spec/powerpc_unknown_netbsd.rs
src/librustc_target/spec/s390x_unknown_linux_gnu.rs
src/librustc_target/spec/sparc64_unknown_linux_gnu.rs
src/librustc_target/spec/sparc_unknown_linux_gnu.rs
src/librustc_target/spec/sparcv9_sun_solaris.rs
src/librustc_target/spec/wasm32_unknown_emscripten.rs
src/librustc_target/spec/x86_64_rumprun_netbsd.rs
src/librustc_traits/implied_outlives_bounds.rs
src/librustc_traits/type_op.rs
src/librustc_tsan/Cargo.toml
src/librustc_tsan/lib.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/intrinsic.rs
src/librustc_typeck/check/wfcheck.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/diagnostics.rs
src/librustc_typeck/outlives/utils.rs
src/librustdoc/clean/mod.rs
src/librustdoc/config.rs
src/librustdoc/html/render.rs
src/librustdoc/html/static/rustdoc.css
src/librustdoc/html/static_files.rs [new file with mode: 0644]
src/librustdoc/lib.rs
src/libstd/Cargo.toml
src/libstd/alloc.rs
src/libstd/ffi/c_str.rs
src/libstd/lib.rs
src/libstd/macros.rs
src/libstd/net/ip.rs
src/libstd/process.rs
src/libstd/sync/mpsc/mod.rs
src/libstd/sync/mpsc/select.rs
src/libstd/sys/cloudabi/mod.rs
src/libstd/sys/redox/mod.rs
src/libstd/sys/unix/alloc.rs [new file with mode: 0644]
src/libstd/sys/unix/mod.rs
src/libstd/sys/wasm/alloc.rs [new file with mode: 0644]
src/libstd/sys/wasm/mod.rs
src/libstd/sys/windows/alloc.rs [new file with mode: 0644]
src/libstd/sys/windows/c.rs
src/libstd/sys/windows/mod.rs
src/libstd/sys_common/alloc.rs [new file with mode: 0644]
src/libstd/sys_common/mod.rs
src/libsyntax/ast.rs
src/libsyntax/ext/base.rs
src/libsyntax/ext/build.rs
src/libsyntax/ext/quote.rs
src/libsyntax/ext/tt/macro_parser.rs
src/libsyntax/parse/parser.rs
src/llvm-emscripten
src/rustllvm/ArchiveWrapper.cpp
src/rustllvm/PassWrapper.cpp
src/rustllvm/RustWrapper.cpp
src/test/codegen/enum-debug-niche-2.rs [new file with mode: 0644]
src/test/codegen/packed.rs
src/test/codegen/stores.rs
src/test/mir-opt/inline-trait-method_2.rs [new file with mode: 0644]
src/test/run-fail/mir_drop_panics.rs
src/test/run-fail/panic-set-handler.rs
src/test/run-pass/associated-types/associated-types-from-supertrait.rs [new file with mode: 0644]
src/test/run-pass/consts/const-endianess.rs
src/test/run-pass/issues/issue-13494.rs
src/test/run-pass/issues/issue-24010.rs [new file with mode: 0644]
src/test/run-pass/traits/trait-alias-object-type.rs [deleted file]
src/test/run-pass/traits/trait-alias-object.rs [new file with mode: 0644]
src/test/rustdoc/inline_cross/auxiliary/use_crate.rs [new file with mode: 0644]
src/test/rustdoc/inline_cross/auxiliary/use_crate_2.rs [new file with mode: 0644]
src/test/rustdoc/inline_cross/use_crate.rs [new file with mode: 0644]
src/test/rustdoc/src-links-external.rs
src/test/ui/associated-types/associated-types-overridden-binding-2.rs [new file with mode: 0644]
src/test/ui/associated-types/associated-types-overridden-binding-2.stderr [new file with mode: 0644]
src/test/ui/associated-types/associated-types-overridden-binding.rs [new file with mode: 0644]
src/test/ui/associated-types/associated-types-overridden-binding.stderr [new file with mode: 0644]
src/test/ui/borrowck/borrowck-box-insensitivity.ast.stderr [new file with mode: 0644]
src/test/ui/borrowck/borrowck-box-insensitivity.mir.stderr [new file with mode: 0644]
src/test/ui/borrowck/borrowck-box-insensitivity.rs
src/test/ui/borrowck/borrowck-box-insensitivity.stderr [deleted file]
src/test/ui/borrowck/borrowck-union-move-assign.nll.stderr
src/test/ui/borrowck/issue-55552-ascribe-wildcard-to-structured-pattern.rs [new file with mode: 0644]
src/test/ui/borrowck/reassignment_immutable_fields_overlapping.nll.stderr
src/test/ui/coherence/coherence-impls-copy.stderr
src/test/ui/consts/auxiliary/promotable_const_fn_lib.rs [new file with mode: 0644]
src/test/ui/consts/const-eval/duration_conversion.rs
src/test/ui/consts/const-eval/mod-static-with-const-fn.rs
src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr
src/test/ui/consts/const-prop-ice.rs [new file with mode: 0644]
src/test/ui/consts/const-prop-ice.stderr [new file with mode: 0644]
src/test/ui/consts/const-prop-ice2.rs [new file with mode: 0644]
src/test/ui/consts/const-prop-ice2.stderr [new file with mode: 0644]
src/test/ui/consts/promote_fn_calls.rs [new file with mode: 0644]
src/test/ui/consts/promote_fn_calls_std.rs [new file with mode: 0644]
src/test/ui/consts/std/cell.rs [new file with mode: 0644]
src/test/ui/consts/std/cell.stderr [new file with mode: 0644]
src/test/ui/consts/std/char.rs [new file with mode: 0644]
src/test/ui/consts/std/iter.rs [new file with mode: 0644]
src/test/ui/consts/std/slice.rs [new file with mode: 0644]
src/test/ui/e0119/issue-28981.stderr
src/test/ui/error-codes/E0191.rs
src/test/ui/error-codes/E0719.rs [new file with mode: 0644]
src/test/ui/error-codes/E0719.stderr [new file with mode: 0644]
src/test/ui/extern/extern-const.fixed [new file with mode: 0644]
src/test/ui/extern/extern-const.rs
src/test/ui/extern/extern-const.stderr
src/test/ui/hygiene/no_implicit_prelude-2018.rs [new file with mode: 0644]
src/test/ui/hygiene/no_implicit_prelude-2018.stderr [new file with mode: 0644]
src/test/ui/hygiene/no_implicit_prelude.rs
src/test/ui/impl-trait/issue-55608-captures-empty-region.rs [new file with mode: 0644]
src/test/ui/impl-trait/issue-55608-captures-empty-region.stderr [new file with mode: 0644]
src/test/ui/inline-asm-bad-constraint.rs
src/test/ui/inline-asm-bad-constraint.stderr
src/test/ui/inline-asm-bad-operand.rs
src/test/ui/inline-asm-bad-operand.stderr
src/test/ui/issue-51947.rs [deleted file]
src/test/ui/issues/issue-23122-2.stderr
src/test/ui/issues/issue-49579.rs
src/test/ui/issues/issue-51947.rs [new file with mode: 0644]
src/test/ui/issues/issue-55796.rs [new file with mode: 0644]
src/test/ui/issues/issue-55796.stderr [new file with mode: 0644]
src/test/ui/lint/issue-50589-multiple-associated-types.rs [deleted file]
src/test/ui/lint/issue-50589-multiple-associated-types.stderr [deleted file]
src/test/ui/lint/lint-unused-mut-variables.lexical.stderr [deleted file]
src/test/ui/lint/lint-unused-mut-variables.nll.stderr [deleted file]
src/test/ui/lint/lint-unused-mut-variables.rs
src/test/ui/lint/lint-unused-mut-variables.stderr [new file with mode: 0644]
src/test/ui/match/match-fn-call.rs [new file with mode: 0644]
src/test/ui/match/match-fn-call.stderr [new file with mode: 0644]
src/test/ui/nll/issue-55344.rs [new file with mode: 0644]
src/test/ui/nll/issue-55394.rs [new file with mode: 0644]
src/test/ui/nll/issue-55394.stderr [new file with mode: 0644]
src/test/ui/nll/issue-55651.rs [new file with mode: 0644]
src/test/ui/range/issue-54505-no-std.rs
src/test/ui/rfc-2306/convert-id-const-no-gate.rs [deleted file]
src/test/ui/rfc-2306/convert-id-const-no-gate.stderr [deleted file]
src/test/ui/rfc-2306/convert-id-const-with-gate.rs
src/test/ui/rfc1445/phantom-data-is-structurally-matchable.rs [new file with mode: 0644]
src/test/ui/traits/trait-alias-object.rs [new file with mode: 0644]
src/test/ui/traits/trait-alias-object.stderr [new file with mode: 0644]
src/test/ui/traits/trait-alias-objects.rs [deleted file]
src/test/ui/traits/trait-alias-objects.stderr [deleted file]
src/test/ui/typeck/issue-55810-must-typeck-match-pats-before-guards.rs [new file with mode: 0644]
src/tools/cargo
src/tools/compiletest/src/runtest.rs
src/tools/rustc-workspace-hack/Cargo.toml
src/tools/tidy/src/pal.rs

index b4317864502cee0fd48979f54fb6f057b47c0bcf..32304c81182f16464301837615f71871247c279b 100644 (file)
@@ -15,16 +15,6 @@ dependencies = [
  "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "alloc_system"
-version = "0.0.0"
-dependencies = [
- "compiler_builtins 0.0.0",
- "core 0.0.0",
- "dlmalloc 0.0.0",
- "libc 0.0.0",
-]
-
 [[package]]
 name = "ammonia"
 version = "1.1.0"
@@ -197,7 +187,8 @@ dependencies = [
  "crates-io 0.21.0",
  "crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "curl 0.4.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl-sys 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.5.12 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -230,7 +221,7 @@ dependencies = [
  "serde_ignored 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "shell-escape 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "tar 0.4.16 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tar 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)",
  "tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "termcolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -474,7 +465,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 name = "crates-io"
 version = "0.21.0"
 dependencies = [
- "curl 0.4.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -561,10 +552,10 @@ dependencies = [
 
 [[package]]
 name = "curl"
-version = "0.4.18"
+version = "0.4.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "curl-sys 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl-sys 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -576,7 +567,7 @@ dependencies = [
 
 [[package]]
 name = "curl-sys"
-version = "0.4.13"
+version = "0.4.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -848,7 +839,7 @@ name = "git2-curl"
 version = "0.8.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "curl 0.4.18 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)",
  "git2 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -966,7 +957,7 @@ dependencies = [
  "flate2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "tar 0.4.16 (registry+https://github.com/rust-lang/crates.io-index)",
+ "tar 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)",
  "walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "xz2 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1088,7 +1079,7 @@ version = "0.7.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
- "curl-sys 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
+ "curl-sys 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "libssh2-sys 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "libz-sys 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2095,6 +2086,7 @@ version = "0.0.0"
 dependencies = [
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_cratesio_shim 0.0.0",
+ "smallvec 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2102,7 +2094,6 @@ name = "rustc_asan"
 version = "0.0.0"
 dependencies = [
  "alloc 0.0.0",
- "alloc_system 0.0.0",
  "build_helper 0.1.0",
  "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "compiler_builtins 0.0.0",
@@ -2274,7 +2265,6 @@ name = "rustc_lsan"
 version = "0.0.0"
 dependencies = [
  "alloc 0.0.0",
- "alloc_system 0.0.0",
  "build_helper 0.1.0",
  "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "compiler_builtins 0.0.0",
@@ -2326,7 +2316,6 @@ name = "rustc_msan"
 version = "0.0.0"
 dependencies = [
  "alloc 0.0.0",
- "alloc_system 0.0.0",
  "build_helper 0.1.0",
  "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "compiler_builtins 0.0.0",
@@ -2438,7 +2427,6 @@ name = "rustc_tsan"
 version = "0.0.0"
 dependencies = [
  "alloc 0.0.0",
- "alloc_system 0.0.0",
  "build_helper 0.1.0",
  "cmake 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
  "compiler_builtins 0.0.0",
@@ -2677,11 +2665,11 @@ name = "std"
 version = "0.0.0"
 dependencies = [
  "alloc 0.0.0",
- "alloc_system 0.0.0",
  "build_helper 0.1.0",
  "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "compiler_builtins 0.0.0",
  "core 0.0.0",
+ "dlmalloc 0.0.0",
  "libc 0.0.0",
  "panic_abort 0.0.0",
  "panic_unwind 0.0.0",
@@ -2838,7 +2826,7 @@ dependencies = [
 
 [[package]]
 name = "tar"
-version = "0.4.16"
+version = "0.4.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3210,8 +3198,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
 "checksum crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "677d453a17e8bd2b913fa38e8b9cf04bcdbb5be790aa294f2389661d72036015"
 "checksum crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "09de9ee0fc255ace04c7fa0763c9395a945c37c8292bb554f8d48361d1dcf1b4"
-"checksum curl 0.4.18 (registry+https://github.com/rust-lang/crates.io-index)" = "a9e5285b49b44401518c947d3b808d14d99a538a6c9ffb3ec0205c11f9fc4389"
-"checksum curl-sys 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "08459503c415173da1ce6b41036a37b8bfdd86af46d45abb9964d4c61fe670ef"
+"checksum curl 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)" = "c7c9d851c825e0c033979d4516c9173bc19a78a96eb4d6ae51d4045440eafa16"
+"checksum curl-sys 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)" = "721c204978be2143fab0a84b708c49d79d1f6100b8785610f456043a90708870"
 "checksum datafrog 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "16d724bf4ffe77cdceeecd461009b5f8d9e23c5d645d68bedb4586bf43e7e142"
 "checksum derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ceed73957c449214f8440eec8ad7fa282b67dc9eacbb24a3085b15d60397a17a"
 "checksum derive_more 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46c7f14685a20f5dd08e7f754f2ea8cc064d8f4214ae21116c106a2768ba7b9b"
@@ -3390,7 +3378,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741"
 "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
 "checksum synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85bb9b7550d063ea184027c9b8c20ac167cd36d3e06b3a40bceb9d746dc1a7b7"
-"checksum tar 0.4.16 (registry+https://github.com/rust-lang/crates.io-index)" = "e8f41ca4a5689f06998f0247fcb60da6c760f1950cc9df2a10d71575ad0b062a"
+"checksum tar 0.4.19 (registry+https://github.com/rust-lang/crates.io-index)" = "69e16840a1e0a1f1a880b739ef1cc6a4b85496c99b8aa786ccffce6e0c15624c"
 "checksum tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c4b103c6d08d323b92ff42c8ce62abcd83ca8efa7fd5bf7927efefec75f58c76"
 "checksum tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9de21546595a0873061940d994bbbc5c35f024ae4fd61ec5c5b159115684f508"
 "checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561"
index fdd8784453bdb8c509b8bf4824921e327fb2246e..cd48e6aa4c4ba36c1ff14711ec602d416de8141c 100644 (file)
@@ -79,8 +79,8 @@ def _download(path, url, probably_big, verbose, exception):
     # see http://serverfault.com/questions/301128/how-to-download
     if sys.platform == 'win32':
         run(["PowerShell.exe", "/nologo", "-Command",
-             "(New-Object System.Net.WebClient)"
-             ".DownloadFile('{}', '{}')".format(url, path)],
+             "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;",
+             "(New-Object System.Net.WebClient).DownloadFile('{}', '{}')".format(url, path)],
             verbose=verbose,
             exception=exception)
     else:
index 885ad07e0873604adb3b420b6eff5cee74f6ad98..cef0849937bf01861602cc947e48c63e562b2fc5 100644 (file)
@@ -736,7 +736,7 @@ pub fn build_codegen_backend(builder: &Builder,
 
             // Pass down configuration from the LLVM build into the build of
             // librustc_llvm and librustc_codegen_llvm.
-            if builder.is_rust_llvm(target) {
+            if builder.is_rust_llvm(target) && backend != "emscripten" {
                 cargo.env("LLVM_RUSTLLVM", "1");
             }
             cargo.env("LLVM_CONFIG", &llvm_config);
index 567b47a70a12cc52143c3c534e2ce45d1dff4529..0aab64465fd1c48ce6974392659cd60a1eca286a 100644 (file)
@@ -859,7 +859,6 @@ fn run(self, builder: &Builder) -> PathBuf {
             "src/build_helper",
             "src/dlmalloc",
             "src/liballoc",
-            "src/liballoc_system",
             "src/libbacktrace",
             "src/libcompiler_builtins",
             "src/libcore",
index cb85cf3d9e9f094f87ba6617250e55ef68a7fd42..9eaffbf83eb4e43e897c93dfc814c4b53ec2f50e 100644 (file)
@@ -20,11 +20,11 @@ COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
 ENV PATH=$PATH:/emsdk-portable
-ENV PATH=$PATH:/emsdk-portable/clang/e1.37.13_64bit/
-ENV PATH=$PATH:/emsdk-portable/emscripten/1.37.13/
-ENV PATH=$PATH:/emsdk-portable/node/4.1.1_64bit/bin/
-ENV EMSCRIPTEN=/emsdk-portable/emscripten/1.37.13/
-ENV BINARYEN_ROOT=/emsdk-portable/clang/e1.37.13_64bit/binaryen/
+ENV PATH=$PATH:/emsdk-portable/clang/e1.38.15_64bit/
+ENV PATH=$PATH:/emsdk-portable/emscripten/1.38.15/
+ENV PATH=$PATH:/emsdk-portable/node/8.9.1_64bit/bin/
+ENV EMSCRIPTEN=/emsdk-portable/emscripten/1.38.15/
+ENV BINARYEN_ROOT=/emsdk-portable/clang/e1.38.15_64bit/binaryen/
 ENV EM_CONFIG=/emsdk-portable/.emscripten
 
 ENV TARGETS=asmjs-unknown-emscripten
index 6ac90d17450a37fbac1bcd610a0b86eaa72b3f8e..0d2bd39303ef8e1191b6986be45d546842b2b734 100644 (file)
@@ -21,11 +21,11 @@ COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
 ENV PATH=$PATH:/emsdk-portable
-ENV PATH=$PATH:/emsdk-portable/clang/e1.37.13_64bit/
-ENV PATH=$PATH:/emsdk-portable/emscripten/1.37.13/
-ENV PATH=$PATH:/node-v8.0.0-linux-x64/bin/
-ENV EMSCRIPTEN=/emsdk-portable/emscripten/1.37.13/
-ENV BINARYEN_ROOT=/emsdk-portable/clang/e1.37.13_64bit/binaryen/
+ENV PATH=$PATH:/emsdk-portable/clang/e1.38.15_64bit/
+ENV PATH=$PATH:/emsdk-portable/emscripten/1.38.15/
+ENV PATH=$PATH:/emsdk-portable/node/8.9.1_64bit/bin/
+ENV EMSCRIPTEN=/emsdk-portable/emscripten/1.38.15/
+ENV BINARYEN_ROOT=/emsdk-portable/clang/e1.38.15_64bit/binaryen/
 ENV EM_CONFIG=/emsdk-portable/.emscripten
 
 ENV TARGETS=wasm32-unknown-emscripten
index d32ed6b461d858394775710d657f2cbe26bbfff4..1d7b33db9ed86b32f94ac2a78f16341052de0dda 100644 (file)
@@ -33,8 +33,8 @@ curl -fL https://s3.amazonaws.com/mozilla-games/emscripten/releases/emsdk-portab
 
 cd /emsdk-portable
 ./emsdk update
-hide_output ./emsdk install sdk-1.37.13-64bit
-./emsdk activate sdk-1.37.13-64bit
+hide_output ./emsdk install sdk-1.38.15-64bit
+./emsdk activate sdk-1.38.15-64bit
 
 # Compile and cache libc
 source ./emsdk_env.sh
@@ -46,8 +46,3 @@ rm -f a.*
 # Make emsdk usable by any user
 cp /root/.emscripten /emsdk-portable
 chmod a+rxw -R /emsdk-portable
-
-# node 8 is required to run wasm
-cd /
-curl -sL https://nodejs.org/dist/v8.0.0/node-v8.0.0-linux-x64.tar.xz | \
-  tar -xJ
index f2a29b0315100cda4328c588c01646e2c0de718d..161f0c0062fa012d2685ef521403c960c50abae4 100644 (file)
@@ -1,4 +1,4 @@
-FROM ubuntu:16.04
+FROM ubuntu:18.04
 
 RUN apt-get update && apt-get install -y --no-install-recommends \
   g++ \
index 296422744fa4059a4b7f0f19e202f76d9830d4ce..61e5b3d0133ff6980bd886d17070197b34f3eace 100644 (file)
@@ -186,6 +186,9 @@ mod bar {
 
 Now we'll have a `Re-exports` line, and `Bar` will not link to anywhere.
 
+One special case: In Rust 2018 and later, if you `pub use` one of your dependencies, `rustdoc` will
+not eagerly inline it as a module unless you add `#[doc(inline)}`.
+
 ## `#[doc(hidden)]`
 
 Any item annotated with `#[doc(hidden)]` will not appear in the documentation, unless
index 74354f605e5370d1824dc58d03d0b4266e4ce23a..63b262d1f3d986ac22aa793a2270c1b735e11a3e 100644 (file)
@@ -73,7 +73,7 @@
 use core::fmt;
 use core::future::Future;
 use core::hash::{Hash, Hasher};
-use core::iter::FusedIterator;
+use core::iter::{Iterator, FromIterator, FusedIterator};
 use core::marker::{Unpin, Unsize};
 use core::mem;
 use core::pin::Pin;
@@ -81,6 +81,7 @@
 use core::ptr::{self, NonNull, Unique};
 use core::task::{LocalWaker, Poll};
 
+use vec::Vec;
 use raw_vec::RawVec;
 use str::from_boxed_utf8_unchecked;
 
@@ -699,6 +700,13 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Box<U>> for Box<T> {}
 #[unstable(feature = "dispatch_from_dyn", issue = "0")]
 impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Box<U>> for Box<T> {}
 
+#[stable(feature = "boxed_slice_from_iter", since = "1.32.0")]
+impl<A> FromIterator<A> for Box<[A]> {
+    fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self {
+        iter.into_iter().collect::<Vec<_>>().into_boxed_slice()
+    }
+}
+
 #[stable(feature = "box_slice_clone", since = "1.3.0")]
 impl<T: Clone> Clone for Box<[T]> {
     fn clone(&self) -> Self {
index 55995742a4a7da7bfa1ce5ec4008145190da7842..f340ea01c5f07d0b6d8bc35865985d621ea4a50a 100644 (file)
@@ -140,3 +140,11 @@ fn str_slice() {
     let boxed: Box<str> = Box::from(s);
     assert_eq!(&*boxed, s)
 }
+
+#[test]
+fn boxed_slice_from_iter() {
+    let iter = 0..100;
+    let boxed: Box<[u32]> = iter.collect();
+    assert_eq!(boxed.len(), 100);
+    assert_eq!(boxed[7], 7);
+}
index 24c8fd3a969ca3e1bde035f6531cf3c6456d7bb2..49e488702b4b9538e7f650d3ec99af540ff09045 100644 (file)
@@ -853,9 +853,10 @@ pub fn range<T: ?Sized, R>(&self, range: R) -> Range<K, V>
     /// ```
     /// use std::collections::BTreeMap;
     ///
-    /// let mut map: BTreeMap<&str, i32> = ["Alice", "Bob", "Carol", "Cheryl"].iter()
-    ///                                                                       .map(|&s| (s, 0))
-    ///                                                                       .collect();
+    /// let mut map: BTreeMap<&str, i32> = ["Alice", "Bob", "Carol", "Cheryl"]
+    ///     .iter()
+    ///     .map(|&s| (s, 0))
+    ///     .collect();
     /// for (_, balance) in map.range_mut("B".."Cheryl") {
     ///     *balance += 100;
     /// }
index 45f035ad04f8ff812de4c3bd4e1862bb5d47c65a..bb52d7990ff5772fdc27c821ee3c730896af9630 100644 (file)
@@ -672,14 +672,16 @@ unsafe fn allocate_for_ptr(ptr: *const T) -> *mut RcBox<T> {
         // Previously, layout was calculated on the expression
         // `&*(ptr as *const RcBox<T>)`, but this created a misaligned
         // reference (see #54908).
-        let (layout, _) = Layout::new::<RcBox<()>>()
-            .extend(Layout::for_value(&*ptr)).unwrap();
+        let layout = Layout::new::<RcBox<()>>()
+            .extend(Layout::for_value(&*ptr)).unwrap().0
+            .pad_to_align().unwrap();
 
         let mem = Global.alloc(layout)
             .unwrap_or_else(|_| handle_alloc_error(layout));
 
         // Initialize the RcBox
         let inner = set_data_ptr(ptr as *mut T, mem.as_ptr() as *mut u8) as *mut RcBox<T>;
+        debug_assert_eq!(Layout::for_value(&*inner), layout);
 
         ptr::write(&mut (*inner).strong, Cell::new(1));
         ptr::write(&mut (*inner).weak, Cell::new(1));
index 2c396b3b06bda34351046554a73a3f41e79844c9..b63b3684964bb64038366cf6d12365614a99c2a9 100644 (file)
@@ -575,14 +575,16 @@ unsafe fn allocate_for_ptr(ptr: *const T) -> *mut ArcInner<T> {
         // Previously, layout was calculated on the expression
         // `&*(ptr as *const ArcInner<T>)`, but this created a misaligned
         // reference (see #54908).
-        let (layout, _) = Layout::new::<ArcInner<()>>()
-            .extend(Layout::for_value(&*ptr)).unwrap();
+        let layout = Layout::new::<ArcInner<()>>()
+            .extend(Layout::for_value(&*ptr)).unwrap().0
+            .pad_to_align().unwrap();
 
         let mem = Global.alloc(layout)
             .unwrap_or_else(|_| handle_alloc_error(layout));
 
         // Initialize the ArcInner
         let inner = set_data_ptr(ptr as *mut T, mem.as_ptr() as *mut u8) as *mut ArcInner<T>;
+        debug_assert_eq!(Layout::for_value(&*inner), layout);
 
         ptr::write(&mut (*inner).strong, atomic::AtomicUsize::new(1));
         ptr::write(&mut (*inner).weak, atomic::AtomicUsize::new(1));
index b6be38107da7f33eefd4607b3cd6c3f145a5de7f..bf256b23f9ac0eb459ad7a29a6be7eb6d239c64f 100644 (file)
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use alloc_system::System;
-use std::alloc::{Global, Alloc, Layout};
+use std::alloc::{Global, Alloc, Layout, System};
 
 /// https://github.com/rust-lang/rust/issues/45955
 #[test]
index 3294837cb91c4ff2fa92defccc08e410ccae84a4..e514a8a69c020701ea4e42fb31425628901722e8 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 #![feature(allocator_api)]
-#![feature(alloc_system)]
 #![feature(box_syntax)]
 #![feature(drain_filter)]
 #![feature(exact_size_is_empty)]
@@ -20,7 +19,6 @@
 #![feature(unboxed_closures)]
 #![feature(repeat_generic_slice)]
 
-extern crate alloc_system;
 extern crate core;
 extern crate rand;
 
diff --git a/src/liballoc_system/Cargo.toml b/src/liballoc_system/Cargo.toml
deleted file mode 100644 (file)
index c34e2f2..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-[package]
-authors = ["The Rust Project Developers"]
-name = "alloc_system"
-version = "0.0.0"
-
-[lib]
-name = "alloc_system"
-path = "lib.rs"
-test = false
-doc = false
-
-[dependencies]
-core = { path = "../libcore" }
-libc = { path = "../rustc/libc_shim" }
-compiler_builtins = { path = "../rustc/compiler_builtins_shim" }
-
-# See comments in the source for what this dependency is
-[target.'cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))'.dependencies]
-dlmalloc = { path = "../rustc/dlmalloc_shim" }
diff --git a/src/liballoc_system/lib.rs b/src/liballoc_system/lib.rs
deleted file mode 100644 (file)
index 0e6887a..0000000
+++ /dev/null
@@ -1,411 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![no_std]
-#![allow(unused_attributes)]
-#![unstable(feature = "alloc_system",
-            reason = "this library is unlikely to be stabilized in its current \
-                      form or name",
-            issue = "32838")]
-
-#![feature(allocator_api)]
-#![feature(core_intrinsics)]
-#![feature(nll)]
-#![feature(staged_api)]
-#![feature(rustc_attrs)]
-#![cfg_attr(
-    all(target_arch = "wasm32", not(target_os = "emscripten")),
-    feature(integer_atomics, stdsimd)
-)]
-#![cfg_attr(any(unix, target_os = "cloudabi", target_os = "redox"), feature(libc))]
-#![rustc_alloc_kind = "lib"]
-
-// The minimum alignment guaranteed by the architecture. This value is used to
-// add fast paths for low alignment values.
-#[cfg(all(any(target_arch = "x86",
-              target_arch = "arm",
-              target_arch = "mips",
-              target_arch = "powerpc",
-              target_arch = "powerpc64",
-              target_arch = "asmjs",
-              target_arch = "wasm32")))]
-#[allow(dead_code)]
-const MIN_ALIGN: usize = 8;
-#[cfg(all(any(target_arch = "x86_64",
-              target_arch = "aarch64",
-              target_arch = "mips64",
-              target_arch = "s390x",
-              target_arch = "sparc64")))]
-#[allow(dead_code)]
-const MIN_ALIGN: usize = 16;
-
-use core::alloc::{Alloc, GlobalAlloc, AllocErr, Layout};
-use core::ptr::NonNull;
-
-/// The default memory allocator provided by the operating system.
-///
-/// This is based on `malloc` on Unix platforms and `HeapAlloc` on Windows,
-/// plus related functions.
-///
-/// This type can be used in a `static` item
-/// with the `#[global_allocator]` attribute
-/// to force the global allocator to be the system’s one.
-/// (The default is jemalloc for executables, on some platforms.)
-///
-/// ```rust
-/// use std::alloc::System;
-///
-/// #[global_allocator]
-/// static A: System = System;
-///
-/// fn main() {
-///     let a = Box::new(4); // Allocates from the system allocator.
-///     println!("{}", a);
-/// }
-/// ```
-///
-/// It can also be used directly to allocate memory
-/// independently of the standard library’s global allocator.
-#[stable(feature = "alloc_system_type", since = "1.28.0")]
-pub struct System;
-
-#[unstable(feature = "allocator_api", issue = "32838")]
-unsafe impl Alloc for System {
-    #[inline]
-    unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
-        NonNull::new(GlobalAlloc::alloc(self, layout)).ok_or(AllocErr)
-    }
-
-    #[inline]
-    unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
-        NonNull::new(GlobalAlloc::alloc_zeroed(self, layout)).ok_or(AllocErr)
-    }
-
-    #[inline]
-    unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) {
-        GlobalAlloc::dealloc(self, ptr.as_ptr(), layout)
-    }
-
-    #[inline]
-    unsafe fn realloc(&mut self,
-                      ptr: NonNull<u8>,
-                      layout: Layout,
-                      new_size: usize) -> Result<NonNull<u8>, AllocErr> {
-        NonNull::new(GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size)).ok_or(AllocErr)
-    }
-}
-
-#[cfg(any(windows, unix, target_os = "cloudabi", target_os = "redox"))]
-mod realloc_fallback {
-    use core::alloc::{GlobalAlloc, Layout};
-    use core::cmp;
-    use core::ptr;
-
-    impl super::System {
-        pub(crate) unsafe fn realloc_fallback(&self, ptr: *mut u8, old_layout: Layout,
-                                              new_size: usize) -> *mut u8 {
-            // Docs for GlobalAlloc::realloc require this to be valid:
-            let new_layout = Layout::from_size_align_unchecked(new_size, old_layout.align());
-
-            let new_ptr = GlobalAlloc::alloc(self, new_layout);
-            if !new_ptr.is_null() {
-                let size = cmp::min(old_layout.size(), new_size);
-                ptr::copy_nonoverlapping(ptr, new_ptr, size);
-                GlobalAlloc::dealloc(self, ptr, old_layout);
-            }
-            new_ptr
-        }
-    }
-}
-
-#[cfg(any(unix, target_os = "cloudabi", target_os = "redox"))]
-mod platform {
-    extern crate libc;
-
-    use core::ptr;
-
-    use MIN_ALIGN;
-    use System;
-    use core::alloc::{GlobalAlloc, Layout};
-
-    #[stable(feature = "alloc_system_type", since = "1.28.0")]
-    unsafe impl GlobalAlloc for System {
-        #[inline]
-        unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
-            if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
-                libc::malloc(layout.size()) as *mut u8
-            } else {
-                #[cfg(target_os = "macos")]
-                {
-                    if layout.align() > (1 << 31) {
-                        return ptr::null_mut()
-                    }
-                }
-                aligned_malloc(&layout)
-            }
-        }
-
-        #[inline]
-        unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
-            if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
-                libc::calloc(layout.size(), 1) as *mut u8
-            } else {
-                let ptr = self.alloc(layout.clone());
-                if !ptr.is_null() {
-                    ptr::write_bytes(ptr, 0, layout.size());
-                }
-                ptr
-            }
-        }
-
-        #[inline]
-        unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
-            libc::free(ptr as *mut libc::c_void)
-        }
-
-        #[inline]
-        unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
-            if layout.align() <= MIN_ALIGN && layout.align() <= new_size {
-                libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8
-            } else {
-                self.realloc_fallback(ptr, layout, new_size)
-            }
-        }
-    }
-
-    #[cfg(any(target_os = "android",
-              target_os = "hermit",
-              target_os = "redox",
-              target_os = "solaris"))]
-    #[inline]
-    unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
-        // On android we currently target API level 9 which unfortunately
-        // doesn't have the `posix_memalign` API used below. Instead we use
-        // `memalign`, but this unfortunately has the property on some systems
-        // where the memory returned cannot be deallocated by `free`!
-        //
-        // Upon closer inspection, however, this appears to work just fine with
-        // Android, so for this platform we should be fine to call `memalign`
-        // (which is present in API level 9). Some helpful references could
-        // possibly be chromium using memalign [1], attempts at documenting that
-        // memalign + free is ok [2] [3], or the current source of chromium
-        // which still uses memalign on android [4].
-        //
-        // [1]: https://codereview.chromium.org/10796020/
-        // [2]: https://code.google.com/p/android/issues/detail?id=35391
-        // [3]: https://bugs.chromium.org/p/chromium/issues/detail?id=138579
-        // [4]: https://chromium.googlesource.com/chromium/src/base/+/master/
-        //                                       /memory/aligned_memory.cc
-        libc::memalign(layout.align(), layout.size()) as *mut u8
-    }
-
-    #[cfg(not(any(target_os = "android",
-                  target_os = "hermit",
-                  target_os = "redox",
-                  target_os = "solaris")))]
-    #[inline]
-    unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
-        let mut out = ptr::null_mut();
-        let ret = libc::posix_memalign(&mut out, layout.align(), layout.size());
-        if ret != 0 {
-            ptr::null_mut()
-        } else {
-            out as *mut u8
-        }
-    }
-}
-
-#[cfg(windows)]
-#[allow(nonstandard_style)]
-mod platform {
-    use MIN_ALIGN;
-    use System;
-    use core::alloc::{GlobalAlloc, Layout};
-
-    type LPVOID = *mut u8;
-    type HANDLE = LPVOID;
-    type SIZE_T = usize;
-    type DWORD = u32;
-    type BOOL = i32;
-
-    extern "system" {
-        fn GetProcessHeap() -> HANDLE;
-        fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> LPVOID;
-        fn HeapReAlloc(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID, dwBytes: SIZE_T) -> LPVOID;
-        fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL;
-        fn GetLastError() -> DWORD;
-    }
-
-    #[repr(C)]
-    struct Header(*mut u8);
-
-    const HEAP_ZERO_MEMORY: DWORD = 0x00000008;
-
-    unsafe fn get_header<'a>(ptr: *mut u8) -> &'a mut Header {
-        &mut *(ptr as *mut Header).offset(-1)
-    }
-
-    unsafe fn align_ptr(ptr: *mut u8, align: usize) -> *mut u8 {
-        let aligned = ptr.add(align - (ptr as usize & (align - 1)));
-        *get_header(aligned) = Header(ptr);
-        aligned
-    }
-
-    #[inline]
-    unsafe fn allocate_with_flags(layout: Layout, flags: DWORD) -> *mut u8 {
-        let ptr = if layout.align() <= MIN_ALIGN {
-            HeapAlloc(GetProcessHeap(), flags, layout.size())
-        } else {
-            let size = layout.size() + layout.align();
-            let ptr = HeapAlloc(GetProcessHeap(), flags, size);
-            if ptr.is_null() {
-                ptr
-            } else {
-                align_ptr(ptr, layout.align())
-            }
-        };
-        ptr as *mut u8
-    }
-
-    #[stable(feature = "alloc_system_type", since = "1.28.0")]
-    unsafe impl GlobalAlloc for System {
-        #[inline]
-        unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
-            allocate_with_flags(layout, 0)
-        }
-
-        #[inline]
-        unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
-            allocate_with_flags(layout, HEAP_ZERO_MEMORY)
-        }
-
-        #[inline]
-        unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
-            if layout.align() <= MIN_ALIGN {
-                let err = HeapFree(GetProcessHeap(), 0, ptr as LPVOID);
-                debug_assert!(err != 0, "Failed to free heap memory: {}",
-                              GetLastError());
-            } else {
-                let header = get_header(ptr);
-                let err = HeapFree(GetProcessHeap(), 0, header.0 as LPVOID);
-                debug_assert!(err != 0, "Failed to free heap memory: {}",
-                              GetLastError());
-            }
-        }
-
-        #[inline]
-        unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
-            if layout.align() <= MIN_ALIGN {
-                HeapReAlloc(GetProcessHeap(), 0, ptr as LPVOID, new_size) as *mut u8
-            } else {
-                self.realloc_fallback(ptr, layout, new_size)
-            }
-        }
-    }
-}
-
-// This is an implementation of a global allocator on the wasm32 platform when
-// emscripten is not in use. In that situation there's no actual runtime for us
-// to lean on for allocation, so instead we provide our own!
-//
-// The wasm32 instruction set has two instructions for getting the current
-// amount of memory and growing the amount of memory. These instructions are the
-// foundation on which we're able to build an allocator, so we do so! Note that
-// the instructions are also pretty "global" and this is the "global" allocator
-// after all!
-//
-// The current allocator here is the `dlmalloc` crate which we've got included
-// in the rust-lang/rust repository as a submodule. The crate is a port of
-// dlmalloc.c from C to Rust and is basically just so we can have "pure Rust"
-// for now which is currently technically required (can't link with C yet).
-//
-// The crate itself provides a global allocator which on wasm has no
-// synchronization as there are no threads!
-#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
-mod platform {
-    extern crate dlmalloc;
-
-    use core::alloc::{GlobalAlloc, Layout};
-    use System;
-
-    static mut DLMALLOC: dlmalloc::Dlmalloc = dlmalloc::DLMALLOC_INIT;
-
-    #[stable(feature = "alloc_system_type", since = "1.28.0")]
-    unsafe impl GlobalAlloc for System {
-        #[inline]
-        unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
-            let _lock = lock::lock();
-            DLMALLOC.malloc(layout.size(), layout.align())
-        }
-
-        #[inline]
-        unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
-            let _lock = lock::lock();
-            DLMALLOC.calloc(layout.size(), layout.align())
-        }
-
-        #[inline]
-        unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
-            let _lock = lock::lock();
-            DLMALLOC.free(ptr, layout.size(), layout.align())
-        }
-
-        #[inline]
-        unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
-            let _lock = lock::lock();
-            DLMALLOC.realloc(ptr, layout.size(), layout.align(), new_size)
-        }
-    }
-
-    #[cfg(target_feature = "atomics")]
-    mod lock {
-        use core::arch::wasm32;
-        use core::sync::atomic::{AtomicI32, Ordering::SeqCst};
-
-        static LOCKED: AtomicI32 = AtomicI32::new(0);
-
-        pub struct DropLock;
-
-        pub fn lock() -> DropLock {
-            loop {
-                if LOCKED.swap(1, SeqCst) == 0 {
-                    return DropLock
-                }
-                unsafe {
-                    let r = wasm32::atomic::wait_i32(
-                        &LOCKED as *const AtomicI32 as *mut i32,
-                        1,  // expected value
-                        -1, // timeout
-                    );
-                    debug_assert!(r == 0 || r == 1);
-                }
-            }
-        }
-
-        impl Drop for DropLock {
-            fn drop(&mut self) {
-                let r = LOCKED.swap(0, SeqCst);
-                debug_assert_eq!(r, 1);
-                unsafe {
-                    wasm32::atomic::wake(
-                        &LOCKED as *const AtomicI32 as *mut i32,
-                        1, // only one thread
-                    );
-                }
-            }
-        }
-    }
-
-    #[cfg(not(target_feature = "atomics"))]
-    mod lock {
-        #[inline]
-        pub fn lock() {} // no atomics, no threads, that's easy!
-    }
-}
index 113a85abecbef4613163b79d0056cde77513faf8..58639808faedbfc5c3e28fe2e73ad1b0d8cb6838 100644 (file)
@@ -218,6 +218,23 @@ pub fn padding_needed_for(&self, align: usize) -> usize {
         len_rounded_up.wrapping_sub(len)
     }
 
+    /// Creates a layout by rounding the size of this layout up to a multiple
+    /// of the layout's alignment.
+    ///
+    /// Returns `Err` if the padded size would overflow.
+    ///
+    /// This is equivalent to adding the result of `padding_needed_for`
+    /// to the layout's current size.
+    #[unstable(feature = "alloc_layout_extra", issue = "55724")]
+    #[inline]
+    pub fn pad_to_align(&self) -> Result<Layout, LayoutErr> {
+        let pad = self.padding_needed_for(self.align());
+        let new_size = self.size().checked_add(pad)
+            .ok_or(LayoutErr { private: () })?;
+
+        Layout::from_size_align(new_size, self.align())
+    }
+
     /// Creates a layout describing the record for `n` instances of
     /// `self`, with a suitable amount of padding between each to
     /// ensure that each instance is given its requested size and
@@ -506,7 +523,7 @@ unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
         ptr
     }
 
-    /// Shink or grow a block of memory to the given `new_size`.
+    /// Shrink or grow a block of memory to the given `new_size`.
     /// The block is described by the given `ptr` pointer and `layout`.
     ///
     /// If this returns a non-null pointer, then ownership of the memory block
@@ -757,7 +774,7 @@ fn usable_size(&self, layout: &Layout) -> (usize, usize) {
     // realloc. alloc_excess, realloc_excess
 
     /// Returns a pointer suitable for holding data described by
-    /// a new layout with `layout`’s alginment and a size given
+    /// a new layout with `layout`’s alignment and a size given
     /// by `new_size`. To
     /// accomplish this, this may extend or shrink the allocation
     /// referenced by `ptr` to fit the new layout.
index 689cf319bd750bd1c710e135c4ee0bd2f54d157d..9cf42eff219ba05a87bbce40768967e8e1e45529 100644 (file)
@@ -474,7 +474,7 @@ impl<T: ?Sized> Cell<T> {
     /// ```
     #[inline]
     #[stable(feature = "cell_as_ptr", since = "1.12.0")]
-    pub fn as_ptr(&self) -> *mut T {
+    pub const fn as_ptr(&self) -> *mut T {
         self.value.get()
     }
 
@@ -1508,7 +1508,7 @@ impl<T: ?Sized> UnsafeCell<T> {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn get(&self) -> *mut T {
+    pub const fn get(&self) -> *mut T {
         &self.value as *const T as *mut T
     }
 }
index 64a17786b0a6b1b7bb92ec7df180190c2458bc1f..35181afea3da6ce72b6a5d83722737984f953fb3 100644 (file)
@@ -903,7 +903,7 @@ pub fn to_uppercase(self) -> ToUppercase {
     /// ```
     #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
     #[inline]
-    pub fn is_ascii(&self) -> bool {
+    pub const fn is_ascii(&self) -> bool {
         *self as u32 <= 0x7F
     }
 
index b900990d0a7266a90a1abb983cb697ea7148c0c7..dbc28ef7cf6a9ce8f3826bf21a3e9065ad809acd 100644 (file)
 /// assert_eq!(vec![1, 3], filtered);
 /// ```
 #[unstable(feature = "convert_id", issue = "53500")]
-#[rustc_const_unstable(feature = "const_convert_id")]
 #[inline]
 pub const fn identity<T>(x: T) -> T { x }
 
index 9176e0d32cbf2703c8a7d656614080caf6c8a320..0c870f9e404a26ca59147ea840bb30760bb16a67 100644 (file)
@@ -17,7 +17,7 @@
 use pin::Pin;
 use task::{Poll, LocalWaker};
 
-/// A future represents an asychronous computation.
+/// A future represents an asynchronous computation.
 ///
 /// A future is a value that may not have finished computing yet. This kind of
 /// "asynchronous value" makes it possible for a thread to continue doing useful
index cceae9249e45626a6642c366242bdc177232f2df..7ed6e4a8f51eb1ea2e3913c7b0cf4d5f5daff44e 100644 (file)
@@ -1465,6 +1465,20 @@ pub fn volatile_copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T,
     /// y < 0 or y >= N, where N is the width of T in bits.
     pub fn unchecked_shr<T>(x: T, y: T) -> T;
 
+    /// Performs rotate left.
+    /// The stabilized versions of this intrinsic are available on the integer
+    /// primitives via the `rotate_left` method. For example,
+    /// [`std::u32::rotate_left`](../../std/primitive.u32.html#method.rotate_left)
+    #[cfg(not(stage0))]
+    pub fn rotate_left<T>(x: T, y: T) -> T;
+
+    /// Performs rotate right.
+    /// The stabilized versions of this intrinsic are available on the integer
+    /// primitives via the `rotate_right` method. For example,
+    /// [`std::u32::rotate_right`](../../std/primitive.u32.html#method.rotate_right)
+    #[cfg(not(stage0))]
+    pub fn rotate_right<T>(x: T, y: T) -> T;
+
     /// Returns (a + b) mod 2<sup>N</sup>, where N is the width of T in bits.
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `wrapping_add` method. For example,
index d500cc99fa13c2641dabc0e3bfc3d898e4fd194e..7fa3a4bcce7bb2357ae1c1e05952c83e89844b24 100644 (file)
@@ -283,7 +283,7 @@ fn default() -> Empty<T> {
 /// assert_eq!(None, nope.next());
 /// ```
 #[stable(feature = "iter_empty", since = "1.2.0")]
-pub fn empty<T>() -> Empty<T> {
+pub const fn empty<T>() -> Empty<T> {
     Empty(marker::PhantomData)
 }
 
index 1bbc7892c6bef664ca4c91524252b436d1c36083..5872ac815c25941a67ed8e3cf75a6188c5ef63df 100644 (file)
@@ -82,7 +82,6 @@
 #![feature(const_fn)]
 #![feature(const_int_ops)]
 #![feature(const_fn_union)]
-#![feature(const_manually_drop_new)]
 #![feature(custom_attribute)]
 #![feature(doc_cfg)]
 #![feature(doc_spotlight)]
 #![feature(const_transmute)]
 #![feature(reverse_bits)]
 #![feature(non_exhaustive)]
+#![feature(structural_match)]
 
 #[prelude_import]
 #[allow(unused)]
 mod tuple;
 mod unit;
 
-// Pull in the the `coresimd` crate directly into libcore. This is where all the
+// Pull in the `coresimd` crate directly into libcore. This is where all the
 // architecture-specific (and vendor-specific) intrinsics are defined. AKA
 // things like SIMD and such. Note that the actual source for all this lies in a
 // different repository, rust-lang-nursery/stdsimd. That's why the setup here is
index a0c87f13e5d5a4debd4b5ad1728f3ffb2a320c3e..c008b78e4509292810c8416d293b573bf15773fd 100644 (file)
@@ -350,9 +350,8 @@ macro_rules! try {
 /// assert_eq!(v, b"s = \"abc 123\"");
 /// ```
 ///
-/// Note: This macro can be used in `no_std` setups as well
-/// In a `no_std` setup you are responsible for the
-/// implementation details of the components.
+/// Note: This macro can be used in `no_std` setups as well.
+/// In a `no_std` setup you are responsible for the implementation details of the components.
 ///
 /// ```no_run
 /// # extern crate core;
@@ -440,7 +439,7 @@ macro_rules! writeln {
 ///
 /// If the determination that the code is unreachable proves incorrect, the
 /// program immediately terminates with a [`panic!`].  The function [`unreachable_unchecked`],
-/// which belongs to the [`std::hint`] module, informs the compilier to
+/// which belongs to the [`std::hint`] module, informs the compiler to
 /// optimize the code out of the release version entirely.
 ///
 /// [`panic!`]:  ../std/macro.panic.html
index 662a8ddd96862d0e70bca2281b8cccc7e207c568..3bcdfabbb245e6f29c4882fddeeb674329ee914b 100644 (file)
@@ -578,6 +578,7 @@ fn default() -> $t<T> {
 ///
 /// [drop check]: ../../nomicon/dropck.html
 #[lang = "phantom_data"]
+#[structural_match]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct PhantomData<T:?Sized>;
 
index 1d0b194487e68d9bc9d65ef6841421544dffe5c9..56146a9a5fd39199500ca98a3a7affed93847019 100644 (file)
@@ -202,7 +202,7 @@ pub fn forget<T>(t: T) {
 ///
 /// ## Size of Enums
 ///
-/// Enums that carry no data other than the descriminant have the same size as C enums
+/// Enums that carry no data other than the discriminant have the same size as C enums
 /// on the platform they are compiled for.
 ///
 /// ## Size of Unions
@@ -809,7 +809,7 @@ pub fn drop<T>(_x: T) { }
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
-    ptr::read(src as *const T as *const U)
+    ptr::read_unaligned(src as *const T as *const U)
 }
 
 /// Opaque type representing the discriminant of an enum.
@@ -942,7 +942,6 @@ impl<T> ManuallyDrop<T> {
     /// ManuallyDrop::new(Box::new(()));
     /// ```
     #[stable(feature = "manually_drop", since = "1.20.0")]
-    #[rustc_const_unstable(feature = "const_manually_drop_new")]
     #[inline]
     pub const fn new(value: T) -> ManuallyDrop<T> {
         ManuallyDrop { value }
@@ -961,7 +960,7 @@ pub const fn new(value: T) -> ManuallyDrop<T> {
     /// ```
     #[stable(feature = "manually_drop", since = "1.20.0")]
     #[inline]
-    pub fn into_inner(slot: ManuallyDrop<T>) -> T {
+    pub const fn into_inner(slot: ManuallyDrop<T>) -> T {
         slot.value
     }
 
@@ -1081,7 +1080,7 @@ pub fn set(&mut self, val: T) {
     ///
     /// # Unsafety
     ///
-    /// It is up to the caller to guarantee that the the `MaybeUninit` really is in an initialized
+    /// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized
     /// state, otherwise this will immediately cause undefined behavior.
     #[unstable(feature = "maybe_uninit", issue = "53491")]
     pub unsafe fn into_inner(self) -> T {
@@ -1092,7 +1091,7 @@ pub unsafe fn into_inner(self) -> T {
     ///
     /// # Unsafety
     ///
-    /// It is up to the caller to guarantee that the the `MaybeUninit` really is in an initialized
+    /// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized
     /// state, otherwise this will immediately cause undefined behavior.
     #[unstable(feature = "maybe_uninit", issue = "53491")]
     pub unsafe fn get_ref(&self) -> &T {
@@ -1103,7 +1102,7 @@ pub unsafe fn get_ref(&self) -> &T {
     ///
     /// # Unsafety
     ///
-    /// It is up to the caller to guarantee that the the `MaybeUninit` really is in an initialized
+    /// It is up to the caller to guarantee that the `MaybeUninit` really is in an initialized
     /// state, otherwise this will immediately cause undefined behavior.
     #[unstable(feature = "maybe_uninit", issue = "53491")]
     pub unsafe fn get_mut(&mut self) -> &mut T {
index d42e05a91f140f2f150c297914a93faf147f4fb9..4e33fcfd76e61cf210d786833b59e131b5e7a1a4 100644 (file)
@@ -22,4 +22,3 @@ pub fn estimate_scaling_factor(mant: u64, exp: i16) -> i16 {
     // therefore this always underestimates (or is exact), but not much.
     (((nbits + exp as i64) * 1292913986) >> 32) as i16
 }
-
index 21a2e72dac8c37f7411b18841087689a37bc1b24..d58015beecb1e7172f38cf54706dfe5d3411cf13 100644 (file)
@@ -658,4 +658,3 @@ pub fn to_exact_fixed_str<'a, T, F>(mut format_exact: F, v: T,
         }
     }
 }
-
index c6cbeea5a0ea61788979c6689e5a910bf9bd2b3e..30b7b4546841268750052647cabb30bec85a7ee2 100644 (file)
@@ -2152,6 +2152,7 @@ macro_rules! uint_impl {
 ", $Feature, "assert_eq!(", stringify!($SelfT), "::min_value(), 0);", $EndFeature, "
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
+            #[rustc_promotable]
             #[inline]
             pub const fn min_value() -> Self { 0 }
         }
@@ -2168,6 +2169,7 @@ pub const fn min_value() -> Self { 0 }
 stringify!($MaxV), ");", $EndFeature, "
 ```"),
             #[stable(feature = "rust1", since = "1.0.0")]
+            #[rustc_promotable]
             #[inline]
             pub const fn max_value() -> Self { !0 }
         }
@@ -2301,7 +2303,12 @@ pub const fn trailing_zeros(self) -> u32 {
             #[rustc_const_unstable(feature = "const_int_rotate")]
             #[inline]
             pub const fn rotate_left(self, n: u32) -> Self {
-                (self << (n % $BITS)) | (self >> (($BITS - (n % $BITS)) % $BITS))
+                #[cfg(not(stage0))] {
+                    unsafe { intrinsics::rotate_left(self, n as $SelfT) }
+                }
+                #[cfg(stage0)] {
+                    (self << (n % $BITS)) | (self >> (($BITS - (n % $BITS)) % $BITS))
+                }
             }
         }
 
@@ -2326,7 +2333,12 @@ pub const fn rotate_left(self, n: u32) -> Self {
             #[rustc_const_unstable(feature = "const_int_rotate")]
             #[inline]
             pub const fn rotate_right(self, n: u32) -> Self {
-                (self >> (n % $BITS)) | (self << (($BITS - (n % $BITS)) % $BITS))
+                #[cfg(not(stage0))] {
+                    unsafe { intrinsics::rotate_right(self, n as $SelfT) }
+                }
+                #[cfg(stage0)] {
+                    (self >> (n % $BITS)) | (self << (($BITS - (n % $BITS)) % $BITS))
+                }
             }
         }
 
index 1c826c2fa76bdd6c08fd13096cd269e70ba5ac79..00134a58d30f1c2e00a5917b4db3a25a0516fbaa 100644 (file)
@@ -387,7 +387,7 @@ pub const fn max_value() -> Self {
 ```"),
                 #[inline]
                 #[unstable(feature = "wrapping_int_impl", issue = "32463")]
-                pub fn count_ones(self) -> u32 {
+                pub const fn count_ones(self) -> u32 {
                     self.0.count_ones()
                 }
             }
@@ -407,7 +407,7 @@ pub fn count_ones(self) -> u32 {
 ```"),
                 #[inline]
                 #[unstable(feature = "wrapping_int_impl", issue = "32463")]
-                pub fn count_zeros(self) -> u32 {
+                pub const fn count_zeros(self) -> u32 {
                     self.0.count_zeros()
                 }
             }
@@ -430,7 +430,7 @@ pub fn count_zeros(self) -> u32 {
 ```"),
                 #[inline]
                 #[unstable(feature = "wrapping_int_impl", issue = "32463")]
-                pub fn trailing_zeros(self) -> u32 {
+                pub const fn trailing_zeros(self) -> u32 {
                     self.0.trailing_zeros()
                 }
             }
@@ -456,7 +456,7 @@ pub fn trailing_zeros(self) -> u32 {
             /// ```
             #[inline]
             #[unstable(feature = "wrapping_int_impl", issue = "32463")]
-            pub fn rotate_left(self, n: u32) -> Self {
+            pub const fn rotate_left(self, n: u32) -> Self {
                 Wrapping(self.0.rotate_left(n))
             }
 
@@ -481,7 +481,7 @@ pub fn rotate_left(self, n: u32) -> Self {
             /// ```
             #[inline]
             #[unstable(feature = "wrapping_int_impl", issue = "32463")]
-            pub fn rotate_right(self, n: u32) -> Self {
+            pub const fn rotate_right(self, n: u32) -> Self {
                 Wrapping(self.0.rotate_right(n))
             }
 
@@ -505,7 +505,7 @@ pub fn rotate_right(self, n: u32) -> Self {
             /// ```
             #[inline]
             #[unstable(feature = "wrapping_int_impl", issue = "32463")]
-            pub fn swap_bytes(self) -> Self {
+            pub const fn swap_bytes(self) -> Self {
                 Wrapping(self.0.swap_bytes())
             }
 
@@ -532,7 +532,7 @@ pub fn swap_bytes(self) -> Self {
             /// ```
             #[unstable(feature = "reverse_bits", issue = "48763")]
             #[inline]
-            pub fn reverse_bits(self) -> Self {
+            pub const fn reverse_bits(self) -> Self {
                 Wrapping(self.0.reverse_bits())
             }
 
@@ -560,7 +560,7 @@ pub fn reverse_bits(self) -> Self {
 ```"),
                 #[inline]
                 #[unstable(feature = "wrapping_int_impl", issue = "32463")]
-                pub fn from_be(x: Self) -> Self {
+                pub const fn from_be(x: Self) -> Self {
                     Wrapping(<$t>::from_be(x.0))
                 }
             }
@@ -589,7 +589,7 @@ pub fn from_be(x: Self) -> Self {
 ```"),
                 #[inline]
                 #[unstable(feature = "wrapping_int_impl", issue = "32463")]
-                pub fn from_le(x: Self) -> Self {
+                pub const fn from_le(x: Self) -> Self {
                     Wrapping(<$t>::from_le(x.0))
                 }
             }
@@ -618,7 +618,7 @@ pub fn from_le(x: Self) -> Self {
 ```"),
                 #[inline]
                 #[unstable(feature = "wrapping_int_impl", issue = "32463")]
-                pub fn to_be(self) -> Self {
+                pub const fn to_be(self) -> Self {
                     Wrapping(self.0.to_be())
                 }
             }
@@ -647,7 +647,7 @@ pub fn to_be(self) -> Self {
 ```"),
                 #[inline]
                 #[unstable(feature = "wrapping_int_impl", issue = "32463")]
-                pub fn to_le(self) -> Self {
+                pub const fn to_le(self) -> Self {
                     Wrapping(self.0.to_le())
                 }
             }
@@ -707,7 +707,7 @@ impl Wrapping<$t> {
 ```"),
                 #[inline]
                 #[unstable(feature = "wrapping_int_impl", issue = "32463")]
-                pub fn leading_zeros(self) -> u32 {
+                pub const fn leading_zeros(self) -> u32 {
                     self.0.leading_zeros()
                 }
             }
@@ -784,7 +784,7 @@ pub fn signum(self) -> Wrapping<$t> {
 ```"),
                 #[inline]
                 #[unstable(feature = "wrapping_int_impl", issue = "32463")]
-                pub fn is_positive(self) -> bool {
+                pub const fn is_positive(self) -> bool {
                     self.0.is_positive()
                 }
             }
@@ -806,7 +806,7 @@ pub fn is_positive(self) -> bool {
 ```"),
                 #[inline]
                 #[unstable(feature = "wrapping_int_impl", issue = "32463")]
-                pub fn is_negative(self) -> bool {
+                pub const fn is_negative(self) -> bool {
                     self.0.is_negative()
                 }
             }
@@ -836,7 +836,7 @@ impl Wrapping<$t> {
 ```"),
                 #[inline]
                 #[unstable(feature = "wrapping_int_impl", issue = "32463")]
-                pub fn leading_zeros(self) -> u32 {
+                pub const fn leading_zeros(self) -> u32 {
                     self.0.leading_zeros()
                 }
             }
index 6cfb1005325ba644223311f773bcdcfc4cd0033c..908490e1c839e5eb53d9eee6acf6ea2a414686f5 100644 (file)
@@ -416,7 +416,7 @@ pub const fn new(start: Idx, end: Idx) -> Self {
     /// ```
     #[stable(feature = "inclusive_range_methods", since = "1.27.0")]
     #[inline]
-    pub fn start(&self) -> &Idx {
+    pub const fn start(&self) -> &Idx {
         &self.start
     }
 
@@ -440,7 +440,7 @@ pub fn start(&self) -> &Idx {
     /// ```
     #[stable(feature = "inclusive_range_methods", since = "1.27.0")]
     #[inline]
-    pub fn end(&self) -> &Idx {
+    pub const fn end(&self) -> &Idx {
         &self.end
     }
 
index 68de82d294529e5cefa0d3eae3159a00674849f3..308dd9c79fa374391e1e222d379725c3c968f27d 100644 (file)
@@ -3,7 +3,7 @@
 //! It is sometimes useful to have objects that are guaranteed to not move,
 //! in the sense that their placement in memory does not change, and can thus be relied upon.
 //!
-//! A prime example of such a scenario would be building self-referencial structs,
+//! A prime example of such a scenario would be building self-referential structs,
 //! since moving an object with pointers to itself will invalidate them,
 //! which could cause undefined behavior.
 //!
@@ -39,7 +39,7 @@
 //! use std::marker::Pinned;
 //! use std::ptr::NonNull;
 //!
-//! // This is a self referencial struct since the slice field points to the data field.
+//! // This is a self-referential struct since the slice field points to the data field.
 //! // We cannot inform the compiler about that with a normal reference,
 //! // since this pattern cannot be described with the usual borrowing rules.
 //! // Instead we use a raw pointer, though one which is known to not be null,
index 62ccf6c865cd96735a92bf30969e5be5de08f815..a7bfc3f51244720b5990f3bde99239b695250e38 100644 (file)
 ///
 /// Additionally, if `T` is not [`Copy`], using the pointed-to value after
 /// calling `drop_in_place` can cause undefined behavior. Note that `*to_drop =
-/// foo` counts as a use because it will cause the the value to be dropped
+/// foo` counts as a use because it will cause the value to be dropped
 /// again. [`write`] can be used to overwrite data without causing it to be
 /// dropped.
 ///
@@ -371,7 +371,7 @@ pub(crate) unsafe fn swap_nonoverlapping_one<T>(x: *mut T, y: *mut T) {
 #[inline]
 unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) {
     // The approach here is to utilize simd to swap x & y efficiently. Testing reveals
-    // that swapping either 32 bytes or 64 bytes at a time is most efficient for intel
+    // that swapping either 32 bytes or 64 bytes at a time is most efficient for Intel
     // Haswell E processors. LLVM is more able to optimize if we give a struct a
     // #[repr(simd)], even if we don't actually use this struct directly.
     //
@@ -1005,7 +1005,7 @@ pub fn is_null(self) -> bool {
     /// # Null-unchecked version
     ///
     /// If you are sure the pointer can never be null and are looking for some kind of
-    /// `as_ref_unchecked` that returns the `&T` instead of `Option<&T>, know that you can
+    /// `as_ref_unchecked` that returns the `&T` instead of `Option<&T>`, know that you can
     /// dereference the pointer directly.
     ///
     /// ```
@@ -1625,7 +1625,7 @@ pub fn is_null(self) -> bool {
     /// # Null-unchecked version
     ///
     /// If you are sure the pointer can never be null and are looking for some kind of
-    /// `as_ref_unchecked` that returns the `&T` instead of `Option<&T>, know that you can
+    /// `as_ref_unchecked` that returns the `&T` instead of `Option<&T>`, know that you can
     /// dereference the pointer directly.
     ///
     /// ```
@@ -2905,7 +2905,7 @@ pub fn new(ptr: *mut T) -> Option<Self> {
     /// Acquires the underlying `*mut` pointer.
     #[stable(feature = "nonnull", since = "1.25.0")]
     #[inline]
-    pub fn as_ptr(self) -> *mut T {
+    pub const fn as_ptr(self) -> *mut T {
         self.pointer.0 as *mut T
     }
 
index 8a6b212020b4e4a0d74f661d675a604bafce40b1..fece328f51f474d45a7a3ae86c171bbf31341a1f 100644 (file)
@@ -385,7 +385,6 @@ pub unsafe fn get_unchecked_mut<I>(&mut self, index: I) -> &mut I::Output
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    #[rustc_const_unstable(feature = "const_slice_as_ptr")]
     pub const fn as_ptr(&self) -> *const T {
         self as *const [T] as *const T
     }
index a2782dd8e2e430f7905c0049d335101bdcadf9b6..e710cbffe4d35da71ffd472d2201a002162a5861 100644 (file)
@@ -2277,7 +2277,6 @@ pub unsafe fn as_bytes_mut(&mut self) -> &mut [u8] {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    #[rustc_const_unstable(feature = "const_str_as_ptr")]
     pub const fn as_ptr(&self) -> *const u8 {
         self as *const str as *const u8
     }
index cfbd431aef0a00e87d5d9f0bf82cfbf15cf90919..938e97503deb6d716f88d693f6f68cf0933294ad 100644 (file)
@@ -209,7 +209,6 @@ 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 const fn as_secs(&self) -> u64 { self.secs }
 
@@ -229,7 +228,6 @@ pub const 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 const fn subsec_millis(&self) -> u32 { self.nanos / NANOS_PER_MILLI }
 
@@ -249,7 +247,6 @@ pub const 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 const fn subsec_micros(&self) -> u32 { self.nanos / NANOS_PER_MICRO }
 
@@ -269,7 +266,6 @@ pub const 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 const fn subsec_nanos(&self) -> u32 { self.nanos }
 
@@ -286,7 +282,7 @@ pub const fn subsec_nanos(&self) -> u32 { self.nanos }
     /// ```
     #[unstable(feature = "duration_as_u128", issue = "50202")]
     #[inline]
-    pub fn as_millis(&self) -> u128 {
+    pub const fn as_millis(&self) -> u128 {
         self.secs as u128 * MILLIS_PER_SEC as u128 + (self.nanos / NANOS_PER_MILLI) as u128
     }
 
@@ -303,7 +299,7 @@ pub fn as_millis(&self) -> u128 {
     /// ```
     #[unstable(feature = "duration_as_u128", issue = "50202")]
     #[inline]
-    pub fn as_micros(&self) -> u128 {
+    pub const fn as_micros(&self) -> u128 {
         self.secs as u128 * MICROS_PER_SEC as u128 + (self.nanos / NANOS_PER_MICRO) as u128
     }
 
@@ -320,7 +316,7 @@ pub fn as_micros(&self) -> u128 {
     /// ```
     #[unstable(feature = "duration_as_u128", issue = "50202")]
     #[inline]
-    pub fn as_nanos(&self) -> u128 {
+    pub const fn as_nanos(&self) -> u128 {
         self.secs as u128 * NANOS_PER_SEC as u128 + self.nanos as u128
     }
 
@@ -478,7 +474,7 @@ pub fn checked_div(self, rhs: u32) -> Option<Duration> {
     /// ```
     #[unstable(feature = "duration_float", issue = "54361")]
     #[inline]
-    pub fn as_float_secs(&self) -> f64 {
+    pub const fn as_float_secs(&self) -> f64 {
         (self.secs as f64) + (self.nanos as f64) / (NANOS_PER_SEC as f64)
     }
 
index 3de855ac943157091696c035096c70399d5bd96e..e525c0574002b2d83e96d9007dcf289ee16b31ca 100644 (file)
@@ -2598,4 +2598,3 @@ pub mod conversions {
     ];
 
 }
-
index b86928534cb244f79ccc09202963576208bf17fc..9235f8e7660a1112609a86e1f4ea85b237b15a08 100644 (file)
@@ -97,7 +97,10 @@ unsafe fn abort() -> ! {
 pub mod personalities {
     #[no_mangle]
     #[cfg(not(any(
-        target_arch = "wasm32",
+        all(
+            target_arch = "wasm32",
+            not(target_os = "emscripten"),
+        ),
         all(
             target_os = "windows",
             target_env = "gnu",
index 1d21a5cf79d107b13e1e417016d88ffcddd84beb..96590c1fc72d400c8724e663dd39598da5fad024 100644 (file)
@@ -2134,7 +2134,7 @@ trait Foo { }
 
 
 register_diagnostics! {
-//  E0006 // merged with E0005
+//  E0006, // merged with E0005
 //  E0101, // replaced with E0282
 //  E0102, // replaced with E0282
 //  E0134,
@@ -2183,9 +2183,7 @@ trait Foo { }
     E0657, // `impl Trait` can only capture lifetimes bound at the fn level
     E0687, // in-band lifetimes cannot be used in `fn`/`Fn` syntax
     E0688, // in-band lifetimes cannot be mixed with explicit lifetime binders
-
     E0697, // closures cannot be static
-
     E0707, // multiple elided lifetimes used in arguments of `async fn`
     E0708, // `async` non-`move` closures with arguments are not currently supported
     E0709, // multiple different lifetimes used in arguments of `async fn`
index e558d945516713d2f690d4b698cbadc6a3c6a886..dd5d4b8f6afff546875f9d0d29e4aad19e103f3a 100644 (file)
@@ -3705,7 +3705,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                 let ohs = P(self.lower_expr(ohs));
                 hir::ExprKind::Unary(op, ohs)
             }
-            ExprKind::Lit(ref l) => hir::ExprKind::Lit(P((**l).clone())),
+            ExprKind::Lit(ref l) => hir::ExprKind::Lit(P((*l).clone())),
             ExprKind::Cast(ref expr, ref ty) => {
                 let expr = P(self.lower_expr(expr));
                 hir::ExprKind::Cast(expr, self.lower_ty(ty, ImplTraitContext::disallowed()))
index a2095ff40c0402da70feed0d958ee80d406e2d1d..f57e3ff913b38dd407a7b856fde7093c2281edc4 100644 (file)
@@ -506,9 +506,9 @@ pub enum TraitBoundModifier {
 }
 
 /// The AST represents all type param bounds as types.
-/// typeck::collect::compute_bounds matches these against
-/// the "special" built-in traits (see middle::lang_items) and
-/// detects Copy, Send and Sync.
+/// `typeck::collect::compute_bounds` matches these against
+/// the "special" built-in traits (see `middle::lang_items`) and
+/// detects `Copy`, `Send` and `Sync`.
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub enum GenericBound {
     Trait(PolyTraitRef, TraitBoundModifier),
index 1963d366e7a66d5d5daa5ba3111852663416bd6c..f833ebc7ca763ec9ffab99f78e997de8249f35cc 100644 (file)
@@ -178,6 +178,7 @@ fn msg_span_from_free_region(self, region: ty::Region<'tcx>) -> (String, Option<
                 self.msg_span_from_early_bound_and_free_regions(region)
             }
             ty::ReStatic => ("the static lifetime".to_owned(), None),
+            ty::ReEmpty => ("an empty lifetime".to_owned(), None),
             _ => bug!("{:?}", region),
         }
     }
index 49858972416d8f1c025b18e4fbd256d9a47bf87a..cc73dd63816aa466b4b75c1eaab89f59e65c120f 100644 (file)
@@ -366,7 +366,8 @@ pub fn constrain_opaque_type<FRR: FreeRegionRelations<'tcx>>(
         let mut types = vec![concrete_ty];
         let bound_region = |r| self.sub_regions(infer::CallReturn(span), least_region, r);
         while let Some(ty) = types.pop() {
-            let mut components = self.tcx.outlives_components(ty);
+            let mut components = smallvec![];
+            self.tcx.push_outlives_components(ty, &mut components);
             while let Some(component) = components.pop() {
                 match component {
                     Component::Region(r) => {
index 523f03c2cfc4773afc81f9c008a0fa7294bb5f92..f2825887f36e2d28dae70de54776647af151f6ee 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 //! Code that handles "type-outlives" constraints like `T: 'a`. This
-//! is based on the `outlives_components` function defined on the tcx,
+//! is based on the `push_outlives_components` function defined on the tcx,
 //! but it adds a bit of heuristics on top, in particular to deal with
 //! associated types and projections.
 //!
@@ -307,17 +307,18 @@ pub fn type_must_outlive(
 
         assert!(!ty.has_escaping_bound_vars());
 
-        let components = self.tcx.outlives_components(ty);
-        self.components_must_outlive(origin, components, region);
+        let mut components = smallvec![];
+        self.tcx.push_outlives_components(ty, &mut components);
+        self.components_must_outlive(origin, &components, region);
     }
 
     fn components_must_outlive(
         &mut self,
         origin: infer::SubregionOrigin<'tcx>,
-        components: Vec<Component<'tcx>>,
+        components: &[Component<'tcx>],
         region: ty::Region<'tcx>,
     ) {
-        for component in components {
+        for component in components.iter() {
             let origin = origin.clone();
             match component {
                 Component::Region(region1) => {
@@ -325,13 +326,13 @@ fn components_must_outlive(
                         .push_sub_region_constraint(origin, region, region1);
                 }
                 Component::Param(param_ty) => {
-                    self.param_ty_must_outlive(origin, region, param_ty);
+                    self.param_ty_must_outlive(origin, region, *param_ty);
                 }
                 Component::Projection(projection_ty) => {
-                    self.projection_must_outlive(origin, region, projection_ty);
+                    self.projection_must_outlive(origin, region, *projection_ty);
                 }
                 Component::EscapingProjection(subcomponents) => {
-                    self.components_must_outlive(origin, subcomponents, region);
+                    self.components_must_outlive(origin, &subcomponents, region);
                 }
                 Component::UnresolvedInferenceVariable(v) => {
                     // ignore this, we presume it will yield an error
index 88d45671b9afdfab86538d6a1b6d6345cfeed3ba..a7a79dd2e6560e6113407cfdb3c1fef2dc9f5971 100644 (file)
@@ -155,7 +155,8 @@ fn recursive_type_bound(&self, ty: Ty<'tcx>) -> VerifyBound<'tcx> {
             .map(|subty| self.type_bound(subty))
             .collect::<Vec<_>>();
 
-        let mut regions = ty.regions();
+        let mut regions = smallvec![];
+        ty.push_regions(&mut regions);
         regions.retain(|r| !r.is_late_bound()); // ignore late-bound regions
         bounds.push(VerifyBound::AllBounds(
             regions
index 266b1c4d4a084dc83dd058713a3397f5371ecf0f..01d87bdbf63374ff4b38e86f077bd8444c38fdfd 100644 (file)
     "detects labels that are never used"
 }
 
-declare_lint! {
-    pub DUPLICATE_ASSOCIATED_TYPE_BINDINGS,
-    Warn,
-    "warns about duplicate associated type bindings in generics"
-}
-
 declare_lint! {
     pub DUPLICATE_MACRO_EXPORTS,
     Deny,
@@ -418,7 +412,6 @@ fn get_lints(&self) -> LintArray {
             ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
             UNSTABLE_NAME_COLLISIONS,
             IRREFUTABLE_LET_PATTERNS,
-            DUPLICATE_ASSOCIATED_TYPE_BINDINGS,
             DUPLICATE_MACRO_EXPORTS,
             INTRA_DOC_LINK_RESOLUTION_FAILURE,
             MISSING_DOC_CODE_EXAMPLES,
index f21f949c9f5cd220d8508c0e95225d1c7e6c6fd0..781a0fa3f663a97fc1a3b7d86691c11faa195ad0 100644 (file)
@@ -62,16 +62,6 @@ macro_rules! span_bug {
     })
 }
 
-#[macro_export]
-macro_rules! static_assert {
-    ($name:ident: $test:expr) => {
-        // Use the bool to access an array such that if the bool is false, the access
-        // is out-of-bounds.
-        #[allow(dead_code)]
-        static $name: () = [()][!$test as usize];
-    }
-}
-
 #[macro_export]
 macro_rules! __impl_stable_hash_field {
     ($field:ident, $ctx:expr, $hasher:expr) => ($field.hash_stable($ctx, $hasher));
index e3f9c51a1235ee934e046c90e09046d9689097d8..671f513d5b9331850caeb02550f4e08d06080785 100644 (file)
@@ -63,7 +63,6 @@
 
 use hir::def_id::CrateNum;
 
-use session;
 use session::config;
 use ty::TyCtxt;
 use middle::cstore::{self, DepKind};
@@ -224,7 +223,6 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // quite yet, so do so here.
     activate_injected_dep(*sess.injected_panic_runtime.get(), &mut ret,
                           &|cnum| tcx.is_panic_runtime(cnum));
-    activate_injected_allocator(sess, &mut ret);
 
     // When dylib B links to dylib A, then when using B we must also link to A.
     // It could be the case, however, that the rlib for A is present (hence we
@@ -303,7 +301,6 @@ fn attempt_static<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<DependencyLis
     // that here and activate them.
     activate_injected_dep(*sess.injected_panic_runtime.get(), &mut ret,
                           &|cnum| tcx.is_panic_runtime(cnum));
-    activate_injected_allocator(sess, &mut ret);
 
     Some(ret)
 }
@@ -336,18 +333,6 @@ fn activate_injected_dep(injected: Option<CrateNum>,
     }
 }
 
-fn activate_injected_allocator(sess: &session::Session,
-                               list: &mut DependencyList) {
-    let cnum = match sess.injected_allocator.get() {
-        Some(cnum) => cnum,
-        None => return,
-    };
-    let idx = cnum.as_usize() - 1;
-    if list[idx] == Linkage::NotLinked {
-        list[idx] = Linkage::Static;
-    }
-}
-
 // After the linkage for a crate has been determined we need to verify that
 // there's only going to be one allocator in the output.
 fn verify_ok<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, list: &[Linkage]) {
diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs
new file mode 100644 (file)
index 0000000..e559970
--- /dev/null
@@ -0,0 +1,233 @@
+// 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.
+
+//! The virtual memory representation of the MIR interpreter
+
+use super::{Pointer, EvalResult, AllocId};
+
+use ty::layout::{Size, Align};
+use syntax::ast::Mutability;
+use std::iter;
+use mir;
+use std::ops::{Deref, DerefMut};
+use rustc_data_structures::sorted_map::SortedMap;
+
+#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+pub struct Allocation<Tag=(),Extra=()> {
+    /// The actual bytes of the allocation.
+    /// Note that the bytes of a pointer represent the offset of the pointer
+    pub bytes: Vec<u8>,
+    /// Maps from byte addresses to extra data for each pointer.
+    /// Only the first byte of a pointer is inserted into the map; i.e.,
+    /// every entry in this map applies to `pointer_size` consecutive bytes starting
+    /// at the given offset.
+    pub relocations: Relocations<Tag>,
+    /// Denotes undefined memory. Reading from undefined memory is forbidden in miri
+    pub undef_mask: UndefMask,
+    /// The alignment of the allocation to detect unaligned reads.
+    pub align: Align,
+    /// Whether the allocation is mutable.
+    /// Also used by codegen to determine if a static should be put into mutable memory,
+    /// which happens for `static mut` and `static` with interior mutability.
+    pub mutability: Mutability,
+    /// Extra state for the machine.
+    pub extra: Extra,
+}
+
+pub trait AllocationExtra<Tag>: ::std::fmt::Debug + Default + Clone {
+    /// Hook for performing extra checks on a memory read access.
+    ///
+    /// Takes read-only access to the allocation so we can keep all the memory read
+    /// operations take `&self`.  Use a `RefCell` in `AllocExtra` if you
+    /// need to mutate.
+    #[inline]
+    fn memory_read(
+        _alloc: &Allocation<Tag, Self>,
+        _ptr: Pointer<Tag>,
+        _size: Size,
+    ) -> EvalResult<'tcx> {
+        Ok(())
+    }
+
+    /// Hook for performing extra checks on a memory write access.
+    #[inline]
+    fn memory_written(
+        _alloc: &mut Allocation<Tag, Self>,
+        _ptr: Pointer<Tag>,
+        _size: Size,
+    ) -> EvalResult<'tcx> {
+        Ok(())
+    }
+}
+
+impl AllocationExtra<()> for () {}
+
+impl<Tag, Extra: Default> Allocation<Tag, Extra> {
+    /// Creates a read-only allocation initialized by the given bytes
+    pub fn from_bytes(slice: &[u8], align: Align) -> Self {
+        let mut undef_mask = UndefMask::new(Size::ZERO);
+        undef_mask.grow(Size::from_bytes(slice.len() as u64), true);
+        Self {
+            bytes: slice.to_owned(),
+            relocations: Relocations::new(),
+            undef_mask,
+            align,
+            mutability: Mutability::Immutable,
+            extra: Extra::default(),
+        }
+    }
+
+    pub fn from_byte_aligned_bytes(slice: &[u8]) -> Self {
+        Allocation::from_bytes(slice, Align::from_bytes(1, 1).unwrap())
+    }
+
+    pub fn undef(size: Size, align: Align) -> Self {
+        assert_eq!(size.bytes() as usize as u64, size.bytes());
+        Allocation {
+            bytes: vec![0; size.bytes() as usize],
+            relocations: Relocations::new(),
+            undef_mask: UndefMask::new(size),
+            align,
+            mutability: Mutability::Mutable,
+            extra: Extra::default(),
+        }
+    }
+}
+
+impl<'tcx> ::serialize::UseSpecializedDecodable for &'tcx Allocation {}
+
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
+pub struct Relocations<Tag=(), Id=AllocId>(SortedMap<Size, (Tag, Id)>);
+
+impl<Tag, Id> Relocations<Tag, Id> {
+    pub fn new() -> Self {
+        Relocations(SortedMap::new())
+    }
+
+    // The caller must guarantee that the given relocations are already sorted
+    // by address and contain no duplicates.
+    pub fn from_presorted(r: Vec<(Size, (Tag, Id))>) -> Self {
+        Relocations(SortedMap::from_presorted_elements(r))
+    }
+}
+
+impl<Tag> Deref for Relocations<Tag> {
+    type Target = SortedMap<Size, (Tag, AllocId)>;
+
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
+impl<Tag> DerefMut for Relocations<Tag> {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        &mut self.0
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Undefined byte tracking
+////////////////////////////////////////////////////////////////////////////////
+
+type Block = u64;
+const BLOCK_SIZE: u64 = 64;
+
+#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
+pub struct UndefMask {
+    blocks: Vec<Block>,
+    len: Size,
+}
+
+impl_stable_hash_for!(struct mir::interpret::UndefMask{blocks, len});
+
+impl UndefMask {
+    pub fn new(size: Size) -> Self {
+        let mut m = UndefMask {
+            blocks: vec![],
+            len: Size::ZERO,
+        };
+        m.grow(size, false);
+        m
+    }
+
+    /// Check whether the range `start..end` (end-exclusive) is entirely defined.
+    ///
+    /// Returns `Ok(())` if it's defined. Otherwise returns the index of the byte
+    /// at which the first undefined access begins.
+    #[inline]
+    pub fn is_range_defined(&self, start: Size, end: Size) -> Result<(), Size> {
+        if end > self.len {
+            return Err(self.len);
+        }
+
+        let idx = (start.bytes()..end.bytes())
+            .map(|i| Size::from_bytes(i))
+            .find(|&i| !self.get(i));
+
+        match idx {
+            Some(idx) => Err(idx),
+            None => Ok(())
+        }
+    }
+
+    pub fn set_range(&mut self, start: Size, end: Size, new_state: bool) {
+        let len = self.len;
+        if end > len {
+            self.grow(end - len, new_state);
+        }
+        self.set_range_inbounds(start, end, new_state);
+    }
+
+    pub fn set_range_inbounds(&mut self, start: Size, end: Size, new_state: bool) {
+        for i in start.bytes()..end.bytes() {
+            self.set(Size::from_bytes(i), new_state);
+        }
+    }
+
+    #[inline]
+    pub fn get(&self, i: Size) -> bool {
+        let (block, bit) = bit_index(i);
+        (self.blocks[block] & 1 << bit) != 0
+    }
+
+    #[inline]
+    pub fn set(&mut self, i: Size, new_state: bool) {
+        let (block, bit) = bit_index(i);
+        if new_state {
+            self.blocks[block] |= 1 << bit;
+        } else {
+            self.blocks[block] &= !(1 << bit);
+        }
+    }
+
+    pub fn grow(&mut self, amount: Size, new_state: bool) {
+        let unused_trailing_bits = self.blocks.len() as u64 * BLOCK_SIZE - self.len.bytes();
+        if amount.bytes() > unused_trailing_bits {
+            let additional_blocks = amount.bytes() / BLOCK_SIZE + 1;
+            assert_eq!(additional_blocks as usize as u64, additional_blocks);
+            self.blocks.extend(
+                iter::repeat(0).take(additional_blocks as usize),
+            );
+        }
+        let start = self.len;
+        self.len += amount;
+        self.set_range_inbounds(start, start + amount, new_state);
+    }
+}
+
+#[inline]
+fn bit_index(bits: Size) -> (usize, usize) {
+    let bits = bits.bytes();
+    let a = bits / BLOCK_SIZE;
+    let b = bits % BLOCK_SIZE;
+    assert_eq!(a as usize as u64, a);
+    assert_eq!(b as usize as u64, b);
+    (a as usize, b as usize)
+}
index e2abf7970d6d821fe9808ac3b2cf4b120fd22eb8..40daf78f546fbf2eb7a234f96446c37f35b8586b 100644 (file)
@@ -17,27 +17,32 @@ macro_rules! err {
 
 mod error;
 mod value;
+mod allocation;
+mod pointer;
 
 pub use self::error::{
     EvalError, EvalResult, EvalErrorKind, AssertMessage, ConstEvalErr, struct_error,
     FrameInfo, ConstEvalResult, ErrorHandled,
 };
 
-pub use self::value::{Scalar, ConstValue};
+pub use self::value::{Scalar, ConstValue, ScalarMaybeUndef};
+
+pub use self::allocation::{
+    Allocation, AllocationExtra,
+    Relocations, UndefMask,
+};
+
+pub use self::pointer::{Pointer, PointerArithmetic};
 
 use std::fmt;
 use mir;
 use hir::def_id::DefId;
 use ty::{self, TyCtxt, Instance};
-use ty::layout::{self, Align, HasDataLayout, Size};
+use ty::layout::{self, Size};
 use middle::region;
-use std::iter;
 use std::io;
-use std::ops::{Deref, DerefMut};
 use std::hash::Hash;
-use syntax::ast::Mutability;
 use rustc_serialize::{Encoder, Decodable, Encodable};
-use rustc_data_structures::sorted_map::SortedMap;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::{Lock as Mutex, HashMapExt};
 use rustc_data_structures::tiny_list::TinyList;
@@ -78,152 +83,6 @@ pub struct GlobalId<'tcx> {
     pub promoted: Option<mir::Promoted>,
 }
 
-////////////////////////////////////////////////////////////////////////////////
-// Pointer arithmetic
-////////////////////////////////////////////////////////////////////////////////
-
-pub trait PointerArithmetic: layout::HasDataLayout {
-    // These are not supposed to be overridden.
-
-    #[inline(always)]
-    fn pointer_size(&self) -> Size {
-        self.data_layout().pointer_size
-    }
-
-    //// Trunace the given value to the pointer size; also return whether there was an overflow
-    #[inline]
-    fn truncate_to_ptr(&self, val: u128) -> (u64, bool) {
-        let max_ptr_plus_1 = 1u128 << self.pointer_size().bits();
-        ((val % max_ptr_plus_1) as u64, val >= max_ptr_plus_1)
-    }
-
-    #[inline]
-    fn offset<'tcx>(&self, val: u64, i: u64) -> EvalResult<'tcx, u64> {
-        let (res, over) = self.overflowing_offset(val, i);
-        if over { err!(Overflow(mir::BinOp::Add)) } else { Ok(res) }
-    }
-
-    #[inline]
-    fn overflowing_offset(&self, val: u64, i: u64) -> (u64, bool) {
-        let (res, over1) = val.overflowing_add(i);
-        let (res, over2) = self.truncate_to_ptr(u128::from(res));
-        (res, over1 || over2)
-    }
-
-    #[inline]
-    fn signed_offset<'tcx>(&self, val: u64, i: i64) -> EvalResult<'tcx, u64> {
-        let (res, over) = self.overflowing_signed_offset(val, i128::from(i));
-        if over { err!(Overflow(mir::BinOp::Add)) } else { Ok(res) }
-    }
-
-    // Overflow checking only works properly on the range from -u64 to +u64.
-    #[inline]
-    fn overflowing_signed_offset(&self, val: u64, i: i128) -> (u64, bool) {
-        // FIXME: is it possible to over/underflow here?
-        if i < 0 {
-            // trickery to ensure that i64::min_value() works fine
-            // this formula only works for true negative values, it panics for zero!
-            let n = u64::max_value() - (i as u64) + 1;
-            val.overflowing_sub(n)
-        } else {
-            self.overflowing_offset(val, i as u64)
-        }
-    }
-}
-
-impl<T: layout::HasDataLayout> PointerArithmetic for T {}
-
-
-/// Pointer is generic over the type that represents a reference to Allocations,
-/// thus making it possible for the most convenient representation to be used in
-/// each context.
-///
-/// Defaults to the index based and loosely coupled AllocId.
-///
-/// Pointer is also generic over the `Tag` associated with each pointer,
-/// which is used to do provenance tracking during execution.
-#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)]
-pub struct Pointer<Tag=(),Id=AllocId> {
-    pub alloc_id: Id,
-    pub offset: Size,
-    pub tag: Tag,
-}
-
-/// Produces a `Pointer` which points to the beginning of the Allocation
-impl From<AllocId> for Pointer {
-    #[inline(always)]
-    fn from(alloc_id: AllocId) -> Self {
-        Pointer::new(alloc_id, Size::ZERO)
-    }
-}
-
-impl<'tcx> Pointer<()> {
-    #[inline(always)]
-    pub fn new(alloc_id: AllocId, offset: Size) -> Self {
-        Pointer { alloc_id, offset, tag: () }
-    }
-
-    #[inline(always)]
-    pub fn with_default_tag<Tag>(self) -> Pointer<Tag>
-        where Tag: Default
-    {
-        Pointer::new_with_tag(self.alloc_id, self.offset, Default::default())
-    }
-}
-
-impl<'tcx, Tag> Pointer<Tag> {
-    #[inline(always)]
-    pub fn new_with_tag(alloc_id: AllocId, offset: Size, tag: Tag) -> Self {
-        Pointer { alloc_id, offset, tag }
-    }
-
-    #[inline]
-    pub fn offset(self, i: Size, cx: &impl HasDataLayout) -> EvalResult<'tcx, Self> {
-        Ok(Pointer::new_with_tag(
-            self.alloc_id,
-            Size::from_bytes(cx.data_layout().offset(self.offset.bytes(), i.bytes())?),
-            self.tag
-        ))
-    }
-
-    #[inline]
-    pub fn overflowing_offset(self, i: Size, cx: &impl HasDataLayout) -> (Self, bool) {
-        let (res, over) = cx.data_layout().overflowing_offset(self.offset.bytes(), i.bytes());
-        (Pointer::new_with_tag(self.alloc_id, Size::from_bytes(res), self.tag), over)
-    }
-
-    #[inline(always)]
-    pub fn wrapping_offset(self, i: Size, cx: &impl HasDataLayout) -> Self {
-        self.overflowing_offset(i, cx).0
-    }
-
-    #[inline]
-    pub fn signed_offset(self, i: i64, cx: &impl HasDataLayout) -> EvalResult<'tcx, Self> {
-        Ok(Pointer::new_with_tag(
-            self.alloc_id,
-            Size::from_bytes(cx.data_layout().signed_offset(self.offset.bytes(), i)?),
-            self.tag,
-        ))
-    }
-
-    #[inline]
-    pub fn overflowing_signed_offset(self, i: i128, cx: &impl HasDataLayout) -> (Self, bool) {
-        let (res, over) = cx.data_layout().overflowing_signed_offset(self.offset.bytes(), i);
-        (Pointer::new_with_tag(self.alloc_id, Size::from_bytes(res), self.tag), over)
-    }
-
-    #[inline(always)]
-    pub fn wrapping_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> Self {
-        self.overflowing_signed_offset(i128::from(i), cx).0
-    }
-
-    #[inline(always)]
-    pub fn erase_tag(self) -> Pointer {
-        Pointer { alloc_id: self.alloc_id, offset: self.offset, tag: () }
-    }
-}
-
-
 #[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd, Debug)]
 pub struct AllocId(pub u64);
 
@@ -528,91 +387,6 @@ pub fn set_id_same_memory(&mut self, id: AllocId, mem: M) {
     }
 }
 
-#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
-pub struct Allocation<Tag=(),Extra=()> {
-    /// The actual bytes of the allocation.
-    /// Note that the bytes of a pointer represent the offset of the pointer
-    pub bytes: Vec<u8>,
-    /// Maps from byte addresses to extra data for each pointer.
-    /// Only the first byte of a pointer is inserted into the map; i.e.,
-    /// every entry in this map applies to `pointer_size` consecutive bytes starting
-    /// at the given offset.
-    pub relocations: Relocations<Tag>,
-    /// Denotes undefined memory. Reading from undefined memory is forbidden in miri
-    pub undef_mask: UndefMask,
-    /// The alignment of the allocation to detect unaligned reads.
-    pub align: Align,
-    /// Whether the allocation is mutable.
-    /// Also used by codegen to determine if a static should be put into mutable memory,
-    /// which happens for `static mut` and `static` with interior mutability.
-    pub mutability: Mutability,
-    /// Extra state for the machine.
-    pub extra: Extra,
-}
-
-impl<Tag, Extra: Default> Allocation<Tag, Extra> {
-    /// Creates a read-only allocation initialized by the given bytes
-    pub fn from_bytes(slice: &[u8], align: Align) -> Self {
-        let mut undef_mask = UndefMask::new(Size::ZERO);
-        undef_mask.grow(Size::from_bytes(slice.len() as u64), true);
-        Self {
-            bytes: slice.to_owned(),
-            relocations: Relocations::new(),
-            undef_mask,
-            align,
-            mutability: Mutability::Immutable,
-            extra: Extra::default(),
-        }
-    }
-
-    pub fn from_byte_aligned_bytes(slice: &[u8]) -> Self {
-        Allocation::from_bytes(slice, Align::from_bytes(1, 1).unwrap())
-    }
-
-    pub fn undef(size: Size, align: Align) -> Self {
-        assert_eq!(size.bytes() as usize as u64, size.bytes());
-        Allocation {
-            bytes: vec![0; size.bytes() as usize],
-            relocations: Relocations::new(),
-            undef_mask: UndefMask::new(size),
-            align,
-            mutability: Mutability::Mutable,
-            extra: Extra::default(),
-        }
-    }
-}
-
-impl<'tcx> ::serialize::UseSpecializedDecodable for &'tcx Allocation {}
-
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
-pub struct Relocations<Tag=(), Id=AllocId>(SortedMap<Size, (Tag, Id)>);
-
-impl<Tag, Id> Relocations<Tag, Id> {
-    pub fn new() -> Self {
-        Relocations(SortedMap::new())
-    }
-
-    // The caller must guarantee that the given relocations are already sorted
-    // by address and contain no duplicates.
-    pub fn from_presorted(r: Vec<(Size, (Tag, Id))>) -> Self {
-        Relocations(SortedMap::from_presorted_elements(r))
-    }
-}
-
-impl<Tag> Deref for Relocations<Tag> {
-    type Target = SortedMap<Size, (Tag, AllocId)>;
-
-    fn deref(&self) -> &Self::Target {
-        &self.0
-    }
-}
-
-impl<Tag> DerefMut for Relocations<Tag> {
-    fn deref_mut(&mut self) -> &mut Self::Target {
-        &mut self.0
-    }
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // Methods to access integers in the target endianness
 ////////////////////////////////////////////////////////////////////////////////
@@ -655,103 +429,3 @@ pub fn truncate(value: u128, size: Size) -> u128 {
     // truncate (shift left to drop out leftover values, shift right to fill with zeroes)
     (value << shift) >> shift
 }
-
-////////////////////////////////////////////////////////////////////////////////
-// Undefined byte tracking
-////////////////////////////////////////////////////////////////////////////////
-
-type Block = u64;
-const BLOCK_SIZE: u64 = 64;
-
-#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
-pub struct UndefMask {
-    blocks: Vec<Block>,
-    len: Size,
-}
-
-impl_stable_hash_for!(struct mir::interpret::UndefMask{blocks, len});
-
-impl UndefMask {
-    pub fn new(size: Size) -> Self {
-        let mut m = UndefMask {
-            blocks: vec![],
-            len: Size::ZERO,
-        };
-        m.grow(size, false);
-        m
-    }
-
-    /// Check whether the range `start..end` (end-exclusive) is entirely defined.
-    ///
-    /// Returns `Ok(())` if it's defined. Otherwise returns the index of the byte
-    /// at which the first undefined access begins.
-    #[inline]
-    pub fn is_range_defined(&self, start: Size, end: Size) -> Result<(), Size> {
-        if end > self.len {
-            return Err(self.len);
-        }
-
-        let idx = (start.bytes()..end.bytes())
-            .map(|i| Size::from_bytes(i))
-            .find(|&i| !self.get(i));
-
-        match idx {
-            Some(idx) => Err(idx),
-            None => Ok(())
-        }
-    }
-
-    pub fn set_range(&mut self, start: Size, end: Size, new_state: bool) {
-        let len = self.len;
-        if end > len {
-            self.grow(end - len, new_state);
-        }
-        self.set_range_inbounds(start, end, new_state);
-    }
-
-    pub fn set_range_inbounds(&mut self, start: Size, end: Size, new_state: bool) {
-        for i in start.bytes()..end.bytes() {
-            self.set(Size::from_bytes(i), new_state);
-        }
-    }
-
-    #[inline]
-    pub fn get(&self, i: Size) -> bool {
-        let (block, bit) = bit_index(i);
-        (self.blocks[block] & 1 << bit) != 0
-    }
-
-    #[inline]
-    pub fn set(&mut self, i: Size, new_state: bool) {
-        let (block, bit) = bit_index(i);
-        if new_state {
-            self.blocks[block] |= 1 << bit;
-        } else {
-            self.blocks[block] &= !(1 << bit);
-        }
-    }
-
-    pub fn grow(&mut self, amount: Size, new_state: bool) {
-        let unused_trailing_bits = self.blocks.len() as u64 * BLOCK_SIZE - self.len.bytes();
-        if amount.bytes() > unused_trailing_bits {
-            let additional_blocks = amount.bytes() / BLOCK_SIZE + 1;
-            assert_eq!(additional_blocks as usize as u64, additional_blocks);
-            self.blocks.extend(
-                iter::repeat(0).take(additional_blocks as usize),
-            );
-        }
-        let start = self.len;
-        self.len += amount;
-        self.set_range_inbounds(start, start + amount, new_state);
-    }
-}
-
-#[inline]
-fn bit_index(bits: Size) -> (usize, usize) {
-    let bits = bits.bytes();
-    let a = bits / BLOCK_SIZE;
-    let b = bits % BLOCK_SIZE;
-    assert_eq!(a as usize as u64, a);
-    assert_eq!(b as usize as u64, b);
-    (a as usize, b as usize)
-}
diff --git a/src/librustc/mir/interpret/pointer.rs b/src/librustc/mir/interpret/pointer.rs
new file mode 100644 (file)
index 0000000..969f2c0
--- /dev/null
@@ -0,0 +1,151 @@
+use mir;
+use ty::layout::{self, HasDataLayout, Size};
+
+use super::{
+    AllocId, EvalResult,
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// Pointer arithmetic
+////////////////////////////////////////////////////////////////////////////////
+
+pub trait PointerArithmetic: layout::HasDataLayout {
+    // These are not supposed to be overridden.
+
+    #[inline(always)]
+    fn pointer_size(&self) -> Size {
+        self.data_layout().pointer_size
+    }
+
+    //// Trunace the given value to the pointer size; also return whether there was an overflow
+    #[inline]
+    fn truncate_to_ptr(&self, val: u128) -> (u64, bool) {
+        let max_ptr_plus_1 = 1u128 << self.pointer_size().bits();
+        ((val % max_ptr_plus_1) as u64, val >= max_ptr_plus_1)
+    }
+
+    #[inline]
+    fn offset<'tcx>(&self, val: u64, i: u64) -> EvalResult<'tcx, u64> {
+        let (res, over) = self.overflowing_offset(val, i);
+        if over { err!(Overflow(mir::BinOp::Add)) } else { Ok(res) }
+    }
+
+    #[inline]
+    fn overflowing_offset(&self, val: u64, i: u64) -> (u64, bool) {
+        let (res, over1) = val.overflowing_add(i);
+        let (res, over2) = self.truncate_to_ptr(u128::from(res));
+        (res, over1 || over2)
+    }
+
+    #[inline]
+    fn signed_offset<'tcx>(&self, val: u64, i: i64) -> EvalResult<'tcx, u64> {
+        let (res, over) = self.overflowing_signed_offset(val, i128::from(i));
+        if over { err!(Overflow(mir::BinOp::Add)) } else { Ok(res) }
+    }
+
+    // Overflow checking only works properly on the range from -u64 to +u64.
+    #[inline]
+    fn overflowing_signed_offset(&self, val: u64, i: i128) -> (u64, bool) {
+        // FIXME: is it possible to over/underflow here?
+        if i < 0 {
+            // trickery to ensure that i64::min_value() works fine
+            // this formula only works for true negative values, it panics for zero!
+            let n = u64::max_value() - (i as u64) + 1;
+            val.overflowing_sub(n)
+        } else {
+            self.overflowing_offset(val, i as u64)
+        }
+    }
+}
+
+impl<T: layout::HasDataLayout> PointerArithmetic for T {}
+
+
+/// Pointer is generic over the type that represents a reference to Allocations,
+/// thus making it possible for the most convenient representation to be used in
+/// each context.
+///
+/// Defaults to the index based and loosely coupled AllocId.
+///
+/// Pointer is also generic over the `Tag` associated with each pointer,
+/// which is used to do provenance tracking during execution.
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)]
+pub struct Pointer<Tag=(),Id=AllocId> {
+    pub alloc_id: Id,
+    pub offset: Size,
+    pub tag: Tag,
+}
+
+/// Produces a `Pointer` which points to the beginning of the Allocation
+impl From<AllocId> for Pointer {
+    #[inline(always)]
+    fn from(alloc_id: AllocId) -> Self {
+        Pointer::new(alloc_id, Size::ZERO)
+    }
+}
+
+impl<'tcx> Pointer<()> {
+    #[inline(always)]
+    pub fn new(alloc_id: AllocId, offset: Size) -> Self {
+        Pointer { alloc_id, offset, tag: () }
+    }
+
+    #[inline(always)]
+    pub fn with_default_tag<Tag>(self) -> Pointer<Tag>
+        where Tag: Default
+    {
+        Pointer::new_with_tag(self.alloc_id, self.offset, Default::default())
+    }
+}
+
+impl<'tcx, Tag> Pointer<Tag> {
+    #[inline(always)]
+    pub fn new_with_tag(alloc_id: AllocId, offset: Size, tag: Tag) -> Self {
+        Pointer { alloc_id, offset, tag }
+    }
+
+    #[inline]
+    pub fn offset(self, i: Size, cx: &impl HasDataLayout) -> EvalResult<'tcx, Self> {
+        Ok(Pointer::new_with_tag(
+            self.alloc_id,
+            Size::from_bytes(cx.data_layout().offset(self.offset.bytes(), i.bytes())?),
+            self.tag
+        ))
+    }
+
+    #[inline]
+    pub fn overflowing_offset(self, i: Size, cx: &impl HasDataLayout) -> (Self, bool) {
+        let (res, over) = cx.data_layout().overflowing_offset(self.offset.bytes(), i.bytes());
+        (Pointer::new_with_tag(self.alloc_id, Size::from_bytes(res), self.tag), over)
+    }
+
+    #[inline(always)]
+    pub fn wrapping_offset(self, i: Size, cx: &impl HasDataLayout) -> Self {
+        self.overflowing_offset(i, cx).0
+    }
+
+    #[inline]
+    pub fn signed_offset(self, i: i64, cx: &impl HasDataLayout) -> EvalResult<'tcx, Self> {
+        Ok(Pointer::new_with_tag(
+            self.alloc_id,
+            Size::from_bytes(cx.data_layout().signed_offset(self.offset.bytes(), i)?),
+            self.tag,
+        ))
+    }
+
+    #[inline]
+    pub fn overflowing_signed_offset(self, i: i128, cx: &impl HasDataLayout) -> (Self, bool) {
+        let (res, over) = cx.data_layout().overflowing_signed_offset(self.offset.bytes(), i);
+        (Pointer::new_with_tag(self.alloc_id, Size::from_bytes(res), self.tag), over)
+    }
+
+    #[inline(always)]
+    pub fn wrapping_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> Self {
+        self.overflowing_signed_offset(i128::from(i), cx).0
+    }
+
+    #[inline(always)]
+    pub fn erase_tag(self) -> Pointer {
+        Pointer { alloc_id: self.alloc_id, offset: self.offset, tag: () }
+    }
+}
index 3f5399396abcf837ea2f3b874427cd197ffae868..47c42c9431a210325e7e8ab9130268c22411ca83 100644 (file)
@@ -392,3 +392,131 @@ fn from(ptr: Pointer<Tag>) -> Self {
         Scalar::Ptr(ptr)
     }
 }
+
+#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)]
+pub enum ScalarMaybeUndef<Tag=(), Id=AllocId> {
+    Scalar(Scalar<Tag, Id>),
+    Undef,
+}
+
+impl<Tag> From<Scalar<Tag>> for ScalarMaybeUndef<Tag> {
+    #[inline(always)]
+    fn from(s: Scalar<Tag>) -> Self {
+        ScalarMaybeUndef::Scalar(s)
+    }
+}
+
+impl<Tag> fmt::Display for ScalarMaybeUndef<Tag> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            ScalarMaybeUndef::Undef => write!(f, "uninitialized bytes"),
+            ScalarMaybeUndef::Scalar(s) => write!(f, "{}", s),
+        }
+    }
+}
+
+impl<'tcx> ScalarMaybeUndef<()> {
+    #[inline]
+    pub fn with_default_tag<Tag>(self) -> ScalarMaybeUndef<Tag>
+        where Tag: Default
+    {
+        match self {
+            ScalarMaybeUndef::Scalar(s) => ScalarMaybeUndef::Scalar(s.with_default_tag()),
+            ScalarMaybeUndef::Undef => ScalarMaybeUndef::Undef,
+        }
+    }
+}
+
+impl<'tcx, Tag> ScalarMaybeUndef<Tag> {
+    #[inline]
+    pub fn erase_tag(self) -> ScalarMaybeUndef
+    {
+        match self {
+            ScalarMaybeUndef::Scalar(s) => ScalarMaybeUndef::Scalar(s.erase_tag()),
+            ScalarMaybeUndef::Undef => ScalarMaybeUndef::Undef,
+        }
+    }
+
+    #[inline]
+    pub fn not_undef(self) -> EvalResult<'static, Scalar<Tag>> {
+        match self {
+            ScalarMaybeUndef::Scalar(scalar) => Ok(scalar),
+            ScalarMaybeUndef::Undef => err!(ReadUndefBytes(Size::from_bytes(0))),
+        }
+    }
+
+    #[inline(always)]
+    pub fn to_ptr(self) -> EvalResult<'tcx, Pointer<Tag>> {
+        self.not_undef()?.to_ptr()
+    }
+
+    #[inline(always)]
+    pub fn to_bits(self, target_size: Size) -> EvalResult<'tcx, u128> {
+        self.not_undef()?.to_bits(target_size)
+    }
+
+    #[inline(always)]
+    pub fn to_bool(self) -> EvalResult<'tcx, bool> {
+        self.not_undef()?.to_bool()
+    }
+
+    #[inline(always)]
+    pub fn to_char(self) -> EvalResult<'tcx, char> {
+        self.not_undef()?.to_char()
+    }
+
+    #[inline(always)]
+    pub fn to_f32(self) -> EvalResult<'tcx, f32> {
+        self.not_undef()?.to_f32()
+    }
+
+    #[inline(always)]
+    pub fn to_f64(self) -> EvalResult<'tcx, f64> {
+        self.not_undef()?.to_f64()
+    }
+
+    #[inline(always)]
+    pub fn to_u8(self) -> EvalResult<'tcx, u8> {
+        self.not_undef()?.to_u8()
+    }
+
+    #[inline(always)]
+    pub fn to_u32(self) -> EvalResult<'tcx, u32> {
+        self.not_undef()?.to_u32()
+    }
+
+    #[inline(always)]
+    pub fn to_u64(self) -> EvalResult<'tcx, u64> {
+        self.not_undef()?.to_u64()
+    }
+
+    #[inline(always)]
+    pub fn to_usize(self, cx: &impl HasDataLayout) -> EvalResult<'tcx, u64> {
+        self.not_undef()?.to_usize(cx)
+    }
+
+    #[inline(always)]
+    pub fn to_i8(self) -> EvalResult<'tcx, i8> {
+        self.not_undef()?.to_i8()
+    }
+
+    #[inline(always)]
+    pub fn to_i32(self) -> EvalResult<'tcx, i32> {
+        self.not_undef()?.to_i32()
+    }
+
+    #[inline(always)]
+    pub fn to_i64(self) -> EvalResult<'tcx, i64> {
+        self.not_undef()?.to_i64()
+    }
+
+    #[inline(always)]
+    pub fn to_isize(self, cx: &impl HasDataLayout) -> EvalResult<'tcx, i64> {
+        self.not_undef()?.to_isize(cx)
+    }
+}
+
+impl_stable_hash_for!(enum ::mir::interpret::ScalarMaybeUndef {
+    Scalar(v),
+    Undef
+});
index c2014a5fdd23a088abb4d599a2df9244c2c7b714..46b61d8ffe64f219e3394ba0db5224710bc50b2d 100644 (file)
@@ -20,6 +20,7 @@
 use mir::visit::MirVisitable;
 use rustc_apfloat::ieee::{Double, Single};
 use rustc_apfloat::Float;
+use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::graph::dominators::{dominators, Dominators};
 use rustc_data_structures::graph::{self, GraphPredecessors, GraphSuccessors};
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
@@ -304,6 +305,20 @@ pub fn vars_iter<'a>(&'a self) -> impl Iterator<Item = Local> + 'a {
         })
     }
 
+    /// Returns an iterator over all user-declared mutable locals.
+    #[inline]
+    pub fn mut_vars_iter<'a>(&'a self) -> impl Iterator<Item = Local> + 'a {
+        (self.arg_count + 1..self.local_decls.len()).filter_map(move |index| {
+            let local = Local::new(index);
+            let decl = &self.local_decls[local];
+            if decl.is_user_variable.is_some() && decl.mutability == Mutability::Mut {
+                Some(local)
+            } else {
+                None
+            }
+        })
+    }
+
     /// Returns an iterator over all user-declared mutable arguments and locals.
     #[inline]
     pub fn mut_vars_and_args_iter<'a>(&'a self) -> impl Iterator<Item = Local> + 'a {
@@ -1704,14 +1719,14 @@ pub struct Statement<'tcx> {
     pub kind: StatementKind<'tcx>,
 }
 
+// `Statement` is used a lot. Make sure it doesn't unintentionally get bigger.
+#[cfg(target_arch = "x86_64")]
+static_assert!(MEM_SIZE_OF_STATEMENT: mem::size_of::<Statement<'_>>() == 56);
+
 impl<'tcx> Statement<'tcx> {
     /// Changes a statement to a nop. This is both faster than deleting instructions and avoids
     /// invalidating statement indices in `Location`s.
     pub fn make_nop(&mut self) {
-        // `Statement` contributes significantly to peak memory usage. Make
-        // sure it doesn't get bigger.
-        static_assert!(STATEMENT_IS_AT_MOST_56_BYTES: mem::size_of::<Statement<'_>>() <= 56);
-
         self.kind = StatementKind::Nop
     }
 
@@ -2706,6 +2721,36 @@ pub fn successor_within_block(&self) -> Location {
         }
     }
 
+    /// Returns `true` if `other` is earlier in the control flow graph than `self`.
+    pub fn is_predecessor_of<'tcx>(&self, other: Location, mir: &Mir<'tcx>) -> bool {
+        // If we are in the same block as the other location and are an earlier statement
+        // then we are a predecessor of `other`.
+        if self.block == other.block && self.statement_index < other.statement_index {
+            return true;
+        }
+
+        // If we're in another block, then we want to check that block is a predecessor of `other`.
+        let mut queue: Vec<BasicBlock> = mir.predecessors_for(other.block).clone();
+        let mut visited = FxHashSet::default();
+
+        while let Some(block) = queue.pop() {
+            // If we haven't visited this block before, then make sure we visit it's predecessors.
+            if visited.insert(block) {
+                queue.append(&mut mir.predecessors_for(block).clone());
+            } else {
+                continue;
+            }
+
+            // If we found the block that `self` is in, then we are a predecessor of `other` (since
+            // we found that block by looking at the predecessors of `other`).
+            if self.block == block {
+                return true;
+            }
+        }
+
+        false
+    }
+
     pub fn dominates(&self, other: Location, dominators: &Dominators<BasicBlock>) -> bool {
         if self.block == other.block {
             self.statement_index <= other.statement_index
index 4b53235eab4af2aa2f1a420e29b80d5ffc77f6cc..f773f46b6f58cd0d3b98c6065ab2e6b54372db7e 100644 (file)
@@ -80,7 +80,8 @@ pub fn projection_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
                          elem: &PlaceElem<'tcx>)
                          -> PlaceTy<'tcx>
     {
-        self.projection_ty_core(tcx, elem, |_, _, ty| ty)
+        self.projection_ty_core(tcx, elem, |_, _, ty| -> Result<Ty<'tcx>, ()> { Ok(ty) })
+            .unwrap()
     }
 
     /// `place_ty.projection_ty_core(tcx, elem, |...| { ... })`
@@ -88,11 +89,12 @@ pub fn projection_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
     /// `Ty` or downcast variant corresponding to that projection.
     /// The `handle_field` callback must map a `Field` to its `Ty`,
     /// (which should be trivial when `T` = `Ty`).
-    pub fn projection_ty_core<V, T>(self,
-                                    tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                                    elem: &ProjectionElem<'tcx, V, T>,
-                                    mut handle_field: impl FnMut(&Self, &Field, &T) -> Ty<'tcx>)
-                                    -> PlaceTy<'tcx>
+    pub fn projection_ty_core<V, T, E>(
+        self,
+        tcx: TyCtxt<'a, 'gcx, 'tcx>,
+        elem: &ProjectionElem<'tcx, V, T>,
+        mut handle_field: impl FnMut(&Self, &Field, &T) -> Result<Ty<'tcx>, E>)
+        -> Result<PlaceTy<'tcx>, E>
     where
         V: ::std::fmt::Debug, T: ::std::fmt::Debug
     {
@@ -142,10 +144,11 @@ pub fn projection_ty_core<V, T>(self,
                         bug!("cannot downcast non-ADT type: `{:?}`", self)
                     }
                 },
-            ProjectionElem::Field(ref f, ref fty) => PlaceTy::Ty { ty: handle_field(&self, f, fty) }
+            ProjectionElem::Field(ref f, ref fty) =>
+                PlaceTy::Ty { ty: handle_field(&self, f, fty)? },
         };
         debug!("projection_ty self: {:?} elem: {:?} yields: {:?}", self, elem, answer);
-        answer
+        Ok(answer)
     }
 }
 
index 5306f2c9689b10844f3796f1534b8f0b528b421a..78aabf86e300d72ae2a8784897db7bff0356a679 100644 (file)
@@ -2082,7 +2082,7 @@ pub fn build_session_options_and_crate_config(
                         error_format,
                         &format!(
                             "optimization level needs to be \
-                             between 0-3 (instead was `{}`)",
+                             between 0-3, s or z (instead was `{}`)",
                             arg
                         ),
                     );
index fe94b62ef19e266c6e0989daba86a1992fd46d45..8cfbd27fc61631f4096e6ed0ddd59322344223e6 100644 (file)
@@ -112,7 +112,6 @@ pub struct Session {
     /// The metadata::creader module may inject an allocator/panic_runtime
     /// dependency if it didn't already find one, and this tracks what was
     /// injected.
-    pub injected_allocator: Once<Option<CrateNum>>,
     pub allocator_kind: Once<Option<AllocatorKind>>,
     pub injected_panic_runtime: Once<Option<CrateNum>>,
 
@@ -963,6 +962,10 @@ pub fn teach(&self, code: &DiagnosticId) -> bool {
         self.opts.debugging_opts.teach && self.diagnostic().must_teach(code)
     }
 
+    pub fn rust_2015(&self) -> bool {
+        self.opts.edition == Edition::Edition2015
+    }
+
     /// Are we allowed to use features from the Rust 2018 edition?
     pub fn rust_2018(&self) -> bool {
         self.opts.edition >= Edition::Edition2018
@@ -1158,7 +1161,6 @@ pub fn build_session_(
         type_length_limit: Once::new(),
         const_eval_stack_frame_limit: 100,
         next_node_id: OneThread::new(Cell::new(NodeId::new(1))),
-        injected_allocator: Once::new(),
         allocator_kind: Once::new(),
         injected_panic_runtime: Once::new(),
         imported_macro_spans: OneThread::new(RefCell::new(FxHashMap::default())),
index b7512790bfb6913414c2e4d34c618b56c9012f19..33b689c60a1188dad35d27597bbe23a67b77ce53 100644 (file)
 pub use self::specialize::{OverlapError, specialization_graph, translate_substs};
 pub use self::specialize::find_associated_item;
 pub use self::engine::{TraitEngine, TraitEngineExt};
-pub use self::util::elaborate_predicates;
-pub use self::util::supertraits;
-pub use self::util::Supertraits;
-pub use self::util::supertrait_def_ids;
-pub use self::util::SupertraitDefIds;
+pub use self::util::{elaborate_predicates, elaborate_trait_ref, elaborate_trait_refs};
+pub use self::util::{supertraits, supertrait_def_ids, Supertraits, SupertraitDefIds};
 pub use self::util::transitive_bounds;
 
 #[allow(dead_code)]
index 6b5eb4293e0285311a0316bdf017530058d665e8..b59bd0e2388737085ad0cf6d4925c1556f78a943 100644 (file)
@@ -885,7 +885,7 @@ fn project_type<'cx, 'gcx, 'tcx>(
     let recursion_limit = *selcx.tcx().sess.recursion_limit.get();
     if obligation.recursion_depth >= recursion_limit {
         debug!("project: overflow!");
-        selcx.infcx().report_overflow_error(&obligation, true);
+        return Err(ProjectionTyError::TraitSelectionError(SelectionError::Overflow));
     }
 
     let obligation_trait_ref = &obligation.predicate.trait_ref(selcx.tcx());
index 0ce1d8f8227553ec5e3d312fa4ca6eda15635c66..d7b5dd049e35088f015a6628a1794e8489089d2b 100644 (file)
@@ -396,7 +396,10 @@ fn to_pretty_impl_header(tcx: TyCtxt<'_, '_, '_>, impl_def_id: DefId) -> Option<
     if !substs.is_noop() {
         types_without_default_bounds.extend(substs.types());
         w.push('<');
-        w.push_str(&substs.iter().map(|k| k.to_string()).collect::<Vec<_>>().join(", "));
+        w.push_str(&substs.iter()
+            .map(|k| k.to_string())
+            .filter(|k| &k[..] != "'_")
+            .collect::<Vec<_>>().join(", "));
         w.push('>');
     }
 
index e237cab5ea135abde38e63f0fb5d56c9a8e42c6d..e44e1453b79654ff1ef0a9cf061ee607d2deaa1d 100644 (file)
@@ -366,7 +366,7 @@ pub fn is_from_trait(&self) -> bool {
     pub fn items(
         &self,
         tcx: TyCtxt<'a, 'gcx, 'tcx>,
-    ) -> impl Iterator<Item = ty::AssociatedItem> + 'a {
+    ) -> ty::AssociatedItemsIterator<'a, 'gcx, 'tcx> {
         tcx.associated_items(self.def_id())
     }
 
index 74f8d67ce04846a97c309a0573037530a4b98225..3a882506b41d6520e90921c0267f3752f75705b4 100644 (file)
@@ -200,8 +200,10 @@ fn push(&mut self, predicate: &ty::Predicate<'tcx>) {
                 }
 
                 let visited = &mut self.visited;
+                let mut components = smallvec![];
+                tcx.push_outlives_components(ty_max, &mut components);
                 self.stack.extend(
-                    tcx.outlives_components(ty_max)
+                    components
                        .into_iter()
                        .filter_map(|component| match component {
                            Component::Region(r) => if r.is_late_bound() {
@@ -333,7 +335,7 @@ fn new(base: I) -> FilterToTraits<I> {
     }
 }
 
-impl<'tcx,I:Iterator<Item = ty::Predicate<'tcx>>> Iterator for FilterToTraits<I> {
+impl<'tcx, I: Iterator<Item = ty::Predicate<'tcx>>> Iterator for FilterToTraits<I> {
     type Item = ty::PolyTraitRef<'tcx>;
 
     fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> {
index 05d9d4bc37d79f540e3c887feb5fcc82ae099be7..f78fad9f7aa9a432a5e0a6bc5f88ad453ae8e43d 100644 (file)
@@ -17,7 +17,7 @@
 use session::config::{BorrowckMode, OutputFilenames};
 use session::config::CrateType;
 use middle;
-use hir::{TraitCandidate, HirId, ItemLocalId, Node};
+use hir::{TraitCandidate, HirId, ItemKind, ItemLocalId, Node};
 use hir::def::{Def, Export};
 use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
 use hir::map as hir_map;
@@ -823,12 +823,6 @@ fn hash_stable<W: StableHasherResult>(&self,
 
 impl<'tcx> CommonTypes<'tcx> {
     fn new(interners: &CtxtInterners<'tcx>) -> CommonTypes<'tcx> {
-        // Ensure our type representation does not grow
-        #[cfg(target_pointer_width = "64")]
-        static_assert!(ASSERT_TY_KIND: ::std::mem::size_of::<ty::TyKind<'_>>() <= 24);
-        #[cfg(target_pointer_width = "64")]
-        static_assert!(ASSERT_TYS: ::std::mem::size_of::<ty::TyS<'_>>() <= 32);
-
         let mk = |sty| CtxtInterners::intern_ty(interners, interners, sty);
         let mk_region = |r| {
             if let Some(r) = interners.region.borrow().get(&r) {
@@ -1602,6 +1596,20 @@ pub fn return_type_impl_trait(
         &self,
         scope_def_id: DefId,
     ) -> Option<Ty<'tcx>> {
+        // HACK: `type_of_def_id()` will fail on these (#55796), so return None
+        let node_id = self.hir.as_local_node_id(scope_def_id).unwrap();
+        match self.hir.get(node_id) {
+            Node::Item(item) => {
+                match item.node {
+                    ItemKind::Fn(..) => { /* type_of_def_id() will work */ }
+                    _ => {
+                        return None;
+                    }
+                }
+            }
+            _ => { /* type_of_def_id() will work or panic */ }
+        }
+
         let ret_ty = self.type_of(scope_def_id);
         match ret_ty.sty {
             ty::FnDef(_, _) => {
index c7c197d11c03beb112b95d85933d45b9d6acc1ef..979cc9b115b5a2e6307631e1dd035956553eab2f 100644 (file)
@@ -294,7 +294,7 @@ pub fn from_hir(visibility: &hir::Visibility, id: NodeId, tcx: TyCtxt<'_, '_, '_
         }
     }
 
-    /// Returns true if an item with this visibility is accessible from the given block.
+    /// Returns `true` if an item with this visibility is accessible from the given block.
     pub fn is_accessible_from<T: DefIdTree>(self, module: DefId, tree: T) -> bool {
         let restriction = match self {
             // Public items are visible everywhere.
@@ -309,7 +309,7 @@ pub fn is_accessible_from<T: DefIdTree>(self, module: DefId, tree: T) -> bool {
         tree.is_descendant_of(module, restriction)
     }
 
-    /// Returns true if this visibility is at least as accessible as the given visibility
+    /// Returns `true` if this visibility is at least as accessible as the given visibility
     pub fn is_at_least<T: DefIdTree>(self, vis: Visibility, tree: T) -> bool {
         let vis_restriction = match vis {
             Visibility::Public => return self == Visibility::Public,
@@ -320,7 +320,7 @@ pub fn is_at_least<T: DefIdTree>(self, vis: Visibility, tree: T) -> bool {
         self.is_accessible_from(vis_restriction, tree)
     }
 
-    // Returns true if this item is visible anywhere in the local crate.
+    // Returns `true` if this item is visible anywhere in the local crate.
     pub fn is_visible_locally(self) -> bool {
         match self {
             Visibility::Public => true,
@@ -451,7 +451,7 @@ pub struct TypeFlags: u32 {
         // FIXME: Rename this to the actual property since it's used for generators too
         const HAS_TY_CLOSURE     = 1 << 9;
 
-        // true if there are "names" of types and regions and so forth
+        // `true` if there are "names" of types and regions and so forth
         // that are local to a particular fn
         const HAS_FREE_LOCAL_NAMES    = 1 << 10;
 
@@ -514,6 +514,10 @@ pub struct TyS<'tcx> {
     outer_exclusive_binder: ty::DebruijnIndex,
 }
 
+// `TyS` is used a lot. Make sure it doesn't unintentionally get bigger.
+#[cfg(target_arch = "x86_64")]
+static_assert!(MEM_SIZE_OF_TY_S: ::std::mem::size_of::<TyS<'_>>() == 32);
+
 impl<'tcx> Ord for TyS<'tcx> {
     fn cmp(&self, other: &TyS<'tcx>) -> Ordering {
         self.sty.cmp(&other.sty)
@@ -544,14 +548,14 @@ impl<'tcx> TyS<'tcx> {
     pub fn is_primitive_ty(&self) -> bool {
         match self.sty {
             TyKind::Bool |
-                TyKind::Char |
-                TyKind::Int(_) |
-                TyKind::Uint(_) |
-                TyKind::Float(_) |
-                TyKind::Infer(InferTy::IntVar(_)) |
-                TyKind::Infer(InferTy::FloatVar(_)) |
-                TyKind::Infer(InferTy::FreshIntTy(_)) |
-                TyKind::Infer(InferTy::FreshFloatTy(_)) => true,
+            TyKind::Char |
+            TyKind::Int(_) |
+            TyKind::Uint(_) |
+            TyKind::Float(_) |
+            TyKind::Infer(InferTy::IntVar(_)) |
+            TyKind::Infer(InferTy::FloatVar(_)) |
+            TyKind::Infer(InferTy::FreshIntTy(_)) |
+            TyKind::Infer(InferTy::FreshFloatTy(_)) => true,
             TyKind::Ref(_, x, _) => x.is_primitive_ty(),
             _ => false,
         }
@@ -953,7 +957,7 @@ pub fn region_param(&'tcx self,
                 _ => bug!("expected lifetime parameter, but found another generic parameter")
             }
         } else {
-            tcx.generics_of(self.parent.expect("parent_count>0 but no parent?"))
+            tcx.generics_of(self.parent.expect("parent_count > 0 but no parent?"))
                .region_param(param, tcx)
         }
     }
@@ -970,7 +974,7 @@ pub fn type_param(&'tcx self,
                 _ => bug!("expected type parameter, but found another generic parameter")
             }
         } else {
-            tcx.generics_of(self.parent.expect("parent_count>0 but no parent?"))
+            tcx.generics_of(self.parent.expect("parent_count > 0 but no parent?"))
                .type_param(param, tcx)
         }
     }
@@ -993,6 +997,7 @@ pub fn instantiate(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: &Substs<'tcx>)
         self.instantiate_into(tcx, &mut instantiated, substs);
         instantiated
     }
+
     pub fn instantiate_own(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: &Substs<'tcx>)
                            -> InstantiatedPredicates<'tcx> {
         InstantiatedPredicates {
@@ -1041,15 +1046,15 @@ pub fn instantiate_supertrait(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
 
 #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
 pub enum Predicate<'tcx> {
-    /// Corresponds to `where Foo : Bar<A,B,C>`. `Foo` here would be
+    /// Corresponds to `where Foo: Bar<A,B,C>`. `Foo` here would be
     /// the `Self` type of the trait reference and `A`, `B`, and `C`
     /// would be the type parameters.
     Trait(PolyTraitPredicate<'tcx>),
 
-    /// where `'a : 'b`
+    /// where `'a: 'b`
     RegionOutlives(PolyRegionOutlivesPredicate<'tcx>),
 
-    /// where `T : 'a`
+    /// where `T: 'a`
     TypeOutlives(PolyTypeOutlivesPredicate<'tcx>),
 
     /// where `<T as TraitRef>::Name == X`, approximately.
@@ -1062,7 +1067,7 @@ pub enum Predicate<'tcx> {
     /// trait must be object-safe
     ObjectSafe(DefId),
 
-    /// No direct syntax. May be thought of as `where T : FnFoo<...>`
+    /// No direct syntax. May be thought of as `where T: FnFoo<...>`
     /// for some substitutions `...` and `T` being a closure type.
     /// Satisfied (or refuted) once we know the closure's kind.
     ClosureKind(DefId, ClosureSubsts<'tcx>, ClosureKind),
@@ -1111,11 +1116,11 @@ pub fn subst_supertrait(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
         //
         // Let's start with an easy case. Consider two traits:
         //
-        //     trait Foo<'a> : Bar<'a,'a> { }
+        //     trait Foo<'a>: Bar<'a,'a> { }
         //     trait Bar<'b,'c> { }
         //
-        // Now, if we have a trait reference `for<'x> T : Foo<'x>`, then
-        // we can deduce that `for<'x> T : Bar<'x,'x>`. Basically, if we
+        // Now, if we have a trait reference `for<'x> T: Foo<'x>`, then
+        // we can deduce that `for<'x> T: Bar<'x,'x>`. Basically, if we
         // knew that `Foo<'x>` (for any 'x) then we also know that
         // `Bar<'x,'x>` (for any 'x). This more-or-less falls out from
         // normal substitution.
@@ -1128,21 +1133,21 @@ pub fn subst_supertrait(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
         //
         // Another example to be careful of is this:
         //
-        //     trait Foo1<'a> : for<'b> Bar1<'a,'b> { }
+        //     trait Foo1<'a>: for<'b> Bar1<'a,'b> { }
         //     trait Bar1<'b,'c> { }
         //
-        // Here, if we have `for<'x> T : Foo1<'x>`, then what do we know?
-        // The answer is that we know `for<'x,'b> T : Bar1<'x,'b>`. The
+        // Here, if we have `for<'x> T: Foo1<'x>`, then what do we know?
+        // The answer is that we know `for<'x,'b> T: Bar1<'x,'b>`. The
         // reason is similar to the previous example: any impl of
-        // `T:Foo1<'x>` must show that `for<'b> T : Bar1<'x, 'b>`.  So
+        // `T:Foo1<'x>` must show that `for<'b> T: Bar1<'x, 'b>`.  So
         // basically we would want to collapse the bound lifetimes from
         // the input (`trait_ref`) and the supertraits.
         //
         // To achieve this in practice is fairly straightforward. Let's
         // consider the more complicated scenario:
         //
-        // - We start out with `for<'x> T : Foo1<'x>`. In this case, `'x`
-        //   has a De Bruijn index of 1. We want to produce `for<'x,'b> T : Bar1<'x,'b>`,
+        // - We start out with `for<'x> T: Foo1<'x>`. In this case, `'x`
+        //   has a De Bruijn index of 1. We want to produce `for<'x,'b> T: Bar1<'x,'b>`,
         //   where both `'x` and `'b` would have a DB index of 1.
         //   The substitution from the input trait-ref is therefore going to be
         //   `'a => 'x` (where `'x` has a DB index of 1).
@@ -1194,6 +1199,7 @@ pub fn subst_supertrait(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
 pub struct TraitPredicate<'tcx> {
     pub trait_ref: TraitRef<'tcx>
 }
+
 pub type PolyTraitPredicate<'tcx> = ty::Binder<TraitPredicate<'tcx>>;
 
 impl<'tcx> TraitPredicate<'tcx> {
@@ -1218,7 +1224,7 @@ pub fn def_id(&self) -> DefId {
 }
 
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
-pub struct OutlivesPredicate<A,B>(pub A, pub B); // `A : B`
+pub struct OutlivesPredicate<A,B>(pub A, pub B); // `A: B`
 pub type PolyOutlivesPredicate<A,B> = ty::Binder<OutlivesPredicate<A,B>>;
 pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate<ty::Region<'tcx>,
                                                            ty::Region<'tcx>>;
@@ -1238,11 +1244,11 @@ pub struct SubtypePredicate<'tcx> {
 /// This kind of predicate has no *direct* correspondent in the
 /// syntax, but it roughly corresponds to the syntactic forms:
 ///
-/// 1. `T : TraitRef<..., Item=Type>`
+/// 1. `T: TraitRef<..., Item=Type>`
 /// 2. `<T as TraitRef<...>>::Item == Type` (NYI)
 ///
 /// In particular, form #1 is "desugared" to the combination of a
-/// normal trait predicate (`T : TraitRef<...>`) and one of these
+/// normal trait predicate (`T: TraitRef<...>`) and one of these
 /// predicates. Form #2 is a broader form in that it also permits
 /// equality between arbitrary types. Processing an instance of
 /// Form #2 eventually yields one of these `ProjectionPredicate`
@@ -1256,14 +1262,14 @@ pub struct ProjectionPredicate<'tcx> {
 pub type PolyProjectionPredicate<'tcx> = Binder<ProjectionPredicate<'tcx>>;
 
 impl<'tcx> PolyProjectionPredicate<'tcx> {
-    /// Returns the def-id of the associated item being projected.
+    /// Returns the `DefId` of the associated item being projected.
     pub fn item_def_id(&self) -> DefId {
         self.skip_binder().projection_ty.item_def_id
     }
 
     pub fn to_poly_trait_ref(&self, tcx: TyCtxt<'_, '_, '_>) -> PolyTraitRef<'tcx> {
-        // Note: unlike with TraitRef::to_poly_trait_ref(),
-        // self.0.trait_ref is permitted to have escaping regions.
+        // Note: unlike with `TraitRef::to_poly_trait_ref()`,
+        // `self.0.trait_ref` is permitted to have escaping regions.
         // This is because here `self` has a `Binder` and so does our
         // return value, so we are preserving the number of binding
         // levels.
@@ -1274,12 +1280,12 @@ pub fn ty(&self) -> Binder<Ty<'tcx>> {
         self.map_bound(|predicate| predicate.ty)
     }
 
-    /// The DefId of the TraitItem for the associated type.
+    /// The `DefId` of the `TraitItem` for the associated type.
     ///
-    /// Note that this is not the DefId of the TraitRef containing this
-    /// associated type, which is in tcx.associated_item(projection_def_id()).container.
+    /// Note that this is not the `DefId` of the `TraitRef` containing this
+    /// associated type, which is in `tcx.associated_item(projection_def_id()).container`.
     pub fn projection_def_id(&self) -> DefId {
-        // ok to skip binder since trait def-id does not care about regions
+        // okay to skip binder since trait def-id does not care about regions
         self.skip_binder().projection_ty.item_def_id
     }
 }
@@ -1515,14 +1521,14 @@ pub fn next_universe(self) -> UniverseIndex {
         UniverseIndex::from_u32(self.private.checked_add(1).unwrap())
     }
 
-    /// True if `self` can name a name from `other` -- in other words,
+    /// Returns `true` if `self` can name a name from `other` -- in other words,
     /// if the set of names in `self` is a superset of those in
     /// `other` (`self >= other`).
     pub fn can_name(self, other: UniverseIndex) -> bool {
         self.private >= other.private
     }
 
-    /// True if `self` cannot name some names from `other` -- in other
+    /// Returns `true` if `self` cannot name some names from `other` -- in other
     /// words, if the set of names in `self` is a strict subset of
     /// those in `other` (`self < other`).
     pub fn cannot_name(self, other: UniverseIndex) -> bool {
@@ -1574,7 +1580,7 @@ pub fn empty() -> Self {
     /// are revealed. This is suitable for monomorphized, post-typeck
     /// environments like codegen or doing optimizations.
     ///
-    /// NB. If you want to have predicates in scope, use `ParamEnv::new`,
+    /// N.B. If you want to have predicates in scope, use `ParamEnv::new`,
     /// or invoke `param_env.with_reveal_all()`.
     pub fn reveal_all() -> Self {
         Self::new(List::empty(), Reveal::All)
@@ -1979,14 +1985,14 @@ pub fn discr_type(&self) -> attr::IntType {
         self.int.unwrap_or(attr::SignedInt(ast::IntTy::Isize))
     }
 
-    /// Returns true if this `#[repr()]` should inhabit "smart enum
+    /// Returns `true` if this `#[repr()]` should inhabit "smart enum
     /// layout" optimizations, such as representing `Foo<&T>` as a
     /// single pointer.
     pub fn inhibit_enum_layout_opt(&self) -> bool {
         self.c() || self.int.is_some()
     }
 
-    /// Returns true if this `#[repr()]` should inhibit struct field reordering
+    /// Returns `true` if this `#[repr()]` should inhibit struct field reordering
     /// optimizations, such as with repr(C) or repr(packed(1)).
     pub fn inhibit_struct_field_reordering_opt(&self) -> bool {
         !(self.flags & ReprFlags::IS_UNOPTIMISABLE).is_empty() || (self.pack == 1)
@@ -2089,7 +2095,7 @@ pub fn is_fundamental(&self) -> bool {
         self.flags.intersects(AdtFlags::IS_FUNDAMENTAL)
     }
 
-    /// Returns true if this is PhantomData<T>.
+    /// Returns `true` if this is PhantomData<T>.
     #[inline]
     pub fn is_phantom_data(&self) -> bool {
         self.flags.intersects(AdtFlags::IS_PHANTOM_DATA)
@@ -2105,7 +2111,7 @@ pub fn is_rc(&self) -> bool {
         self.flags.intersects(AdtFlags::IS_RC)
     }
 
-    /// Returns true if this is Box<T>.
+    /// Returns `true` if this is Box<T>.
     #[inline]
     pub fn is_box(&self) -> bool {
         self.flags.intersects(AdtFlags::IS_BOX)
@@ -2422,7 +2428,7 @@ pub fn trait_did(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> DefId {
         }
     }
 
-    /// True if this a type that impls this closure kind
+    /// Returns `true` if this a type that impls this closure kind
     /// must also implement `other`.
     pub fn extends(self, other: ty::ClosureKind) -> bool {
         match (self, other) {
@@ -2475,7 +2481,7 @@ pub fn walk_shallow(&'tcx self) -> smallvec::IntoIter<walk::TypeWalkerArray<'tcx
     ///
     /// Note: prefer `ty.walk()` where possible.
     pub fn maybe_walk<F>(&'tcx self, mut f: F)
-        where F : FnMut(Ty<'tcx>) -> bool
+        where F: FnMut(Ty<'tcx>) -> bool
     {
         let mut walker = self.walk();
         while let Some(ty) = walker.next() {
@@ -2672,13 +2678,20 @@ pub fn find_field_index(self, ident: Ident, variant: &VariantDef) -> Option<usiz
     pub fn associated_items(
         self,
         def_id: DefId,
-    ) -> impl Iterator<Item = AssociatedItem> + 'a {
-        let def_ids = self.associated_item_def_ids(def_id);
-        Box::new((0..def_ids.len()).map(move |i| self.associated_item(def_ids[i])))
-            as Box<dyn Iterator<Item = AssociatedItem> + 'a>
+    ) -> AssociatedItemsIterator<'a, 'gcx, 'tcx> {
+        // Ideally, we would use `-> impl Iterator` here, but it falls
+        // afoul of the conservative "capture [restrictions]" we put
+        // in place, so we use a hand-written iterator.
+        //
+        // [restrictions]: https://github.com/rust-lang/rust/issues/34511#issuecomment-373423999
+        AssociatedItemsIterator {
+            tcx: self,
+            def_ids: self.associated_item_def_ids(def_id),
+            next_index: 0,
+        }
     }
 
-    /// Returns true if the impls are the same polarity and the trait either
+    /// Returns `true` if the impls are the same polarity and the trait either
     /// has no items or is annotated #[marker] and prevents item overrides.
     pub fn impls_are_allowed_to_overlap(self, def_id1: DefId, def_id2: DefId) -> bool {
         if self.features().overlapping_marker_traits {
@@ -2802,7 +2815,7 @@ pub fn has_attr(self, did: DefId, attr: &str) -> bool {
         attr::contains_name(&self.get_attrs(did), attr)
     }
 
-    /// Returns true if this is an `auto trait`.
+    /// Returns `true` if this is an `auto trait`.
     pub fn trait_is_auto(self, trait_def_id: DefId) -> bool {
         self.trait_def(trait_def_id).has_auto_impl
     }
@@ -2872,6 +2885,22 @@ pub fn adjust_ident(self, mut ident: Ident, scope: DefId, block: NodeId) -> (Ide
     }
 }
 
+pub struct AssociatedItemsIterator<'a, 'gcx: 'tcx, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'gcx, 'tcx>,
+    def_ids: Lrc<Vec<DefId>>,
+    next_index: usize,
+}
+
+impl Iterator for AssociatedItemsIterator<'_, '_, '_> {
+    type Item = AssociatedItem;
+
+    fn next(&mut self) -> Option<AssociatedItem> {
+        let def_id = self.def_ids.get(self.next_index)?;
+        self.next_index += 1;
+        Some(self.tcx.associated_item(*def_id))
+    }
+}
+
 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     pub fn with_freevars<T, F>(self, fid: NodeId, f: F) -> T where
         F: FnOnce(&[hir::Freevar]) -> T,
index 449730c9d0601d6c991e7705131b3eb71ed122fe..7fac88a3d78f1855b97371e8dd793adf88572625 100644 (file)
@@ -12,6 +12,7 @@
 // refers to rules defined in RFC 1214 (`OutlivesFooBar`), so see that
 // RFC for reference.
 
+use smallvec::SmallVec;
 use ty::{self, Ty, TyCtxt, TypeFoldable};
 
 #[derive(Debug)]
@@ -55,17 +56,15 @@ pub enum Component<'tcx> {
 }
 
 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
-    /// Returns all the things that must outlive `'a` for the condition
+    /// Push onto `out` all the things that must outlive `'a` for the condition
     /// `ty0: 'a` to hold. Note that `ty0` must be a **fully resolved type**.
-    pub fn outlives_components(&self, ty0: Ty<'tcx>)
-                               -> Vec<Component<'tcx>> {
-        let mut components = vec![];
-        self.compute_components(ty0, &mut components);
-        debug!("components({:?}) = {:?}", ty0, components);
-        components
+    pub fn push_outlives_components(&self, ty0: Ty<'tcx>,
+                                    out: &mut SmallVec<[Component<'tcx>; 4]>) {
+        self.compute_components(ty0, out);
+        debug!("components({:?}) = {:?}", ty0, out);
     }
 
-    fn compute_components(&self, ty: Ty<'tcx>, out: &mut Vec<Component<'tcx>>) {
+    fn compute_components(&self, ty: Ty<'tcx>, out: &mut SmallVec<[Component<'tcx>; 4]>) {
         // Descend through the types, looking for the various "base"
         // components and collecting them into `out`. This is not written
         // with `collect()` because of the need to sometimes skip subtrees
@@ -164,7 +163,7 @@ fn compute_components(&self, ty: Ty<'tcx>, out: &mut Vec<Component<'tcx>>) {
                 // list is maintained explicitly, because bound regions
                 // themselves can be readily identified.
 
-                push_region_constraints(out, ty.regions());
+                push_region_constraints(ty, out);
                 for subty in ty.walk_shallow() {
                     self.compute_components(subty, out);
                 }
@@ -173,15 +172,17 @@ fn compute_components(&self, ty: Ty<'tcx>, out: &mut Vec<Component<'tcx>>) {
     }
 
     fn capture_components(&self, ty: Ty<'tcx>) -> Vec<Component<'tcx>> {
-        let mut temp = vec![];
-        push_region_constraints(&mut temp, ty.regions());
+        let mut temp = smallvec![];
+        push_region_constraints(ty, &mut temp);
         for subty in ty.walk_shallow() {
             self.compute_components(subty, &mut temp);
         }
-        temp
+        temp.into_iter().collect()
     }
 }
 
-fn push_region_constraints<'tcx>(out: &mut Vec<Component<'tcx>>, regions: Vec<ty::Region<'tcx>>) {
+fn push_region_constraints<'tcx>(ty: Ty<'tcx>, out: &mut SmallVec<[Component<'tcx>; 4]>) {
+    let mut regions = smallvec![];
+    ty.push_regions(&mut regions);
     out.extend(regions.iter().filter(|&r| !r.is_late_bound()).map(|r| Component::Region(r)));
 }
index 3dc31c517169f2a0f9708186e3315cc797e74793..54550b8a2055f44214f38b818c6b8b88836201b6 100644 (file)
@@ -450,8 +450,7 @@ fn compute_cnum_map(tcx: TyCtxt<'_, '_, '_>,
                                      .map(|&(cnum, ..)| cnum)
                                      .max()
                                      .unwrap_or(0) + 1;
-            let mut map = IndexVec::new();
-            map.resize(map_size as usize, None);
+            let mut map = IndexVec::from_elem_n(None, map_size as usize);
 
             for &(prev_cnum, ref crate_name, crate_disambiguator) in prev_cnums {
                 let key = (crate_name.clone(), crate_disambiguator);
index 28b58d62175bc21f270ef57a38d478c2df832c54..bd3a34cae90f4330c4aaf2cfa8c5bfe245dd1d5c 100644 (file)
@@ -22,6 +22,7 @@
 use util::captures::Captures;
 use mir::interpret::{Scalar, Pointer};
 
+use smallvec::SmallVec;
 use std::iter;
 use std::cmp::Ordering;
 use rustc_target::spec::abi;
@@ -210,6 +211,10 @@ pub enum TyKind<'tcx> {
     Error,
 }
 
+// `TyKind` is used a lot. Make sure it doesn't unintentionally get bigger.
+#[cfg(target_arch = "x86_64")]
+static_assert!(MEM_SIZE_OF_TY_KIND: ::std::mem::size_of::<TyKind<'_>>() == 24);
+
 /// A closure can be modeled as a struct that looks like:
 ///
 ///     struct Closure<'l0...'li, T0...Tj, CK, CS, U0...Uk> {
@@ -627,7 +632,7 @@ pub fn iter<'a>(&'a self)
 /// A complete reference to a trait. These take numerous guises in syntax,
 /// but perhaps the most recognizable form is in a where clause:
 ///
-///     T : Foo<U>
+///     T: Foo<U>
 ///
 /// This would be represented by a trait-reference where the def-id is the
 /// def-id for the trait `Foo` and the substs define `T` as parameter 0,
@@ -637,8 +642,8 @@ pub fn iter<'a>(&'a self)
 /// that case the `Self` parameter is absent from the substitutions.
 ///
 /// Note that a `TraitRef` introduces a level of region binding, to
-/// account for higher-ranked trait bounds like `T : for<'a> Foo<&'a
-/// U>` or higher-ranked object types.
+/// account for higher-ranked trait bounds like `T: for<'a> Foo<&'a U>`
+/// or higher-ranked object types.
 #[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
 pub struct TraitRef<'tcx> {
     pub def_id: DefId,
@@ -663,7 +668,7 @@ pub fn self_ty(&self) -> Ty<'tcx> {
         self.substs.type_at(0)
     }
 
-    pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a {
+    pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator<Item = Ty<'tcx>> + 'a {
         // Select only the "input types" from a trait-reference. For
         // now this is all the types that appear in the
         // trait-reference, but it should eventually exclude
@@ -886,16 +891,16 @@ pub struct ProjectionTy<'tcx> {
     /// The parameters of the associated item.
     pub substs: &'tcx Substs<'tcx>,
 
-    /// The DefId of the TraitItem for the associated type N.
+    /// The `DefId` of the `TraitItem` for the associated type `N`.
     ///
-    /// Note that this is not the DefId of the TraitRef containing this
-    /// associated type, which is in tcx.associated_item(item_def_id).container.
+    /// Note that this is not the `DefId` of the `TraitRef` containing this
+    /// associated type, which is in `tcx.associated_item(item_def_id).container`.
     pub item_def_id: DefId,
 }
 
 impl<'a, 'tcx> ProjectionTy<'tcx> {
-    /// Construct a ProjectionTy by searching the trait from trait_ref for the
-    /// associated item named item_name.
+    /// Construct a `ProjectionTy` by searching the trait from `trait_ref` for the
+    /// associated item named `item_name`.
     pub fn from_ref_and_name(
         tcx: TyCtxt<'_, '_, '_>, trait_ref: ty::TraitRef<'tcx>, item_name: Ident
     ) -> ProjectionTy<'tcx> {
@@ -1846,28 +1851,27 @@ pub fn ty_adt_def(&self) -> Option<&'tcx AdtDef> {
         }
     }
 
-    /// Returns the regions directly referenced from this type (but
-    /// not types reachable from this type via `walk_tys`). This
-    /// ignores late-bound regions binders.
-    pub fn regions(&self) -> Vec<ty::Region<'tcx>> {
+    /// Push onto `out` the regions directly referenced from this type (but not
+    /// types reachable from this type via `walk_tys`). This ignores late-bound
+    /// regions binders.
+    pub fn push_regions(&self, out: &mut SmallVec<[ty::Region<'tcx>; 4]>) {
         match self.sty {
             Ref(region, _, _) => {
-                vec![region]
+                out.push(region);
             }
             Dynamic(ref obj, region) => {
-                let mut v = vec![region];
-                v.extend(obj.principal().skip_binder().substs.regions());
-                v
+                out.push(region);
+                out.extend(obj.principal().skip_binder().substs.regions());
             }
             Adt(_, substs) | Opaque(_, substs) => {
-                substs.regions().collect()
+                out.extend(substs.regions())
             }
             Closure(_, ClosureSubsts { ref substs }) |
             Generator(_, GeneratorSubsts { ref substs }, _) => {
-                substs.regions().collect()
+                out.extend(substs.regions())
             }
             Projection(ref data) | UnnormalizedProjection(ref data) => {
-                data.substs.regions().collect()
+                out.extend(data.substs.regions())
             }
             FnDef(..) |
             FnPtr(_) |
@@ -1887,9 +1891,7 @@ pub fn regions(&self) -> Vec<ty::Region<'tcx>> {
             Param(_) |
             Bound(..) |
             Infer(_) |
-            Error => {
-                vec![]
-            }
+            Error => {}
         }
     }
 
index c1aed36c92ddf3bfd60170781ea85bf88ff9bb82..b28e7c9fb199be7daaacce299e889784c7375078 100644 (file)
@@ -27,7 +27,7 @@
 use std::mem;
 use std::num::NonZeroUsize;
 
-/// An entity in the Rust typesystem, which can be one of
+/// An entity in the Rust type system, which can be one of
 /// several kinds (only types and lifetimes for now).
 /// To reduce memory usage, a `Kind` is a interned pointer,
 /// with the lowest 2 bits being reserved for a tag to
@@ -171,7 +171,7 @@ fn decode<D: Decoder>(d: &mut D) -> Result<Kind<'tcx>, D::Error> {
 pub type Substs<'tcx> = List<Kind<'tcx>>;
 
 impl<'a, 'gcx, 'tcx> Substs<'tcx> {
-    /// Creates a Substs that maps each generic parameter to itself.
+    /// Creates a `Substs` that maps each generic parameter to itself.
     pub fn identity_for_item(tcx: TyCtxt<'a, 'gcx, 'tcx>, def_id: DefId)
                              -> &'tcx Substs<'tcx> {
         Substs::for_item(tcx, def_id, |param, _| {
@@ -179,9 +179,9 @@ pub fn identity_for_item(tcx: TyCtxt<'a, 'gcx, 'tcx>, def_id: DefId)
         })
     }
 
-    /// Creates a Substs for generic parameter definitions,
+    /// Creates a `Substs` for generic parameter definitions,
     /// by calling closures to obtain each kind.
-    /// The closures get to observe the Substs as they're
+    /// The closures get to observe the `Substs` as they're
     /// being built, which can be used to correctly
     /// substitute defaults of generic parameters.
     pub fn for_item<F>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
@@ -242,7 +242,7 @@ pub fn is_noop(&self) -> bool {
     }
 
     #[inline]
-    pub fn types(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a {
+    pub fn types(&'a self) -> impl DoubleEndedIterator<Item = Ty<'tcx>> + 'a {
         self.iter().filter_map(|k| {
             if let UnpackedKind::Type(ty) = k.unpack() {
                 Some(ty)
@@ -253,7 +253,7 @@ pub fn types(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a {
     }
 
     #[inline]
-    pub fn regions(&'a self) -> impl DoubleEndedIterator<Item=ty::Region<'tcx>> + 'a {
+    pub fn regions(&'a self) -> impl DoubleEndedIterator<Item = ty::Region<'tcx>> + 'a {
         self.iter().filter_map(|k| {
             if let UnpackedKind::Lifetime(lt) = k.unpack() {
                 Some(lt)
@@ -332,7 +332,7 @@ impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Substs<'tcx> {}
 // `foo`. Or use `foo.subst_spanned(tcx, substs, Some(span))` when
 // there is more information available (for better errors).
 
-pub trait Subst<'tcx> : Sized {
+pub trait Subst<'tcx>: Sized {
     fn subst<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
                        substs: &[Kind<'tcx>]) -> Self {
         self.subst_spanned(tcx, substs, None)
index 735b74f156500356c1e66759ec55fe6de32510de..a8a5da90c7a6bb41418cb0b5cf20447eca1fff38 100644 (file)
@@ -10,3 +10,4 @@ path = "lib.rs"
 [dependencies]
 bitflags = "1.0"
 rustc_cratesio_shim = { path = "../librustc_cratesio_shim" }
+smallvec = { version = "0.6.5", features = ["union"] }
index 87d59d2e763cbe89743452e59379e8888f639f3a..4f405858e350ce8269b9fba6dfe8512f2f6474ed 100644 (file)
@@ -11,6 +11,7 @@
 use {Category, ExpInt, IEK_INF, IEK_NAN, IEK_ZERO};
 use {Float, FloatConvert, ParseError, Round, Status, StatusAnd};
 
+use smallvec::{SmallVec, smallvec};
 use std::cmp::{self, Ordering};
 use std::convert::TryFrom;
 use std::fmt::{self, Write};
@@ -1962,7 +1963,7 @@ fn from_decimal_string(s: &str, round: Round) -> Result<StatusAnd<Self>, ParseEr
         // to hold the full significand, and an extra limb required by
         // tcMultiplyPart.
         let max_limbs = limbs_for_bits(1 + 196 * significand_digits / 59);
-        let mut dec_sig = Vec::with_capacity(max_limbs);
+        let mut dec_sig: SmallVec<[Limb; 1]> = SmallVec::with_capacity(max_limbs);
 
         // Convert to binary efficiently - we do almost all multiplication
         // in a Limb. When this would overflow do we do a single
@@ -2021,11 +2022,11 @@ fn from_decimal_string(s: &str, round: Round) -> Result<StatusAnd<Self>, ParseEr
 
             const FIRST_EIGHT_POWERS: [Limb; 8] = [1, 5, 25, 125, 625, 3125, 15625, 78125];
 
-            let mut p5_scratch = vec![];
-            let mut p5 = vec![FIRST_EIGHT_POWERS[4]];
+            let mut p5_scratch = smallvec![];
+            let mut p5: SmallVec<[Limb; 1]> = smallvec![FIRST_EIGHT_POWERS[4]];
 
-            let mut r_scratch = vec![];
-            let mut r = vec![FIRST_EIGHT_POWERS[power & 7]];
+            let mut r_scratch = smallvec![];
+            let mut r: SmallVec<[Limb; 1]> = smallvec![FIRST_EIGHT_POWERS[power & 7]];
             power >>= 3;
 
             while power > 0 {
@@ -2064,7 +2065,7 @@ fn from_decimal_string(s: &str, round: Round) -> Result<StatusAnd<Self>, ParseEr
             let calc_precision = (LIMB_BITS << attempt) - 1;
             attempt += 1;
 
-            let calc_normal_from_limbs = |sig: &mut Vec<Limb>,
+            let calc_normal_from_limbs = |sig: &mut SmallVec<[Limb; 1]>,
                                           limbs: &[Limb]|
              -> StatusAnd<ExpInt> {
                 sig.resize(limbs_for_bits(calc_precision), 0);
index 6ea722ba769c16181aac010ec8c025bd2eb9e5d2..69c9f385409e4a268a1c0d17a39233e64c39bdbf 100644 (file)
@@ -53,6 +53,7 @@
 
 #[macro_use]
 extern crate bitflags;
+extern crate smallvec;
 
 use std::cmp::Ordering;
 use std::fmt;
index 34d8b75a5bfb3476a1f587d33ad663f2d8498f37..734564c2d856777ab450b935e26c2537199259fa 100644 (file)
@@ -15,6 +15,5 @@ cmake = "0.1.18"
 
 [dependencies]
 alloc = { path = "../liballoc" }
-alloc_system = { path = "../liballoc_system" }
 core = { path = "../libcore" }
 compiler_builtins = { path = "../rustc/compiler_builtins_shim" }
index 7b845e631ffa341d88db3950e9748e75558e063b..47f917e40c1ff53a5b81e490e026a3bdaa54fc61 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 #![sanitizer_runtime]
-#![feature(alloc_system)]
 #![feature(nll)]
 #![feature(sanitizer_runtime)]
 #![feature(staged_api)]
 #![unstable(feature = "sanitizer_runtime_lib",
             reason = "internal implementation detail of sanitizers",
             issue = "0")]
-
-extern crate alloc_system;
-
-use alloc_system::System;
-
-#[global_allocator]
-static ALLOC: System = System;
index e50534a4e1dc95fc7d19eaf5f3c6d4f0e691046c..03b0b04d4014694f5571b97745f9cffd48504ef3 100644 (file)
@@ -19,7 +19,7 @@
 use type_of::{LayoutLlvmExt, PointerKind};
 use value::Value;
 
-use rustc_target::abi::{LayoutOf, Size, TyLayout, Abi as LayoutAbi};
+use rustc_target::abi::{HasDataLayout, LayoutOf, Size, TyLayout, Abi as LayoutAbi};
 use rustc::ty::{self, Ty};
 use rustc::ty::layout;
 
@@ -225,9 +225,10 @@ fn store(&self, bx: &Builder<'_, 'll, 'tcx>, val: &'ll Value, dst: PlaceRef<'ll,
                 // ...and then memcpy it to the intended destination.
                 base::call_memcpy(bx,
                                   bx.pointercast(dst.llval, Type::i8p(cx)),
+                                  self.layout.align,
                                   bx.pointercast(llscratch, Type::i8p(cx)),
+                                  scratch_align,
                                   C_usize(cx, self.layout.size.bytes()),
-                                  self.layout.align.min(scratch_align),
                                   MemFlags::empty());
 
                 bx.lifetime_end(llscratch, scratch_size);
@@ -276,6 +277,7 @@ fn adjust_for_abi(&mut self,
                       cx: &CodegenCx<'ll, 'tcx>,
                       abi: Abi);
     fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type;
+    fn ptr_to_llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type;
     fn llvm_cconv(&self) -> llvm::CallConv;
     fn apply_attrs_llfn(&self, llfn: &'ll Value);
     fn apply_attrs_callsite(&self, bx: &Builder<'a, 'll, 'tcx>, callsite: &'ll Value);
@@ -657,6 +659,13 @@ fn llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type {
         }
     }
 
+    fn ptr_to_llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type {
+        unsafe {
+            llvm::LLVMPointerType(self.llvm_type(cx),
+                                  cx.data_layout().instruction_address_space as c_uint)
+        }
+    }
+
     fn llvm_cconv(&self) -> llvm::CallConv {
         match self.conv {
             Conv::C => llvm::CCallConv,
index ce4cb1ea3a0423cac94695cb53dba75ab751be8d..54245a36017ab9e5631040292287495957d49730 100644 (file)
@@ -83,15 +83,16 @@ pub fn src_files(&mut self) -> Vec<String> {
         if self.src_archive().is_none() {
             return Vec::new()
         }
+
         let archive = self.src_archive.as_ref().unwrap().as_ref().unwrap();
-        let ret = archive.iter()
-                         .filter_map(|child| child.ok())
-                         .filter(is_relevant_child)
-                         .filter_map(|child| child.name())
-                         .filter(|name| !self.removals.iter().any(|x| x == name))
-                         .map(|name| name.to_string())
-                         .collect();
-        return ret;
+
+        archive.iter()
+               .filter_map(|child| child.ok())
+               .filter(is_relevant_child)
+               .filter_map(|child| child.name())
+               .filter(|name| !self.removals.iter().any(|x| x == name))
+               .map(|name| name.to_owned())
+               .collect()
     }
 
     fn src_archive(&mut self) -> Option<&ArchiveRO> {
@@ -171,7 +172,7 @@ pub fn add_file(&mut self, file: &Path) {
         let name = file.file_name().unwrap().to_str().unwrap();
         self.additions.push(Addition::File {
             path: file.to_path_buf(),
-            name_in_archive: name.to_string(),
+            name_in_archive: name.to_owned(),
         });
     }
 
@@ -184,13 +185,8 @@ pub fn update_symbols(&mut self) {
     /// Combine the provided files, rlibs, and native libraries into a single
     /// `Archive`.
     pub fn build(&mut self) {
-        let kind = match self.llvm_archive_kind() {
-            Ok(kind) => kind,
-            Err(kind) => {
-                self.config.sess.fatal(&format!("Don't know how to build archive of type: {}",
-                                                kind));
-            }
-        };
+        let kind = self.llvm_archive_kind().unwrap_or_else(|kind|
+            self.config.sess.fatal(&format!("Don't know how to build archive of type: {}", kind)));
 
         if let Err(e) = self.build_with_llvm(kind) {
             self.config.sess.fatal(&format!("failed to build archive: {}", e));
@@ -281,10 +277,9 @@ fn build_with_llvm(&mut self, kind: ArchiveKind) -> io::Result<()> {
             let ret = if r.into_result().is_err() {
                 let err = llvm::LLVMRustGetLastError();
                 let msg = if err.is_null() {
-                    "failed to write archive".to_string()
+                    "failed to write archive".into()
                 } else {
                     String::from_utf8_lossy(CStr::from_ptr(err).to_bytes())
-                            .into_owned()
                 };
                 Err(io::Error::new(io::ErrorKind::Other, msg))
             } else {
@@ -293,7 +288,7 @@ fn build_with_llvm(&mut self, kind: ArchiveKind) -> io::Result<()> {
             for member in members {
                 llvm::LLVMRustArchiveMemberFree(member);
             }
-            return ret
+            ret
         }
     }
 }
index 9a3dd9d2f88147bb3f0607f15811630698883323..0b264de18c124b4f19567053dccfe96506a8f980 100644 (file)
@@ -42,7 +42,7 @@
 
 // This is the "magic number" expected at the beginning of a LLVM bytecode
 // object in an rlib.
-pub const RLIB_BYTECODE_OBJECT_MAGIC: &'static [u8] = b"RUST_OBJECT";
+pub const RLIB_BYTECODE_OBJECT_MAGIC: &[u8] = b"RUST_OBJECT";
 
 // The version number this compiler will write to bytecode objects in rlibs
 pub const RLIB_BYTECODE_OBJECT_VERSION: u8 = 2;
@@ -106,39 +106,39 @@ pub struct DecodedBytecode<'a> {
 }
 
 impl<'a> DecodedBytecode<'a> {
-    pub fn new(data: &'a [u8]) -> Result<DecodedBytecode<'a>, String> {
+    pub fn new(data: &'a [u8]) -> Result<DecodedBytecode<'a>, &'static str> {
         if !data.starts_with(RLIB_BYTECODE_OBJECT_MAGIC) {
-            return Err("magic bytecode prefix not found".to_string())
+            return Err("magic bytecode prefix not found")
         }
         let data = &data[RLIB_BYTECODE_OBJECT_MAGIC.len()..];
         if !data.starts_with(&[RLIB_BYTECODE_OBJECT_VERSION, 0, 0, 0]) {
-            return Err("wrong version prefix found in bytecode".to_string())
+            return Err("wrong version prefix found in bytecode")
         }
         let data = &data[4..];
         if data.len() < 4 {
-            return Err("bytecode corrupted".to_string())
+            return Err("bytecode corrupted")
         }
         let identifier_len = unsafe {
             u32::from_le(ptr::read_unaligned(data.as_ptr() as *const u32)) as usize
         };
         let data = &data[4..];
         if data.len() < identifier_len {
-            return Err("bytecode corrupted".to_string())
+            return Err("bytecode corrupted")
         }
         let identifier = match str::from_utf8(&data[..identifier_len]) {
             Ok(s) => s,
-            Err(_) => return Err("bytecode corrupted".to_string())
+            Err(_) => return Err("bytecode corrupted")
         };
         let data = &data[identifier_len..];
         if data.len() < 8 {
-            return Err("bytecode corrupted".to_string())
+            return Err("bytecode corrupted")
         }
         let bytecode_len = unsafe {
             u64::from_le(ptr::read_unaligned(data.as_ptr() as *const u64)) as usize
         };
         let data = &data[8..];
         if data.len() < bytecode_len {
-            return Err("bytecode corrupted".to_string())
+            return Err("bytecode corrupted")
         }
         let encoded_bytecode = &data[..bytecode_len];
 
index dd95c3d986299491466baebddfd2d84a1c39e6b9..111637b6aa967800090441756dced4a984e29572 100644 (file)
@@ -47,8 +47,8 @@
 use syntax::attr;
 
 pub use rustc_codegen_utils::link::{find_crate_name, filename_for_input, default_output_for_target,
-                                  invalid_output_for_target, out_filename, check_file_is_writeable,
-                                  filename_for_metadata};
+                                    invalid_output_for_target, filename_for_metadata,
+                                    out_filename, check_file_is_writeable};
 
 // The third parameter is for env vars, used on windows to set up the
 // path for MSVC to find its DLLs, and gcc to find its bundled
@@ -107,13 +107,10 @@ pub fn get_linker(sess: &Session, linker: &Path, flavor: LinkerFlavor) -> (PathB
 }
 
 pub fn remove(sess: &Session, path: &Path) {
-    match fs::remove_file(path) {
-        Ok(..) => {}
-        Err(e) => {
-            sess.err(&format!("failed to remove {}: {}",
-                             path.display(),
-                             e));
-        }
+    if let Err(e) = fs::remove_file(path) {
+        sess.err(&format!("failed to remove {}: {}",
+                          path.display(),
+                          e));
     }
 }
 
@@ -147,9 +144,7 @@ pub(crate) fn link_binary(sess: &Session,
 
     // Remove the temporary object file and metadata if we aren't saving temps
     if !sess.opts.cg.save_temps {
-        if sess.opts.output_types.should_codegen() &&
-            !preserve_objects_for_their_debuginfo(sess)
-        {
+        if sess.opts.output_types.should_codegen() && !preserve_objects_for_their_debuginfo(sess) {
             for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) {
                 remove(sess, obj);
             }
@@ -186,7 +181,7 @@ fn preserve_objects_for_their_debuginfo(sess: &Session) -> bool {
     // the objects as they're losslessly contained inside the archives.
     let output_linked = sess.crate_types.borrow()
         .iter()
-        .any(|x| *x != config::CrateType::Rlib && *x != config::CrateType::Staticlib);
+        .any(|&x| x != config::CrateType::Rlib && x != config::CrateType::Staticlib);
     if !output_linked {
         return false
     }
@@ -270,7 +265,7 @@ pub(crate) fn ignored_for_lto(sess: &Session, info: &CrateInfo, cnum: CrateNum)
     // crates providing these functions don't participate in LTO (e.g.
     // no_builtins or compiler builtins crates).
     !sess.target.target.options.no_builtins &&
-        (info.is_no_builtins.contains(&cnum) || info.compiler_builtins == Some(cnum))
+        (info.compiler_builtins == Some(cnum) || info.is_no_builtins.contains(&cnum))
 }
 
 fn link_binary_output(sess: &Session,
@@ -291,13 +286,10 @@ fn link_binary_output(sess: &Session,
         // final destination, with a `fs::rename` call. In order for the rename to
         // always succeed, the temporary file needs to be on the same filesystem,
         // which is why we create it inside the output directory specifically.
-        let metadata_tmpdir = match TempFileBuilder::new()
+        let metadata_tmpdir = TempFileBuilder::new()
             .prefix("rmeta")
             .tempdir_in(out_filename.parent().unwrap())
-        {
-            Ok(tmpdir) => tmpdir,
-            Err(err) => sess.fatal(&format!("couldn't create a temp dir: {}", err)),
-        };
+            .unwrap_or_else(|err| sess.fatal(&format!("couldn't create a temp dir: {}", err)));
         let metadata = emit_metadata(sess, codegen_results, &metadata_tmpdir);
         if let Err(e) = fs::rename(metadata, &out_filename) {
             sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e));
@@ -305,10 +297,8 @@ fn link_binary_output(sess: &Session,
         out_filenames.push(out_filename);
     }
 
-    let tmpdir = match TempFileBuilder::new().prefix("rustc").tempdir() {
-        Ok(tmpdir) => tmpdir,
-        Err(err) => sess.fatal(&format!("couldn't create a temp dir: {}", err)),
-    };
+    let tmpdir = TempFileBuilder::new().prefix("rustc").tempdir().unwrap_or_else(|err|
+        sess.fatal(&format!("couldn't create a temp dir: {}", err)));
 
     if outputs.outputs.should_codegen() {
         let out_filename = out_filename(sess, crate_type, outputs, crate_name);
@@ -342,7 +332,8 @@ fn archive_search_paths(sess: &Session) -> Vec<PathBuf> {
     sess.target_filesearch(PathKind::Native).for_each_lib_search_path(|path, _| {
         search.push(path.to_path_buf());
     });
-    return search;
+
+    search
 }
 
 fn archive_config<'a>(sess: &'a Session,
@@ -814,8 +805,8 @@ fn escape_string(s: &[u8]) -> String {
                     .unwrap_or_else(|_| {
                         let mut x = "Non-UTF-8 output: ".to_string();
                         x.extend(s.iter()
-                                 .flat_map(|&b| ascii::escape_default(b))
-                                 .map(|b| char::from_u32(b as u32).unwrap()));
+                                  .flat_map(|&b| ascii::escape_default(b))
+                                  .map(char::from));
                         x
                     })
             }
@@ -870,9 +861,8 @@ fn escape_string(s: &[u8]) -> String {
         sess.opts.debuginfo != DebugInfo::None &&
         !preserve_objects_for_their_debuginfo(sess)
     {
-        match Command::new("dsymutil").arg(out_filename).output() {
-            Ok(..) => {}
-            Err(e) => sess.fatal(&format!("failed to run dsymutil: {}", e)),
+        if let Err(e) = Command::new("dsymutil").arg(out_filename).output() {
+            sess.fatal(&format!("failed to run dsymutil: {}", e))
         }
     }
 
@@ -1012,8 +1002,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                 // ensure the line is interpreted as one whole argument.
                 for c in self.arg.chars() {
                     match c {
-                        '\\' |
-                        ' ' => write!(f, "\\{}", c)?,
+                        '\\' | ' ' => write!(f, "\\{}", c)?,
                         c => write!(f, "{}", c)?,
                     }
                 }
@@ -1426,7 +1415,6 @@ fn link_sanitizer_runtime(cmd: &mut dyn Linker,
         for f in archive.src_files() {
             if f.ends_with(RLIB_BYTECODE_EXTENSION) || f == METADATA_FILENAME {
                 archive.remove_file(&f);
-                continue
             }
         }
 
index 3d96fef7c0d6f09e9e47f93c52e475fd0d700627..60b06c579cb402e66066338e52d55eb5b93579d2 100644 (file)
@@ -205,11 +205,11 @@ pub(crate) fn run(cgcx: &CodegenContext,
         Lto::Fat => {
             assert!(cached_modules.is_empty());
             let opt_jobs = fat_lto(cgcx,
-                                  &diag_handler,
-                                  modules,
-                                  upstream_modules,
-                                  &symbol_white_list,
-                                  timeline);
+                                   &diag_handler,
+                                   modules,
+                                   upstream_modules,
+                                   &symbol_white_list,
+                                   timeline);
             opt_jobs.map(|opt_jobs| (opt_jobs, vec![]))
         }
         Lto::Thin |
@@ -296,7 +296,7 @@ fn fat_lto(cgcx: &CodegenContext,
                 let data = bc_decoded.data();
                 linker.add(&data).map_err(|()| {
                     let msg = format!("failed to load bc of {:?}", name);
-                    write::llvm_err(&diag_handler, msg)
+                    write::llvm_err(&diag_handler, &msg)
                 })
             })?;
             timeline.record(&format!("link {:?}", name));
@@ -310,8 +310,8 @@ fn fat_lto(cgcx: &CodegenContext,
         unsafe {
             let ptr = symbol_white_list.as_ptr();
             llvm::LLVMRustRunRestrictionPass(llmod,
-                                            ptr as *const *const libc::c_char,
-                                            symbol_white_list.len() as libc::size_t);
+                                             ptr as *const *const libc::c_char,
+                                             symbol_white_list.len() as libc::size_t);
             cgcx.save_temp_bitcode(&module, "lto.after-restriction");
         }
 
@@ -490,7 +490,7 @@ fn thin_lto(cgcx: &CodegenContext,
             symbol_white_list.as_ptr(),
             symbol_white_list.len() as u32,
         ).ok_or_else(|| {
-            write::llvm_err(&diag_handler, "failed to prepare thin LTO context".to_string())
+            write::llvm_err(&diag_handler, "failed to prepare thin LTO context")
         })?;
 
         info!("thin LTO data created");
@@ -595,9 +595,7 @@ fn run_pass_manager(cgcx: &CodegenContext,
         };
         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");
-                }
+                llvm::LLVMRustPassManagerBuilderPopulateThinLTOPassManager(b, pm);
             } else {
                 llvm::LLVMPassManagerBuilderPopulateLTOPassManager(b, pm,
                     /* Internalize = */ False,
@@ -617,8 +615,7 @@ fn run_pass_manager(cgcx: &CodegenContext,
             llvm::LLVMRustAddPass(pm, pass.unwrap());
         }
 
-        time_ext(cgcx.time_passes, None, "LTO passes", ||
-             llvm::LLVMRunPassManager(pm, llmod));
+        time_ext(cgcx.time_passes, None, "LTO passes", || llvm::LLVMRunPassManager(pm, llmod));
 
         llvm::LLVMDisposePassManager(pm);
     }
@@ -747,7 +744,7 @@ unsafe fn optimize(&mut self, cgcx: &CodegenContext, timeline: &mut Timeline)
     {
         let diag_handler = cgcx.create_diag_handler();
         let tm = (cgcx.tm_factory)().map_err(|e| {
-            write::llvm_err(&diag_handler, e)
+            write::llvm_err(&diag_handler, &e)
         })?;
 
         // Right now the implementation we've got only works over serialized
@@ -762,7 +759,7 @@ unsafe fn optimize(&mut self, cgcx: &CodegenContext, timeline: &mut Timeline)
             self.data().len(),
             self.shared.module_names[self.idx].as_ptr(),
         ).ok_or_else(|| {
-            let msg = "failed to parse bitcode for thin LTO module".to_string();
+            let msg = "failed to parse bitcode for thin LTO module";
             write::llvm_err(&diag_handler, msg)
         })? as *const _;
         let module = ModuleCodegen {
@@ -786,7 +783,7 @@ unsafe fn optimize(&mut self, cgcx: &CodegenContext, timeline: &mut Timeline)
             let mut cu2 = ptr::null_mut();
             llvm::LLVMRustThinLTOGetDICompileUnit(llmod, &mut cu1, &mut cu2);
             if !cu2.is_null() {
-                let msg = "multiple source DICompileUnits found".to_string();
+                let msg = "multiple source DICompileUnits found";
                 return Err(write::llvm_err(&diag_handler, msg))
             }
 
@@ -807,25 +804,25 @@ unsafe fn optimize(&mut self, cgcx: &CodegenContext, timeline: &mut Timeline)
             // You can find some more comments about these functions in the LLVM
             // bindings we've got (currently `PassWrapper.cpp`)
             if !llvm::LLVMRustPrepareThinLTORename(self.shared.data.0, llmod) {
-                let msg = "failed to prepare thin LTO module".to_string();
+                let msg = "failed to prepare thin LTO module";
                 return Err(write::llvm_err(&diag_handler, msg))
             }
             cgcx.save_temp_bitcode(&module, "thin-lto-after-rename");
             timeline.record("rename");
             if !llvm::LLVMRustPrepareThinLTOResolveWeak(self.shared.data.0, llmod) {
-                let msg = "failed to prepare thin LTO module".to_string();
+                let msg = "failed to prepare thin LTO module";
                 return Err(write::llvm_err(&diag_handler, msg))
             }
             cgcx.save_temp_bitcode(&module, "thin-lto-after-resolve");
             timeline.record("resolve");
             if !llvm::LLVMRustPrepareThinLTOInternalize(self.shared.data.0, llmod) {
-                let msg = "failed to prepare thin LTO module".to_string();
+                let msg = "failed to prepare thin LTO module";
                 return Err(write::llvm_err(&diag_handler, msg))
             }
             cgcx.save_temp_bitcode(&module, "thin-lto-after-internalize");
             timeline.record("internalize");
             if !llvm::LLVMRustPrepareThinLTOImport(self.shared.data.0, llmod) {
-                let msg = "failed to prepare thin LTO module".to_string();
+                let msg = "failed to prepare thin LTO module";
                 return Err(write::llvm_err(&diag_handler, msg))
             }
             cgcx.save_temp_bitcode(&module, "thin-lto-after-import");
@@ -920,12 +917,6 @@ unsafe fn from_thin_lto_data(data: *const llvm::ThinLTOData) -> ThinLTOImports {
 }
 
 fn module_name_to_str(c_str: &CStr) -> &str {
-    match c_str.to_str() {
-        Ok(s) => s,
-        Err(e) => {
-            bug!("Encountered non-utf8 LLVM module name `{}`: {}",
-                c_str.to_string_lossy(),
-                e)
-        }
-    }
+    c_str.to_str().unwrap_or_else(|e|
+        bug!("Encountered non-utf8 LLVM module name `{}`: {}", c_str.to_string_lossy(), e))
 }
index 9609cb0c1553b205319775ae8f6378a14c7d73ca..ee4a9b30a1a8542224ed72a67ad9318ae60d5f4a 100644 (file)
@@ -42,7 +42,7 @@ pub fn get_rpath_flags(config: &mut RPathConfig) -> Vec<String> {
 
     // Use DT_RUNPATH instead of DT_RPATH if available
     if config.linker_is_gnu {
-        flags.push("-Wl,--enable-new-dtags".to_string());
+        flags.push("-Wl,--enable-new-dtags".to_owned());
     }
 
     flags
@@ -59,7 +59,8 @@ fn rpaths_to_flags(rpaths: &[String]) -> Vec<String> {
             ret.push(format!("-Wl,-rpath,{}", &(*rpath)));
         }
     }
-    return ret;
+
+    ret
 }
 
 fn get_rpaths(config: &mut RPathConfig, libs: &[PathBuf]) -> Vec<String> {
@@ -92,7 +93,8 @@ fn log_rpaths(desc: &str, rpaths: &[String]) {
 
     // Remove duplicates
     let rpaths = minimize_rpaths(&rpaths);
-    return rpaths;
+
+    rpaths
 }
 
 fn get_rpaths_relative_to_output(config: &mut RPathConfig,
@@ -117,8 +119,7 @@ fn get_rpath_relative_to_output(config: &mut RPathConfig, lib: &Path) -> String
     let relative = path_relative_from(&lib, &output).unwrap_or_else(||
         panic!("couldn't create relative path from {:?} to {:?}", output, lib));
     // FIXME (#9639): This needs to handle non-utf8 paths
-    format!("{}/{}", prefix,
-            relative.to_str().expect("non-utf8 component in path"))
+    format!("{}/{}", prefix, relative.to_str().expect("non-utf8 component in path"))
 }
 
 // This routine is adapted from the *old* Path's `path_relative_from`
@@ -168,7 +169,7 @@ fn get_install_prefix_rpath(config: &mut RPathConfig) -> String {
     let path = (config.get_install_prefix_lib_path)();
     let path = env::current_dir().unwrap().join(&path);
     // FIXME (#9639): This needs to handle non-utf8 paths
-    path.to_str().expect("non-utf8 component in rpath").to_string()
+    path.to_str().expect("non-utf8 component in rpath").to_owned()
 }
 
 fn minimize_rpaths(rpaths: &[String]) -> Vec<String> {
index f37854b7bcae0b3386b06c5f4d95cc68da87163d..7101255173cafd08d5bd88aecb4237b57dbc8530 100644 (file)
@@ -42,7 +42,7 @@
 /// https://github.com/llvm-mirror/llvm/commit/0f32e1365, although support still
 /// needs to be added, tracked at https://bugs.llvm.org/show_bug.cgi?id=37168
 pub fn rewrite_imports(path: &Path, import_map: &FxHashMap<String, String>) {
-    if import_map.len() == 0 {
+    if import_map.is_empty() {
         return
     }
 
@@ -127,7 +127,7 @@ impl<'a> Iterator for WasmSections<'a> {
     type Item = (u8, &'a [u8]);
 
     fn next(&mut self) -> Option<(u8, &'a [u8])> {
-        if self.0.data.len() == 0 {
+        if self.0.data.is_empty() {
             return None
         }
 
index 184be4b9eab39d76841af69ce451f065c2ee9757..8973852caa86b351d594d5ae1e730198ade33fe6 100644 (file)
@@ -64,7 +64,7 @@
 use std::thread;
 use libc::{c_uint, c_void, c_char, size_t};
 
-pub const RELOC_MODEL_ARGS : [(&'static str, llvm::RelocMode); 7] = [
+pub const RELOC_MODEL_ARGS : [(&str, llvm::RelocMode); 7] = [
     ("pic", llvm::RelocMode::PIC),
     ("static", llvm::RelocMode::Static),
     ("default", llvm::RelocMode::Default),
@@ -81,7 +81,7 @@
     ("large", llvm::CodeModel::Large),
 ];
 
-pub const TLS_MODEL_ARGS : [(&'static str, llvm::ThreadLocalMode); 4] = [
+pub const TLS_MODEL_ARGS : [(&str, llvm::ThreadLocalMode); 4] = [
     ("global-dynamic", llvm::ThreadLocalMode::GeneralDynamic),
     ("local-dynamic", llvm::ThreadLocalMode::LocalDynamic),
     ("initial-exec", llvm::ThreadLocalMode::InitialExec),
@@ -90,7 +90,7 @@
 
 const PRE_THIN_LTO_BC_EXT: &str = "pre-thin-lto.bc";
 
-pub fn llvm_err(handler: &errors::Handler, msg: String) -> FatalError {
+pub fn llvm_err(handler: &errors::Handler, msg: &str) -> FatalError {
     match llvm::last_error() {
         Some(err) => handler.fatal(&format!("{}: {}", msg, err)),
         None => handler.fatal(&msg),
@@ -106,11 +106,10 @@ pub fn write_output_file(
         file_type: llvm::FileType) -> Result<(), FatalError> {
     unsafe {
         let output_c = path2cstr(output);
-        let result = llvm::LLVMRustWriteOutputFile(
-                target, pm, m, output_c.as_ptr(), file_type);
+        let result = llvm::LLVMRustWriteOutputFile(target, pm, m, output_c.as_ptr(), file_type);
         if result.into_result().is_err() {
             let msg = format!("could not write output to {}", output.display());
-            Err(llvm_err(handler, msg))
+            Err(llvm_err(handler, &msg))
         } else {
             Ok(())
         }
@@ -140,7 +139,7 @@ pub fn create_target_machine(
     find_features: bool,
 ) -> &'static mut llvm::TargetMachine {
     target_machine_factory(sess, find_features)().unwrap_or_else(|err| {
-        llvm_err(sess.diagnostic(), err).raise()
+        llvm_err(sess.diagnostic(), &err).raise()
     })
 }
 
@@ -456,7 +455,7 @@ fn drop(&mut self) {
 unsafe extern "C" fn report_inline_asm<'a, 'b>(cgcx: &'a CodegenContext,
                                                msg: &'b str,
                                                cookie: c_uint) {
-    cgcx.diag_emitter.inline_asm_error(cookie as u32, msg.to_string());
+    cgcx.diag_emitter.inline_asm_error(cookie as u32, msg.to_owned());
 }
 
 unsafe extern "C" fn inline_asm_handler(diag: &SMDiagnostic,
@@ -590,8 +589,7 @@ unsafe fn optimize(cgcx: &CodegenContext,
 
             for pass in &config.passes {
                 if !addpass(pass) {
-                    diag_handler.warn(&format!("unknown pass `{}`, ignoring",
-                                            pass));
+                    diag_handler.warn(&format!("unknown pass `{}`, ignoring", pass));
                 }
                 if pass == "name-anon-globals" {
                     have_name_anon_globals_pass = true;
@@ -601,8 +599,8 @@ unsafe fn optimize(cgcx: &CodegenContext,
             for pass in &cgcx.plugin_passes {
                 if !addpass(pass) {
                     diag_handler.err(&format!("a plugin asked for LLVM pass \
-                                            `{}` but LLVM does not \
-                                            recognize it", pass));
+                                               `{}` but LLVM does not \
+                                               recognize it", pass));
                 }
                 if pass == "name-anon-globals" {
                     have_name_anon_globals_pass = true;
@@ -613,12 +611,12 @@ unsafe fn optimize(cgcx: &CodegenContext,
                 // As described above, this will probably cause an error in LLVM
                 if config.no_prepopulate_passes {
                     diag_handler.err("The current compilation is going to use thin LTO buffers \
-                                     without running LLVM's NameAnonGlobals pass. \
-                                     This will likely cause errors in LLVM. Consider adding \
-                                     -C passes=name-anon-globals to the compiler command line.");
+                                      without running LLVM's NameAnonGlobals pass. \
+                                      This will likely cause errors in LLVM. Consider adding \
+                                      -C passes=name-anon-globals to the compiler command line.");
                 } else {
                     bug!("We are using thin LTO buffers without running the NameAnonGlobals pass. \
-                         This will likely cause errors in LLVM and should never happen.");
+                          This will likely cause errors in LLVM and should never happen.");
                 }
             }
         }
@@ -704,9 +702,9 @@ unsafe fn codegen(cgcx: &CodegenContext,
         // escape the closure itself, and the manager should only be
         // used once.
         unsafe fn with_codegen<'ll, F, R>(tm: &'ll llvm::TargetMachine,
-                                    llmod: &'ll llvm::Module,
-                                    no_builtins: bool,
-                                    f: F) -> R
+                                          llmod: &'ll llvm::Module,
+                                          no_builtins: bool,
+                                          f: F) -> R
             where F: FnOnce(&'ll mut PassManager<'ll>) -> R,
         {
             let cpm = llvm::LLVMCreatePassManager();
@@ -818,7 +816,7 @@ extern "C" fn demangle_callback(input_ptr: *const c_char,
                 };
                 with_codegen(tm, llmod, config.no_builtins, |cpm| {
                     write_output_file(diag_handler, tm, cpm, llmod, &path,
-                                    llvm::FileType::AssemblyFile)
+                                      llvm::FileType::AssemblyFile)
                 })?;
                 timeline.record("asm");
             }
@@ -826,7 +824,7 @@ extern "C" fn demangle_callback(input_ptr: *const c_char,
             if write_obj {
                 with_codegen(tm, llmod, config.no_builtins, |cpm| {
                     write_output_file(diag_handler, tm, cpm, llmod, &obj_out,
-                                    llvm::FileType::ObjectFile)
+                                      llvm::FileType::ObjectFile)
                 })?;
                 timeline.record("obj");
             } else if asm_to_obj {
@@ -947,11 +945,11 @@ fn need_pre_thin_lto_bitcode_for_incr_comp(sess: &Session) -> bool {
 }
 
 pub fn start_async_codegen(tcx: TyCtxt,
-                               time_graph: Option<TimeGraph>,
-                               metadata: EncodedMetadata,
-                               coordinator_receive: Receiver<Box<dyn Any + Send>>,
-                               total_cgus: usize)
-                               -> OngoingCodegen {
+                           time_graph: Option<TimeGraph>,
+                           metadata: EncodedMetadata,
+                           coordinator_receive: Receiver<Box<dyn Any + Send>>,
+                           total_cgus: usize)
+                           -> OngoingCodegen {
     let sess = tcx.sess;
     let crate_name = tcx.crate_name(LOCAL_CRATE);
     let crate_hash = tcx.crate_hash(LOCAL_CRATE);
@@ -1116,7 +1114,8 @@ fn copy_all_cgu_workproducts_to_incr_comp_cache_dir(
         }
 
         if let Some((id, product)) =
-                copy_cgu_workproducts_to_incr_comp_cache_dir(sess, &module.name, &files) {
+            copy_cgu_workproducts_to_incr_comp_cache_dir(sess, &module.name, &files)
+        {
             work_products.insert(id, product);
         }
     }
@@ -1441,15 +1440,12 @@ fn execute_copy_from_cache_work_item(cgcx: &CodegenContext,
                module.name,
                source_file,
                obj_out.display());
-        match link_or_copy(&source_file, &obj_out) {
-            Ok(_) => { }
-            Err(err) => {
-                let diag_handler = cgcx.create_diag_handler();
-                diag_handler.err(&format!("unable to copy {} to {}: {}",
-                                          source_file.display(),
-                                          obj_out.display(),
-                                          err));
-            }
+        if let Err(err) = link_or_copy(&source_file, &obj_out) {
+            let diag_handler = cgcx.create_diag_handler();
+            diag_handler.err(&format!("unable to copy {} to {}: {}",
+                                      source_file.display(),
+                                      obj_out.display(),
+                                      err));
         }
     }
 
@@ -1584,10 +1580,8 @@ fn start_executing_work(tcx: TyCtxt,
 
         let (name, mut cmd) = get_linker(sess, &linker, flavor);
         cmd.args(&sess.target.target.options.asm_args);
-        Some(Arc::new(AssemblerCommand {
-            name,
-            cmd,
-        }))
+
+        Some(Arc::new(AssemblerCommand { name, cmd }))
     } else {
         None
     };
@@ -2186,9 +2180,9 @@ pub fn run_assembler(cgcx: &CodegenContext, handler: &Handler, assembly: &Path,
                 handler.struct_err(&format!("linking with `{}` failed: {}",
                                             pname.display(),
                                             prog.status))
-                    .note(&format!("{:?}", &cmd))
-                    .note(str::from_utf8(&note[..]).unwrap())
-                    .emit();
+                       .note(&format!("{:?}", &cmd))
+                       .note(str::from_utf8(&note[..]).unwrap())
+                       .emit();
                 handler.abort_if_errors();
             }
         },
@@ -2450,8 +2444,8 @@ pub(crate) fn join(
     }
 
     pub(crate) fn submit_pre_codegened_module_to_llvm(&self,
-                                                       tcx: TyCtxt,
-                                                       module: ModuleCodegen) {
+                                                      tcx: TyCtxt,
+                                                      module: ModuleCodegen) {
         self.wait_for_signal_to_codegen_item();
         self.check_for_errors(tcx.sess);
 
index fb33fe85b005441782f340c8f880a687273bbf3e..806025937cb110c75028094c56caee1e6fda7f1e 100644 (file)
@@ -53,7 +53,7 @@
 use attributes;
 use builder::{Builder, MemFlags};
 use callee;
-use common::{C_bool, C_bytes_in_context, C_i32, C_usize};
+use common::{C_bool, C_bytes_in_context, C_usize};
 use rustc_mir::monomorphize::item::DefPathBasedNames;
 use common::{C_struct_in_context, C_array, val_ty};
 use consts;
@@ -77,7 +77,6 @@
 use std::any::Any;
 use std::cmp;
 use std::ffi::CString;
-use std::i32;
 use std::ops::{Deref, DerefMut};
 use std::sync::mpsc;
 use std::time::{Instant, Duration};
@@ -319,8 +318,8 @@ pub fn coerce_unsized_into(
                 }
 
                 if src_f.layout.ty == dst_f.layout.ty {
-                    memcpy_ty(bx, dst_f.llval, src_f.llval, src_f.layout,
-                              src_f.align.min(dst_f.align), MemFlags::empty());
+                    memcpy_ty(bx, dst_f.llval, dst_f.align, src_f.llval, src_f.align,
+                              src_f.layout, MemFlags::empty());
                 } else {
                     coerce_unsized_into(bx, src_f, dst_f);
                 }
@@ -420,36 +419,34 @@ pub fn to_immediate_scalar(
 pub fn call_memcpy(
     bx: &Builder<'_, 'll, '_>,
     dst: &'ll Value,
+    dst_align: Align,
     src: &'ll Value,
+    src_align: Align,
     n_bytes: &'ll Value,
-    align: Align,
     flags: MemFlags,
 ) {
     if flags.contains(MemFlags::NONTEMPORAL) {
         // HACK(nox): This is inefficient but there is no nontemporal memcpy.
-        let val = bx.load(src, align);
+        let val = bx.load(src, src_align);
         let ptr = bx.pointercast(dst, val_ty(val).ptr_to());
-        bx.store_with_flags(val, ptr, align, flags);
+        bx.store_with_flags(val, ptr, dst_align, flags);
         return;
     }
     let cx = bx.cx;
-    let ptr_width = &cx.sess().target.target.target_pointer_width;
-    let key = format!("llvm.memcpy.p0i8.p0i8.i{}", ptr_width);
-    let memcpy = cx.get_intrinsic(&key);
     let src_ptr = bx.pointercast(src, Type::i8p(cx));
     let dst_ptr = bx.pointercast(dst, Type::i8p(cx));
     let size = bx.intcast(n_bytes, cx.isize_ty, false);
-    let align = C_i32(cx, align.abi() as i32);
-    let volatile = C_bool(cx, flags.contains(MemFlags::VOLATILE));
-    bx.call(memcpy, &[dst_ptr, src_ptr, size, align, volatile], None);
+    let volatile = flags.contains(MemFlags::VOLATILE);
+    bx.memcpy(dst_ptr, dst_align.abi(), src_ptr, src_align.abi(), size, volatile);
 }
 
 pub fn memcpy_ty(
     bx: &Builder<'_, 'll, 'tcx>,
     dst: &'ll Value,
+    dst_align: Align,
     src: &'ll Value,
+    src_align: Align,
     layout: TyLayout<'tcx>,
-    align: Align,
     flags: MemFlags,
 ) {
     let size = layout.size.bytes();
@@ -457,7 +454,7 @@ pub fn memcpy_ty(
         return;
     }
 
-    call_memcpy(bx, dst, src, C_usize(bx.cx, size), align, flags);
+    call_memcpy(bx, dst, dst_align, src, src_align, C_usize(bx.cx, size), flags);
 }
 
 pub fn call_memset(
index f70a68c72489a457df330d85794677f40ce912ca..9db4015013e28a7fa810ebf41ea6ebb776142ef8 100644 (file)
@@ -781,6 +781,24 @@ pub fn call(&self, llfn: &'ll Value, args: &[&'ll Value],
         }
     }
 
+    pub fn memcpy(&self, dst: &'ll Value, dst_align: u64,
+                  src: &'ll Value, src_align: u64,
+                  size: &'ll Value, is_volatile: bool) -> &'ll Value {
+        unsafe {
+            llvm::LLVMRustBuildMemCpy(self.llbuilder, dst, dst_align as c_uint,
+                                      src, src_align as c_uint, size, is_volatile)
+        }
+    }
+
+    pub fn memmove(&self, dst: &'ll Value, dst_align: u64,
+                  src: &'ll Value, src_align: u64,
+                  size: &'ll Value, is_volatile: bool) -> &'ll Value {
+        unsafe {
+            llvm::LLVMRustBuildMemMove(self.llbuilder, dst, dst_align as c_uint,
+                                      src, src_align as c_uint, size, is_volatile)
+        }
+    }
+
     pub fn minnum(&self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         self.count_insn("minnum");
         unsafe {
@@ -856,8 +874,7 @@ pub fn vector_reduce_fadd_fast(&self, acc: &'ll Value, src: &'ll Value) -> &'ll
             // FIXME: add a non-fast math version once
             // https://bugs.llvm.org/show_bug.cgi?id=36732
             // is fixed.
-            let instr = llvm::LLVMRustBuildVectorReduceFAdd(self.llbuilder, acc, src)
-                .expect("LLVMRustBuildVectorReduceFAdd is not available in LLVM version < 5.0");
+            let instr = llvm::LLVMRustBuildVectorReduceFAdd(self.llbuilder, acc, src);
             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
             instr
         }
@@ -868,66 +885,43 @@ pub fn vector_reduce_fmul_fast(&self, acc: &'ll Value, src: &'ll Value) -> &'ll
             // FIXME: add a non-fast math version once
             // https://bugs.llvm.org/show_bug.cgi?id=36732
             // is fixed.
-            let instr = llvm::LLVMRustBuildVectorReduceFMul(self.llbuilder, acc, src)
-                .expect("LLVMRustBuildVectorReduceFMul is not available in LLVM version < 5.0");
+            let instr = llvm::LLVMRustBuildVectorReduceFMul(self.llbuilder, acc, src);
             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
             instr
         }
     }
     pub fn vector_reduce_add(&self, src: &'ll Value) -> &'ll Value {
         self.count_insn("vector.reduce.add");
-        unsafe {
-            let instr = llvm::LLVMRustBuildVectorReduceAdd(self.llbuilder, src);
-            instr.expect("LLVMRustBuildVectorReduceAdd is not available in LLVM version < 5.0")
-        }
+        unsafe { llvm::LLVMRustBuildVectorReduceAdd(self.llbuilder, src) }
     }
     pub fn vector_reduce_mul(&self, src: &'ll Value) -> &'ll Value {
         self.count_insn("vector.reduce.mul");
-        unsafe {
-            let instr = llvm::LLVMRustBuildVectorReduceMul(self.llbuilder, src);
-            instr.expect("LLVMRustBuildVectorReduceMul is not available in LLVM version < 5.0")
-        }
+        unsafe { llvm::LLVMRustBuildVectorReduceMul(self.llbuilder, src) }
     }
     pub fn vector_reduce_and(&self, src: &'ll Value) -> &'ll Value {
         self.count_insn("vector.reduce.and");
-        unsafe {
-            let instr = llvm::LLVMRustBuildVectorReduceAnd(self.llbuilder, src);
-            instr.expect("LLVMRustBuildVectorReduceAnd is not available in LLVM version < 5.0")
-        }
+        unsafe { llvm::LLVMRustBuildVectorReduceAnd(self.llbuilder, src) }
     }
     pub fn vector_reduce_or(&self, src: &'ll Value) -> &'ll Value {
         self.count_insn("vector.reduce.or");
-        unsafe {
-            let instr = llvm::LLVMRustBuildVectorReduceOr(self.llbuilder, src);
-            instr.expect("LLVMRustBuildVectorReduceOr is not available in LLVM version < 5.0")
-        }
+        unsafe { llvm::LLVMRustBuildVectorReduceOr(self.llbuilder, src) }
     }
     pub fn vector_reduce_xor(&self, src: &'ll Value) -> &'ll Value {
         self.count_insn("vector.reduce.xor");
-        unsafe {
-            let instr = llvm::LLVMRustBuildVectorReduceXor(self.llbuilder, src);
-            instr.expect("LLVMRustBuildVectorReduceXor is not available in LLVM version < 5.0")
-        }
+        unsafe { llvm::LLVMRustBuildVectorReduceXor(self.llbuilder, src) }
     }
     pub fn vector_reduce_fmin(&self, src: &'ll Value) -> &'ll Value {
         self.count_insn("vector.reduce.fmin");
-        unsafe {
-            let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ false);
-            instr.expect("LLVMRustBuildVectorReduceFMin is not available in LLVM version < 5.0")
-        }
+        unsafe { llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ false) }
     }
     pub fn vector_reduce_fmax(&self, src: &'ll Value) -> &'ll Value {
         self.count_insn("vector.reduce.fmax");
-        unsafe {
-            let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ false);
-            instr.expect("LLVMRustBuildVectorReduceFMax is not available in LLVM version < 5.0")
-        }
+        unsafe { llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ false) }
     }
     pub fn vector_reduce_fmin_fast(&self, src: &'ll Value) -> &'ll Value {
         self.count_insn("vector.reduce.fmin_fast");
         unsafe {
-            let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ true)
-                .expect("LLVMRustBuildVectorReduceFMin is not available in LLVM version < 5.0");
+            let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ true);
             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
             instr
         }
@@ -935,25 +929,18 @@ pub fn vector_reduce_fmin_fast(&self, src: &'ll Value) -> &'ll Value {
     pub fn vector_reduce_fmax_fast(&self, src: &'ll Value) -> &'ll Value {
         self.count_insn("vector.reduce.fmax_fast");
         unsafe {
-            let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ true)
-                .expect("LLVMRustBuildVectorReduceFMax is not available in LLVM version < 5.0");
+            let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ true);
             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
             instr
         }
     }
     pub fn vector_reduce_min(&self, src: &'ll Value, is_signed: bool) -> &'ll Value {
         self.count_insn("vector.reduce.min");
-        unsafe {
-            let instr = llvm::LLVMRustBuildVectorReduceMin(self.llbuilder, src, is_signed);
-            instr.expect("LLVMRustBuildVectorReduceMin is not available in LLVM version < 5.0")
-        }
+        unsafe { llvm::LLVMRustBuildVectorReduceMin(self.llbuilder, src, is_signed) }
     }
     pub fn vector_reduce_max(&self, src: &'ll Value, is_signed: bool) -> &'ll Value {
         self.count_insn("vector.reduce.max");
-        unsafe {
-            let instr = llvm::LLVMRustBuildVectorReduceMax(self.llbuilder, src, is_signed);
-            instr.expect("LLVMRustBuildVectorReduceMax is not available in LLVM version < 5.0")
-        }
+        unsafe { llvm::LLVMRustBuildVectorReduceMax(self.llbuilder, src, is_signed) }
     }
 
     pub fn extract_value(&self, agg_val: &'ll Value, idx: u64) -> &'ll Value {
index 120449ae2af4c2518294656eaac3aa6fb68370d5..81d615b5ad70a3505ba53819730a29fa6d1227f6 100644 (file)
@@ -530,12 +530,6 @@ macro_rules! mk_struct {
     let t_v4f64 = Type::vector(t_f64, 4);
     let t_v8f64 = Type::vector(t_f64, 8);
 
-    ifn!("llvm.memcpy.p0i8.p0i8.i16", fn(i8p, i8p, t_i16, t_i32, i1) -> void);
-    ifn!("llvm.memcpy.p0i8.p0i8.i32", fn(i8p, i8p, t_i32, t_i32, i1) -> void);
-    ifn!("llvm.memcpy.p0i8.p0i8.i64", fn(i8p, i8p, t_i64, t_i32, i1) -> void);
-    ifn!("llvm.memmove.p0i8.p0i8.i16", fn(i8p, i8p, t_i16, t_i32, i1) -> void);
-    ifn!("llvm.memmove.p0i8.p0i8.i32", fn(i8p, i8p, t_i32, t_i32, i1) -> void);
-    ifn!("llvm.memmove.p0i8.p0i8.i64", fn(i8p, i8p, t_i64, t_i32, i1) -> void);
     ifn!("llvm.memset.p0i8.i16", fn(i8p, t_i8, t_i16, t_i32, i1) -> void);
     ifn!("llvm.memset.p0i8.i32", fn(i8p, t_i8, t_i32, t_i32, i1) -> void);
     ifn!("llvm.memset.p0i8.i64", fn(i8p, t_i8, t_i64, t_i32, i1) -> void);
@@ -726,6 +720,18 @@ macro_rules! mk_struct {
     ifn!("llvm.bitreverse.i64", fn(t_i64) -> t_i64);
     ifn!("llvm.bitreverse.i128", fn(t_i128) -> t_i128);
 
+    ifn!("llvm.fshl.i8", fn(t_i8, t_i8, t_i8) -> t_i8);
+    ifn!("llvm.fshl.i16", fn(t_i16, t_i16, t_i16) -> t_i16);
+    ifn!("llvm.fshl.i32", fn(t_i32, t_i32, t_i32) -> t_i32);
+    ifn!("llvm.fshl.i64", fn(t_i64, t_i64, t_i64) -> t_i64);
+    ifn!("llvm.fshl.i128", fn(t_i128, t_i128, t_i128) -> t_i128);
+
+    ifn!("llvm.fshr.i8", fn(t_i8, t_i8, t_i8) -> t_i8);
+    ifn!("llvm.fshr.i16", fn(t_i16, t_i16, t_i16) -> t_i16);
+    ifn!("llvm.fshr.i32", fn(t_i32, t_i32, t_i32) -> t_i32);
+    ifn!("llvm.fshr.i64", fn(t_i64, t_i64, t_i64) -> t_i64);
+    ifn!("llvm.fshr.i128", fn(t_i128, t_i128, t_i128) -> t_i128);
+
     ifn!("llvm.sadd.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1});
     ifn!("llvm.sadd.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1});
     ifn!("llvm.sadd.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1});
index ba1e3f5960c8596b0d4c484aff8f703fd986d8ef..38b3a1b9c1ab73fdaef222e193102e61ee6316f8 100644 (file)
@@ -23,6 +23,7 @@
 use llvm;
 use llvm::debuginfo::{DIType, DIFile, DIScope, DIDescriptor,
                       DICompositeType, DILexicalBlock, DIFlags};
+use llvm_util;
 
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc::hir::CodegenFnAttrFlags;
@@ -1169,9 +1170,8 @@ fn prepare_union_metadata(
 fn use_enum_fallback(cx: &CodegenCx) -> bool {
     // On MSVC we have to use the fallback mode, because LLVM doesn't
     // lower variant parts to PDB.
-    return cx.sess().target.target.options.is_like_msvc || unsafe {
-        llvm::LLVMRustVersionMajor() < 7
-    };
+    return cx.sess().target.target.options.is_like_msvc
+        || llvm_util::get_major_version() < 7;
 }
 
 // Describes the members of an enum value: An enum is described as a union of
@@ -1279,7 +1279,7 @@ fn create_member_descriptions(&self, cx: &CodegenCx<'ll, 'tcx>)
                 niche_start,
                 ref variants,
                 dataful_variant,
-                ..
+                ref niche,
             } => {
                 if fallback {
                     let variant = self.layout.for_variant(cx, dataful_variant);
@@ -1361,11 +1361,11 @@ fn compute_field_path<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
                         let niche_value = if i == dataful_variant {
                             None
                         } else {
-                            let niche = (i as u128)
+                            let value = (i as u128)
                                 .wrapping_sub(*niche_variants.start() as u128)
                                 .wrapping_add(niche_start);
-                            assert_eq!(niche as u64 as u128, niche);
-                            Some(niche as u64)
+                            let value = value & ((1u128 << niche.value.size(cx).bits()) - 1);
+                            Some(value as u64)
                         };
 
                         MemberDescription {
index e44bd2d23672fcb371facfb0459b2a351595414d..a5f90149f4ac47293715041893956d31d8c5bae2 100644 (file)
@@ -13,6 +13,7 @@
 use attributes;
 use intrinsics::{self, Intrinsic};
 use llvm::{self, TypeKind};
+use llvm_util;
 use abi::{Abi, FnType, LlvmType, PassMode};
 use mir::place::PlaceRef;
 use mir::operand::{OperandRef, OperandValue};
@@ -23,7 +24,7 @@
 use type_::Type;
 use type_of::LayoutLlvmExt;
 use rustc::ty::{self, Ty};
-use rustc::ty::layout::{HasDataLayout, LayoutOf};
+use rustc::ty::layout::LayoutOf;
 use rustc::hir;
 use syntax::ast;
 use syntax::symbol::Symbol;
@@ -284,7 +285,8 @@ pub fn codegen_intrinsic_call(
         "ctlz" | "ctlz_nonzero" | "cttz" | "cttz_nonzero" | "ctpop" | "bswap" |
         "bitreverse" | "add_with_overflow" | "sub_with_overflow" |
         "mul_with_overflow" | "overflowing_add" | "overflowing_sub" | "overflowing_mul" |
-        "unchecked_div" | "unchecked_rem" | "unchecked_shl" | "unchecked_shr" | "exact_div" => {
+        "unchecked_div" | "unchecked_rem" | "unchecked_shl" | "unchecked_shr" | "exact_div" |
+        "rotate_left" | "rotate_right" => {
             let ty = arg_tys[0];
             match int_type_width_signed(ty, cx) {
                 Some((width, signed)) =>
@@ -363,6 +365,27 @@ pub fn codegen_intrinsic_call(
                             } else {
                                 bx.lshr(args[0].immediate(), args[1].immediate())
                             },
+                        "rotate_left" | "rotate_right" => {
+                            let is_left = name == "rotate_left";
+                            let val = args[0].immediate();
+                            let raw_shift = args[1].immediate();
+                            if llvm_util::get_major_version() >= 7 {
+                                // rotate = funnel shift with first two args the same
+                                let llvm_name = &format!("llvm.fsh{}.i{}",
+                                                         if is_left { 'l' } else { 'r' }, width);
+                                let llfn = cx.get_intrinsic(llvm_name);
+                                bx.call(llfn, &[val, val, raw_shift], None)
+                            } else {
+                                // rotate_left: (X << (S % BW)) | (X >> ((BW - S) % BW))
+                                // rotate_right: (X << ((BW - S) % BW)) | (X >> (S % BW))
+                                let width = C_uint(Type::ix(cx, width), width);
+                                let shift = bx.urem(raw_shift, width);
+                                let inv_shift = bx.urem(bx.sub(width, raw_shift), width);
+                                let shift1 = bx.shl(val, if is_left { shift } else { inv_shift });
+                                let shift2 = bx.lshr(val, if !is_left { shift } else { inv_shift });
+                                bx.or(shift1, shift2)
+                            }
+                        },
                         _ => bug!(),
                     },
                 None => {
@@ -690,28 +713,14 @@ fn copy_intrinsic(
     let cx = bx.cx;
     let (size, align) = cx.size_and_align_of(ty);
     let size = C_usize(cx, size.bytes());
-    let align = C_i32(cx, align.abi() as i32);
-
-    let operation = if allow_overlap {
-        "memmove"
-    } else {
-        "memcpy"
-    };
-
-    let name = format!("llvm.{}.p0i8.p0i8.i{}", operation,
-                       cx.data_layout().pointer_size.bits());
-
+    let align = align.abi();
     let dst_ptr = bx.pointercast(dst, Type::i8p(cx));
     let src_ptr = bx.pointercast(src, Type::i8p(cx));
-    let llfn = cx.get_intrinsic(&name);
-
-    bx.call(llfn,
-        &[dst_ptr,
-        src_ptr,
-        bx.mul(size, count),
-        align,
-        C_bool(cx, volatile)],
-        None)
+    if allow_overlap {
+        bx.memmove(dst_ptr, align, src_ptr, align, bx.mul(size, count), volatile)
+    } else {
+        bx.memcpy(dst_ptr, align, src_ptr, align, bx.mul(size, count), volatile)
+    }
 }
 
 fn memset_intrinsic(
index 12d4670e4be4bed52973273fdaf37e5b3bb2b598..612581c1ac671067cbb4efb219aa93260fed01db 100644 (file)
@@ -998,6 +998,22 @@ pub fn LLVMRustBuildCall(B: &Builder<'a>,
                              Bundle: Option<&OperandBundleDef<'a>>,
                              Name: *const c_char)
                              -> &'a Value;
+    pub fn LLVMRustBuildMemCpy(B: &Builder<'a>,
+                               Dst: &'a Value,
+                               DstAlign: c_uint,
+                               Src: &'a Value,
+                               SrcAlign: c_uint,
+                               Size: &'a Value,
+                               IsVolatile: bool)
+                               -> &'a Value;
+    pub fn LLVMRustBuildMemMove(B: &Builder<'a>,
+                                Dst: &'a Value,
+                                DstAlign: c_uint,
+                                Src: &'a Value,
+                                SrcAlign: c_uint,
+                                Size: &'a Value,
+                                IsVolatile: bool)
+                                -> &'a Value;
     pub fn LLVMBuildSelect(B: &Builder<'a>,
                            If: &'a Value,
                            Then: &'a Value,
@@ -1041,42 +1057,42 @@ pub fn LLVMBuildInsertValue(B: &Builder<'a>,
     pub fn LLVMRustBuildVectorReduceFAdd(B: &Builder<'a>,
                                          Acc: &'a Value,
                                          Src: &'a Value)
-                                         -> Option<&'a Value>;
+                                         -> &'a Value;
     pub fn LLVMRustBuildVectorReduceFMul(B: &Builder<'a>,
                                          Acc: &'a Value,
                                          Src: &'a Value)
-                                         -> Option<&'a Value>;
+                                         -> &'a Value;
     pub fn LLVMRustBuildVectorReduceAdd(B: &Builder<'a>,
                                         Src: &'a Value)
-                                        -> Option<&'a Value>;
+                                        -> &'a Value;
     pub fn LLVMRustBuildVectorReduceMul(B: &Builder<'a>,
                                         Src: &'a Value)
-                                        -> Option<&'a Value>;
+                                        -> &'a Value;
     pub fn LLVMRustBuildVectorReduceAnd(B: &Builder<'a>,
                                         Src: &'a Value)
-                                        -> Option<&'a Value>;
+                                        -> &'a Value;
     pub fn LLVMRustBuildVectorReduceOr(B: &Builder<'a>,
                                        Src: &'a Value)
-                                       -> Option<&'a Value>;
+                                       -> &'a Value;
     pub fn LLVMRustBuildVectorReduceXor(B: &Builder<'a>,
                                         Src: &'a Value)
-                                        -> Option<&'a Value>;
+                                        -> &'a Value;
     pub fn LLVMRustBuildVectorReduceMin(B: &Builder<'a>,
                                         Src: &'a Value,
                                         IsSigned: bool)
-                                        -> Option<&'a Value>;
+                                        -> &'a Value;
     pub fn LLVMRustBuildVectorReduceMax(B: &Builder<'a>,
                                         Src: &'a Value,
                                         IsSigned: bool)
-                                        -> Option<&'a Value>;
+                                        -> &'a Value;
     pub fn LLVMRustBuildVectorReduceFMin(B: &Builder<'a>,
                                          Src: &'a Value,
                                          IsNaN: bool)
-                                         -> Option<&'a Value>;
+                                         -> &'a Value;
     pub fn LLVMRustBuildVectorReduceFMax(B: &Builder<'a>,
                                          Src: &'a Value,
                                          IsNaN: bool)
-                                         -> Option<&'a Value>;
+                                         -> &'a Value;
 
     pub fn LLVMRustBuildMinNum(
         B: &Builder<'a>,
@@ -1157,7 +1173,7 @@ pub fn LLVMPassManagerBuilderPopulateLTOPassManager(PMB: &PassManagerBuilder,
                                                         RunInliner: Bool);
     pub fn LLVMRustPassManagerBuilderPopulateThinLTOPassManager(
         PMB: &PassManagerBuilder,
-        PM: &PassManager) -> bool;
+        PM: &PassManager);
 
     // Stuff that's in rustllvm/ because it's not upstream yet.
 
index 0a80fdddbf9fdb4197d3b0b2f937a47e2c423a18..eaa599e0cd0fa67f8382eda55fe7575f9aadf9ad 100644 (file)
@@ -243,7 +243,8 @@ pub fn target_feature_whitelist(sess: &Session)
         "hexagon" => HEXAGON_WHITELIST,
         "mips" | "mips64" => MIPS_WHITELIST,
         "powerpc" | "powerpc64" => POWERPC_WHITELIST,
-        "wasm32" => WASM_WHITELIST,
+        // wasm32 on emscripten does not support these target features
+        "wasm32" if !sess.target.target.options.is_like_emscripten => WASM_WHITELIST,
         _ => &[],
     }
 }
@@ -256,6 +257,10 @@ pub fn print_version() {
     }
 }
 
+pub fn get_major_version() -> u32 {
+    unsafe { llvm::LLVMRustVersionMajor() }
+}
+
 pub fn print_passes() {
     // Can be called without initializing LLVM
     unsafe { llvm::LLVMRustPrintPasses(); }
index d38f343d01f34981b5088ff949df6494df9fd924..0dc5a4ddde82c538bc820518cff99dfb18b3f5cd 100644 (file)
@@ -39,7 +39,7 @@ pub fn get_fn(self, bx: &Builder<'a, 'll, 'tcx>,
         // Load the data pointer from the object.
         debug!("get_fn({:?}, {:?})", llvtable, self);
 
-        let llvtable = bx.pointercast(llvtable, fn_ty.llvm_type(bx.cx).ptr_to().ptr_to());
+        let llvtable = bx.pointercast(llvtable, fn_ty.ptr_to_llvm_type(bx.cx).ptr_to());
         let ptr_align = bx.tcx().data_layout.pointer_align;
         let ptr = bx.load(bx.inbounds_gep(llvtable, &[C_usize(bx.cx, self.0)]), ptr_align);
         bx.nonnull_metadata(ptr);
index a7f4c48c89bd6c99ef8e7a559e702f14d0033b26..3f9921a5cf930b68372a3584a17f6b725727d6f4 100644 (file)
@@ -784,7 +784,8 @@ fn codegen_argument(&mut self,
                     // have scary latent bugs around.
 
                     let scratch = PlaceRef::alloca(bx, arg.layout, "arg");
-                    base::memcpy_ty(bx, scratch.llval, llval, op.layout, align, MemFlags::empty());
+                    base::memcpy_ty(bx, scratch.llval, scratch.align, llval, align,
+                                    op.layout, MemFlags::empty());
                     (scratch.llval, scratch.align, true)
                 } else {
                     (llval, align, true)
index a6e2ccf92e4e3fd416a028c1950679fb0fce14a0..e5b25ea068b3b7fd463c7fabc7afd987a7cd3a0b 100644 (file)
@@ -12,6 +12,7 @@
 use libc::c_uint;
 use llvm::{self, BasicBlock};
 use llvm::debuginfo::DIScope;
+use llvm_util;
 use rustc::ty::{self, Ty, TypeFoldable, UpvarSubsts};
 use rustc::ty::layout::{LayoutOf, TyLayout};
 use rustc::mir::{self, Mir};
@@ -612,7 +613,7 @@ fn arg_local_refs(
             // doesn't actually strip the offset when splitting the closure
             // environment into its components so it ends up out of bounds.
             // (cuviper) It seems to be fine without the alloca on LLVM 6 and later.
-            let env_alloca = !env_ref && unsafe { llvm::LLVMRustVersionMajor() < 6 };
+            let env_alloca = !env_ref && llvm_util::get_major_version() < 6;
             let env_ptr = if env_alloca {
                 let scratch = PlaceRef::alloca(bx,
                     bx.cx.layout_of(tcx.mk_mut_ptr(arg.layout.ty)),
index d1b6aa7fc4280c9cfddc1486b5601a7ca2aa05ab..c76cbfcd9717711e244a7a3b6e1421be3dfd0e2c 100644 (file)
@@ -282,8 +282,8 @@ fn store_with_flags(
         }
         match self {
             OperandValue::Ref(r, None, source_align) => {
-                base::memcpy_ty(bx, dest.llval, r, dest.layout,
-                                source_align.min(dest.align), flags)
+                base::memcpy_ty(bx, dest.llval, dest.align, r, source_align,
+                                dest.layout, flags)
             }
             OperandValue::Ref(_, Some(_), _) => {
                 bug!("cannot directly store unsized values");
@@ -324,7 +324,7 @@ pub fn store_unsized(self, bx: &Builder<'a, 'll, 'tcx>, indirect_dest: PlaceRef<
         // Allocate an appropriate region on the stack, and copy the value into it
         let (llsize, _) = glue::size_and_align_of_dst(&bx, unsized_ty, Some(llextra));
         let lldst = bx.array_alloca(Type::i8(bx.cx), llsize, "unsized_tmp", max_align);
-        base::call_memcpy(&bx, lldst, llptr, llsize, min_align, flags);
+        base::call_memcpy(&bx, lldst, max_align, llptr, min_align, llsize, flags);
 
         // Store the allocated region and the extra to the indirect place.
         let indirect_operand = OperandValue::Pair(lldst, llextra);
index 51a233d79162539d3e194db44f9db903eb38aa75..6fb78fe4aa5a4124c590b755153451f3a4fab0c0 100644 (file)
@@ -234,6 +234,8 @@ pub fn set_struct_body(&'ll self, els: &[&'ll Type], packed: bool) {
     }
 
     pub fn ptr_to(&self) -> &Type {
+        assert_ne!(self.kind(), TypeKind::Function,
+                   "don't call ptr_to on function types, use ptr_to_llvm_type on FnType instead");
         unsafe {
             llvm::LLVMPointerType(self, 0)
         }
index b01d7e3a776f7145b791bfe7670db6f55636f6f4..fea02edf7be01b70748d68f73f53285515b6e5d2 100644 (file)
@@ -265,7 +265,7 @@ fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type {
                         ty::ParamEnv::reveal_all(),
                         &sig,
                     );
-                    FnType::new(cx, sig, &[]).llvm_type(cx).ptr_to()
+                    FnType::new(cx, sig, &[]).ptr_to_llvm_type(cx)
                 }
                 _ => self.scalar_llvm_type_at(cx, scalar, Size::ZERO)
             };
index c1f41fd509a143fbfa03769c5b315dc163353305..ae1d77f1521893f84a705b94c03ae89b880a76b0 100644 (file)
@@ -224,9 +224,9 @@ fn push_cross_lang_lto_args(&mut self, plugin_path: Option<&OsStr>) {
 }
 
 impl<'a> Linker for GccLinker<'a> {
-    fn link_dylib(&mut self, lib: &str) { self.hint_dynamic(); self.cmd.arg(format!("-l{}",lib)); }
+    fn link_dylib(&mut self, lib: &str) { self.hint_dynamic(); self.cmd.arg(format!("-l{}", lib)); }
     fn link_staticlib(&mut self, lib: &str) {
-        self.hint_static(); self.cmd.arg(format!("-l{}",lib));
+        self.hint_static(); self.cmd.arg(format!("-l{}", lib));
     }
     fn link_rlib(&mut self, lib: &Path) { self.hint_static(); self.cmd.arg(lib); }
     fn include_path(&mut self, path: &Path) { self.cmd.arg("-L").arg(path); }
@@ -243,7 +243,7 @@ fn link_staticlib(&mut self, lib: &str) {
 
     fn link_rust_dylib(&mut self, lib: &str, _path: &Path) {
         self.hint_dynamic();
-        self.cmd.arg(format!("-l{}",lib));
+        self.cmd.arg(format!("-l{}", lib));
     }
 
     fn link_framework(&mut self, framework: &str) {
@@ -261,7 +261,7 @@ fn link_whole_staticlib(&mut self, lib: &str, search_path: &[PathBuf]) {
         self.hint_static();
         let target = &self.sess.target.target;
         if !target.options.is_like_osx {
-            self.linker_arg("--whole-archive").cmd.arg(format!("-l{}",lib));
+            self.linker_arg("--whole-archive").cmd.arg(format!("-l{}", lib));
             self.linker_arg("--no-whole-archive");
         } else {
             // -force_load is the macOS equivalent of --whole-archive, but it
@@ -343,17 +343,13 @@ fn pgo_gen(&mut self) {
     }
 
     fn debuginfo(&mut self) {
-        match self.sess.opts.debuginfo {
-            DebugInfo::None => {
-                // If we are building without debuginfo enabled and we were called with
-                // `-Zstrip-debuginfo-if-disabled=yes`, tell the linker to strip any debuginfo
-                // found when linking to get rid of symbols from libstd.
-                match self.sess.opts.debugging_opts.strip_debuginfo_if_disabled {
-                    Some(true) => { self.linker_arg("-S"); },
-                    _ => {},
-                }
-            },
-            _ => {},
+        if let DebugInfo::None = self.sess.opts.debuginfo {
+            // If we are building without debuginfo enabled and we were called with
+            // `-Zstrip-debuginfo-if-disabled=yes`, tell the linker to strip any debuginfo
+            // found when linking to get rid of symbols from libstd.
+            if let Some(true) = self.sess.opts.debugging_opts.strip_debuginfo_if_disabled {
+                self.linker_arg("-S");
+            }
         };
     }
 
@@ -373,8 +369,7 @@ fn build_dylib(&mut self, out_filename: &Path) {
             // purely to support rustbuild right now, we should get a more
             // principled solution at some point to force the compiler to pass
             // the right `-Wl,-install_name` with an `@rpath` in it.
-            if self.sess.opts.cg.rpath ||
-               self.sess.opts.debugging_opts.osx_rpath_install_name {
+            if self.sess.opts.cg.rpath || self.sess.opts.debugging_opts.osx_rpath_install_name {
                 self.linker_arg("-install_name");
                 let mut v = OsString::from("@rpath/");
                 v.push(out_filename.file_name().unwrap());
@@ -461,9 +456,8 @@ fn subsystem(&mut self, subsystem: &str) {
 
     fn finalize(&mut self) -> Command {
         self.hint_dynamic(); // Reset to default before returning the composed command line.
-        let mut cmd = Command::new("");
-        ::std::mem::swap(&mut cmd, &mut self.cmd);
-        cmd
+
+        ::std::mem::replace(&mut self.cmd, Command::new(""))
     }
 
     fn group_start(&mut self) {
@@ -715,9 +709,7 @@ fn subsystem(&mut self, subsystem: &str) {
     }
 
     fn finalize(&mut self) -> Command {
-        let mut cmd = Command::new("");
-        ::std::mem::swap(&mut cmd, &mut self.cmd);
-        cmd
+        ::std::mem::replace(&mut self.cmd, Command::new(""))
     }
 
     // MSVC doesn't need group indicators
@@ -865,7 +857,7 @@ fn export_symbols(&mut self, _tmpdir: &Path, crate_type: CrateType) {
             let res = encoder.emit_seq(symbols.len(), |encoder| {
                 for (i, sym) in symbols.iter().enumerate() {
                     encoder.emit_seq_elt(i, |encoder| {
-                        encoder.emit_str(&("_".to_string() + sym))
+                        encoder.emit_str(&("_".to_owned() + sym))
                     })?;
                 }
                 Ok(())
@@ -885,9 +877,7 @@ fn subsystem(&mut self, _subsystem: &str) {
     }
 
     fn finalize(&mut self) -> Command {
-        let mut cmd = Command::new("");
-        ::std::mem::swap(&mut cmd, &mut self.cmd);
-        cmd
+        ::std::mem::replace(&mut self.cmd, Command::new(""))
     }
 
     // Appears not necessary on Emscripten
@@ -1085,9 +1075,7 @@ fn finalize(&mut self) -> Command {
         // indicative of bugs, let's prevent them.
         self.cmd.arg("--fatal-warnings");
 
-        let mut cmd = Command::new("");
-        ::std::mem::swap(&mut cmd, &mut self.cmd);
-        cmd
+        ::std::mem::replace(&mut self.cmd, Command::new(""))
     }
 
     // Not needed for now with LLD
index 2d650f7f18d6f5654b7da9ceb4f353365b0a24be..dff7e518630e4d23628aea3f6db9000caf04a35a 100644 (file)
@@ -47,11 +47,10 @@ fn crate_export_threshold(crate_type: config::CrateType) -> SymbolExportLevel {
     }
 }
 
-pub fn crates_export_threshold(crate_types: &[config::CrateType])
-                                      -> SymbolExportLevel {
-    if crate_types.iter().any(|&crate_type| {
-        crate_export_threshold(crate_type) == SymbolExportLevel::Rust
-    }) {
+pub fn crates_export_threshold(crate_types: &[config::CrateType]) -> SymbolExportLevel {
+    if crate_types.iter().any(|&crate_type|
+        crate_export_threshold(crate_type) == SymbolExportLevel::Rust)
+    {
         SymbolExportLevel::Rust
     } else {
         SymbolExportLevel::C
@@ -359,7 +358,7 @@ fn is_unreachable_local_definition_provider(tcx: TyCtxt, def_id: DefId) -> bool
         !tcx.reachable_set(LOCAL_CRATE).0.contains(&node_id)
     } else {
         bug!("is_unreachable_local_definition called with non-local DefId: {:?}",
-              def_id)
+             def_id)
     }
 }
 
@@ -388,6 +387,16 @@ fn symbol_export_level(tcx: TyCtxt, sym_def_id: DefId) -> SymbolExportLevel {
         codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL);
 
     if is_extern && !std_internal {
+        // Emscripten cannot export statics, so reduce their export level here
+        if tcx.sess.target.target.options.is_like_emscripten {
+            if let Some(Node::Item(&hir::Item {
+                node: hir::ItemKind::Static(..),
+                ..
+            })) = tcx.hir.get_if_local(sym_def_id) {
+                return SymbolExportLevel::Rust;
+            }
+        }
+
         SymbolExportLevel::C
     } else {
         SymbolExportLevel::Rust
index 07e5548216f3cee30dcf4fa17f434961053016e2..135abebdacb7acacb4499d1bc0c1176a2decf11f 100644 (file)
@@ -57,6 +57,7 @@
 
 pub use rustc_serialize::hex::ToHex;
 
+pub mod macros;
 pub mod svh;
 pub mod base_n;
 pub mod bit_set;
diff --git a/src/librustc_data_structures/macros.rs b/src/librustc_data_structures/macros.rs
new file mode 100644 (file)
index 0000000..3cc91b0
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/// A simple static assertion macro. The first argument should be a unique
+/// ALL_CAPS identifier that describes the condition.
+#[macro_export]
+macro_rules! static_assert {
+    ($name:ident: $test:expr) => {
+        // Use the bool to access an array such that if the bool is false, the access
+        // is out-of-bounds.
+        #[allow(dead_code)]
+        static $name: () = [()][!$test as usize];
+    }
+}
index 720e8def5ab1c2a7d30abec1e97e67649736e39e..7e69e98071d4b1fa29ad1453d8f9733f8e1e1424 100644 (file)
@@ -108,7 +108,13 @@ pub enum ColorConfig {
 impl ColorConfig {
     fn to_color_choice(&self) -> ColorChoice {
         match *self {
-            ColorConfig::Always => ColorChoice::Always,
+            ColorConfig::Always => {
+                if atty::is(atty::Stream::Stderr) {
+                    ColorChoice::Always
+                } else {
+                    ColorChoice::AlwaysAnsi
+                }
+            }
             ColorConfig::Never => ColorChoice::Never,
             ColorConfig::Auto if atty::is(atty::Stream::Stderr) => {
                 ColorChoice::Auto
index f289acc032be8fd5cca2a547d18c253cf1ba1558..8c0e9bd11a173da5813c13157f8244af22204632 100644 (file)
@@ -317,11 +317,6 @@ macro_rules! add_lint_group {
             reference: "issue #51443 <https://github.com/rust-lang/rust/issues/51443>",
             edition: None,
         },
-        FutureIncompatibleInfo {
-            id: LintId::of(DUPLICATE_ASSOCIATED_TYPE_BINDINGS),
-            reference: "issue #50589 <https://github.com/rust-lang/rust/issues/50589>",
-            edition: None,
-        },
         FutureIncompatibleInfo {
             id: LintId::of(PROC_MACRO_DERIVE_RESOLUTION_FALLBACK),
             reference: "issue #50504 <https://github.com/rust-lang/rust/issues/50504>",
index 9c19b53742654e4c760056a09d1233d25fad7851..2573825a5ff45775601bfa7f14a25265d3998eaf 100644 (file)
@@ -15,6 +15,5 @@ cmake = "0.1.18"
 
 [dependencies]
 alloc = { path = "../liballoc" }
-alloc_system = { path = "../liballoc_system" }
 core = { path = "../libcore" }
 compiler_builtins = { path = "../rustc/compiler_builtins_shim" }
index 7b845e631ffa341d88db3950e9748e75558e063b..47f917e40c1ff53a5b81e490e026a3bdaa54fc61 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 #![sanitizer_runtime]
-#![feature(alloc_system)]
 #![feature(nll)]
 #![feature(sanitizer_runtime)]
 #![feature(staged_api)]
 #![unstable(feature = "sanitizer_runtime_lib",
             reason = "internal implementation detail of sanitizers",
             issue = "0")]
-
-extern crate alloc_system;
-
-use alloc_system::System;
-
-#[global_allocator]
-static ALLOC: System = System;
index 7733ab2e246d1135fa3fac808b73ce98c0375852..a14dd99eeb3b381653048d6e6dc871712397b625 100644 (file)
@@ -16,7 +16,7 @@
 use schema::CrateRoot;
 use rustc_data_structures::sync::{Lrc, RwLock, Lock};
 
-use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX};
+use rustc::hir::def_id::CrateNum;
 use rustc_data_structures::svh::Svh;
 use rustc::middle::allocator::AllocatorKind;
 use rustc::middle::cstore::DepKind;
@@ -864,7 +864,6 @@ fn inject_allocator_crate(&mut self, krate: &ast::Crate) {
             needs_allocator = needs_allocator || data.root.needs_allocator;
         });
         if !needs_allocator {
-            self.sess.injected_allocator.set(None);
             self.sess.allocator_kind.set(None);
             return
         }
@@ -872,20 +871,15 @@ fn inject_allocator_crate(&mut self, krate: &ast::Crate) {
         // At this point we've determined that we need an allocator. Let's see
         // if our compilation session actually needs an allocator based on what
         // we're emitting.
-        let mut need_lib_alloc = false;
-        let mut need_exe_alloc = false;
-        for ct in self.sess.crate_types.borrow().iter() {
-            match *ct {
-                config::CrateType::Executable => need_exe_alloc = true,
-                config::CrateType::Dylib |
-                config::CrateType::ProcMacro |
-                config::CrateType::Cdylib |
-                config::CrateType::Staticlib => need_lib_alloc = true,
-                config::CrateType::Rlib => {}
-            }
-        }
-        if !need_lib_alloc && !need_exe_alloc {
-            self.sess.injected_allocator.set(None);
+        let all_rlib = self.sess.crate_types.borrow()
+            .iter()
+            .all(|ct| {
+                match *ct {
+                    config::CrateType::Rlib => true,
+                    _ => false,
+                }
+            });
+        if all_rlib {
             self.sess.allocator_kind.set(None);
             return
         }
@@ -924,103 +918,27 @@ fn inject_allocator_crate(&mut self, krate: &ast::Crate) {
         });
         if global_allocator.is_some() {
             self.sess.allocator_kind.set(Some(AllocatorKind::Global));
-            self.sess.injected_allocator.set(None);
             return
         }
 
         // Ok we haven't found a global allocator but we still need an
-        // allocator. At this point we'll either fall back to the "library
-        // allocator" or the "exe allocator" depending on a few variables. Let's
-        // figure out which one.
-        //
-        // Note that here we favor linking to the "library allocator" as much as
-        // possible. If we're not creating rustc's version of libstd
-        // (need_lib_alloc and prefer_dynamic) then we select `None`, and if the
-        // exe allocation crate doesn't exist for this target then we also
-        // select `None`.
-        let exe_allocation_crate_data =
-            if need_lib_alloc && !self.sess.opts.cg.prefer_dynamic {
-                None
-            } else {
-                self.sess
-                    .target
-                    .target
-                    .options
-                    .exe_allocation_crate
-                    .as_ref()
-                    .map(|name| {
-                        // We've determined that we're injecting an "exe allocator" which means
-                        // that we're going to load up a whole new crate. An example of this is
-                        // that we're producing a normal binary on Linux which means we need to
-                        // load the `alloc_jemalloc` crate to link as an allocator.
-                        let name = Symbol::intern(name);
-                        let (cnum, data) = self.resolve_crate(&None,
-                                                              name,
-                                                              name,
-                                                              None,
-                                                              None,
-                                                              DUMMY_SP,
-                                                              PathKind::Crate,
-                                                              DepKind::Implicit)
-                            .unwrap_or_else(|err| err.report());
-                        self.sess.injected_allocator.set(Some(cnum));
-                        data
-                    })
-            };
-
-        let allocation_crate_data = exe_allocation_crate_data.or_else(|| {
-            // No allocator was injected
-            self.sess.injected_allocator.set(None);
-
-            if attr::contains_name(&krate.attrs, "default_lib_allocator") {
-                // Prefer self as the allocator if there's a collision
-                return None;
+        // allocator. At this point our allocator request is typically fulfilled
+        // by the standard library, denoted by the `#![default_lib_allocator]`
+        // attribute.
+        let mut has_default = attr::contains_name(&krate.attrs, "default_lib_allocator");
+        self.cstore.iter_crate_data(|_, data| {
+            if data.root.has_default_lib_allocator {
+                has_default = true;
             }
-            // We're not actually going to inject an allocator, we're going to
-            // require that something in our crate graph is the default lib
-            // allocator. This is typically libstd, so this'll rarely be an
-            // error.
-            let mut allocator = None;
-            self.cstore.iter_crate_data(|_, data| {
-                if allocator.is_none() && data.root.has_default_lib_allocator {
-                    allocator = Some(data.clone());
-                }
-            });
-            allocator
         });
 
-        match allocation_crate_data {
-            Some(data) => {
-                // We have an allocator. We detect separately what kind it is, to allow for some
-                // flexibility in misconfiguration.
-                let attrs = data.get_item_attrs(CRATE_DEF_INDEX, self.sess);
-                let kind_interned = attr::first_attr_value_str_by_name(&attrs, "rustc_alloc_kind")
-                    .map(Symbol::as_str);
-                let kind_str = kind_interned
-                    .as_ref()
-                    .map(|s| s as &str);
-                let alloc_kind = match kind_str {
-                    None |
-                    Some("lib") => AllocatorKind::DefaultLib,
-                    Some("exe") => AllocatorKind::DefaultExe,
-                    Some(other) => {
-                        self.sess.err(&format!("Allocator kind {} not known", other));
-                        return;
-                    }
-                };
-                self.sess.allocator_kind.set(Some(alloc_kind));
-            },
-            None => {
-                if !attr::contains_name(&krate.attrs, "default_lib_allocator") {
-                    self.sess.err("no global memory allocator found but one is \
-                                   required; link to std or \
-                                   add #[global_allocator] to a static item \
-                                   that implements the GlobalAlloc trait.");
-                    return;
-                }
-                self.sess.allocator_kind.set(Some(AllocatorKind::DefaultLib));
-            }
+        if !has_default {
+            self.sess.err("no global memory allocator found but one is \
+                           required; link to std or \
+                           add #[global_allocator] to a static item \
+                           that implements the GlobalAlloc trait.");
         }
+        self.sess.allocator_kind.set(Some(AllocatorKind::DefaultLib));
 
         fn has_global_allocator(krate: &ast::Crate) -> bool {
             struct Finder(bool);
@@ -1083,8 +1001,6 @@ fn inject_dependency_if(&self,
 
 impl<'a> CrateLoader<'a> {
     pub fn postprocess(&mut self, krate: &ast::Crate) {
-        // inject the sanitizer runtime before the allocator runtime because all
-        // sanitizers force the use of the `alloc_system` allocator
         self.inject_sanitizer_runtime();
         self.inject_profiler_runtime();
         self.inject_allocator_crate(krate);
index db56ce4627410408318632f98e3ee53ac4ce9279..c432826dca865de3a8cba3850b947966b462a1b1 100644 (file)
@@ -21,7 +21,6 @@
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_data_structures::bit_set::BitSet;
 use std::fmt;
-use std::hash::Hash;
 use std::ops::Index;
 
 crate struct BorrowSet<'tcx> {
@@ -233,21 +232,13 @@ fn visit_assign(
 
             self.insert_as_pending_if_two_phase(location, &assigned_place, region, kind, idx);
 
-            insert(&mut self.region_map, &region, idx);
+            self.region_map.entry(region).or_default().insert(idx);
             if let Some(local) = borrowed_place.root_local() {
-                insert(&mut self.local_map, &local, idx);
+                self.local_map.entry(local).or_default().insert(idx);
             }
         }
 
-        return self.super_assign(block, assigned_place, rvalue, location);
-
-        fn insert<'a, K, V>(map: &'a mut FxHashMap<K, FxHashSet<V>>, k: &K, v: V)
-        where
-            K: Clone + Eq + Hash,
-            V: Eq + Hash,
-        {
-            map.entry(k.clone()).or_default().insert(v);
-        }
+        self.super_assign(block, assigned_place, rvalue, location)
     }
 
     fn visit_place(
index d4f00ab3bb91a217bfdf7f8738f01455ae8f6409..eeb111dcd9b83aeeab441bb7c0f921ce66aca47d 100644 (file)
@@ -281,23 +281,21 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
     // Note that this set is expected to be small - only upvars from closures
     // would have a chance of erroneously adding non-user-defined mutable vars
     // to the set.
-    let temporary_used_locals: FxHashSet<Local> = mbcx
-        .used_mut
-        .iter()
+    let temporary_used_locals: FxHashSet<Local> = mbcx.used_mut.iter()
         .filter(|&local| mbcx.mir.local_decls[*local].is_user_variable.is_none())
         .cloned()
         .collect();
-    mbcx.gather_used_muts(temporary_used_locals);
+    // For the remaining unused locals that are marked as mutable, we avoid linting any that
+    // were never initialized. These locals may have been removed as unreachable code; or will be
+    // linted as unused variables.
+    let unused_mut_locals = mbcx.mir.mut_vars_iter()
+        .filter(|local| !mbcx.used_mut.contains(local))
+        .collect();
+    mbcx.gather_used_muts(temporary_used_locals, unused_mut_locals);
 
     debug!("mbcx.used_mut: {:?}", mbcx.used_mut);
-
     let used_mut = mbcx.used_mut;
-
-    for local in mbcx
-        .mir
-        .mut_vars_and_args_iter()
-        .filter(|local| !used_mut.contains(local))
-    {
+    for local in mbcx.mir.mut_vars_and_args_iter().filter(|local| !used_mut.contains(local)) {
         if let ClearCrossCrate::Set(ref vsi) = mbcx.mir.source_scope_local_data {
             let local_decl = &mbcx.mir.local_decls[local];
 
@@ -1719,12 +1717,13 @@ fn check_if_assigned_path_is_moved(
             }
         }
 
-        fn check_parent_of_field<'cx, 'gcx, 'tcx>(this: &mut MirBorrowckCtxt<'cx, 'gcx, 'tcx>,
-                                                  context: Context,
-                                                  base: &Place<'tcx>,
-                                                  span: Span,
-                                                  flow_state: &Flows<'cx, 'gcx, 'tcx>)
-        {
+        fn check_parent_of_field<'cx, 'gcx, 'tcx>(
+            this: &mut MirBorrowckCtxt<'cx, 'gcx, 'tcx>,
+            context: Context,
+            base: &Place<'tcx>,
+            span: Span,
+            flow_state: &Flows<'cx, 'gcx, 'tcx>,
+        ) {
             // rust-lang/rust#21232: Until Rust allows reads from the
             // initialized parts of partially initialized structs, we
             // will, starting with the 2018 edition, reject attempts
@@ -1776,6 +1775,24 @@ fn check_parent_of_field<'cx, 'gcx, 'tcx>(this: &mut MirBorrowckCtxt<'cx, 'gcx,
             }
 
             if let Some((prefix, mpi)) = shortest_uninit_seen {
+                // Check for a reassignment into a uninitialized field of a union (for example,
+                // after a move out). In this case, do not report a error here. There is an
+                // exception, if this is the first assignment into the union (that is, there is
+                // no move out from an earlier location) then this is an attempt at initialization
+                // of the union - we should error in that case.
+                let tcx = this.infcx.tcx;
+                if let ty::TyKind::Adt(def, _) = base.ty(this.mir, tcx).to_ty(tcx).sty {
+                    if def.is_union() {
+                        if this.move_data.path_map[mpi].iter().any(|moi| {
+                            this.move_data.moves[*moi].source.is_predecessor_of(
+                                context.loc, this.mir,
+                            )
+                        }) {
+                            return;
+                        }
+                    }
+                }
+
                 this.report_use_of_moved_or_uninitialized(
                     context,
                     InitializationRequiringAction::PartialAssignment,
index 99372a511a9de5e2c2307b83255c68c7d38bff93..a32fb0503a814e6ba74f7e65f3134091de8eded8 100644 (file)
@@ -687,22 +687,24 @@ fn give_name_if_anonymous_region_appears_in_output(
 
         let mir_node_id = tcx.hir.as_local_node_id(mir_def_id).expect("non-local mir");
 
-        let (return_span, mir_description) =
-            if let hir::ExprKind::Closure(_, _, _, span, gen_move) =
-                tcx.hir.expect_expr(mir_node_id).node
-            {
-                (
-                    tcx.sess.source_map().end_point(span),
-                    if gen_move.is_some() {
-                        " of generator"
-                    } else {
-                        " of closure"
-                    },
-                )
-            } else {
-                // unreachable?
-                (mir.span, "")
-            };
+        let (return_span, mir_description) = match tcx.hir.get(mir_node_id) {
+            hir::Node::Expr(hir::Expr {
+                node: hir::ExprKind::Closure(_, _, _, span, gen_move),
+                ..
+            }) => (
+                tcx.sess.source_map().end_point(*span),
+                if gen_move.is_some() {
+                    " of generator"
+                } else {
+                    " of closure"
+                },
+            ),
+            hir::Node::ImplItem(hir::ImplItem {
+                node: hir::ImplItemKind::Method(method_sig, _),
+                ..
+            }) => (method_sig.decl.output.span(), ""),
+            _ => (mir.span, ""),
+        };
 
         Some(RegionName {
             // This counter value will already have been used, so this function will increment it
index 734ddbc3ab9a72af39babca2f7080aac3e3577c9..a057f2f45c0105e8090de91b4e049d2f4a466523 100644 (file)
@@ -1021,20 +1021,39 @@ fn relate_type_and_user_type(
                 let v1 = ty::Contravariant.xform(v);
 
                 let tcx = self.infcx.tcx;
-                let mut projected_ty = PlaceTy::from_ty(ty);
+                let ty = self.normalize(ty, locations);
+
+                // We need to follow any provided projetions into the type.
+                //
+                // if we hit a ty var as we descend, then just skip the
+                // attempt to relate the mir local with any type.
+                #[derive(Debug)] struct HitTyVar;
+                let mut curr_projected_ty: Result<PlaceTy, HitTyVar>;
+
+                curr_projected_ty = Ok(PlaceTy::from_ty(ty));
                 for proj in &user_ty.projs {
-                    projected_ty = projected_ty.projection_ty_core(
+                    let projected_ty = if let Ok(projected_ty) = curr_projected_ty {
+                        projected_ty
+                    } else {
+                        break;
+                    };
+                    curr_projected_ty = projected_ty.projection_ty_core(
                         tcx, proj, |this, field, &()| {
-                            let ty = this.field_ty(tcx, field);
-                            self.normalize(ty, locations)
+                            if this.to_ty(tcx).is_ty_var() {
+                                Err(HitTyVar)
+                            } else {
+                                let ty = this.field_ty(tcx, field);
+                                Ok(self.normalize(ty, locations))
+                            }
                         });
                 }
                 debug!("user_ty base: {:?} freshened: {:?} projs: {:?} yields: {:?}",
-                       user_ty.base, ty, user_ty.projs, projected_ty);
+                       user_ty.base, ty, user_ty.projs, curr_projected_ty);
 
-                let ty = projected_ty.to_ty(tcx);
-
-                self.relate_types(ty, v1, a, locations, category)?;
+                if let Ok(projected_ty) = curr_projected_ty {
+                    let ty = projected_ty.to_ty(tcx);
+                    self.relate_types(ty, v1, a, locations, category)?;
+                }
             }
             UserTypeAnnotation::TypeOf(def_id, canonical_substs) => {
                 let (
index dad87ed65a7d41dce53b003a4265773651b6801c..7c75fb59917c00e5b73e8eb5dff46c2a15d9c75f 100644 (file)
 // except according to those terms.
 
 use rustc::mir::visit::{PlaceContext, Visitor};
-use rustc::mir::{Local, Location, Place};
+use rustc::mir::{BasicBlock, Local, Location, Place, Statement, StatementKind, TerminatorKind};
 
 use rustc_data_structures::fx::FxHashSet;
 
 use borrow_check::MirBorrowckCtxt;
 
 impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
-    /// Walks the MIR looking for assignments to a set of locals, as part of the unused mutable
-    /// local variables lint, to update the context's `used_mut` in a single walk.
-    crate fn gather_used_muts(&mut self, locals: FxHashSet<Local>) {
-        let mut visitor = GatherUsedMutsVisitor {
-            needles: locals,
-            mbcx: self,
-        };
-        visitor.visit_mir(visitor.mbcx.mir);
+    /// Walks the MIR adding to the set of `used_mut` locals that will be ignored for the purposes
+    /// of the `unused_mut` lint.
+    ///
+    /// `temporary_used_locals` should contain locals that were found to be temporary, mutable and
+    ///  used from borrow checking. This function looks for assignments into these locals from
+    ///  user-declared locals and adds those user-defined locals to the `used_mut` set. This can
+    ///  occur due to a rare case involving upvars in closures.
+    ///
+    /// `never_initialized_mut_locals` should contain the set of user-declared mutable locals
+    ///  (not arguments) that have not already been marked as being used.
+    ///  This function then looks for assignments from statements or the terminator into the locals
+    ///  from this set and removes them from the set. This leaves only those locals that have not
+    ///  been assigned to - this set is used as a proxy for locals that were not initialized due to
+    ///  unreachable code. These locals are then considered "used" to silence the lint for them.
+    ///  See #55344 for context.
+    crate fn gather_used_muts(
+        &mut self,
+        temporary_used_locals: FxHashSet<Local>,
+        mut never_initialized_mut_locals: FxHashSet<Local>,
+    ) {
+        {
+            let mut visitor = GatherUsedMutsVisitor {
+                temporary_used_locals,
+                never_initialized_mut_locals: &mut never_initialized_mut_locals,
+                mbcx: self,
+            };
+            visitor.visit_mir(visitor.mbcx.mir);
+        }
+
+        // Take the union of the existed `used_mut` set with those variables we've found were
+        // never initialized.
+        debug!("gather_used_muts: never_initialized_mut_locals={:?}", never_initialized_mut_locals);
+        self.used_mut = self.used_mut.union(&never_initialized_mut_locals).cloned().collect();
     }
 }
 
-/// MIR visitor gathering the assignments to a set of locals, in a single walk.
-/// 'visit = the duration of the MIR walk
+/// MIR visitor for collecting used mutable variables.
+/// The 'visit lifetime represents the duration of the MIR walk.
 struct GatherUsedMutsVisitor<'visit, 'cx: 'visit, 'gcx: 'tcx, 'tcx: 'cx> {
-    needles: FxHashSet<Local>,
+    temporary_used_locals: FxHashSet<Local>,
+    never_initialized_mut_locals: &'visit mut FxHashSet<Local>,
     mbcx: &'visit mut MirBorrowckCtxt<'cx, 'gcx, 'tcx>,
 }
 
 impl<'visit, 'cx, 'gcx, 'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'visit, 'cx, 'gcx, 'tcx> {
+    fn visit_terminator_kind(
+        &mut self,
+        _block: BasicBlock,
+        kind: &TerminatorKind<'tcx>,
+        _location: Location,
+    ) {
+        debug!("visit_terminator_kind: kind={:?}", kind);
+        match &kind {
+            TerminatorKind::Call { destination: Some((into, _)), .. } => {
+                if let Some(local) = into.base_local() {
+                    debug!(
+                        "visit_terminator_kind: kind={:?} local={:?} \
+                         never_initialized_mut_locals={:?}",
+                        kind, local, self.never_initialized_mut_locals
+                    );
+                    let _ = self.never_initialized_mut_locals.remove(&local);
+                }
+            },
+            _ => {},
+        }
+    }
+
+    fn visit_statement(
+        &mut self,
+        _block: BasicBlock,
+        statement: &Statement<'tcx>,
+        _location: Location,
+    ) {
+        match &statement.kind {
+            StatementKind::Assign(into, _) => {
+                // Remove any locals that we found were initialized from the
+                // `never_initialized_mut_locals` set. At the end, the only remaining locals will
+                // be those that were never initialized - we will consider those as being used as
+                // they will either have been removed by unreachable code optimizations; or linted
+                // as unused variables.
+                if let Some(local) = into.base_local() {
+                    debug!(
+                        "visit_statement: statement={:?} local={:?} \
+                         never_initialized_mut_locals={:?}",
+                        statement, local, self.never_initialized_mut_locals
+                    );
+                    let _ = self.never_initialized_mut_locals.remove(&local);
+                }
+            },
+            _ => {},
+        }
+    }
+
     fn visit_local(
         &mut self,
         local: &Local,
         place_context: PlaceContext<'tcx>,
         location: Location,
     ) {
-        if !self.needles.contains(local) {
-            return;
-        }
-
-        if place_context.is_place_assignment() {
+        if place_context.is_place_assignment() && self.temporary_used_locals.contains(local) {
             // Propagate the Local assigned at this Location as a used mutable local variable
             for moi in &self.mbcx.move_data.loc_map[location] {
                 let mpi = &self.mbcx.move_data.moves[*moi].path;
index 874e862de238b7e1e8e253e0af83caac4eb71189..2399f0bc1a0751d5c31294d18c7bfe27e2a231aa 100644 (file)
@@ -430,6 +430,20 @@ fn gather_move(&mut self, place: &Place<'tcx>) {
     fn gather_init(&mut self, place: &Place<'tcx>, kind: InitKind) {
         debug!("gather_init({:?}, {:?})", self.loc, place);
 
+        let place = match place {
+            // Check if we are assigning into a field of a union, if so, lookup the place
+            // of the union so it is marked as initialized again.
+            Place::Projection(box Projection {
+                base,
+                elem: ProjectionElem::Field(_, _),
+            }) if match base.ty(self.builder.mir, self.builder.tcx).to_ty(self.builder.tcx).sty {
+                    ty::TyKind::Adt(def, _) if def.is_union() => true,
+                    _ => false,
+            } => base,
+            // Otherwise, lookup the place.
+            _ => place,
+        };
+
         if let LookupResult::Exact(path) = self.builder.data.rev_lookup.find(place) {
             let init = self.builder.data.inits.push(Init {
                 location: InitLocation::Statement(self.loc),
index cb2a750f4e3b6cc4a987a5fe88ee6ac31ff9833c..3eb3d7600fd31600819df3ff5efda1c006131fa0 100644 (file)
@@ -150,6 +150,24 @@ pub fn emulate_intrinsic(
                 }
                 self.write_scalar(val, dest)?;
             }
+            "rotate_left" | "rotate_right" => {
+                // rotate_left: (X << (S % BW)) | (X >> ((BW - S) % BW))
+                // rotate_right: (X << ((BW - S) % BW)) | (X >> (S % BW))
+                let layout = self.layout_of(substs.type_at(0))?;
+                let val_bits = self.read_scalar(args[0])?.to_bits(layout.size)?;
+                let raw_shift_bits = self.read_scalar(args[1])?.to_bits(layout.size)?;
+                let width_bits = layout.size.bits() as u128;
+                let shift_bits = raw_shift_bits % width_bits;
+                let inv_shift_bits = (width_bits - raw_shift_bits) % width_bits;
+                let result_bits = if intrinsic_name == "rotate_left" {
+                    (val_bits << shift_bits) | (val_bits >> inv_shift_bits)
+                } else {
+                    (val_bits >> shift_bits) | (val_bits << inv_shift_bits)
+                };
+                let truncated_bits = self.truncate(result_bits, layout);
+                let result = Scalar::from_uint(truncated_bits, layout.size);
+                self.write_scalar(result, dest)?;
+            }
             "transmute" => {
                 self.copy_op_transmute(args[0], dest)?;
             }
index 27cf28ef41e8ac3a261d2d0a0a1d01dd3cdc97b7..047996777ea968907592791c4c3701049ab8670a 100644 (file)
@@ -20,7 +20,7 @@
 use rustc::ty::{self, layout::{Size, TyLayout}, query::TyCtxtAt};
 
 use super::{
-    Allocation, AllocId, EvalResult, Scalar,
+    Allocation, AllocId, EvalResult, Scalar, AllocationExtra,
     EvalContext, PlaceTy, MPlaceTy, OpTy, Pointer, MemoryKind,
 };
 
@@ -78,7 +78,7 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
     type PointerTag: ::std::fmt::Debug + Default + Copy + Eq + Hash + 'static;
 
     /// Extra data stored in every allocation.
-    type AllocExtra: ::std::fmt::Debug + Default + Clone;
+    type AllocExtra: AllocationExtra<Self::PointerTag>;
 
     /// Memory's allocation map
     type MemoryMap:
@@ -174,26 +174,6 @@ fn box_alloc(
         dest: PlaceTy<'tcx, Self::PointerTag>,
     ) -> EvalResult<'tcx>;
 
-    /// Hook for performing extra checks on a memory read access.
-    #[inline]
-    fn memory_read(
-        _alloc: &Allocation<Self::PointerTag, Self::AllocExtra>,
-        _ptr: Pointer<Self::PointerTag>,
-        _size: Size,
-    ) -> EvalResult<'tcx> {
-        Ok(())
-    }
-
-    /// Hook for performing extra checks on a memory write access.
-    #[inline]
-    fn memory_written(
-        _alloc: &mut Allocation<Self::PointerTag, Self::AllocExtra>,
-        _ptr: Pointer<Self::PointerTag>,
-        _size: Size,
-    ) -> EvalResult<'tcx> {
-        Ok(())
-    }
-
     /// Hook for performing extra checks when memory gets deallocated.
     #[inline]
     fn memory_deallocated(
index 6a109efe3c43e2cc3ae6dcc9b61e90852653b0c4..10bc984a447a3c17d74a12bd7eaf4ce927625196 100644 (file)
@@ -28,7 +28,7 @@
 use syntax::ast::Mutability;
 
 use super::{
-    Pointer, AllocId, Allocation, ConstValue, GlobalId,
+    Pointer, AllocId, Allocation, ConstValue, GlobalId, AllocationExtra,
     EvalResult, Scalar, EvalErrorKind, AllocType, PointerArithmetic,
     Machine, AllocMap, MayLeak, ScalarMaybeUndef, ErrorHandled,
 };
@@ -637,7 +637,7 @@ fn get_bytes_internal(
         }
 
         let alloc = self.get(ptr.alloc_id)?;
-        M::memory_read(alloc, ptr, size)?;
+        AllocationExtra::memory_read(alloc, ptr, size)?;
 
         assert_eq!(ptr.offset.bytes() as usize as u64, ptr.offset.bytes());
         assert_eq!(size.bytes() as usize as u64, size.bytes());
@@ -683,7 +683,7 @@ fn get_bytes_mut(
         self.clear_relocations(ptr, size)?;
 
         let alloc = self.get_mut(ptr.alloc_id)?;
-        M::memory_written(alloc, ptr, size)?;
+        AllocationExtra::memory_written(alloc, ptr, size)?;
 
         assert_eq!(ptr.offset.bytes() as usize as u64, ptr.offset.bytes());
         assert_eq!(size.bytes() as usize as u64, size.bytes());
index 83a2d14b7ca4cdf9896d81e46758e697b6b67de0..d43ec0bd349abd301dac2c96f8c4971eebc8d290 100644 (file)
@@ -12,7 +12,6 @@
 //! All high-level functions to read from memory work on operands as sources.
 
 use std::convert::TryInto;
-use std::fmt;
 
 use rustc::{mir, ty};
 use rustc::ty::layout::{self, Size, LayoutOf, TyLayout, HasDataLayout, IntegerExt};
     EvalResult, EvalErrorKind
 };
 use super::{EvalContext, Machine, MemPlace, MPlaceTy, MemoryKind};
-
-#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, RustcEncodable, RustcDecodable, Hash)]
-pub enum ScalarMaybeUndef<Tag=(), Id=AllocId> {
-    Scalar(Scalar<Tag, Id>),
-    Undef,
-}
-
-impl<Tag> From<Scalar<Tag>> for ScalarMaybeUndef<Tag> {
-    #[inline(always)]
-    fn from(s: Scalar<Tag>) -> Self {
-        ScalarMaybeUndef::Scalar(s)
-    }
-}
-
-impl<Tag> fmt::Display for ScalarMaybeUndef<Tag> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            ScalarMaybeUndef::Undef => write!(f, "uninitialized bytes"),
-            ScalarMaybeUndef::Scalar(s) => write!(f, "{}", s),
-        }
-    }
-}
-
-impl<'tcx> ScalarMaybeUndef<()> {
-    #[inline]
-    pub fn with_default_tag<Tag>(self) -> ScalarMaybeUndef<Tag>
-        where Tag: Default
-    {
-        match self {
-            ScalarMaybeUndef::Scalar(s) => ScalarMaybeUndef::Scalar(s.with_default_tag()),
-            ScalarMaybeUndef::Undef => ScalarMaybeUndef::Undef,
-        }
-    }
-}
-
-impl<'tcx, Tag> ScalarMaybeUndef<Tag> {
-    #[inline]
-    pub fn erase_tag(self) -> ScalarMaybeUndef
-    {
-        match self {
-            ScalarMaybeUndef::Scalar(s) => ScalarMaybeUndef::Scalar(s.erase_tag()),
-            ScalarMaybeUndef::Undef => ScalarMaybeUndef::Undef,
-        }
-    }
-
-    #[inline]
-    pub fn not_undef(self) -> EvalResult<'static, Scalar<Tag>> {
-        match self {
-            ScalarMaybeUndef::Scalar(scalar) => Ok(scalar),
-            ScalarMaybeUndef::Undef => err!(ReadUndefBytes(Size::from_bytes(0))),
-        }
-    }
-
-    #[inline(always)]
-    pub fn to_ptr(self) -> EvalResult<'tcx, Pointer<Tag>> {
-        self.not_undef()?.to_ptr()
-    }
-
-    #[inline(always)]
-    pub fn to_bits(self, target_size: Size) -> EvalResult<'tcx, u128> {
-        self.not_undef()?.to_bits(target_size)
-    }
-
-    #[inline(always)]
-    pub fn to_bool(self) -> EvalResult<'tcx, bool> {
-        self.not_undef()?.to_bool()
-    }
-
-    #[inline(always)]
-    pub fn to_char(self) -> EvalResult<'tcx, char> {
-        self.not_undef()?.to_char()
-    }
-
-    #[inline(always)]
-    pub fn to_f32(self) -> EvalResult<'tcx, f32> {
-        self.not_undef()?.to_f32()
-    }
-
-    #[inline(always)]
-    pub fn to_f64(self) -> EvalResult<'tcx, f64> {
-        self.not_undef()?.to_f64()
-    }
-
-    #[inline(always)]
-    pub fn to_u8(self) -> EvalResult<'tcx, u8> {
-        self.not_undef()?.to_u8()
-    }
-
-    #[inline(always)]
-    pub fn to_u32(self) -> EvalResult<'tcx, u32> {
-        self.not_undef()?.to_u32()
-    }
-
-    #[inline(always)]
-    pub fn to_u64(self) -> EvalResult<'tcx, u64> {
-        self.not_undef()?.to_u64()
-    }
-
-    #[inline(always)]
-    pub fn to_usize(self, cx: &impl HasDataLayout) -> EvalResult<'tcx, u64> {
-        self.not_undef()?.to_usize(cx)
-    }
-
-    #[inline(always)]
-    pub fn to_i8(self) -> EvalResult<'tcx, i8> {
-        self.not_undef()?.to_i8()
-    }
-
-    #[inline(always)]
-    pub fn to_i32(self) -> EvalResult<'tcx, i32> {
-        self.not_undef()?.to_i32()
-    }
-
-    #[inline(always)]
-    pub fn to_i64(self) -> EvalResult<'tcx, i64> {
-        self.not_undef()?.to_i64()
-    }
-
-    #[inline(always)]
-    pub fn to_isize(self, cx: &impl HasDataLayout) -> EvalResult<'tcx, i64> {
-        self.not_undef()?.to_isize(cx)
-    }
-}
-
+pub use rustc::mir::interpret::ScalarMaybeUndef;
 
 /// A `Value` represents a single immediate self-contained Rust value.
 ///
index 19430c85cf73c20877b02ab7451bcb0e19f82a2a..6f8bbf3c4a97de0475f2807c7b018a4c748b468d 100644 (file)
@@ -24,7 +24,7 @@
     GlobalId, AllocId, Allocation, Scalar, EvalResult, Pointer, PointerArithmetic
 };
 use super::{
-    EvalContext, Machine, AllocMap,
+    EvalContext, Machine, AllocMap, AllocationExtra,
     Immediate, ImmTy, ScalarMaybeUndef, Operand, OpTy, MemoryKind
 };
 
@@ -264,6 +264,7 @@ impl<'a, 'mir, 'tcx, Tag, M> EvalContext<'a, 'mir, 'tcx, M>
     Tag: ::std::fmt::Debug+Default+Copy+Eq+Hash+'static,
     M: Machine<'a, 'mir, 'tcx, PointerTag=Tag>,
     M::MemoryMap: AllocMap<AllocId, (MemoryKind<M::MemoryKinds>, Allocation<Tag, M::AllocExtra>)>,
+    M::AllocExtra: AllocationExtra<Tag>,
 {
     /// Take a value, which represents a (thin or fat) reference, and make it a place.
     /// Alignment is just based on the type.  This is the inverse of `create_ref`.
index 0926ddb59665995aafc943f63d40e256fd205ee4..4b63335ad964cba9480d1de819e583631ffa35bb 100644 (file)
@@ -195,11 +195,6 @@ fn snapshot(&self, ctx: &'a Ctx) -> Self::Item {
     }
 }
 
-impl_stable_hash_for!(enum ::interpret::ScalarMaybeUndef {
-    Scalar(v),
-    Undef
-});
-
 impl_snapshot_for!(enum ScalarMaybeUndef {
     Scalar(s),
     Undef,
index 8fde0c9b8afd93e78d25ff9f03468be8ac4edfce..84aa5b6756660ceb4f224c37324e1ec6fe7d3668 100644 (file)
@@ -17,7 +17,7 @@
 use rustc::ty;
 use rustc_data_structures::fx::FxHashSet;
 use rustc::mir::interpret::{
-    Scalar, AllocType, EvalResult, EvalErrorKind
+    Scalar, AllocType, EvalResult, EvalErrorKind,
 };
 
 use super::{
index 76a8501fb177a89c4375e3c99fa175a8da097aaf..54983b8f4e026abd40026540e985dd2095a7cd80 100644 (file)
@@ -196,7 +196,7 @@ fn build_drop_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let source_info = SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE };
 
     let return_block = BasicBlock::new(1);
-    let mut blocks = IndexVec::new();
+    let mut blocks = IndexVec::with_capacity(2);
     let block = |blocks: &mut IndexVec<_, _>, kind| {
         blocks.push(BasicBlockData {
             statements: vec![],
@@ -768,7 +768,8 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         }));
     }
 
-    let mut blocks = IndexVec::new();
+    let n_blocks = if let Adjustment::RefMut = rcvr_adjustment { 5 } else { 2 };
+    let mut blocks = IndexVec::with_capacity(n_blocks);
     let block = |blocks: &mut IndexVec<_, _>, statements, kind, is_cleanup| {
         blocks.push(BasicBlockData {
             statements,
index 4d3b422ab28171770a340aa99bfead908262e78e..98311444e28718d3b24aef07a04d92ba9a221e22 100644 (file)
@@ -37,6 +37,7 @@
 use rustc::mir::{Rvalue, Statement, StatementKind};
 use rustc::mir::visit::{MutVisitor, Visitor, TyContext};
 use rustc::ty::{Ty, RegionKind, TyCtxt};
+use smallvec::smallvec;
 use transform::{MirPass, MirSource};
 
 pub struct CleanEndRegions;
@@ -80,7 +81,11 @@ fn visit_rvalue(&mut self,
 
     fn visit_ty(&mut self, ty: &Ty<'tcx>, _: TyContext) {
         // Gather regions that occur in types
-        for re in ty.walk().flat_map(|t| t.regions()) {
+        let mut regions = smallvec![];
+        for t in ty.walk() {
+            t.push_regions(&mut regions);
+        }
+        for re in regions {
             match *re {
                 RegionKind::ReScope(ce) => { self.seen_regions.insert(ce); }
                 _ => {},
index 4f92ba400481bfc2759e4f1fab4ba40cb3efd934..885d70dc4304dee3e3cd02c3118df7555aab58b6 100644 (file)
@@ -591,8 +591,8 @@ fn visit_terminator_kind(
         if let TerminatorKind::Assert { expected, msg, cond, .. } = kind {
             if let Some(value) = self.eval_operand(cond, source_info) {
                 trace!("assertion on {:?} should be {:?}", value, expected);
-                let expected = Immediate::Scalar(Scalar::from_bool(*expected).into());
-                if expected != value.0.to_immediate() {
+                let expected = ScalarMaybeUndef::from(Scalar::from_bool(*expected));
+                if expected != self.ecx.read_scalar(value.0).unwrap() {
                     // poison all places this operand references so that further code
                     // doesn't use the invalid value
                     match cond {
@@ -628,20 +628,20 @@ fn visit_terminator_kind(
                             let len = self
                                 .eval_operand(len, source_info)
                                 .expect("len must be const");
-                            let len = match len.0.to_immediate() {
-                                Immediate::Scalar(ScalarMaybeUndef::Scalar(Scalar::Bits {
+                            let len = match self.ecx.read_scalar(len.0) {
+                                Ok(ScalarMaybeUndef::Scalar(Scalar::Bits {
                                     bits, ..
                                 })) => bits,
-                                _ => bug!("const len not primitive: {:?}", len),
+                                other => bug!("const len not primitive: {:?}", other),
                             };
                             let index = self
                                 .eval_operand(index, source_info)
                                 .expect("index must be const");
-                            let index = match index.0.to_immediate() {
-                                Immediate::Scalar(ScalarMaybeUndef::Scalar(Scalar::Bits {
+                            let index = match self.ecx.read_scalar(index.0) {
+                                Ok(ScalarMaybeUndef::Scalar(Scalar::Bits {
                                     bits, ..
                                 })) => bits,
-                                _ => bug!("const index not primitive: {:?}", index),
+                                other => bug!("const index not primitive: {:?}", other),
                             };
                             format!(
                                 "index out of bounds: \
index 199cf5650fda8c2f6f5f82d2f239e26d56a1f560..1cce0de5152fda7bd649b1b92c80235f9a2958d6 100644 (file)
@@ -19,7 +19,7 @@
 
 use rustc::mir::*;
 use rustc::mir::visit::*;
-use rustc::ty::{self, Instance, InstanceDef, Ty, TyCtxt};
+use rustc::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt};
 use rustc::ty::subst::{Subst,Substs};
 
 use std::collections::VecDeque;
@@ -85,39 +85,16 @@ fn run_pass(&self, caller_mir: &mut Mir<'tcx>) {
         // Only do inlining into fn bodies.
         let id = self.tcx.hir.as_local_node_id(self.source.def_id).unwrap();
         let body_owner_kind = self.tcx.hir.body_owner_kind(id);
+
         if let (hir::BodyOwnerKind::Fn, None) = (body_owner_kind, self.source.promoted) {
 
             for (bb, bb_data) in caller_mir.basic_blocks().iter_enumerated() {
-                // Don't inline calls that are in cleanup blocks.
-                if bb_data.is_cleanup { continue; }
-
-                // Only consider direct calls to functions
-                let terminator = bb_data.terminator();
-                if let TerminatorKind::Call {
-                    func: ref op, .. } = terminator.kind {
-                        if let ty::FnDef(callee_def_id, substs) = op.ty(caller_mir, self.tcx).sty {
-                            if let Some(instance) = Instance::resolve(self.tcx,
-                                                                      param_env,
-                                                                      callee_def_id,
-                                                                      substs) {
-                                let is_virtual =
-                                    if let InstanceDef::Virtual(..) = instance.def {
-                                        true
-                                    } else {
-                                        false
-                                    };
-
-                                if !is_virtual {
-                                    callsites.push_back(CallSite {
-                                        callee: instance.def_id(),
-                                        substs: instance.substs,
-                                        bb,
-                                        location: terminator.source_info
-                                    });
-                                }
-                            }
-                        }
-                    }
+                if let Some(callsite) = self.get_valid_function_call(bb,
+                                                                     bb_data,
+                                                                     caller_mir,
+                                                                     param_env) {
+                    callsites.push_back(callsite);
+                }
             }
         } else {
             return;
@@ -137,7 +114,7 @@ fn run_pass(&self, caller_mir: &mut Mir<'tcx>) {
 
                 let callee_mir = match self.tcx.try_optimized_mir(callsite.location.span,
                                                                   callsite.callee) {
-                    Ok(callee_mir) if self.should_inline(callsite, callee_mir) => {
+                    Ok(callee_mir) if self.consider_optimizing(callsite, callee_mir) => {
                         self.tcx.subst_and_normalize_erasing_regions(
                             &callsite.substs,
                             param_env,
@@ -163,20 +140,13 @@ fn run_pass(&self, caller_mir: &mut Mir<'tcx>) {
 
                 // Add callsites from inlined function
                 for (bb, bb_data) in caller_mir.basic_blocks().iter_enumerated().skip(start) {
-                    // Only consider direct calls to functions
-                    let terminator = bb_data.terminator();
-                    if let TerminatorKind::Call {
-                        func: Operand::Constant(ref f), .. } = terminator.kind {
-                        if let ty::FnDef(callee_def_id, substs) = f.ty.sty {
-                            // Don't inline the same function multiple times.
-                            if callsite.callee != callee_def_id {
-                                callsites.push_back(CallSite {
-                                    callee: callee_def_id,
-                                    substs,
-                                    bb,
-                                    location: terminator.source_info
-                                });
-                            }
+                    if let Some(new_callsite) = self.get_valid_function_call(bb,
+                                                                             bb_data,
+                                                                             caller_mir,
+                                                                             param_env) {
+                        // Don't inline the same function multiple times.
+                        if callsite.callee != new_callsite.callee {
+                            callsites.push_back(new_callsite);
                         }
                     }
                 }
@@ -198,6 +168,52 @@ fn run_pass(&self, caller_mir: &mut Mir<'tcx>) {
         }
     }
 
+    fn get_valid_function_call(&self,
+                               bb: BasicBlock,
+                               bb_data: &BasicBlockData<'tcx>,
+                               caller_mir: &Mir<'tcx>,
+                               param_env: ParamEnv<'tcx>,
+    ) -> Option<CallSite<'tcx>> {
+        // Don't inline calls that are in cleanup blocks.
+        if bb_data.is_cleanup { return None; }
+
+        // Only consider direct calls to functions
+        let terminator = bb_data.terminator();
+        if let TerminatorKind::Call { func: ref op, .. } = terminator.kind {
+            if let ty::FnDef(callee_def_id, substs) = op.ty(caller_mir, self.tcx).sty {
+                let instance = Instance::resolve(self.tcx,
+                                                 param_env,
+                                                 callee_def_id,
+                                                 substs)?;
+
+                if let InstanceDef::Virtual(..) = instance.def {
+                    return None;
+                }
+
+                return Some(CallSite {
+                    callee: instance.def_id(),
+                    substs: instance.substs,
+                    bb,
+                    location: terminator.source_info
+                });
+            }
+        }
+
+        None
+    }
+
+    fn consider_optimizing(&self,
+                           callsite: CallSite<'tcx>,
+                           callee_mir: &Mir<'tcx>)
+                           -> bool
+    {
+        debug!("consider_optimizing({:?})", callsite);
+        self.should_inline(callsite, callee_mir)
+            && self.tcx.consider_optimizing(|| format!("Inline {:?} into {:?}",
+                                                       callee_mir.span,
+                                                       callsite))
+    }
+
     fn should_inline(&self,
                      callsite: CallSite<'tcx>,
                      callee_mir: &Mir<'tcx>)
index e79da88a2464bf7d75d0b6815bd52bc4f316065a..c5add6260789a34e485f5852b45695cc3d093374 100644 (file)
@@ -310,16 +310,11 @@ fn promote_candidate(mut self, candidate: Candidate) {
                     match statement.kind {
                         StatementKind::Assign(_, box Rvalue::Ref(_, _, ref mut place)) => {
                             // Find the underlying local for this (necessarily interior) borrow.
-                            // HACK(eddyb) using a recursive function because of mutable borrows.
-                            fn interior_base<'a, 'tcx>(place: &'a mut Place<'tcx>)
-                                                       -> &'a mut Place<'tcx> {
-                                if let Place::Projection(ref mut proj) = *place {
-                                    assert_ne!(proj.elem, ProjectionElem::Deref);
-                                    return interior_base(&mut proj.base);
-                                }
-                                place
-                            }
-                            let place = interior_base(place);
+                            let mut place = place;
+                            while let Place::Projection(ref mut proj) = *place {
+                                assert_ne!(proj.elem, ProjectionElem::Deref);
+                                place = &mut proj.base;
+                            };
 
                             let ty = place.ty(local_decls, self.tcx).to_ty(self.tcx);
                             let span = statement.source_info.span;
index ca9c4eb9b8bb971f3d8bca1046c98d2afb4c30ee..03497be03087b4fbafa495ca41cf9279cf694949 100644 (file)
@@ -869,6 +869,8 @@ fn visit_terminator_kind(&mut self,
                             | "overflowing_mul"
                             | "unchecked_shl"
                             | "unchecked_shr"
+                            | "rotate_left"
+                            | "rotate_right"
                             | "add_with_overflow"
                             | "sub_with_overflow"
                             | "mul_with_overflow"
index 17ec2b96438ad02b97746e66de4a6d5a9c7021ad..29165675a2ad7e346052ccad9cdab39cf7d406b4 100644 (file)
@@ -15,6 +15,5 @@ cmake = "0.1.18"
 
 [dependencies]
 alloc = { path = "../liballoc" }
-alloc_system = { path = "../liballoc_system" }
 core = { path = "../libcore" }
 compiler_builtins = { path = "../rustc/compiler_builtins_shim" }
index 7b845e631ffa341d88db3950e9748e75558e063b..47f917e40c1ff53a5b81e490e026a3bdaa54fc61 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 #![sanitizer_runtime]
-#![feature(alloc_system)]
 #![feature(nll)]
 #![feature(sanitizer_runtime)]
 #![feature(staged_api)]
 #![unstable(feature = "sanitizer_runtime_lib",
             reason = "internal implementation detail of sanitizers",
             issue = "0")]
-
-extern crate alloc_system;
-
-use alloc_system::System;
-
-#[global_allocator]
-static ALLOC: System = System;
index 43a5fdb7a025ff2977da7a3666cc132ec80661d6..db5b516e7b23b4c3fe5441a8876098b5e51177d7 100644 (file)
@@ -663,10 +663,13 @@ struct Flags: u8 {
                     binding.map(|binding| (binding, Flags::MODULE, Flags::empty()))
                 }
                 WhereToResolve::MacroUsePrelude => {
-                    match self.macro_use_prelude.get(&ident.name).cloned() {
-                        Some(binding) => Ok((binding, Flags::PRELUDE, Flags::empty())),
-                        None => Err(Determinacy::Determined),
+                    let mut result = Err(Determinacy::Determined);
+                    if use_prelude || self.session.rust_2015() {
+                        if let Some(binding) = self.macro_use_prelude.get(&ident.name).cloned() {
+                            result = Ok((binding, Flags::PRELUDE, Flags::empty()));
+                        }
                     }
+                    result
                 }
                 WhereToResolve::BuiltinMacros => {
                     match self.builtin_macros.get(&ident.name).cloned() {
@@ -685,7 +688,8 @@ struct Flags: u8 {
                     }
                 }
                 WhereToResolve::LegacyPluginHelpers => {
-                    if self.session.plugin_attributes.borrow().iter()
+                    if (use_prelude || self.session.rust_2015()) &&
+                       self.session.plugin_attributes.borrow().iter()
                                                      .any(|(name, _)| ident.name == &**name) {
                         let binding = (Def::NonMacroAttr(NonMacroAttrKind::LegacyPluginHelper),
                                        ty::Visibility::Public, ident.span, Mark::root())
index c7d0469e556a75cf15127c71c153ff21d414d94a..15f61a033447fffacc782b2b4bc011f71a1d65ce 100644 (file)
@@ -35,7 +35,8 @@ pub struct TargetDataLayout {
     pub aggregate_align: Align,
 
     /// Alignments for vector types.
-    pub vector_align: Vec<(Size, Align)>
+    pub vector_align: Vec<(Size, Align)>,
+    pub instruction_address_space: u32,
 }
 
 impl Default for TargetDataLayout {
@@ -57,13 +58,22 @@ fn default() -> TargetDataLayout {
             vector_align: vec![
                 (Size::from_bits(64), Align::from_bits(64, 64).unwrap()),
                 (Size::from_bits(128), Align::from_bits(128, 128).unwrap())
-            ]
+            ],
+            instruction_address_space: 0,
         }
     }
 }
 
 impl TargetDataLayout {
     pub fn parse(target: &Target) -> Result<TargetDataLayout, String> {
+        // Parse an address space index from a string.
+        let parse_address_space = |s: &str, cause: &str| {
+            s.parse::<u32>().map_err(|err| {
+                format!("invalid address space `{}` for `{}` in \"data-layout\": {}",
+                        s, cause, err)
+            })
+        };
+
         // Parse a bit count from a string.
         let parse_bits = |s: &str, kind: &str, cause: &str| {
             s.parse::<u64>().map_err(|err| {
@@ -96,6 +106,9 @@ pub fn parse(target: &Target) -> Result<TargetDataLayout, String> {
             match spec.split(':').collect::<Vec<_>>()[..] {
                 ["e"] => dl.endian = Endian::Little,
                 ["E"] => dl.endian = Endian::Big,
+                [p] if p.starts_with("P") => {
+                    dl.instruction_address_space = parse_address_space(&p[1..], "P")?
+                }
                 ["a", ref a..] => dl.aggregate_align = align(a, "a")?,
                 ["f32", ref a..] => dl.f32_align = align(a, "f32")?,
                 ["f64", ref a..] => dl.f64_align = align(a, "f64")?,
index 541f0564a01e2cfd82f1db1efdc24e8d75cfb3dd..b120f57192bfb7b0bb0d3b68a2198cc70f64082a 100644 (file)
@@ -14,9 +14,6 @@ pub fn target() -> TargetResult {
     let mut base = super::freebsd_base::opts();
     base.max_atomic_width = Some(128);
 
-    // see #36994
-    base.exe_allocation_crate = None;
-
     Ok(Target {
         llvm_target: "aarch64-unknown-freebsd".to_string(),
         target_endian: "little".to_string(),
index 2351d01469215499afd996d4ecfdd1ea9cd536b0..af7ec6a1787f0853ae77fe5bb51b77c4656099b5 100644 (file)
@@ -14,9 +14,6 @@ pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
     base.max_atomic_width = Some(128);
 
-    // see #36994
-    base.exe_allocation_crate = None;
-
     Ok(Target {
         llvm_target: "aarch64-unknown-linux-gnu".to_string(),
         target_endian: "little".to_string(),
index 5ab55a076f45b255f0009ab8412032744b2b54cf..e5ca91aabe56a46118933651d2b95403d03ce53d 100644 (file)
@@ -14,9 +14,6 @@ pub fn target() -> TargetResult {
     let mut base = super::linux_musl_base::opts();
     base.max_atomic_width = Some(128);
 
-    // see #36994
-    base.exe_allocation_crate = None;
-
     Ok(Target {
         llvm_target: "aarch64-unknown-linux-musl".to_string(),
         target_endian: "little".to_string(),
index 2a24f771e92897811a9c5ad1ed48fd0c547ee038..168eac685e4f3a4da8ce6eabf072fbe23d050494 100644 (file)
@@ -21,7 +21,6 @@ pub fn opts() -> TargetOptions {
     ]);
 
     TargetOptions {
-        exe_allocation_crate: None,
         executables: true,
         has_elf_tls: true,
         linker_is_gnu: true,
index 4ebc930d48b6fa2178ddb6e6c1ca22cc061fcb8c..7932adf3b1054077714b92de197ef4da3563180c 100644 (file)
@@ -30,7 +30,6 @@ pub fn opts() -> TargetOptions {
     TargetOptions {
         executables: true,
         has_elf_tls: false,
-        exe_allocation_crate: None,
         panic_strategy: PanicStrategy::Abort,
         linker: Some("ld".to_string()),
         pre_link_args: args,
index 7a3f3c2a518bc7d065602ce42d30d3f9abc1ad1e..c87f14977cb1d5f50702d58e47874e6699835816 100644 (file)
@@ -24,31 +24,6 @@ pub fn opts() -> TargetOptions {
     // argument is *not* necessary for normal builds, but it can't hurt!
     base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-Wl,--eh-frame-hdr".to_string());
 
-    // There's a whole bunch of circular dependencies when dealing with MUSL
-    // unfortunately. To put this in perspective libc is statically linked to
-    // liblibc and libunwind is statically linked to libstd:
-    //
-    // * libcore depends on `fmod` which is in libc (transitively in liblibc).
-    //   liblibc, however, depends on libcore.
-    // * compiler-rt has personality symbols that depend on libunwind, but
-    //   libunwind is in libstd which depends on compiler-rt.
-    //
-    // Recall that linkers discard libraries and object files as much as
-    // possible, and with all the static linking and archives flying around with
-    // MUSL the linker is super aggressively stripping out objects. For example
-    // the first case has fmod stripped from liblibc (it's in its own object
-    // file) so it's not there when libcore needs it. In the second example all
-    // the unused symbols from libunwind are stripped (each is in its own object
-    // file in libstd) before we end up linking compiler-rt which depends on
-    // those symbols.
-    //
-    // To deal with these circular dependencies we just force the compiler to
-    // link everything as a group, not stripping anything out until everything
-    // is processed. The linker will still perform a pass to strip out object
-    // files but it won't do so until all objects/archives have been processed.
-    base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-Wl,-(".to_string());
-    base.post_link_args.insert(LinkerFlavor::Gcc, vec!["-Wl,-)".to_string()]);
-
     // When generating a statically linked executable there's generally some
     // small setup needed which is listed in these files. These are provided by
     // a musl toolchain and are linked by default by the `musl-gcc` script. Note
index 1f60d918908d019a63de628d96dbfaa59a569a47..b80b6b561cd42554172e95cc4d21ae429e533510 100644 (file)
@@ -28,9 +28,6 @@ pub fn target() -> TargetResult {
             features: "+mips64r2".to_string(),
             max_atomic_width: Some(64),
 
-            // see #36994
-            exe_allocation_crate: None,
-
             ..super::linux_base::opts()
         },
     })
index e42fde8d403fbcd4e37a8e0d8f1e91a92accbc63..1c835af6e412b1e9ea6db09aa9638b242a28cc38 100644 (file)
@@ -28,9 +28,6 @@ pub fn target() -> TargetResult {
             features: "+mips64r2".to_string(),
             max_atomic_width: Some(64),
 
-            // see #36994
-            exe_allocation_crate: None,
-
             ..super::linux_base::opts()
         },
     })
index 59e15137cf40d9e932bca7d3053b7d3b2eed5cd2..6331031c9a2847176752ff2b7c8b12b02852afc5 100644 (file)
@@ -27,9 +27,6 @@ pub fn target() -> TargetResult {
             features: "+mips32r2,+fpxx,+nooddspreg".to_string(),
             max_atomic_width: Some(32),
 
-            // see #36994
-            exe_allocation_crate: None,
-
             ..super::linux_base::opts()
         },
     })
index 8ee399ba56c329534235c6968f7ce0a0826f29a7..0b20765172a0250911ee289344bb425c329fd5a9 100644 (file)
@@ -15,8 +15,6 @@ pub fn target() -> TargetResult {
     base.cpu = "mips32r2".to_string();
     base.features = "+mips32r2,+soft-float".to_string();
     base.max_atomic_width = Some(32);
-    // see #36994
-    base.exe_allocation_crate = None;
     base.crt_static_default = false;
     Ok(Target {
         llvm_target: "mips-unknown-linux-musl".to_string(),
index 384ab1e413123cf164a6730f7252095f314e0847..d3f614c982ae4903eae0f7c0dc22b5ed7a14e67e 100644 (file)
@@ -27,9 +27,6 @@ pub fn target() -> TargetResult {
             features: "+mips32r2,+soft-float".to_string(),
             max_atomic_width: Some(32),
 
-            // see #36994
-            exe_allocation_crate: None,
-
             ..super::linux_base::opts()
         },
     })
index edd29164caca897677971d06f4ec8ecb9c4c3c8b..79ebefa79a320065ff012d4590ef9547fb83a54e 100644 (file)
@@ -28,9 +28,6 @@ pub fn target() -> TargetResult {
             features: "+mips32r2,+fpxx,+nooddspreg".to_string(),
             max_atomic_width: Some(32),
 
-            // see #36994
-            exe_allocation_crate: None,
-
             ..super::linux_base::opts()
         },
     })
index 1d9378ca1b81407baf89bcb4694469a1f5b800c4..042e2b71c32565f98dedcf716bef3257686e6340 100644 (file)
@@ -15,8 +15,6 @@ pub fn target() -> TargetResult {
     base.cpu = "mips32r2".to_string();
     base.features = "+mips32r2,+soft-float".to_string();
     base.max_atomic_width = Some(32);
-    // see #36994
-    base.exe_allocation_crate = None;
     base.crt_static_default = false;
     Ok(Target {
         llvm_target: "mipsel-unknown-linux-musl".to_string(),
index a1db1791bb7ce6027f35f6bdf59e4b9cd63de7f7..8cb5cd3f03a677f024841f1572563d916c361526 100644 (file)
@@ -28,9 +28,6 @@ pub fn target() -> TargetResult {
             features: "+mips32r2,+soft-float".to_string(),
             max_atomic_width: Some(32),
 
-            // see #36994
-            exe_allocation_crate: None,
-
             ..super::linux_base::opts()
         },
     })
index c8af81c02ea4a48b5a8a72cd7e1307272532fd63..16dc2a91030f1723c0f937feb6788b9a1c3fb30f 100644 (file)
@@ -596,9 +596,6 @@ pub struct TargetOptions {
     /// `eh_unwind_resume` lang item.
     pub custom_unwind_resume: bool,
 
-    /// If necessary, a different crate to link exe allocators by default
-    pub exe_allocation_crate: Option<String>,
-
     /// Flag indicating whether ELF TLS (e.g. #[thread_local]) is available for
     /// this target.
     pub has_elf_tls: bool,
@@ -740,7 +737,6 @@ fn default() -> TargetOptions {
             link_env: Vec::new(),
             archive_format: "gnu".to_string(),
             custom_unwind_resume: false,
-            exe_allocation_crate: None,
             allow_asm: true,
             has_elf_tls: false,
             obj_is_bitcode: false,
@@ -1025,7 +1021,6 @@ macro_rules! key {
         key!(archive_format);
         key!(allow_asm, bool);
         key!(custom_unwind_resume, bool);
-        key!(exe_allocation_crate, optional);
         key!(has_elf_tls, bool);
         key!(obj_is_bitcode, bool);
         key!(no_integrated_as, bool);
@@ -1235,7 +1230,6 @@ macro_rules! target_option_val {
         target_option_val!(archive_format);
         target_option_val!(allow_asm);
         target_option_val!(custom_unwind_resume);
-        target_option_val!(exe_allocation_crate);
         target_option_val!(has_elf_tls);
         target_option_val!(obj_is_bitcode);
         target_option_val!(no_integrated_as);
index 1959871161343aa656d32cfdd816f357f6ff619b..1d0afcd5e0c608b4721024d301fe2b5187ed25b9 100644 (file)
@@ -20,9 +20,6 @@ pub fn target() -> TargetResult {
     // for now. https://github.com/rust-lang/rust/pull/43170#issuecomment-315411474
     base.relro_level = RelroLevel::Partial;
 
-    // see #36994
-    base.exe_allocation_crate = None;
-
     Ok(Target {
         llvm_target: "powerpc64-unknown-linux-gnu".to_string(),
         target_endian: "big".to_string(),
index 39840692dff188efd4e951f1681d87d1d989d7b6..01811c5a0c32227e2fcc72e20379cd2ae20dbb9c 100644 (file)
@@ -16,9 +16,6 @@ pub fn target() -> TargetResult {
     base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
     base.max_atomic_width = Some(64);
 
-    // see #36994
-    base.exe_allocation_crate = None;
-
     Ok(Target {
         llvm_target: "powerpc64le-unknown-linux-gnu".to_string(),
         target_endian: "little".to_string(),
index 34ec82412289df36845f34a920fd13bcf33bff5c..590c5ba8d54b49fcba547674347ccbe4debe6d51 100644 (file)
@@ -16,9 +16,6 @@ pub fn target() -> TargetResult {
     base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
     base.max_atomic_width = Some(64);
 
-    // see #36994
-    base.exe_allocation_crate = None;
-
     Ok(Target {
         llvm_target: "powerpc64le-unknown-linux-musl".to_string(),
         target_endian: "little".to_string(),
index c05b110a75d391e888c465d9d9ce74ec2709ab07..99d8d99fbb2b620c59a8c08b2b854fa9054ffd1b 100644 (file)
@@ -15,9 +15,6 @@ pub fn target() -> TargetResult {
     base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string());
     base.max_atomic_width = Some(32);
 
-    // see #36994
-    base.exe_allocation_crate = None;
-
     Ok(Target {
         llvm_target: "powerpc-unknown-linux-gnu".to_string(),
         target_endian: "big".to_string(),
index c76c3119c87c5deab3f7b39477472c102df01f0b..9b15b0a5dc4b7b3c80c81b411535733b3423a6fd 100644 (file)
@@ -15,9 +15,6 @@ pub fn target() -> TargetResult {
     base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-mspe".to_string());
     base.max_atomic_width = Some(32);
 
-    // see #36994
-    base.exe_allocation_crate = None;
-
     Ok(Target {
         llvm_target: "powerpc-unknown-linux-gnuspe".to_string(),
         target_endian: "big".to_string(),
index 740222c9608054400464792a6e1901b732297cf9..98625a63f52980adefeac771fe27a349f44af36b 100644 (file)
@@ -15,9 +15,6 @@ pub fn target() -> TargetResult {
     base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string());
     base.max_atomic_width = Some(32);
 
-    // see #36994
-    base.exe_allocation_crate = None;
-
     Ok(Target {
         llvm_target: "powerpc-unknown-netbsd".to_string(),
         target_endian: "big".to_string(),
index c9a9625ebab95b59d85e99ca711589f525dc9f17..bd8b7e435d340e1a0cc676b65d1d391423ff4524 100644 (file)
@@ -19,8 +19,6 @@ pub fn target() -> TargetResult {
     // Pass the -vector feature string to LLVM to respect this assumption.
     base.features = "-vector".to_string();
     base.max_atomic_width = Some(64);
-    // see #36994
-    base.exe_allocation_crate = None;
     base.min_global_align = Some(16);
 
     Ok(Target {
index f68b5fd24bf755dd128cc1ce49b374600e97525c..f2b99aa46d2d0cfc7f7fc72b39cce4a1856a3b37 100644 (file)
@@ -14,7 +14,6 @@ pub fn target() -> TargetResult {
     let mut base = super::linux_base::opts();
     base.cpu = "v9".to_string();
     base.max_atomic_width = Some(64);
-    base.exe_allocation_crate = None;
 
     Ok(Target {
         llvm_target: "sparc64-unknown-linux-gnu".to_string(),
index 4e352374f90b064a9132f1b1036f16084d2a29ec..81db39cd23f87d288915989613f2e5192391af51 100644 (file)
@@ -15,7 +15,6 @@ pub fn target() -> TargetResult {
     base.cpu = "v9".to_string();
     base.max_atomic_width = Some(64);
     base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-mv8plus".to_string());
-    base.exe_allocation_crate = None;
 
     Ok(Target {
         llvm_target: "sparc-unknown-linux-gnu".to_string(),
index 8bc233107b8bb5bf1c49616c65392bb7c76e2c5c..5029e857eb5431378e8a83fb4cf8e55f0bac56f6 100644 (file)
@@ -16,7 +16,6 @@ pub fn target() -> TargetResult {
     // llvm calls this "v9"
     base.cpu = "v9".to_string();
     base.max_atomic_width = Some(64);
-    base.exe_allocation_crate = None;
 
     Ok(Target {
         llvm_target: "sparcv9-sun-solaris".to_string(),
index b4c09f86b8a97c96c34bd96513a8e20b02b5c38d..2c80f3b4b3b02c68da0f9670601f9f8191ae5c9b 100644 (file)
 use super::{LinkArgs, LinkerFlavor, Target, TargetOptions};
 
 pub fn target() -> Result<Target, String> {
+    // FIXME(nikic) BINARYEN_TRAP_MODE=clamp is needed to avoid trapping in our
+    // -Zsaturating-float-casts implementation. This can be dropped if/when
+    // we have native fpto[su]i.sat intrinsics, or the implementation otherwise
+    // stops relying on non-trapping fpto[su]i.
     let mut post_link_args = LinkArgs::new();
     post_link_args.insert(LinkerFlavor::Em,
                           vec!["-s".to_string(),
                                "BINARYEN=1".to_string(),
                                "-s".to_string(),
-                               "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()]);
+                               "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string(),
+                               "-s".to_string(),
+                               "BINARYEN_TRAP_MODE='clamp'".to_string()]);
 
     let opts = TargetOptions {
         dynamic_linking: false,
index 684bf5a6c1026e2e950e679decfc18a22f883cda..e7570cd2da6ec84fd4cfa9b19fbe0849e2ef7ab1 100644 (file)
@@ -21,7 +21,6 @@ pub fn target() -> TargetResult {
     base.has_rpath = false;
     base.position_independent_executables = false;
     base.disable_redzone = true;
-    base.exe_allocation_crate = None;
     base.stack_probes = true;
 
     Ok(Target {
index 7cc064f9c3d3d81906ad96caaa92a9e4c5e79a23..7514c2c18e7ca8f77aec0fbe7fcd15be28e12c8a 100644 (file)
@@ -20,6 +20,7 @@
 use rustc::ty::outlives::Component;
 use rustc::ty::query::Providers;
 use rustc::ty::wf;
+use smallvec::{SmallVec, smallvec};
 use syntax::ast::DUMMY_NODE_ID;
 use syntax::source_map::DUMMY_SP;
 use rustc::traits::FulfillmentContext;
@@ -133,7 +134,8 @@ fn compute_implied_outlives_bounds<'tcx>(
                     None => vec![],
                     Some(ty::OutlivesPredicate(ty_a, r_b)) => {
                         let ty_a = infcx.resolve_type_vars_if_possible(&ty_a);
-                        let components = tcx.outlives_components(ty_a);
+                        let mut components = smallvec![];
+                        tcx.push_outlives_components(ty_a, &mut components);
                         implied_bounds_from_components(r_b, components)
                     }
                 },
@@ -155,7 +157,7 @@ fn compute_implied_outlives_bounds<'tcx>(
 /// those relationships.
 fn implied_bounds_from_components(
     sub_region: ty::Region<'tcx>,
-    sup_components: Vec<Component<'tcx>>,
+    sup_components: SmallVec<[Component<'tcx>; 4]>,
 ) -> Vec<OutlivesBound<'tcx>> {
     sup_components
         .into_iter()
index 2ed02a4cdab1e1a71d642439b3cae7c6ee940d56..e635bc9efc45c0572326d00d87d6776d014aae6d 100644 (file)
@@ -151,17 +151,35 @@ fn relate_mir_and_user_ty(
         debug!("relate_type_and_user_type: ty of def-id is {:?}", ty);
         let ty = self.normalize(ty);
 
-        let mut projected_ty = PlaceTy::from_ty(ty);
+        // We need to follow any provided projetions into the type.
+        //
+        // if we hit a ty var as we descend, then just skip the
+        // attempt to relate the mir local with any type.
+
+        struct HitTyVar;
+        let mut curr_projected_ty: Result<PlaceTy, HitTyVar>;
+        curr_projected_ty = Ok(PlaceTy::from_ty(ty));
         for proj in projs {
-            projected_ty = projected_ty.projection_ty_core(
+            let projected_ty = if let Ok(projected_ty) = curr_projected_ty {
+                projected_ty
+            } else {
+                break;
+            };
+            curr_projected_ty = projected_ty.projection_ty_core(
                 tcx, proj, |this, field, &()| {
-                    let ty = this.field_ty(tcx, field);
-                    self.normalize(ty)
+                    if this.to_ty(tcx).is_ty_var() {
+                        Err(HitTyVar)
+                    } else {
+                        let ty = this.field_ty(tcx, field);
+                        Ok(self.normalize(ty))
+                    }
                 });
         }
-        let ty = projected_ty.to_ty(tcx);
 
-        self.relate(mir_ty, variance, ty)?;
+        if let Ok(projected_ty) = curr_projected_ty {
+            let ty = projected_ty.to_ty(tcx);
+            self.relate(mir_ty, variance, ty)?;
+        }
 
         if let Some(UserSelfTy {
             impl_def_id,
index 8bb67c0bbac5f4e601154bf939c328550d71cba0..baadb64511ae1887aa50eff616ed18772919a77a 100644 (file)
@@ -15,6 +15,5 @@ cmake = "0.1.18"
 
 [dependencies]
 alloc = { path = "../liballoc" }
-alloc_system = { path = "../liballoc_system" }
 core = { path = "../libcore" }
 compiler_builtins = { path = "../rustc/compiler_builtins_shim" }
index 7b845e631ffa341d88db3950e9748e75558e063b..47f917e40c1ff53a5b81e490e026a3bdaa54fc61 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 #![sanitizer_runtime]
-#![feature(alloc_system)]
 #![feature(nll)]
 #![feature(sanitizer_runtime)]
 #![feature(staged_api)]
 #![unstable(feature = "sanitizer_runtime_lib",
             reason = "internal implementation detail of sanitizers",
             issue = "0")]
-
-extern crate alloc_system;
-
-use alloc_system::System;
-
-#[global_allocator]
-static ALLOC: System = System;
index 18f8473b5b56d7d88fb600878aaa16ff8fbbe0b3..572e79407a10be41586bc8b9d38d5aeb33de66a6 100644 (file)
@@ -37,7 +37,7 @@
 use syntax::ast;
 use syntax::ptr::P;
 use syntax::feature_gate::{GateIssue, emit_feature_err};
-use syntax_pos::{Span, MultiSpan};
+use syntax_pos::{DUMMY_SP, Span, MultiSpan};
 
 pub trait AstConv<'gcx, 'tcx> {
     fn tcx<'a>(&'a self) -> TyCtxt<'a, 'gcx, 'tcx>;
@@ -451,7 +451,7 @@ pub fn create_substs_for_generic_args<'a, 'b>(
         }
 
         // We manually build up the substitution, rather than using convenience
-        // methods in subst.rs so that we can iterate over the arguments and
+        // methods in `subst.rs` so that we can iterate over the arguments and
         // parameters in lock-step linearly, rather than trying to match each pair.
         let mut substs: SmallVec<[Kind<'tcx>; 8]> = SmallVec::with_capacity(count);
 
@@ -469,7 +469,7 @@ pub fn create_substs_for_generic_args<'a, 'b>(
                 }
             }
 
-            // (Unless it's been handled in `parent_substs`) `Self` is handled first.
+            // `Self` is handled first, unless it's been handled in `parent_substs`.
             if has_self {
                 if let Some(&param) = params.peek() {
                     if param.index == 0 {
@@ -698,7 +698,7 @@ pub fn instantiate_mono_trait_ref(&self,
                                         trait_ref.path.segments.last().unwrap())
     }
 
-    /// Get the DefId of the given trait ref. It _must_ actually be a trait.
+    /// Get the `DefId` of the given trait ref. It _must_ actually be a trait.
     fn trait_def_id(&self, trait_ref: &hir::TraitRef) -> DefId {
         let path = &trait_ref.path;
         match path.def {
@@ -711,7 +711,7 @@ fn trait_def_id(&self, trait_ref: &hir::TraitRef) -> DefId {
         }
     }
 
-    /// The given `trait_ref` must actually be trait.
+    /// The given trait ref must actually be a trait.
     pub(super) fn instantiate_poly_trait_ref_inner(&self,
         trait_ref: &hir::TraitRef,
         self_ty: Ty<'tcx>,
@@ -738,7 +738,7 @@ pub(super) fn instantiate_poly_trait_ref_inner(&self,
             let predicate: Result<_, ErrorReported> =
                 self.ast_type_binding_to_poly_projection_predicate(
                     trait_ref.ref_id, poly_trait_ref, binding, speculative, &mut dup_bindings);
-            // ok to ignore Err because ErrorReported (see above)
+            // okay to ignore Err because of ErrorReported (see above)
             Some((predicate.ok()?, binding.span))
         }));
 
@@ -831,7 +831,7 @@ fn ast_type_binding_to_poly_projection_predicate(
         let tcx = self.tcx();
 
         if !speculative {
-            // Given something like `U : SomeTrait<T=X>`, we want to produce a
+            // Given something like `U: SomeTrait<T = X>`, we want to produce a
             // predicate like `<U as SomeTrait>::T = X`. This is somewhat
             // subtle in the event that `T` is defined in a supertrait of
             // `SomeTrait`, because in that case we need to upcast.
@@ -839,7 +839,7 @@ fn ast_type_binding_to_poly_projection_predicate(
             // That is, consider this case:
             //
             // ```
-            // trait SubTrait : SuperTrait<int> { }
+            // trait SubTrait: SuperTrait<int> { }
             // trait SuperTrait<A> { type T; }
             //
             // ... B : SubTrait<T=foo> ...
@@ -908,16 +908,14 @@ fn ast_type_binding_to_poly_projection_predicate(
         if !speculative {
             dup_bindings.entry(assoc_ty.def_id)
                 .and_modify(|prev_span| {
-                    let mut err = self.tcx().struct_span_lint_node(
-                        ::rustc::lint::builtin::DUPLICATE_ASSOCIATED_TYPE_BINDINGS,
-                        ref_id,
-                        binding.span,
-                        &format!("associated type binding `{}` specified more than once",
-                                 binding.item_name)
-                    );
-                    err.span_label(binding.span, "used more than once");
-                    err.span_label(*prev_span, format!("first use of `{}`", binding.item_name));
-                    err.emit();
+                    struct_span_err!(self.tcx().sess, binding.span, E0719,
+                                     "the value of the associated type `{}` (from the trait `{}`) \
+                                      is already specified",
+                                     binding.item_name,
+                                     tcx.item_path_str(assoc_ty.container.id()))
+                        .span_label(binding.span, "re-bound here")
+                        .span_label(*prev_span, format!("`{}` bound here first", binding.item_name))
+                        .emit();
                 })
                 .or_insert(binding.span);
         }
@@ -969,7 +967,7 @@ fn conv_object_ty_poly_trait_ref(&self,
             return tcx.types.err;
         }
 
-        let mut projection_bounds = vec![];
+        let mut projection_bounds = Vec::new();
         let dummy_self = tcx.mk_ty(TRAIT_OBJECT_DUMMY_SELF);
         let principal = self.instantiate_poly_trait_ref(&trait_bounds[0],
                                                         dummy_self,
@@ -994,23 +992,8 @@ fn conv_object_ty_poly_trait_ref(&self,
                 .emit();
         }
 
-        // Erase the dummy_self (TRAIT_OBJECT_DUMMY_SELF) used above.
-        let existential_principal = principal.map_bound(|trait_ref| {
-            self.trait_ref_to_existential(trait_ref)
-        });
-        let existential_projections = projection_bounds.iter().map(|(bound, _)| {
-            bound.map_bound(|b| {
-                let trait_ref = self.trait_ref_to_existential(b.projection_ty.trait_ref(tcx));
-                ty::ExistentialProjection {
-                    ty: b.ty,
-                    item_def_id: b.projection_ty.item_def_id,
-                    substs: trait_ref.substs,
-                }
-            })
-        });
-
         // Check that there are no gross object safety violations;
-        // most importantly, that the supertraits don't contain Self,
+        // most importantly, that the supertraits don't contain `Self`,
         // to avoid ICEs.
         let object_safety_violations =
             tcx.global_tcx().astconv_object_safety_violations(principal.def_id());
@@ -1021,13 +1004,22 @@ fn conv_object_ty_poly_trait_ref(&self,
             return tcx.types.err;
         }
 
-        // Use a BTreeSet to keep output in a more consistent order.
+        // Use a `BTreeSet` to keep output in a more consistent order.
         let mut associated_types = BTreeSet::default();
 
-        for tr in traits::supertraits(tcx, principal) {
-            associated_types.extend(tcx.associated_items(tr.def_id())
-                .filter(|item| item.kind == ty::AssociatedKind::Type)
-                .map(|item| item.def_id));
+        for tr in traits::elaborate_trait_ref(tcx, principal) {
+            match tr {
+                ty::Predicate::Trait(pred) => {
+                    associated_types.extend(tcx.associated_items(pred.def_id())
+                                    .filter(|item| item.kind == ty::AssociatedKind::Type)
+                                    .map(|item| item.def_id));
+                }
+                ty::Predicate::Projection(pred) => {
+                    // Include projections defined on supertraits.
+                    projection_bounds.push((pred, DUMMY_SP))
+                }
+                _ => ()
+            }
         }
 
         for (projection_bound, _) in &projection_bounds {
@@ -1046,11 +1038,26 @@ fn conv_object_ty_poly_trait_ref(&self,
                 .emit();
         }
 
+        // Erase the `dummy_self` (`TRAIT_OBJECT_DUMMY_SELF`) used above.
+        let existential_principal = principal.map_bound(|trait_ref| {
+            self.trait_ref_to_existential(trait_ref)
+        });
+        let existential_projections = projection_bounds.iter().map(|(bound, _)| {
+            bound.map_bound(|b| {
+                let trait_ref = self.trait_ref_to_existential(b.projection_ty.trait_ref(tcx));
+                ty::ExistentialProjection {
+                    ty: b.ty,
+                    item_def_id: b.projection_ty.item_def_id,
+                    substs: trait_ref.substs,
+                }
+            })
+        });
+
         // Dedup auto traits so that `dyn Trait + Send + Send` is the same as `dyn Trait + Send`.
         auto_traits.sort();
         auto_traits.dedup();
 
-        // skip_binder is okay, because the predicates are re-bound.
+        // Calling `skip_binder` is okay, because the predicates are re-bound.
         let mut v =
             iter::once(ty::ExistentialPredicate::Trait(*existential_principal.skip_binder()))
             .chain(auto_traits.into_iter().map(ty::ExistentialPredicate::AutoTrait))
@@ -1128,8 +1135,7 @@ fn find_bound_for_assoc_item(&self,
                                       span)
     }
 
-
-    // Checks that bounds contains exactly one element and reports appropriate
+    // Checks that `bounds` contains exactly one element and reports appropriate
     // errors otherwise.
     fn one_bound_for_assoc_type<I>(&self,
                                    mut bounds: I,
@@ -1186,11 +1192,11 @@ fn one_bound_for_assoc_type<I>(&self,
     }
 
     // Create a type from a path to an associated type.
-    // For a path A::B::C::D, ty and ty_path_def are the type and def for A::B::C
-    // and item_segment is the path segment for D. We return a type and a def for
+    // For a path `A::B::C::D`, `ty` and `ty_path_def` are the type and def for `A::B::C`
+    // and item_segment is the path segment for `D`. We return a type and a def for
     // the whole path.
-    // Will fail except for T::A and Self::A; i.e., if ty/ty_path_def are not a type
-    // parameter or Self.
+    // Will fail except for `T::A` and `Self::A`; i.e., if `ty`/`ty_path_def` are not a type
+    // parameter or `Self`.
     pub fn associated_path_def_to_ty(&self,
                                      ref_id: ast::NodeId,
                                      span: Span,
@@ -1210,7 +1216,7 @@ pub fn associated_path_def_to_ty(&self,
         // item is declared.
         let bound = match (&ty.sty, ty_path_def) {
             (_, Def::SelfTy(Some(_), Some(impl_def_id))) => {
-                // `Self` in an impl of a trait - we have a concrete self type and a
+                // `Self` in an impl of a trait - we have a concrete `self` type and a
                 // trait reference.
                 let trait_ref = match tcx.impl_trait_ref(impl_def_id) {
                     Some(trait_ref) => trait_ref,
@@ -1361,7 +1367,7 @@ pub fn def_to_ty(&self,
         let span = path.span;
         match path.def {
             Def::Existential(did) => {
-                // check for desugared impl trait
+                // Check for desugared impl trait.
                 assert!(ty::is_impl_trait_defn(tcx, did).is_none());
                 let item_segment = path.segments.split_last().unwrap();
                 self.prohibit_generics(item_segment.1);
@@ -1398,7 +1404,7 @@ pub fn def_to_ty(&self,
                 tcx.mk_ty_param(index, tcx.hir.name(node_id).as_interned_str())
             }
             Def::SelfTy(_, Some(def_id)) => {
-                // Self in impl (we know the concrete type).
+                // `Self` in impl (we know the concrete type)
 
                 assert_eq!(opt_self_ty, None);
                 self.prohibit_generics(&path.segments);
@@ -1406,7 +1412,7 @@ pub fn def_to_ty(&self,
                 tcx.at(span).type_of(def_id)
             }
             Def::SelfTy(Some(_), None) => {
-                // Self in trait.
+                // `Self` in trait
                 assert_eq!(opt_self_ty, None);
                 self.prohibit_generics(&path.segments);
                 tcx.mk_self_type()
index 40f2072079a5a1ba203536b642b3f3d14ea8c53c..a477df6ae2d568e4d296876c7a9fd0c91a442612 100644 (file)
@@ -626,9 +626,9 @@ pub fn check_match(&self,
         let discrim_diverges = self.diverges.get();
         self.diverges.set(Diverges::Maybe);
 
-        // Typecheck the patterns first, so that we get types for all the
-        // bindings.
-        let all_arm_pats_diverge = arms.iter().map(|arm| {
+        // rust-lang/rust#55810: Typecheck patterns first (via eager
+        // collection into `Vec`), so we get types for all bindings.
+        let all_arm_pats_diverge: Vec<_> = arms.iter().map(|arm| {
             let mut all_pats_diverge = Diverges::WarnedAlways;
             for p in &arm.pats {
                 self.diverges.set(Diverges::Maybe);
@@ -644,7 +644,7 @@ pub fn check_match(&self,
                 Diverges::Maybe => Diverges::Maybe,
                 Diverges::Always | Diverges::WarnedAlways => Diverges::WarnedAlways,
             }
-        });
+        }).collect();
 
         // Now typecheck the blocks.
         //
@@ -814,11 +814,6 @@ fn check_pat_tuple_struct(&self,
             report_unexpected_def(def);
             return self.tcx.types.err;
         }
-        // Replace constructor type with constructed type for tuple struct patterns.
-        let pat_ty = pat_ty.fn_sig(tcx).output();
-        let pat_ty = pat_ty.no_bound_vars().expect("expected fn type");
-
-        self.demand_eqtype(pat.span, expected, pat_ty);
 
         let variant = match def {
             Def::Err => {
@@ -836,6 +831,13 @@ fn check_pat_tuple_struct(&self,
             }
             _ => bug!("unexpected pattern definition: {:?}", def)
         };
+
+        // Replace constructor type with constructed type for tuple struct patterns.
+        let pat_ty = pat_ty.fn_sig(tcx).output();
+        let pat_ty = pat_ty.no_bound_vars().expect("expected fn type");
+
+        self.demand_eqtype(pat.span, expected, pat_ty);
+
         // Type check subpatterns.
         if subpats.len() == variant.fields.len() ||
                 subpats.len() < variant.fields.len() && ddpos.is_some() {
index 3156458b4aa4abe0690057c9cbfccfadb98e72a0..84967aaf72f5797cf034129985d507d607760554 100644 (file)
@@ -292,7 +292,8 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
             "unchecked_div" | "unchecked_rem" | "exact_div" =>
                 (1, vec![param(0), param(0)], param(0)),
-            "unchecked_shl" | "unchecked_shr" =>
+            "unchecked_shl" | "unchecked_shr" |
+            "rotate_left" | "rotate_right" =>
                 (1, vec![param(0), param(0)], param(0)),
 
             "overflowing_add" | "overflowing_sub" | "overflowing_mul" =>
index 266b9e3c0abad33bf63ff5b9f455e98907d1c2dc..8574443190d7c7a2d6a70f8737e3b1b7565de272 100644 (file)
@@ -28,9 +28,9 @@
 use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use rustc::hir;
 
-/// Helper type of a temporary returned by .for_item(...).
+/// Helper type of a temporary returned by `.for_item(...)`.
 /// Necessary because we can't write the following bound:
-/// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(FnCtxt<'b, 'gcx, 'tcx>).
+/// `F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(FnCtxt<'b, 'gcx, 'tcx>)`.
 struct CheckWfFcxBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     inherited: super::InheritedBuilder<'a, 'gcx, 'tcx>,
     id: ast::NodeId,
@@ -186,6 +186,8 @@ fn check_associated_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                    item_id: ast::NodeId,
                                    span: Span,
                                    sig_if_method: Option<&hir::MethodSig>) {
+    debug!("check_associated_item: {:?}", item_id);
+
     let code = ObligationCauseCode::MiscObligation;
     for_id(tcx, item_id, span).with_fcx(|fcx, tcx| {
         let item = fcx.tcx.associated_item(fcx.tcx.hir.local_def_id(item_id));
@@ -311,6 +313,8 @@ fn check_type_defn<'a, 'tcx, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 }
 
 fn check_trait<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, item: &hir::Item) {
+    debug!("check_trait: {:?}", item.id);
+
     let trait_def_id = tcx.hir.local_def_id(item.id);
 
     let trait_def = tcx.trait_def(trait_def_id);
@@ -1012,7 +1016,7 @@ fn impl_implied_bounds(&self, impl_def_id: DefId, span: Span) -> Vec<Ty<'tcx>> {
             }
 
             None => {
-                // Inherent impl: take implied bounds from the self type.
+                // Inherent impl: take implied bounds from the `self` type.
                 let self_ty = self.tcx.type_of(impl_def_id);
                 let self_ty = self.normalize_associated_types_in(span, &self_ty);
                 vec![self_ty]
index be09cfce8cae6424ad9dc1fbde3ba554e211f3db..d5f5cbb562e78514581bea80c91fc6e1237add51 100644 (file)
@@ -1978,9 +1978,9 @@ pub enum SizedByDefault {
     No,
 }
 
-/// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or
-/// a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the
-/// built-in trait (formerly known as kind): Send.
+/// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped `Ty`
+/// or a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the
+/// built-in trait `Send`.
 pub fn compute_bounds<'gcx: 'tcx, 'tcx>(
     astconv: &dyn AstConv<'gcx, 'tcx>,
     param_ty: Ty<'tcx>,
@@ -1988,8 +1988,8 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(
     sized_by_default: SizedByDefault,
     span: Span,
 ) -> Bounds<'tcx> {
-    let mut region_bounds = vec![];
-    let mut trait_bounds = vec![];
+    let mut region_bounds = Vec::new();
+    let mut trait_bounds = Vec::new();
 
     for ast_bound in ast_bounds {
         match *ast_bound {
@@ -1999,7 +1999,7 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(
         }
     }
 
-    let mut projection_bounds = vec![];
+    let mut projection_bounds = Vec::new();
 
     let mut trait_bounds: Vec<_> = trait_bounds.iter().map(|&bound| {
         (astconv.instantiate_poly_trait_ref(bound, param_ty, &mut projection_bounds), bound.span)
index c81aea2465b7be40b39d5840be6c07bbeb915061..a985c3e9fdf449bfc8b57664c867ef065d1025f6 100644 (file)
@@ -4909,4 +4909,5 @@ fn is_null(self: *const Self) -> bool {
     E0641, // cannot cast to/from a pointer with an unknown kind
     E0645, // trait aliases not finished
     E0698, // type inside generator must be known in this context
+    E0719, // duplicate values for associated type binding
 }
index d748d93d8988e63470b142ac6381cf7f01f9285b..6ed59837eb49a2c23a709491a25918c5e49d4c03 100644 (file)
@@ -11,6 +11,7 @@
 use rustc::ty::outlives::Component;
 use rustc::ty::subst::{Kind, UnpackedKind};
 use rustc::ty::{self, Region, RegionKind, Ty, TyCtxt};
+use smallvec::smallvec;
 use std::collections::BTreeSet;
 
 /// Tracks the `T: 'a` or `'a: 'a` predicates that we have inferred
@@ -40,7 +41,9 @@ pub fn insert_outlives_predicate<'tcx>(
             //
             // Or if within `struct Foo<U>` you had `T = Vec<U>`, then
             // we would want to add `U: 'outlived_region`
-            for component in tcx.outlives_components(ty) {
+            let mut components = smallvec![];
+            tcx.push_outlives_components(ty, &mut components);
+            for component in components {
                 match component {
                     Component::Region(r) => {
                         // This would arise from something like:
index c39b71e33ca0cecfe1491bcead121dd6e4c5f472..5a020749f3577d4b2eaaf351d13ced1a26bb612d 100644 (file)
@@ -3499,13 +3499,16 @@ fn clean(&self, cx: &DocContext) -> Vec<Item> {
         // forcefully don't inline if this is not public or if the
         // #[doc(no_inline)] attribute is present.
         // Don't inline doc(hidden) imports so they can be stripped at a later stage.
-        let denied = !self.vis.node.is_pub() || self.attrs.iter().any(|a| {
+        let mut denied = !self.vis.node.is_pub() || self.attrs.iter().any(|a| {
             a.name() == "doc" && match a.meta_item_list() {
                 Some(l) => attr::list_contains_name(&l, "no_inline") ||
                            attr::list_contains_name(&l, "hidden"),
                 None => false,
             }
         });
+        // Also check whether imports were asked to be inlined, in case we're trying to re-export a
+        // crate in Rust 2018+
+        let please_inline = self.attrs.lists("doc").has_word("inline");
         let path = self.path.clean(cx);
         let inner = if self.glob {
             if !denied {
@@ -3518,6 +3521,16 @@ fn clean(&self, cx: &DocContext) -> Vec<Item> {
             Import::Glob(resolve_use_source(cx, path))
         } else {
             let name = self.name;
+            if !please_inline {
+                match path.def {
+                    Def::Mod(did) => if !did.is_local() && did.index == CRATE_DEF_INDEX {
+                        // if we're `pub use`ing an extern crate root, don't inline it unless we
+                        // were specifically asked for it
+                        denied = true;
+                    }
+                    _ => {}
+                }
+            }
             if !denied {
                 let mut visited = FxHashSet::default();
                 if let Some(items) = inline::try_inline(cx, path.def, name, &mut visited) {
index 903aafed64116db84093377ec9f96d0dfd138ff8..7dafe67485a6e92d86f2972fb34571a874a8aeec 100644 (file)
@@ -29,6 +29,7 @@
 use externalfiles::ExternalHtml;
 use html;
 use html::markdown::IdMap;
+use html::static_files;
 use opts;
 use passes::{self, DefaultPassOption};
 use theme;
@@ -261,7 +262,7 @@ pub fn from_matches(matches: &getopts::Matches) -> Result<Options, isize> {
 
         let to_check = matches.opt_strs("theme-checker");
         if !to_check.is_empty() {
-            let paths = theme::load_css_paths(include_bytes!("html/static/themes/light.css"));
+            let paths = theme::load_css_paths(static_files::themes::LIGHT.as_bytes());
             let mut errors = 0;
 
             println!("rustdoc: [theme-checker] Starting tests!");
@@ -338,7 +339,7 @@ pub fn from_matches(matches: &getopts::Matches) -> Result<Options, isize> {
 
         let mut themes = Vec::new();
         if matches.opt_present("themes") {
-            let paths = theme::load_css_paths(include_bytes!("html/static/themes/light.css"));
+            let paths = theme::load_css_paths(static_files::themes::LIGHT.as_bytes());
 
             for (theme_file, theme_s) in matches.opt_strs("themes")
                                                 .iter()
index efd71ad0763e0e61abcbeb638f1e15c6118952d7..f560350d5105d6298de6fada8d39894894cd1ca0 100644 (file)
@@ -76,7 +76,7 @@
 use html::format::fmt_impl_for_trait_page;
 use html::item_type::ItemType;
 use html::markdown::{self, Markdown, MarkdownHtml, MarkdownSummaryLine, ErrorCodes, IdMap};
-use html::{highlight, layout};
+use html::{highlight, layout, static_files};
 
 use minifier;
 
@@ -767,10 +767,10 @@ fn write_shared(
     // overwrite them anyway to make sure that they're fresh and up-to-date.
 
     write_minify(cx.dst.join(&format!("rustdoc{}.css", cx.shared.resource_suffix)),
-                 include_str!("static/rustdoc.css"),
+                 static_files::RUSTDOC_CSS,
                  options.enable_minification)?;
     write_minify(cx.dst.join(&format!("settings{}.css", cx.shared.resource_suffix)),
-                 include_str!("static/settings.css"),
+                 static_files::SETTINGS_CSS,
                  options.enable_minification)?;
 
     // To avoid "light.css" to be overwritten, we'll first run over the received themes and only
@@ -790,15 +790,15 @@ fn write_shared(
     }
 
     write(cx.dst.join(&format!("brush{}.svg", cx.shared.resource_suffix)),
-          include_bytes!("static/brush.svg"))?;
+          static_files::BRUSH_SVG)?;
     write(cx.dst.join(&format!("wheel{}.svg", cx.shared.resource_suffix)),
-          include_bytes!("static/wheel.svg"))?;
+          static_files::WHEEL_SVG)?;
     write_minify(cx.dst.join(&format!("light{}.css", cx.shared.resource_suffix)),
-                 include_str!("static/themes/light.css"),
+                 static_files::themes::LIGHT,
                  options.enable_minification)?;
     themes.insert("light".to_owned());
     write_minify(cx.dst.join(&format!("dark{}.css", cx.shared.resource_suffix)),
-                 include_str!("static/themes/dark.css"),
+                 static_files::themes::DARK,
                  options.enable_minification)?;
     themes.insert("dark".to_owned());
 
@@ -854,16 +854,16 @@ fn write_shared(
     )?;
 
     write_minify(cx.dst.join(&format!("main{}.js", cx.shared.resource_suffix)),
-                 include_str!("static/main.js"),
+                 static_files::MAIN_JS,
                  options.enable_minification)?;
     write_minify(cx.dst.join(&format!("settings{}.js", cx.shared.resource_suffix)),
-                 include_str!("static/settings.js"),
+                 static_files::SETTINGS_JS,
                  options.enable_minification)?;
 
     {
         let mut data = format!("var resourcesSuffix = \"{}\";\n",
                                cx.shared.resource_suffix);
-        data.push_str(include_str!("static/storage.js"));
+        data.push_str(static_files::STORAGE_JS);
         write_minify(cx.dst.join(&format!("storage{}.js", cx.shared.resource_suffix)),
                      &data,
                      options.enable_minification)?;
@@ -882,36 +882,36 @@ fn write_shared(
         }
     }
     write_minify(cx.dst.join(&format!("normalize{}.css", cx.shared.resource_suffix)),
-                 include_str!("static/normalize.css"),
+                 static_files::NORMALIZE_CSS,
                  options.enable_minification)?;
     write(cx.dst.join("FiraSans-Regular.woff"),
-          include_bytes!("static/FiraSans-Regular.woff"))?;
+          static_files::fira_sans::REGULAR)?;
     write(cx.dst.join("FiraSans-Medium.woff"),
-          include_bytes!("static/FiraSans-Medium.woff"))?;
+          static_files::fira_sans::MEDIUM)?;
     write(cx.dst.join("FiraSans-LICENSE.txt"),
-          include_bytes!("static/FiraSans-LICENSE.txt"))?;
+          static_files::fira_sans::LICENSE)?;
     write(cx.dst.join("Heuristica-Italic.woff"),
-          include_bytes!("static/Heuristica-Italic.woff"))?;
+          static_files::heuristica::ITALIC)?;
     write(cx.dst.join("Heuristica-LICENSE.txt"),
-          include_bytes!("static/Heuristica-LICENSE.txt"))?;
+          static_files::heuristica::LICENSE)?;
     write(cx.dst.join("SourceSerifPro-Regular.woff"),
-          include_bytes!("static/SourceSerifPro-Regular.woff"))?;
+          static_files::source_serif_pro::REGULAR)?;
     write(cx.dst.join("SourceSerifPro-Bold.woff"),
-          include_bytes!("static/SourceSerifPro-Bold.woff"))?;
+          static_files::source_serif_pro::BOLD)?;
     write(cx.dst.join("SourceSerifPro-LICENSE.txt"),
-          include_bytes!("static/SourceSerifPro-LICENSE.txt"))?;
+          static_files::source_serif_pro::LICENSE)?;
     write(cx.dst.join("SourceCodePro-Regular.woff"),
-          include_bytes!("static/SourceCodePro-Regular.woff"))?;
+          static_files::source_code_pro::REGULAR)?;
     write(cx.dst.join("SourceCodePro-Semibold.woff"),
-          include_bytes!("static/SourceCodePro-Semibold.woff"))?;
+          static_files::source_code_pro::SEMIBOLD)?;
     write(cx.dst.join("SourceCodePro-LICENSE.txt"),
-          include_bytes!("static/SourceCodePro-LICENSE.txt"))?;
+          static_files::source_code_pro::LICENSE)?;
     write(cx.dst.join("LICENSE-MIT.txt"),
-          include_bytes!("static/LICENSE-MIT.txt"))?;
+          static_files::LICENSE_MIT)?;
     write(cx.dst.join("LICENSE-APACHE.txt"),
-          include_bytes!("static/LICENSE-APACHE.txt"))?;
+          static_files::LICENSE_APACHE)?;
     write(cx.dst.join("COPYRIGHT.txt"),
-          include_bytes!("static/COPYRIGHT.txt"))?;
+          static_files::COPYRIGHT)?;
 
     fn collect(path: &Path, krate: &str, key: &str) -> io::Result<(Vec<String>, Vec<String>)> {
         let mut ret = Vec::new();
index 374e11c29a5174e3b7f39192b96a5d386b9bc546..0f9104f91b4c028c94a34542303bdd15c9121417 100644 (file)
@@ -70,7 +70,7 @@
 /* General structure and fonts */
 
 body {
-       font: 16px/1.4 "Source Serif Pro", Georgia, Times, "Times New Roman", serif;
+       font: 16px/1.4 "Source Serif Pro", serif;
        margin: 0;
        position: relative;
        padding: 10px 15px 20px 15px;
@@ -114,7 +114,7 @@ h3.impl, h3.method, h3.type {
 h1, h2, h3, h4,
 .sidebar, a.source, .search-input, .content table :not(code)>a,
 .collapse-toggle, div.item-list .out-of-band {
-       font-family: "Fira Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
+       font-family: "Fira Sans", sans-serif;
 }
 
 ol, ul {
@@ -133,7 +133,7 @@ summary {
 }
 
 code, pre {
-       font-family: "Source Code Pro", Menlo, Monaco, Consolas, "DejaVu Sans Mono", Inconsolata, monospace;
+       font-family: "Source Code Pro", monospace;
        white-space: pre-wrap;
 }
 .docblock code, .docblock-short code {
@@ -420,7 +420,7 @@ h4 > code, h3 > code, .invisible > code {
 }
 #main > .since {
        top: inherit;
-       font-family: "Fira Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
+       font-family: "Fira Sans", sans-serif;
 }
 
 .content table:not(.table-display) {
@@ -1343,7 +1343,7 @@ h3.important {
 kbd {
        display: inline-block;
        padding: 3px 5px;
-       font: 15px "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
+       font: 15px monospace;
        line-height: 10px;
        vertical-align: middle;
        border: solid 1px;
diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs
new file mode 100644 (file)
index 0000000..3baa082
--- /dev/null
@@ -0,0 +1,111 @@
+// 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.
+
+//! Static files bundled with documentation output.
+//!
+//! All the static files are included here for centralized access in case anything other than the
+//! HTML rendering code (say, the theme checker) needs to access one of these files.
+//!
+//! Note about types: CSS and JavaScript files are included as `&'static str` to allow for the
+//! minifier to run on them. All other files are included as `&'static [u8]` so they can be
+//! directly written to a `Write` handle.
+
+/// The file contents of the main `rustdoc.css` file, responsible for the core layout of the page.
+pub static RUSTDOC_CSS: &'static str = include_str!("static/rustdoc.css");
+
+/// The file contents of `settings.css`, responsible for the items on the settings page.
+pub static SETTINGS_CSS: &'static str = include_str!("static/settings.css");
+
+/// The file contents of `normalize.css`, included to even out standard elements between browser
+/// implementations.
+pub static NORMALIZE_CSS: &'static str = include_str!("static/normalize.css");
+
+/// The file contents of `main.js`, which contains the core JavaScript used on documentation pages,
+/// including search behavior and docblock folding, among others.
+pub static MAIN_JS: &'static str = include_str!("static/main.js");
+
+/// The file contents of `settings.js`, which contains the JavaScript used to handle the settings
+/// page.
+pub static SETTINGS_JS: &'static str = include_str!("static/settings.js");
+
+/// The file contents of `storage.js`, which contains functionality related to browser Local
+/// Storage, used to store documentation settings.
+pub static STORAGE_JS: &'static str = include_str!("static/storage.js");
+
+/// The file contents of `brush.svg`, the icon used for the theme-switch button.
+pub static BRUSH_SVG: &'static [u8] = include_bytes!("static/brush.svg");
+
+/// The file contents of `wheel.svg`, the icon used for the settings button.
+pub static WHEEL_SVG: &'static [u8] = include_bytes!("static/wheel.svg");
+
+/// The contents of `COPYRIGHT.txt`, the license listing for files distributed with documentation
+/// output.
+pub static COPYRIGHT: &'static [u8] = include_bytes!("static/COPYRIGHT.txt");
+
+/// The contents of `LICENSE-APACHE.txt`, the text of the Apache License, version 2.0.
+pub static LICENSE_APACHE: &'static [u8] = include_bytes!("static/LICENSE-APACHE.txt");
+
+/// The contents of `LICENSE-MIT.txt`, the text of the MIT License.
+pub static LICENSE_MIT: &'static [u8] = include_bytes!("static/LICENSE-MIT.txt");
+
+/// The built-in themes given to every documentation site.
+pub mod themes {
+    /// The "light" theme, selected by default when no setting is available. Used as the basis for
+    /// the `--theme-checker` functionality.
+    pub static LIGHT: &'static str = include_str!("static/themes/light.css");
+
+    /// The "dark" theme.
+    pub static DARK: &'static str = include_str!("static/themes/dark.css");
+}
+
+/// Files related to the Fira Sans font.
+pub mod fira_sans {
+    /// The file `FiraSans-Regular.woff`, the Regular variant of the Fira Sans font.
+    pub static REGULAR: &'static [u8] = include_bytes!("static/FiraSans-Regular.woff");
+
+    /// The file `FiraSans-Medium.woff`, the Medium variant of the Fira Sans font.
+    pub static MEDIUM: &'static [u8] = include_bytes!("static/FiraSans-Medium.woff");
+
+    /// The file `FiraSans-LICENSE.txt`, the license text for the Fira Sans font.
+    pub static LICENSE: &'static [u8] = include_bytes!("static/FiraSans-LICENSE.txt");
+}
+
+/// Files related to the Heuristica font.
+pub mod heuristica {
+    /// The file `Heuristica-Italic.woff`, the Italic variant of the Heuristica font.
+    pub static ITALIC: &'static [u8] = include_bytes!("static/Heuristica-Italic.woff");
+
+    /// The file `Heuristica-LICENSE.txt`, the license text for the Heuristica font.
+    pub static LICENSE: &'static [u8] = include_bytes!("static/Heuristica-LICENSE.txt");
+}
+
+/// Files related to the Source Serif Pro font.
+pub mod source_serif_pro {
+    /// The file `SourceSerifPro-Regular.woff`, the Regular variant of the Source Serif Pro font.
+    pub static REGULAR: &'static [u8] = include_bytes!("static/SourceSerifPro-Regular.woff");
+
+    /// The file `SourceSerifPro-Bold.woff`, the Bold variant of the Source Serif Pro font.
+    pub static BOLD: &'static [u8] = include_bytes!("static/SourceSerifPro-Bold.woff");
+
+    /// The file `SourceSerifPro-LICENSE.txt`, the license text for the Source Serif Pro font.
+    pub static LICENSE: &'static [u8] = include_bytes!("static/SourceSerifPro-LICENSE.txt");
+}
+
+/// Files related to the Source Code Pro font.
+pub mod source_code_pro {
+    /// The file `SourceCodePro-Regular.woff`, the Regular variant of the Source Code Pro font.
+    pub static REGULAR: &'static [u8] = include_bytes!("static/SourceCodePro-Regular.woff");
+
+    /// The file `SourceCodePro-Semibold.woff`, the Semibold variant of the Source Code Pro font.
+    pub static SEMIBOLD: &'static [u8] = include_bytes!("static/SourceCodePro-Semibold.woff");
+
+    /// The file `SourceCodePro-LICENSE.txt`, the license text of the Source Code Pro font.
+    pub static LICENSE: &'static [u8] = include_bytes!("static/SourceCodePro-LICENSE.txt");
+}
index f0f36f0355ed6bef960b767854a52b5b8abf9fae..4b043b26d8650d6a6149062d13cd202979e48000 100644 (file)
@@ -78,6 +78,7 @@ pub mod html {
     crate mod layout;
     pub mod markdown;
     crate mod render;
+    crate mod static_files;
     crate mod toc;
 }
 mod markdown;
index 0f22459b34349fe79a22a8a3f9e5a33e4aa03cf7..2b1d515c83b75a4d0090bc519a4d5104f09a82fc 100644 (file)
@@ -14,7 +14,6 @@ crate-type = ["dylib", "rlib"]
 
 [dependencies]
 alloc = { path = "../liballoc" }
-alloc_system = { path = "../liballoc_system" }
 panic_unwind = { path = "../libpanic_unwind", optional = true }
 panic_abort = { path = "../libpanic_abort" }
 core = { path = "../libcore" }
@@ -36,6 +35,9 @@ rustc_lsan = { path = "../librustc_lsan" }
 rustc_msan = { path = "../librustc_msan" }
 rustc_tsan = { path = "../librustc_tsan" }
 
+[target.'cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))'.dependencies]
+dlmalloc = { path = '../rustc/dlmalloc_shim' }
+
 [build-dependencies]
 cc = "1.0"
 build_helper = { path = "../build_helper" }
index 1ff342fa7a7bea25213c1bb5bf4d4ea8a374dc90..485b2ffe1975ed5c5973066ceb1df9d6b9d8efac 100644 (file)
 
 use core::sync::atomic::{AtomicPtr, Ordering};
 use core::{mem, ptr};
+use core::ptr::NonNull;
 use sys_common::util::dumb_print;
 
 #[stable(feature = "alloc_module", since = "1.28.0")]
 #[doc(inline)]
 pub use alloc_crate::alloc::*;
 
+/// The default memory allocator provided by the operating system.
+///
+/// This is based on `malloc` on Unix platforms and `HeapAlloc` on Windows,
+/// plus related functions.
+///
+/// This type implements the `GlobalAlloc` trait and Rust programs by deafult
+/// work as if they had this definition:
+///
+/// ```rust
+/// use std::alloc::System;
+///
+/// #[global_allocator]
+/// static A: System = System;
+///
+/// fn main() {
+///     let a = Box::new(4); // Allocates from the system allocator.
+///     println!("{}", a);
+/// }
+/// ```
+///
+/// You can also define your own wrapper around `System` if you'd like, such as
+/// keeping track of the number of all bytes allocated:
+///
+/// ```rust
+/// use std::alloc::{System, GlobalAlloc, Layout};
+/// use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering::SeqCst};
+///
+/// struct Counter;
+///
+/// static ALLOCATED: AtomicUsize = ATOMIC_USIZE_INIT;
+///
+/// unsafe impl GlobalAlloc for Counter {
+///     unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
+///         let ret = System.alloc(layout);
+///         if !ret.is_null() {
+///             ALLOCATED.fetch_add(layout.size(), SeqCst);
+///         }
+///         return ret
+///     }
+///
+///     unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
+///         System.dealloc(ptr, layout);
+///         ALLOCATED.fetch_sub(layout.size(), SeqCst);
+///     }
+/// }
+///
+/// #[global_allocator]
+/// static A: Counter = Counter;
+///
+/// fn main() {
+///     println!("allocated bytes before main: {}", ALLOCATED.load(SeqCst));
+/// }
+/// ```
+///
+/// It can also be used directly to allocate memory independently of whatever
+/// global allocator has been selected for a Rust program. For example if a Rust
+/// program opts in to using jemalloc as the global allocator, `System` will
+/// still allocate memory using `malloc` and `HeapAlloc`.
 #[stable(feature = "alloc_system_type", since = "1.28.0")]
-#[doc(inline)]
-pub use alloc_system::System;
+#[derive(Debug, Copy, Clone)]
+pub struct System;
+
+#[unstable(feature = "allocator_api", issue = "32838")]
+unsafe impl Alloc for System {
+    #[inline]
+    unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
+        NonNull::new(GlobalAlloc::alloc(self, layout)).ok_or(AllocErr)
+    }
+
+    #[inline]
+    unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> {
+        NonNull::new(GlobalAlloc::alloc_zeroed(self, layout)).ok_or(AllocErr)
+    }
+
+    #[inline]
+    unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) {
+        GlobalAlloc::dealloc(self, ptr.as_ptr(), layout)
+    }
+
+    #[inline]
+    unsafe fn realloc(&mut self,
+                      ptr: NonNull<u8>,
+                      layout: Layout,
+                      new_size: usize) -> Result<NonNull<u8>, AllocErr> {
+        NonNull::new(GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size)).ok_or(AllocErr)
+    }
+}
 
 static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut());
 
index dfec13cd2ec007e74d4d0a1f9447b602890b1d34..66718b95408ca160f90bb3fd6f40506addc8a1be 100644 (file)
@@ -1091,7 +1091,7 @@ pub fn from_bytes_with_nul(bytes: &[u8])
     /// [`CString`]: struct.CString.html
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn as_ptr(&self) -> *const c_char {
+    pub const fn as_ptr(&self) -> *const c_char {
         self.inner.as_ptr()
     }
 
@@ -1178,7 +1178,7 @@ pub fn to_str(&self) -> Result<&str, str::Utf8Error> {
     ///
     /// If the contents of the `CStr` are valid UTF-8 data, this
     /// function will return a [`Cow`]`::`[`Borrowed`]`(`[`&str`]`)`
-    /// with the the corresponding [`&str`] slice. Otherwise, it will
+    /// with the corresponding [`&str`] slice. Otherwise, it will
     /// replace any invalid UTF-8 sequences with
     /// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD] and return a
     /// [`Cow`]`::`[`Owned`]`(`[`String`]`)` with the result.
index f27beb0b46cafd9fe47b98bc909fb962b4ffac61..f460d109c894a50b4f12ff30c27982c90a80891d 100644 (file)
 #![cfg_attr(test, feature(test, update_panic_count))]
 #![feature(alloc)]
 #![feature(alloc_error_handler)]
-#![feature(alloc_system)]
 #![feature(allocator_api)]
 #![feature(allocator_internals)]
 #![feature(allow_internal_unsafe)]
 
 #[cfg(stage0)]
 #[global_allocator]
-static ALLOC: alloc_system::System = alloc_system::System;
+static ALLOC: alloc::System = alloc::System;
 
 // Explicitly import the prelude. The compiler uses this same unstable attribute
 // to import the prelude implicitly when building crates that depend on std.
 #[allow(unused_imports)] // macros from `alloc` are not used on all platforms
 #[macro_use]
 extern crate alloc as alloc_crate;
-extern crate alloc_system;
 #[doc(masked)]
 extern crate libc;
 
@@ -495,7 +493,7 @@ pub mod task {
 // compiler
 pub mod rt;
 
-// Pull in the the `stdsimd` crate directly into libstd. This is the same as
+// Pull in the `stdsimd` crate directly into libstd. This is the same as
 // libcore's arch/simd modules where the source of truth here is in a different
 // repository, but we pull things in here manually to get it into libstd.
 //
index 34bbbb53d5ff1c1eaa86b0d9713464565098bf76..96c92ceb5bb4127052b311a03b2ed4b5b86f6625 100644 (file)
@@ -399,6 +399,8 @@ macro_rules! await {
 /// For more information about select, see the `std::sync::mpsc::Select` structure.
 #[macro_export]
 #[unstable(feature = "mpsc_select", issue = "27800")]
+#[rustc_deprecated(since = "1.32.0",
+                   reason = "channel selection will be removed in a future release")]
 macro_rules! select {
     (
         $($name:pat = $rx:ident.$meth:ident() => $code:expr),+
index d45a66ef6653257455594c7239fe002bc91acbb9..2517c45696a2db4875c82fcf8d05b87b3800cf9e 100644 (file)
@@ -424,7 +424,7 @@ pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
     /// assert_eq!(Ipv4Addr::new(45, 22, 13, 197).is_unspecified(), false);
     /// ```
     #[stable(feature = "ip_shared", since = "1.12.0")]
-    pub fn is_unspecified(&self) -> bool {
+    pub const fn is_unspecified(&self) -> bool {
         self.inner.s_addr == 0
     }
 
@@ -862,7 +862,6 @@ impl Ipv6Addr {
     /// let addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_unstable(feature = "const_ip")]
     pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16,
                      g: u16, h: u16) -> Ipv6Addr {
         Ipv6Addr {
@@ -1224,7 +1223,7 @@ pub fn to_ipv4(&self) -> Option<Ipv4Addr> {
     ///            [255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
     /// ```
     #[stable(feature = "ipv6_to_octets", since = "1.12.0")]
-    pub fn octets(&self) -> [u8; 16] {
+    pub const fn octets(&self) -> [u8; 16] {
         self.inner.s6_addr
     }
 }
index a9219f75362db4dddb74cb879b98b305d05d5731..327ad7f64c23f299bc36b0d38563f2996547281c 100644 (file)
@@ -764,14 +764,15 @@ pub fn spawn(&mut self) -> io::Result<Child> {
     ///
     /// ```should_panic
     /// use std::process::Command;
+    /// use std::io::{self, Write};
     /// let output = Command::new("/bin/cat")
     ///                      .arg("file.txt")
     ///                      .output()
     ///                      .expect("failed to execute process");
     ///
     /// println!("status: {}", output.status);
-    /// println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
-    /// println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
+    /// io::stdout().write_all(&output.stdout).unwrap();
+    /// io::stderr().write_all(&output.stderr).unwrap();
     ///
     /// assert!(output.status.success());
     /// ```
@@ -951,6 +952,7 @@ pub fn piped() -> Stdio { Stdio(imp::Stdio::MakePipe) }
     ///
     /// ```no_run
     /// use std::process::{Command, Stdio};
+    /// use std::io::{self, Write};
     ///
     /// let output = Command::new("rev")
     ///     .stdin(Stdio::inherit())
@@ -958,7 +960,8 @@ pub fn piped() -> Stdio { Stdio(imp::Stdio::MakePipe) }
     ///     .output()
     ///     .expect("Failed to execute command");
     ///
-    /// println!("You piped in the reverse of: {}", String::from_utf8_lossy(&output.stdout));
+    /// print!("You piped in the reverse of: ");
+    /// io::stdout().write_all(&output.stdout).unwrap();
     /// ```
     #[stable(feature = "process", since = "1.0.0")]
     pub fn inherit() -> Stdio { Stdio(imp::Stdio::Inherit) }
index 81f98a55c117149bd5bfe8aa0e9f3d907853eb81..059ced4f56efda5f3fea5e7ebcc63681d8d4f698 100644 (file)
 //! ```
 
 #![stable(feature = "rust1", since = "1.0.0")]
+#![allow(deprecated)] // for mpsc_select
 
 // A description of how Rust's channel implementation works
 //
index a7a284cfb7994a766b1d3781c9d5b34e22effdec..2ec4b52dbf3cba3153f9db2721f227465a7a24a4 100644 (file)
 #![unstable(feature = "mpsc_select",
             reason = "This implementation, while likely sufficient, is unsafe and \
                       likely to be error prone. At some point in the future this \
-                      module will likely be replaced, and it is currently \
-                      unknown how much API breakage that will cause. The ability \
-                      to select over a number of channels will remain forever, \
-                      but no guarantees beyond this are being made",
+                      module will be removed.",
             issue = "27800")]
+#![rustc_deprecated(since = "1.32.0",
+                    reason = "channel selection will be removed in a future release")]
 
 
 use fmt;
index 9e943c17fc85f788f9ebbc4656778a4ef50c9c33..dfb56472c6c83a90d1223339fd82a86443577c8a 100644 (file)
@@ -12,6 +12,8 @@
 use libc;
 use mem;
 
+#[path = "../unix/alloc.rs"]
+pub mod alloc;
 pub mod args;
 #[cfg(feature = "backtrace")]
 pub mod backtrace;
index f943257c687330c368622f087e42bde74c625f45..edb407ecd23ce6af9ce6497eb790e34c674659fc 100644 (file)
@@ -15,6 +15,8 @@
 pub use libc::strlen;
 pub use self::rand::hashmap_random_keys;
 
+#[path = "../unix/alloc.rs"]
+pub mod alloc;
 pub mod args;
 #[cfg(feature = "backtrace")]
 pub mod backtrace;
diff --git a/src/libstd/sys/unix/alloc.rs b/src/libstd/sys/unix/alloc.rs
new file mode 100644 (file)
index 0000000..2a7f193
--- /dev/null
@@ -0,0 +1,100 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use ptr;
+use libc;
+use sys_common::alloc::{MIN_ALIGN, realloc_fallback};
+use alloc::{GlobalAlloc, Layout, System};
+
+#[stable(feature = "alloc_system_type", since = "1.28.0")]
+unsafe impl GlobalAlloc for System {
+    #[inline]
+    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
+        if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
+            libc::malloc(layout.size()) as *mut u8
+        } else {
+            #[cfg(target_os = "macos")]
+            {
+                if layout.align() > (1 << 31) {
+                    return ptr::null_mut()
+                }
+            }
+            aligned_malloc(&layout)
+        }
+    }
+
+    #[inline]
+    unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
+        if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
+            libc::calloc(layout.size(), 1) as *mut u8
+        } else {
+            let ptr = self.alloc(layout.clone());
+            if !ptr.is_null() {
+                ptr::write_bytes(ptr, 0, layout.size());
+            }
+            ptr
+        }
+    }
+
+    #[inline]
+    unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
+        libc::free(ptr as *mut libc::c_void)
+    }
+
+    #[inline]
+    unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
+        if layout.align() <= MIN_ALIGN && layout.align() <= new_size {
+            libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8
+        } else {
+            realloc_fallback(self, ptr, layout, new_size)
+        }
+    }
+}
+
+#[cfg(any(target_os = "android",
+          target_os = "hermit",
+          target_os = "redox",
+          target_os = "solaris"))]
+#[inline]
+unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
+    // On android we currently target API level 9 which unfortunately
+    // doesn't have the `posix_memalign` API used below. Instead we use
+    // `memalign`, but this unfortunately has the property on some systems
+    // where the memory returned cannot be deallocated by `free`!
+    //
+    // Upon closer inspection, however, this appears to work just fine with
+    // Android, so for this platform we should be fine to call `memalign`
+    // (which is present in API level 9). Some helpful references could
+    // possibly be chromium using memalign [1], attempts at documenting that
+    // memalign + free is ok [2] [3], or the current source of chromium
+    // which still uses memalign on android [4].
+    //
+    // [1]: https://codereview.chromium.org/10796020/
+    // [2]: https://code.google.com/p/android/issues/detail?id=35391
+    // [3]: https://bugs.chromium.org/p/chromium/issues/detail?id=138579
+    // [4]: https://chromium.googlesource.com/chromium/src/base/+/master/
+    //                                       /memory/aligned_memory.cc
+    libc::memalign(layout.align(), layout.size()) as *mut u8
+}
+
+#[cfg(not(any(target_os = "android",
+              target_os = "hermit",
+              target_os = "redox",
+              target_os = "solaris")))]
+#[inline]
+unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
+    let mut out = ptr::null_mut();
+    let ret = libc::posix_memalign(&mut out, layout.align(), layout.size());
+    if ret != 0 {
+        ptr::null_mut()
+    } else {
+        out as *mut u8
+    }
+}
index 17214be5b054957da532e8d555f447bf252b349e..e8101bd0bc96452a9efe395097509a24fb989f92 100644 (file)
@@ -36,6 +36,7 @@
 #[macro_use]
 pub mod weak;
 
+pub mod alloc;
 pub mod args;
 pub mod android;
 #[cfg(feature = "backtrace")]
diff --git a/src/libstd/sys/wasm/alloc.rs b/src/libstd/sys/wasm/alloc.rs
new file mode 100644 (file)
index 0000000..0faa3c9
--- /dev/null
@@ -0,0 +1,105 @@
+// 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.
+
+//! This is an implementation of a global allocator on the wasm32 platform when
+//! emscripten is not in use. In that situation there's no actual runtime for us
+//! to lean on for allocation, so instead we provide our own!
+//!
+//! The wasm32 instruction set has two instructions for getting the current
+//! amount of memory and growing the amount of memory. These instructions are the
+//! foundation on which we're able to build an allocator, so we do so! Note that
+//! the instructions are also pretty "global" and this is the "global" allocator
+//! after all!
+//!
+//! The current allocator here is the `dlmalloc` crate which we've got included
+//! in the rust-lang/rust repository as a submodule. The crate is a port of
+//! dlmalloc.c from C to Rust and is basically just so we can have "pure Rust"
+//! for now which is currently technically required (can't link with C yet).
+//!
+//! The crate itself provides a global allocator which on wasm has no
+//! synchronization as there are no threads!
+
+extern crate dlmalloc;
+
+use alloc::{GlobalAlloc, Layout, System};
+
+static mut DLMALLOC: dlmalloc::Dlmalloc = dlmalloc::DLMALLOC_INIT;
+
+#[stable(feature = "alloc_system_type", since = "1.28.0")]
+unsafe impl GlobalAlloc for System {
+    #[inline]
+    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
+        let _lock = lock::lock();
+        DLMALLOC.malloc(layout.size(), layout.align())
+    }
+
+    #[inline]
+    unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
+        let _lock = lock::lock();
+        DLMALLOC.calloc(layout.size(), layout.align())
+    }
+
+    #[inline]
+    unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
+        let _lock = lock::lock();
+        DLMALLOC.free(ptr, layout.size(), layout.align())
+    }
+
+    #[inline]
+    unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
+        let _lock = lock::lock();
+        DLMALLOC.realloc(ptr, layout.size(), layout.align(), new_size)
+    }
+}
+
+#[cfg(target_feature = "atomics")]
+mod lock {
+    use arch::wasm32;
+    use sync::atomic::{AtomicI32, Ordering::SeqCst};
+
+    static LOCKED: AtomicI32 = AtomicI32::new(0);
+
+    pub struct DropLock;
+
+    pub fn lock() -> DropLock {
+        loop {
+            if LOCKED.swap(1, SeqCst) == 0 {
+                return DropLock
+            }
+            unsafe {
+                let r = wasm32::atomic::wait_i32(
+                    &LOCKED as *const AtomicI32 as *mut i32,
+                    1,  // expected value
+                    -1, // timeout
+                );
+                debug_assert!(r == 0 || r == 1);
+            }
+        }
+    }
+
+    impl Drop for DropLock {
+        fn drop(&mut self) {
+            let r = LOCKED.swap(0, SeqCst);
+            debug_assert_eq!(r, 1);
+            unsafe {
+                wasm32::atomic::wake(
+                    &LOCKED as *const AtomicI32 as *mut i32,
+                    1, // only one thread
+                );
+            }
+        }
+    }
+}
+
+#[cfg(not(target_feature = "atomics"))]
+mod lock {
+    #[inline]
+    pub fn lock() {} // no atomics, no threads, that's easy!
+}
index e11b4d71aaeea90cf01cee2b66eb99cc2423d90e..e8f7e32ac9177253c30c0b4d2e47c07317fe1663 100644 (file)
@@ -32,6 +32,7 @@
 use ffi::{OsString, OsStr};
 use time::Duration;
 
+pub mod alloc;
 pub mod args;
 #[cfg(feature = "backtrace")]
 pub mod backtrace;
diff --git a/src/libstd/sys/windows/alloc.rs b/src/libstd/sys/windows/alloc.rs
new file mode 100644 (file)
index 0000000..e5de3e0
--- /dev/null
@@ -0,0 +1,77 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use alloc::{GlobalAlloc, Layout, System};
+use sys::c;
+use sys_common::alloc::{MIN_ALIGN, realloc_fallback};
+
+#[repr(C)]
+struct Header(*mut u8);
+
+unsafe fn get_header<'a>(ptr: *mut u8) -> &'a mut Header {
+    &mut *(ptr as *mut Header).offset(-1)
+}
+
+unsafe fn align_ptr(ptr: *mut u8, align: usize) -> *mut u8 {
+    let aligned = ptr.add(align - (ptr as usize & (align - 1)));
+    *get_header(aligned) = Header(ptr);
+    aligned
+}
+
+#[inline]
+unsafe fn allocate_with_flags(layout: Layout, flags: c::DWORD) -> *mut u8 {
+    if layout.align() <= MIN_ALIGN {
+        return c::HeapAlloc(c::GetProcessHeap(), flags, layout.size()) as *mut u8
+    }
+
+    let size = layout.size() + layout.align();
+    let ptr = c::HeapAlloc(c::GetProcessHeap(), flags, size);
+    if ptr.is_null() {
+        ptr as *mut u8
+    } else {
+        align_ptr(ptr as *mut u8, layout.align())
+    }
+}
+
+#[stable(feature = "alloc_system_type", since = "1.28.0")]
+unsafe impl GlobalAlloc for System {
+    #[inline]
+    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
+        allocate_with_flags(layout, 0)
+    }
+
+    #[inline]
+    unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
+        allocate_with_flags(layout, c::HEAP_ZERO_MEMORY)
+    }
+
+    #[inline]
+    unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
+        if layout.align() <= MIN_ALIGN {
+            let err = c::HeapFree(c::GetProcessHeap(), 0, ptr as c::LPVOID);
+            debug_assert!(err != 0, "Failed to free heap memory: {}",
+                          c::GetLastError());
+        } else {
+            let header = get_header(ptr);
+            let err = c::HeapFree(c::GetProcessHeap(), 0, header.0 as c::LPVOID);
+            debug_assert!(err != 0, "Failed to free heap memory: {}",
+                          c::GetLastError());
+        }
+    }
+
+    #[inline]
+    unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
+        if layout.align() <= MIN_ALIGN {
+            c::HeapReAlloc(c::GetProcessHeap(), 0, ptr as c::LPVOID, new_size) as *mut u8
+        } else {
+            realloc_fallback(self, ptr, layout, new_size)
+        }
+    }
+}
index f4bd9c22bb93fc1d1637c2d8e8a0d4088cd69c4d..c84874a3e880f56dfcaa688903e9f1d75b6df379 100644 (file)
@@ -309,6 +309,8 @@ pub struct ipv6_mreq {
 
 pub const STACK_SIZE_PARAM_IS_A_RESERVATION: DWORD = 0x00010000;
 
+pub const HEAP_ZERO_MEMORY: DWORD = 0x00000008;
+
 #[repr(C)]
 #[cfg(not(target_pointer_width = "64"))]
 pub struct WSADATA {
@@ -1277,6 +1279,11 @@ pub fn select(nfds: c_int,
 
     #[link_name = "SystemFunction036"]
     pub fn RtlGenRandom(RandomBuffer: *mut u8, RandomBufferLength: ULONG) -> BOOLEAN;
+
+    pub fn GetProcessHeap() -> HANDLE;
+    pub fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> LPVOID;
+    pub fn HeapReAlloc(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID, dwBytes: SIZE_T) -> LPVOID;
+    pub fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL;
 }
 
 // Functions that aren't available on every version of Windows that we support,
index 31ef9fa2bedfd4a4a0091c661a19db158ae75c0c..f880bc8c050be28a5aa8f4f8fd4b5b28e54c5ec4 100644 (file)
@@ -22,6 +22,7 @@
 
 #[macro_use] pub mod compat;
 
+pub mod alloc;
 pub mod args;
 #[cfg(feature = "backtrace")]
 pub mod backtrace;
diff --git a/src/libstd/sys_common/alloc.rs b/src/libstd/sys_common/alloc.rs
new file mode 100644 (file)
index 0000000..439a9df
--- /dev/null
@@ -0,0 +1,50 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(dead_code)]
+
+use alloc::{GlobalAlloc, Layout, System};
+use cmp;
+use ptr;
+
+// The minimum alignment guaranteed by the architecture. This value is used to
+// add fast paths for low alignment values.
+#[cfg(all(any(target_arch = "x86",
+              target_arch = "arm",
+              target_arch = "mips",
+              target_arch = "powerpc",
+              target_arch = "powerpc64",
+              target_arch = "asmjs",
+              target_arch = "wasm32")))]
+pub const MIN_ALIGN: usize = 8;
+#[cfg(all(any(target_arch = "x86_64",
+              target_arch = "aarch64",
+              target_arch = "mips64",
+              target_arch = "s390x",
+              target_arch = "sparc64")))]
+pub const MIN_ALIGN: usize = 16;
+
+pub unsafe fn realloc_fallback(
+    alloc: &System,
+    ptr: *mut u8,
+    old_layout: Layout,
+    new_size: usize,
+) -> *mut u8 {
+    // Docs for GlobalAlloc::realloc require this to be valid:
+    let new_layout = Layout::from_size_align_unchecked(new_size, old_layout.align());
+
+    let new_ptr = GlobalAlloc::alloc(alloc, new_layout);
+    if !new_ptr.is_null() {
+        let size = cmp::min(old_layout.size(), new_size);
+        ptr::copy_nonoverlapping(ptr, new_ptr, size);
+        GlobalAlloc::dealloc(alloc, ptr, old_layout);
+    }
+    new_ptr
+}
index d0c4d6a773746e70cc175de3a0866085532d6609..4b8cde3d1f486792fa0d788ab99db674c784949a 100644 (file)
@@ -38,6 +38,7 @@ macro_rules! rtassert {
     })
 }
 
+pub mod alloc;
 pub mod at_exit_imp;
 #[cfg(feature = "backtrace")]
 pub mod backtrace;
index cfedda18a7e22886e2e972cc30d82a36157976a5..808e19d6f120f0f069f6fb5bc7a940fbffaf2db9 100644 (file)
@@ -20,6 +20,8 @@
 use ptr::P;
 use rustc_data_structures::indexed_vec;
 use rustc_data_structures::indexed_vec::Idx;
+#[cfg(target_arch = "x86_64")]
+use rustc_data_structures::static_assert;
 use rustc_target::spec::abi::Abi;
 use source_map::{dummy_spanned, respan, Spanned};
 use symbol::{keywords, Symbol};
@@ -924,6 +926,10 @@ pub struct Expr {
     pub attrs: ThinVec<Attribute>,
 }
 
+// `Expr` is used a lot. Make sure it doesn't unintentionally get bigger.
+#[cfg(target_arch = "x86_64")]
+static_assert!(MEM_SIZE_OF_EXPR: std::mem::size_of::<Expr>() == 88);
+
 impl Expr {
     /// Whether this expression would be valid somewhere that expects a value, for example, an `if`
     /// condition.
@@ -1086,7 +1092,7 @@ pub enum ExprKind {
     /// A unary operation (For example: `!x`, `*x`)
     Unary(UnOp, P<Expr>),
     /// A literal (For example: `1`, `"foo"`)
-    Lit(P<Lit>),
+    Lit(Lit),
     /// A cast (`foo as f64`)
     Cast(P<Expr>, P<Ty>),
     Type(P<Expr>, P<Ty>),
index 1701c8da2c5bdc6283b491a97c45d3b516ca046f..88ee80e60888f93a2d8cace0b01a332e29443aa5 100644 (file)
@@ -491,7 +491,7 @@ pub fn expr(sp: Span) -> Box<dyn MacResult+'static> {
     pub fn raw_expr(sp: Span) -> P<ast::Expr> {
         P(ast::Expr {
             id: ast::DUMMY_NODE_ID,
-            node: ast::ExprKind::Lit(P(source_map::respan(sp, ast::LitKind::Bool(false)))),
+            node: ast::ExprKind::Lit(source_map::respan(sp, ast::LitKind::Bool(false))),
             span: sp,
             attrs: ThinVec::new(),
         })
index 7928ec1606b1d5b986db8f9a7df31474016d851d..cacec867cf198053cc6b187d4bf9cba2db551dcb 100644 (file)
@@ -695,7 +695,7 @@ fn expr_struct_ident(&self, span: Span,
     }
 
     fn expr_lit(&self, sp: Span, lit: ast::LitKind) -> P<ast::Expr> {
-        self.expr(sp, ast::ExprKind::Lit(P(respan(sp, lit))))
+        self.expr(sp, ast::ExprKind::Lit(respan(sp, lit)))
     }
     fn expr_usize(&self, span: Span, i: usize) -> P<ast::Expr> {
         self.expr_lit(span, ast::LitKind::Int(i as u128,
index 37800a334c6daf7ca4d54efe97e76ef9fb902426..c6e0adbb5a43e087a73b867cd13843dcc1db37a5 100644 (file)
@@ -274,7 +274,7 @@ fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
             // FIXME: This is wrong
             P(ast::Expr {
                 id: ast::DUMMY_NODE_ID,
-                node: ast::ExprKind::Lit(P(self.clone())),
+                node: ast::ExprKind::Lit(self.clone()),
                 span: DUMMY_SP,
                 attrs: ThinVec::new(),
             }).to_tokens(cx)
@@ -305,7 +305,7 @@ fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
                     let lit = ast::LitKind::Int(val as u128, ast::LitIntType::Signed($tag));
                     let lit = P(ast::Expr {
                         id: ast::DUMMY_NODE_ID,
-                        node: ast::ExprKind::Lit(P(dummy_spanned(lit))),
+                        node: ast::ExprKind::Lit(dummy_spanned(lit)),
                         span: DUMMY_SP,
                         attrs: ThinVec::new(),
                     });
index 06c1d58070e21fe3524dcc9463e51cbb2e3c7d2a..7a0a764d4639ae117bc78e33ce412a8b5d5c1f9a 100644 (file)
 /// Either a sequence of token trees or a single one. This is used as the representation of the
 /// sequence of tokens that make up a matcher.
 #[derive(Clone)]
-enum TokenTreeOrTokenTreeSlice<'a> {
+enum TokenTreeOrTokenTreeSlice<'tt> {
     Tt(TokenTree),
-    TtSeq(&'a [TokenTree]),
+    TtSeq(&'tt [TokenTree]),
 }
 
-impl<'a> TokenTreeOrTokenTreeSlice<'a> {
+impl<'tt> TokenTreeOrTokenTreeSlice<'tt> {
     /// Returns the number of constituent top-level token trees of `self` (top-level in that it
     /// will not recursively descend into subtrees).
     fn len(&self) -> usize {
@@ -136,23 +136,41 @@ fn get_tt(&self, index: usize) -> TokenTree {
 /// This is used by `inner_parse_loop` to keep track of delimited submatchers that we have
 /// descended into.
 #[derive(Clone)]
-struct MatcherTtFrame<'a> {
+struct MatcherTtFrame<'tt> {
     /// The "parent" matcher that we are descending into.
-    elts: TokenTreeOrTokenTreeSlice<'a>,
+    elts: TokenTreeOrTokenTreeSlice<'tt>,
     /// The position of the "dot" in `elts` at the time we descended.
     idx: usize,
 }
 
 type NamedMatchVec = SmallVec<[NamedMatch; 4]>;
 
-/// Represents a single "position" (aka "matcher position", aka "item"), as described in the module
-/// documentation.
+/// Represents a single "position" (aka "matcher position", aka "item"), as
+/// described in the module documentation.
+///
+/// Here:
+///
+/// - `'root` represents the lifetime of the stack slot that holds the root
+///   `MatcherPos`. As described in `MatcherPosHandle`, the root `MatcherPos`
+///   structure is stored on the stack, but subsequent instances are put into
+///   the heap.
+/// - `'tt` represents the lifetime of the token trees that this matcher
+///   position refers to.
+///
+/// It is important to distinguish these two lifetimes because we have a
+/// `SmallVec<TokenTreeOrTokenTreeSlice<'tt>>` below, and the destructor of
+/// that is considered to possibly access the data from its elements (it lacks
+/// a `#[may_dangle]` attribute). As a result, the compiler needs to know that
+/// all the elements in that `SmallVec` strictly outlive the root stack slot
+/// lifetime. By separating `'tt` from `'root`, we can show that.
 #[derive(Clone)]
-struct MatcherPos<'a> {
+struct MatcherPos<'root, 'tt: 'root> {
     /// The token or sequence of tokens that make up the matcher
-    top_elts: TokenTreeOrTokenTreeSlice<'a>,
+    top_elts: TokenTreeOrTokenTreeSlice<'tt>,
+
     /// The position of the "dot" in this matcher
     idx: usize,
+
     /// The first span of source source that the beginning of this matcher corresponds to. In other
     /// words, the token in the source whose span is `sp_open` is matched against the first token of
     /// the matcher.
@@ -182,26 +200,31 @@ struct MatcherPos<'a> {
     /// in this matcher.
     match_hi: usize,
 
-    // Specifically used if we are matching a repetition. If we aren't both should be `None`.
+    // The following fields are used if we are matching a repetition. If we aren't, they should be
+    // `None`.
+
     /// The KleeneOp of this sequence if we are in a repetition.
     seq_op: Option<quoted::KleeneOp>,
-    /// The separator if we are in a repetition
+
+    /// The separator if we are in a repetition.
     sep: Option<Token>,
+
     /// The "parent" matcher position if we are in a repetition. That is, the matcher position just
     /// before we enter the sequence.
-    up: Option<MatcherPosHandle<'a>>,
+    up: Option<MatcherPosHandle<'root, 'tt>>,
 
-    // Specifically used to "unzip" token trees. By "unzip", we mean to unwrap the delimiters from
-    // a delimited token tree (e.g. something wrapped in `(` `)`) or to get the contents of a doc
-    // comment...
+    /// Specifically used to "unzip" token trees. By "unzip", we mean to unwrap the delimiters from
+    /// a delimited token tree (e.g. something wrapped in `(` `)`) or to get the contents of a doc
+    /// comment...
+    ///
     /// When matching against matchers with nested delimited submatchers (e.g. `pat ( pat ( .. )
     /// pat ) pat`), we need to keep track of the matchers we are descending into. This stack does
     /// that where the bottom of the stack is the outermost matcher.
-    // Also, throughout the comments, this "descent" is often referred to as "unzipping"...
-    stack: Vec<MatcherTtFrame<'a>>,
+    /// Also, throughout the comments, this "descent" is often referred to as "unzipping"...
+    stack: SmallVec<[MatcherTtFrame<'tt>; 1]>,
 }
 
-impl<'a> MatcherPos<'a> {
+impl<'root, 'tt> MatcherPos<'root, 'tt> {
     /// Add `m` as a named match for the `idx`-th metavar.
     fn push_match(&mut self, idx: usize, m: NamedMatch) {
         let matches = Rc::make_mut(&mut self.matches[idx]);
@@ -218,12 +241,12 @@ fn push_match(&mut self, idx: usize, m: NamedMatch) {
 // Therefore, the initial MatcherPos is always allocated on the stack,
 // subsequent ones (of which there aren't that many) are allocated on the heap,
 // and this type is used to encapsulate both cases.
-enum MatcherPosHandle<'a> {
-    Ref(&'a mut MatcherPos<'a>),
-    Box(Box<MatcherPos<'a>>),
+enum MatcherPosHandle<'root, 'tt: 'root> {
+    Ref(&'root mut MatcherPos<'root, 'tt>),
+    Box(Box<MatcherPos<'root, 'tt>>),
 }
 
-impl<'a> Clone for MatcherPosHandle<'a> {
+impl<'root, 'tt> Clone for MatcherPosHandle<'root, 'tt> {
     // This always produces a new Box.
     fn clone(&self) -> Self {
         MatcherPosHandle::Box(match *self {
@@ -233,8 +256,8 @@ fn clone(&self) -> Self {
     }
 }
 
-impl<'a> Deref for MatcherPosHandle<'a> {
-    type Target = MatcherPos<'a>;
+impl<'root, 'tt> Deref for MatcherPosHandle<'root, 'tt> {
+    type Target = MatcherPos<'root, 'tt>;
     fn deref(&self) -> &Self::Target {
         match *self {
             MatcherPosHandle::Ref(ref r) => r,
@@ -243,8 +266,8 @@ fn deref(&self) -> &Self::Target {
     }
 }
 
-impl<'a> DerefMut for MatcherPosHandle<'a> {
-    fn deref_mut(&mut self) -> &mut MatcherPos<'a> {
+impl<'root, 'tt> DerefMut for MatcherPosHandle<'root, 'tt> {
+    fn deref_mut(&mut self) -> &mut MatcherPos<'root, 'tt> {
         match *self {
             MatcherPosHandle::Ref(ref mut r) => r,
             MatcherPosHandle::Box(ref mut b) => b,
@@ -292,7 +315,7 @@ fn create_matches(len: usize) -> Box<[Rc<NamedMatchVec>]> {
 
 /// Generate the top-level matcher position in which the "dot" is before the first token of the
 /// matcher `ms` and we are going to start matching at the span `open` in the source.
-fn initial_matcher_pos(ms: &[TokenTree], open: Span) -> MatcherPos {
+fn initial_matcher_pos<'root, 'tt>(ms: &'tt [TokenTree], open: Span) -> MatcherPos<'root, 'tt> {
     let match_idx_hi = count_names(ms);
     let matches = create_matches(match_idx_hi);
     MatcherPos {
@@ -312,7 +335,7 @@ fn initial_matcher_pos(ms: &[TokenTree], open: Span) -> MatcherPos {
         match_hi: match_idx_hi,
 
         // Haven't descended into any delimiters, so empty stack
-        stack: vec![],
+        stack: smallvec![],
 
         // Haven't descended into any sequences, so both of these are `None`.
         seq_op: None,
@@ -445,12 +468,12 @@ fn token_name_eq(t1: &Token, t2: &Token) -> bool {
 /// # Returns
 ///
 /// A `ParseResult`. Note that matches are kept track of through the items generated.
-fn inner_parse_loop<'a>(
+fn inner_parse_loop<'root, 'tt>(
     sess: &ParseSess,
-    cur_items: &mut SmallVec<[MatcherPosHandle<'a>; 1]>,
-    next_items: &mut Vec<MatcherPosHandle<'a>>,
-    eof_items: &mut SmallVec<[MatcherPosHandle<'a>; 1]>,
-    bb_items: &mut SmallVec<[MatcherPosHandle<'a>; 1]>,
+    cur_items: &mut SmallVec<[MatcherPosHandle<'root, 'tt>; 1]>,
+    next_items: &mut Vec<MatcherPosHandle<'root, 'tt>>,
+    eof_items: &mut SmallVec<[MatcherPosHandle<'root, 'tt>; 1]>,
+    bb_items: &mut SmallVec<[MatcherPosHandle<'root, 'tt>; 1]>,
     token: &Token,
     span: syntax_pos::Span,
 ) -> ParseResult<()> {
@@ -554,7 +577,7 @@ fn inner_parse_loop<'a>(
 
                     let matches = create_matches(item.matches.len());
                     cur_items.push(MatcherPosHandle::Box(Box::new(MatcherPos {
-                        stack: vec![],
+                        stack: smallvec![],
                         sep: seq.separator.clone(),
                         seq_op: Some(seq.op),
                         idx: 0,
index c8a686da179fbbcba51d828313dcced3743ee9fc..68e7e40c43efe4a1b74c035905c376c629e5662f 100644 (file)
@@ -1989,7 +1989,7 @@ fn parse_lit_token(&mut self) -> PResult<'a, LitKind> {
         let minus_lo = self.span;
         let minus_present = self.eat(&token::BinOp(token::Minus));
         let lo = self.span;
-        let literal = P(self.parse_lit()?);
+        let literal = self.parse_lit()?;
         let hi = self.prev_span;
         let expr = self.mk_expr(lo.to(hi), ExprKind::Lit(literal), ThinVec::new());
 
index 2717444753318e461e0c3b30dacd03ffbac96903..7f23313edff8beccb3fe44b815714269c5124c15 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 2717444753318e461e0c3b30dacd03ffbac96903
+Subproject commit 7f23313edff8beccb3fe44b815714269c5124c15
index 390450a520526cfd25b2a76ea5739139f502bbf1..1355c0377ce913eed566ae4d08f80689087cc095 100644 (file)
@@ -204,9 +204,7 @@ LLVMRustWriteArchive(char *Dst, size_t NumMembers,
         LLVMRustSetLastError(toString(MOrErr.takeError()).c_str());
         return LLVMRustResult::Failure;
       }
-#if LLVM_VERSION_GE(5, 0)
       MOrErr->MemberName = sys::path::filename(MOrErr->MemberName);
-#endif
       Members.push_back(std::move(*MOrErr));
     } else {
       Expected<NewArchiveMember> MOrErr =
index 200175da1bf2a57d7387db7a79e0866a667eb5b2..3b0046222a95a45e5a3dc04c36ce14de435f3010 100644 (file)
@@ -36,9 +36,6 @@
 #include "llvm/Transforms/IPO/FunctionImport.h"
 #include "llvm/Transforms/Utils/FunctionImportUtils.h"
 #include "llvm/LTO/LTO.h"
-#if LLVM_VERSION_LE(4, 0)
-#include "llvm/Object/ModuleSummaryIndexObjectFile.h"
-#endif
 
 #include "llvm-c/Transforms/PassManagerBuilder.h"
 
@@ -111,12 +108,11 @@ extern "C" void LLVMRustAddPass(LLVMPassManagerRef PMR, LLVMPassRef RustPass) {
 }
 
 extern "C"
-bool LLVMRustPassManagerBuilderPopulateThinLTOPassManager(
+void LLVMRustPassManagerBuilderPopulateThinLTOPassManager(
   LLVMPassManagerBuilderRef PMBR,
   LLVMPassManagerRef PMR
 ) {
   unwrap(PMBR)->populateThinLTOPassManager(*unwrap(PMR));
-  return true;
 }
 
 #ifdef LLVM_COMPONENT_X86
@@ -429,7 +425,7 @@ extern "C" void LLVMRustConfigurePassManagerBuilder(
     LLVMPassManagerBuilderRef PMBR, LLVMRustCodeGenOptLevel OptLevel,
     bool MergeFunctions, bool SLPVectorize, bool LoopVectorize, bool PrepareForThinLTO,
     const char* PGOGenPath, const char* PGOUsePath) {
-#if LLVM_RUSTLLVM
+#if LLVM_VERSION_GE(7, 0)
   unwrap(PMBR)->MergeFunctions = MergeFunctions;
 #endif
   unwrap(PMBR)->SLPVectorize = SLPVectorize;
@@ -869,21 +865,10 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules,
 
     Ret->ModuleMap[module->identifier] = mem_buffer;
 
-#if LLVM_VERSION_GE(5, 0)
     if (Error Err = readModuleSummaryIndex(mem_buffer, Ret->Index, i)) {
       LLVMRustSetLastError(toString(std::move(Err)).c_str());
       return nullptr;
     }
-#else
-    Expected<std::unique_ptr<object::ModuleSummaryIndexObjectFile>> ObjOrErr =
-      object::ModuleSummaryIndexObjectFile::create(mem_buffer);
-    if (!ObjOrErr) {
-      LLVMRustSetLastError(toString(ObjOrErr.takeError()).c_str());
-      return nullptr;
-    }
-    auto Index = (*ObjOrErr)->takeIndex();
-    Ret->Index.mergeFrom(std::move(Index), i);
-#endif
   }
 
   // Collect for each module the list of function it defines (GUID -> Summary)
@@ -900,7 +885,6 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules,
   // combined index
   //
   // This is copied from `lib/LTO/ThinLTOCodeGenerator.cpp`
-#if LLVM_VERSION_GE(5, 0)
 #if LLVM_VERSION_GE(7, 0)
   auto deadIsPrevailing = [&](GlobalValue::GUID G) {
     return PrevailingType::Unknown;
@@ -915,16 +899,6 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules,
     Ret->ImportLists,
     Ret->ExportLists
   );
-#else
-  auto DeadSymbols = computeDeadSymbols(Ret->Index, Ret->GUIDPreservedSymbols);
-  ComputeCrossModuleImport(
-    Ret->Index,
-    Ret->ModuleToDefinedGVSummaries,
-    Ret->ImportLists,
-    Ret->ExportLists,
-    &DeadSymbols
-  );
-#endif
 
   // Resolve LinkOnce/Weak symbols, this has to be computed early be cause it
   // impacts the caching.
@@ -934,13 +908,8 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules,
   StringMap<std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>> ResolvedODR;
   DenseMap<GlobalValue::GUID, const GlobalValueSummary *> PrevailingCopy;
   for (auto &I : Ret->Index) {
-#if LLVM_VERSION_GE(5, 0)
     if (I.second.SummaryList.size() > 1)
       PrevailingCopy[I.first] = getFirstDefinitionForLinker(I.second.SummaryList);
-#else
-    if (I.second.size() > 1)
-      PrevailingCopy[I.first] = getFirstDefinitionForLinker(I.second);
-#endif
   }
   auto isPrevailing = [&](GlobalValue::GUID GUID, const GlobalValueSummary *S) {
     const auto &Prevailing = PrevailingCopy.find(GUID);
@@ -962,19 +931,11 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules,
   // linkage will stay as external, and internal will stay as internal.
   std::set<GlobalValue::GUID> ExportedGUIDs;
   for (auto &List : Ret->Index) {
-#if LLVM_VERSION_GE(5, 0)
     for (auto &GVS: List.second.SummaryList) {
-#else
-    for (auto &GVS: List.second) {
-#endif
       if (GlobalValue::isLocalLinkage(GVS->linkage()))
         continue;
       auto GUID = GVS->getOriginalName();
-#if LLVM_VERSION_GE(5, 0)
       if (GVS->flags().Live)
-#else
-      if (!DeadSymbols.count(GUID))
-#endif
         ExportedGUIDs.insert(GUID);
     }
   }
index 3dbde46f762411598632ce24b23b7df7c877d0dc..f423503e19fbead4659f67c13a177e8556c61306 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #include "rustllvm.h"
+#include "llvm/IR/CallSite.h"
 #include "llvm/IR/DebugInfoMetadata.h"
 #include "llvm/IR/DiagnosticInfo.h"
 #include "llvm/IR/DiagnosticPrinter.h"
 #include "llvm/Object/ObjectFile.h"
 #include "llvm/Bitcode/BitcodeWriterPass.h"
 #include "llvm/Support/Signals.h"
-
-#include "llvm/IR/CallSite.h"
-
-#if LLVM_VERSION_GE(5, 0)
 #include "llvm/ADT/Optional.h"
-#else
-#include <cstdlib>
-#endif
 
 #include <iostream>
 
@@ -212,14 +206,7 @@ extern "C" void LLVMRustAddCallSiteAttribute(LLVMValueRef Instr, unsigned Index,
                                              LLVMRustAttribute RustAttr) {
   CallSite Call = CallSite(unwrap<Instruction>(Instr));
   Attribute Attr = Attribute::get(Call->getContext(), fromRust(RustAttr));
-#if LLVM_VERSION_GE(5, 0)
   Call.addAttribute(Index, Attr);
-#else
-  AttrBuilder B(Attr);
-  Call.setAttributes(Call.getAttributes().addAttributes(
-      Call->getContext(), Index,
-      AttributeSet::get(Call->getContext(), Index, B)));
-#endif
 }
 
 extern "C" void LLVMRustAddAlignmentCallSiteAttr(LLVMValueRef Instr,
@@ -228,14 +215,8 @@ extern "C" void LLVMRustAddAlignmentCallSiteAttr(LLVMValueRef Instr,
   CallSite Call = CallSite(unwrap<Instruction>(Instr));
   AttrBuilder B;
   B.addAlignmentAttr(Bytes);
-#if LLVM_VERSION_GE(5, 0)
   Call.setAttributes(Call.getAttributes().addAttributes(
       Call->getContext(), Index, B));
-#else
-  Call.setAttributes(Call.getAttributes().addAttributes(
-      Call->getContext(), Index,
-      AttributeSet::get(Call->getContext(), Index, B)));
-#endif
 }
 
 extern "C" void LLVMRustAddDereferenceableCallSiteAttr(LLVMValueRef Instr,
@@ -244,14 +225,8 @@ extern "C" void LLVMRustAddDereferenceableCallSiteAttr(LLVMValueRef Instr,
   CallSite Call = CallSite(unwrap<Instruction>(Instr));
   AttrBuilder B;
   B.addDereferenceableAttr(Bytes);
-#if LLVM_VERSION_GE(5, 0)
   Call.setAttributes(Call.getAttributes().addAttributes(
       Call->getContext(), Index, B));
-#else
-  Call.setAttributes(Call.getAttributes().addAttributes(
-      Call->getContext(), Index,
-      AttributeSet::get(Call->getContext(), Index, B)));
-#endif
 }
 
 extern "C" void LLVMRustAddDereferenceableOrNullCallSiteAttr(LLVMValueRef Instr,
@@ -260,14 +235,8 @@ extern "C" void LLVMRustAddDereferenceableOrNullCallSiteAttr(LLVMValueRef Instr,
   CallSite Call = CallSite(unwrap<Instruction>(Instr));
   AttrBuilder B;
   B.addDereferenceableOrNullAttr(Bytes);
-#if LLVM_VERSION_GE(5, 0)
   Call.setAttributes(Call.getAttributes().addAttributes(
       Call->getContext(), Index, B));
-#else
-  Call.setAttributes(Call.getAttributes().addAttributes(
-      Call->getContext(), Index,
-      AttributeSet::get(Call->getContext(), Index, B)));
-#endif
 }
 
 extern "C" void LLVMRustAddFunctionAttribute(LLVMValueRef Fn, unsigned Index,
@@ -275,11 +244,7 @@ extern "C" void LLVMRustAddFunctionAttribute(LLVMValueRef Fn, unsigned Index,
   Function *A = unwrap<Function>(Fn);
   Attribute Attr = Attribute::get(A->getContext(), fromRust(RustAttr));
   AttrBuilder B(Attr);
-#if LLVM_VERSION_GE(5, 0)
   A->addAttributes(Index, B);
-#else
-  A->addAttributes(Index, AttributeSet::get(A->getContext(), Index, B));
-#endif
 }
 
 extern "C" void LLVMRustAddAlignmentAttr(LLVMValueRef Fn,
@@ -288,11 +253,7 @@ extern "C" void LLVMRustAddAlignmentAttr(LLVMValueRef Fn,
   Function *A = unwrap<Function>(Fn);
   AttrBuilder B;
   B.addAlignmentAttr(Bytes);
-#if LLVM_VERSION_GE(5, 0)
   A->addAttributes(Index, B);
-#else
-  A->addAttributes(Index, AttributeSet::get(A->getContext(), Index, B));
-#endif
 }
 
 extern "C" void LLVMRustAddDereferenceableAttr(LLVMValueRef Fn, unsigned Index,
@@ -300,11 +261,7 @@ extern "C" void LLVMRustAddDereferenceableAttr(LLVMValueRef Fn, unsigned Index,
   Function *A = unwrap<Function>(Fn);
   AttrBuilder B;
   B.addDereferenceableAttr(Bytes);
-#if LLVM_VERSION_GE(5, 0)
   A->addAttributes(Index, B);
-#else
-  A->addAttributes(Index, AttributeSet::get(A->getContext(), Index, B));
-#endif
 }
 
 extern "C" void LLVMRustAddDereferenceableOrNullAttr(LLVMValueRef Fn,
@@ -313,11 +270,7 @@ extern "C" void LLVMRustAddDereferenceableOrNullAttr(LLVMValueRef Fn,
   Function *A = unwrap<Function>(Fn);
   AttrBuilder B;
   B.addDereferenceableOrNullAttr(Bytes);
-#if LLVM_VERSION_GE(5, 0)
   A->addAttributes(Index, B);
-#else
-  A->addAttributes(Index, AttributeSet::get(A->getContext(), Index, B));
-#endif
 }
 
 extern "C" void LLVMRustAddFunctionAttrStringValue(LLVMValueRef Fn,
@@ -327,11 +280,7 @@ extern "C" void LLVMRustAddFunctionAttrStringValue(LLVMValueRef Fn,
   Function *F = unwrap<Function>(Fn);
   AttrBuilder B;
   B.addAttribute(Name, Value);
-#if LLVM_VERSION_GE(5, 0)
   F->addAttributes(Index, B);
-#else
-  F->addAttributes(Index, AttributeSet::get(F->getContext(), Index, B));
-#endif
 }
 
 extern "C" void LLVMRustRemoveFunctionAttributes(LLVMValueRef Fn,
@@ -341,12 +290,7 @@ extern "C" void LLVMRustRemoveFunctionAttributes(LLVMValueRef Fn,
   Attribute Attr = Attribute::get(F->getContext(), fromRust(RustAttr));
   AttrBuilder B(Attr);
   auto PAL = F->getAttributes();
-#if LLVM_VERSION_GE(5, 0)
   auto PALNew = PAL.removeAttributes(F->getContext(), Index, B);
-#else
-  const AttributeSet PALNew = PAL.removeAttributes(
-      F->getContext(), Index, AttributeSet::get(F->getContext(), Index, B));
-#endif
   F->setAttributes(PALNew);
 }
 
@@ -396,7 +340,6 @@ enum class LLVMRustSynchronizationScope {
   CrossThread,
 };
 
-#if LLVM_VERSION_GE(5, 0)
 static SyncScope::ID fromRust(LLVMRustSynchronizationScope Scope) {
   switch (Scope) {
   case LLVMRustSynchronizationScope::SingleThread:
@@ -407,18 +350,6 @@ static SyncScope::ID fromRust(LLVMRustSynchronizationScope Scope) {
     report_fatal_error("bad SynchronizationScope.");
   }
 }
-#else
-static SynchronizationScope fromRust(LLVMRustSynchronizationScope Scope) {
-  switch (Scope) {
-  case LLVMRustSynchronizationScope::SingleThread:
-    return SingleThread;
-  case LLVMRustSynchronizationScope::CrossThread:
-    return CrossThread;
-  default:
-    report_fatal_error("bad SynchronizationScope.");
-  }
-}
-#endif
 
 extern "C" LLVMValueRef
 LLVMRustBuildAtomicFence(LLVMBuilderRef B, LLVMAtomicOrdering Order,
@@ -463,18 +394,6 @@ extern "C" void LLVMRustAppendModuleInlineAsm(LLVMModuleRef M, const char *Asm)
 
 typedef DIBuilder *LLVMRustDIBuilderRef;
 
-#if LLVM_VERSION_LT(5, 0)
-typedef struct LLVMOpaqueMetadata *LLVMMetadataRef;
-
-namespace llvm {
-DEFINE_ISA_CONVERSION_FUNCTIONS(Metadata, LLVMMetadataRef)
-
-inline Metadata **unwrap(LLVMMetadataRef *Vals) {
-  return reinterpret_cast<Metadata **>(Vals);
-}
-}
-#endif
-
 template <typename DIT> DIT *unwrapDIPtr(LLVMMetadataRef Ref) {
   return (DIT *)(Ref ? unwrap<MDNode>(Ref) : nullptr);
 }
@@ -590,11 +509,6 @@ static DINode::DIFlags fromRust(LLVMRustDIFlags Flags) {
   if (isSet(Flags & LLVMRustDIFlags::FlagRValueReference)) {
     Result |= DINode::DIFlags::FlagRValueReference;
   }
-#if LLVM_VERSION_LE(4, 0)
-  if (isSet(Flags & LLVMRustDIFlags::FlagExternalTypeRef)) {
-    Result |= DINode::DIFlags::FlagExternalTypeRef;
-  }
-#endif
   if (isSet(Flags & LLVMRustDIFlags::FlagIntroducedVirtual)) {
     Result |= DINode::DIFlags::FlagIntroducedVirtual;
   }
@@ -693,9 +607,7 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreatePointerType(
     uint64_t SizeInBits, uint32_t AlignInBits, const char *Name) {
   return wrap(Builder->createPointerType(unwrapDI<DIType>(PointeeTy),
                                          SizeInBits, AlignInBits,
-#if LLVM_VERSION_GE(5, 0)
                                          /* DWARFAddressSpace */ None,
-#endif
                                          Name));
 }
 
@@ -902,12 +814,7 @@ LLVMRustDIBuilderCreateNameSpace(LLVMRustDIBuilderRef Builder,
                                  LLVMMetadataRef Scope, const char *Name,
                                  LLVMMetadataRef File, unsigned LineNo) {
   return wrap(Builder->createNameSpace(
-      unwrapDI<DIDescriptor>(Scope), Name
-#if LLVM_VERSION_LT(5, 0)
-      ,
-      unwrapDI<DIFile>(File), LineNo
-#endif
-      ,
+      unwrapDI<DIDescriptor>(Scope), Name,
       false // ExportSymbols (only relevant for C++ anonymous namespaces)
       ));
 }
@@ -937,12 +844,7 @@ extern "C" int64_t LLVMRustDIBuilderCreateOpDeref() {
 }
 
 extern "C" int64_t LLVMRustDIBuilderCreateOpPlusUconst() {
-#if LLVM_VERSION_GE(5, 0)
   return dwarf::DW_OP_plus_uconst;
-#else
-  // older LLVM used `plus` to behave like `plus_uconst`.
-  return dwarf::DW_OP_plus;
-#endif
 }
 
 extern "C" void LLVMRustWriteTypeToString(LLVMTypeRef Ty, RustStringRef Str) {
@@ -1014,21 +916,12 @@ extern "C" void LLVMRustUnpackOptimizationDiagnostic(
   *FunctionOut = wrap(&Opt->getFunction());
 
   RawRustStringOstream FilenameOS(FilenameOut);
-#if LLVM_VERSION_GE(5,0)
   DiagnosticLocation loc = Opt->getLocation();
   if (loc.isValid()) {
     *Line = loc.getLine();
     *Column = loc.getColumn();
     FilenameOS << loc.getFilename();
   }
-#else
-  const DebugLoc &loc = Opt->getDebugLoc();
-  if (loc) {
-    *Line = loc.getLine();
-    *Column = loc.getCol();
-    FilenameOS << cast<DIScope>(loc.getScope())->getFilename();
-  }
-#endif
 
   RawRustStringOstream MessageOS(MessageOut);
   MessageOS << Opt->getMsg();
@@ -1237,6 +1130,40 @@ extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMValueRef Fn,
       unwrap(Fn), makeArrayRef(unwrap(Args), NumArgs), Bundles, Name));
 }
 
+extern "C" LLVMValueRef LLVMRustBuildMemCpy(LLVMBuilderRef B,
+                                            LLVMValueRef Dst, unsigned DstAlign,
+                                            LLVMValueRef Src, unsigned SrcAlign,
+                                            LLVMValueRef Size, bool IsVolatile) {
+#if LLVM_VERSION_GE(7, 0)
+  return wrap(unwrap(B)->CreateMemCpy(
+      unwrap(Dst), DstAlign,
+      unwrap(Src), SrcAlign,
+      unwrap(Size), IsVolatile));
+#else
+  unsigned Align = std::min(DstAlign, SrcAlign);
+  return wrap(unwrap(B)->CreateMemCpy(
+      unwrap(Dst), unwrap(Src),
+      unwrap(Size), Align, IsVolatile));
+#endif
+}
+
+extern "C" LLVMValueRef LLVMRustBuildMemMove(LLVMBuilderRef B,
+                                             LLVMValueRef Dst, unsigned DstAlign,
+                                             LLVMValueRef Src, unsigned SrcAlign,
+                                             LLVMValueRef Size, bool IsVolatile) {
+#if LLVM_VERSION_GE(7, 0)
+  return wrap(unwrap(B)->CreateMemMove(
+      unwrap(Dst), DstAlign,
+      unwrap(Src), SrcAlign,
+      unwrap(Size), IsVolatile));
+#else
+  unsigned Align = std::min(DstAlign, SrcAlign);
+  return wrap(unwrap(B)->CreateMemMove(
+      unwrap(Dst), unwrap(Src),
+      unwrap(Size), Align, IsVolatile));
+#endif
+}
+
 extern "C" LLVMValueRef
 LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args,
                     unsigned NumArgs, LLVMBasicBlockRef Then,
@@ -1451,7 +1378,6 @@ LLVMRustModuleCost(LLVMModuleRef M) {
 }
 
 // Vector reductions:
-#if LLVM_VERSION_GE(5, 0)
 extern "C" LLVMValueRef
 LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef B, LLVMValueRef Acc, LLVMValueRef Src) {
     return wrap(unwrap(B)->CreateFAddReduce(unwrap(Acc),unwrap(Src)));
@@ -1497,54 +1423,6 @@ LLVMRustBuildVectorReduceFMax(LLVMBuilderRef B, LLVMValueRef Src, bool NoNaN) {
   return wrap(unwrap(B)->CreateFPMaxReduce(unwrap(Src), NoNaN));
 }
 
-#else
-
-extern "C" LLVMValueRef
-LLVMRustBuildVectorReduceFAdd(LLVMBuilderRef, LLVMValueRef, LLVMValueRef) {
-  return nullptr;
-}
-extern "C" LLVMValueRef
-LLVMRustBuildVectorReduceFMul(LLVMBuilderRef, LLVMValueRef, LLVMValueRef) {
-  return nullptr;
-}
-extern "C" LLVMValueRef
-LLVMRustBuildVectorReduceAdd(LLVMBuilderRef, LLVMValueRef) {
-  return nullptr;
-}
-extern "C" LLVMValueRef
-LLVMRustBuildVectorReduceMul(LLVMBuilderRef, LLVMValueRef) {
-  return nullptr;
-}
-extern "C" LLVMValueRef
-LLVMRustBuildVectorReduceAnd(LLVMBuilderRef, LLVMValueRef) {
-  return nullptr;
-}
-extern "C" LLVMValueRef
-LLVMRustBuildVectorReduceOr(LLVMBuilderRef, LLVMValueRef) {
-  return nullptr;
-}
-extern "C" LLVMValueRef
-LLVMRustBuildVectorReduceXor(LLVMBuilderRef, LLVMValueRef) {
-  return nullptr;
-}
-extern "C" LLVMValueRef
-LLVMRustBuildVectorReduceMin(LLVMBuilderRef, LLVMValueRef, bool) {
-  return nullptr;
-}
-extern "C" LLVMValueRef
-LLVMRustBuildVectorReduceMax(LLVMBuilderRef, LLVMValueRef, bool) {
-  return nullptr;
-}
-extern "C" LLVMValueRef
-LLVMRustBuildVectorReduceFMin(LLVMBuilderRef, LLVMValueRef, bool) {
-  return nullptr;
-}
-extern "C" LLVMValueRef
-LLVMRustBuildVectorReduceFMax(LLVMBuilderRef, LLVMValueRef, bool) {
-  return nullptr;
-}
-#endif
-
 #if LLVM_VERSION_GE(6, 0)
 extern "C" LLVMValueRef
 LLVMRustBuildMinNum(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS) {
diff --git a/src/test/codegen/enum-debug-niche-2.rs b/src/test/codegen/enum-debug-niche-2.rs
new file mode 100644 (file)
index 0000000..c0ee051
--- /dev/null
@@ -0,0 +1,63 @@
+// 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.
+
+// This test depends on a patch that was committed to upstream LLVM
+// before 7.0, then backported to the Rust LLVM fork.  It tests that
+// optimized enum debug info accurately reflects the enum layout.
+
+// ignore-tidy-linelength
+// ignore-windows
+// min-system-llvm-version 7.0
+
+// compile-flags: -g -C no-prepopulate-passes
+
+// CHECK: {{.*}}DICompositeType{{.*}}tag: DW_TAG_variant_part,{{.*}}size: 32,{{.*}}
+// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "Placeholder",{{.*}}extraData: i64 4294967295{{[,)].*}}
+// CHECK: {{.*}}DIDerivedType{{.*}}tag: DW_TAG_member,{{.*}}name: "Error",{{.*}}extraData: i64 0{{[,)].*}}
+
+#![feature(never_type)]
+#![feature(nll)]
+
+#[derive(Copy, Clone)]
+pub struct Entity {
+    private: std::num::NonZeroU32,
+}
+
+#[derive(Copy, Clone, PartialEq, Eq)]
+pub struct Declaration;
+
+impl TypeFamily for Declaration {
+    type Base = Base;
+    type Placeholder = !;
+
+    fn intern_base_data(_: BaseKind<Self>) {}
+}
+
+#[derive(Copy, Clone)]
+pub struct Base;
+
+pub trait TypeFamily: Copy + 'static {
+    type Base: Copy;
+    type Placeholder: Copy;
+
+    fn intern_base_data(_: BaseKind<Self>);
+}
+
+#[derive(Copy, Clone)]
+pub enum BaseKind<F: TypeFamily> {
+    Named(Entity),
+    Placeholder(F::Placeholder),
+    Error,
+}
+
+pub fn main() {
+    let x = BaseKind::Error::<Declaration>;
+    let y = 7;
+}
index 10dd12909b6444a65772dfa4cd5a0c7aa85aad05..b50f5b6f16fedad9743b5be8b2be36fea7a6eb7b 100644 (file)
@@ -65,7 +65,7 @@ pub struct BigPacked2 {
 pub fn call_pkd1(f: fn() -> Array) -> BigPacked1 {
 // CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca %Array
 // CHECK: call void %{{.*}}(%Array* noalias nocapture sret dereferenceable(32) [[ALLOCA]])
-// CHECK: call void @llvm.memcpy.{{.*}}(i8* align 1 %{{.*}}, i8* align 1 %{{.*}}, i{{[0-9]+}} 32, i1 false)
+// CHECK: call void @llvm.memcpy.{{.*}}(i8* align 1 %{{.*}}, i8* align 4 %{{.*}}, i{{[0-9]+}} 32, i1 false)
     // check that calls whose destination is a field of a packed struct
     // go through an alloca rather than calling the function with an
     // unaligned destination.
@@ -77,7 +77,7 @@ pub fn call_pkd1(f: fn() -> Array) -> BigPacked1 {
 pub fn call_pkd2(f: fn() -> Array) -> BigPacked2 {
 // CHECK: [[ALLOCA:%[_a-z0-9]+]] = alloca %Array
 // CHECK: call void %{{.*}}(%Array* noalias nocapture sret dereferenceable(32) [[ALLOCA]])
-// CHECK: call void @llvm.memcpy.{{.*}}(i8* align 2 %{{.*}}, i8* align 2 %{{.*}}, i{{[0-9]+}} 32, i1 false)
+// CHECK: call void @llvm.memcpy.{{.*}}(i8* align 2 %{{.*}}, i8* align 4 %{{.*}}, i{{[0-9]+}} 32, i1 false)
     // check that calls whose destination is a field of a packed struct
     // go through an alloca rather than calling the function with an
     // unaligned destination.
index 0aaf00bfdbe8ef1597825ed81c7d0ade8c1287f0..871bee13b1931eddf04b259ad387f3bd2cb70f08 100644 (file)
@@ -31,7 +31,7 @@ pub struct Bytes {
 // CHECK: store i32 %0, i32* [[TMP]]
 // CHECK: [[Y8:%[0-9]+]] = bitcast [4 x i8]* %y to i8*
 // CHECK: [[TMP8:%[0-9]+]] = bitcast i32* [[TMP]] to i8*
-// CHECK: call void @llvm.memcpy.{{.*}}(i8* align 1 [[Y8]], i8* align 1 [[TMP8]], i{{[0-9]+}} 4, i1 false)
+// CHECK: call void @llvm.memcpy.{{.*}}(i8* align 1 [[Y8]], i8* align 4 [[TMP8]], i{{[0-9]+}} 4, i1 false)
     *x = y;
 }
 
@@ -45,6 +45,6 @@ pub fn small_struct_alignment(x: &mut Bytes, y: Bytes) {
 // CHECK: store i32 %0, i32* [[TMP]]
 // CHECK: [[Y8:%[0-9]+]] = bitcast %Bytes* %y to i8*
 // CHECK: [[TMP8:%[0-9]+]] = bitcast i32* [[TMP]] to i8*
-// CHECK: call void @llvm.memcpy.{{.*}}(i8* align 1 [[Y8]], i8* align 1 [[TMP8]], i{{[0-9]+}} 4, i1 false)
+// CHECK: call void @llvm.memcpy.{{.*}}(i8* align 1 [[Y8]], i8* align 4 [[TMP8]], i{{[0-9]+}} 4, i1 false)
     *x = y;
 }
diff --git a/src/test/mir-opt/inline-trait-method_2.rs b/src/test/mir-opt/inline-trait-method_2.rs
new file mode 100644 (file)
index 0000000..aa756f4
--- /dev/null
@@ -0,0 +1,36 @@
+// compile-flags: -Z span_free_formats -Z mir-opt-level=3
+
+#[inline]
+fn test(x: &dyn X) -> bool {
+    x.y()
+}
+
+fn test2(x: &dyn X) -> bool {
+    test(x)
+}
+
+trait X {
+    fn y(&self) -> bool {
+        false
+    }
+}
+
+impl X for () {
+    fn y(&self) -> bool {
+        true
+    }
+}
+
+fn main() {
+    println!("Should be true: {}", test2(&()));
+}
+
+// END RUST SOURCE
+// START rustc.test2.Inline.after.mir
+// ...
+// bb0: {
+// ...
+//     _0 = const X::y(move _2) -> bb1;
+// }
+// ...
+// END rustc.test2.Inline.after.mir
index 51191dd7087e483e3f9ae7eabdfe067bbfc83a72..b3980f32d2736b2195fac070946da713d2f598d5 100644 (file)
@@ -17,7 +17,7 @@ fn drop(&mut self) {
         if self.0 == 1 {
             panic!("panic 1");
         } else {
-            eprint!("drop {}", self.0);
+            eprintln!("drop {}", self.0);
         }
     }
 }
index 2d430be07ef2f2eff1f3fe97566a15696f18ba9f..2fa933d513a669e4910e58ae5f330410166c6ab8 100644 (file)
@@ -14,7 +14,7 @@
 
 fn main() {
     panic::set_hook(Box::new(|i| {
-        eprint!("greetings from the panic handler");
+        eprintln!("greetings from the panic handler");
     }));
     panic!("foobar");
 }
diff --git a/src/test/run-pass/associated-types/associated-types-from-supertrait.rs b/src/test/run-pass/associated-types/associated-types-from-supertrait.rs
new file mode 100644 (file)
index 0000000..e69c0af
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Foo: Iterator<Item = i32> {}
+trait Bar: Foo {}
+
+fn main() {
+    let _: &dyn Bar;
+}
index 4ac469557098523dd588881eb2a66ecaf8f205fb..529c21354e3838a2eccf54d2dd6b22438f853dd6 100644 (file)
@@ -23,7 +23,7 @@ fn main() {
     assert_eq!(BE_U32, b(55u32).to_be());
     assert_eq!(LE_U32, b(55u32).to_le());
 
-    #[cfg(not(target_arch = "asmjs"))]
+    #[cfg(not(target_os = "emscripten"))]
     {
         const BE_U128: u128 = 999999u128.to_be();
         const LE_I128: i128 = (-999999i128).to_le();
index 0750a4c89593665a2a745e4e68d6c24424ef4b74..a31ad72b0881a8228f15dfce376e5f0f88ab2c78 100644 (file)
@@ -16,6 +16,7 @@
 // expose is still present.
 
 #![feature(mpsc_select)]
+#![allow(deprecated)]
 
 use std::sync::mpsc::{channel, Sender, Receiver};
 use std::thread;
diff --git a/src/test/run-pass/issues/issue-24010.rs b/src/test/run-pass/issues/issue-24010.rs
new file mode 100644 (file)
index 0000000..cce8bb8
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Foo: Fn(i32) -> i32 + Send {}
+
+impl<T: ?Sized + Fn(i32) -> i32 + Send> Foo for T {}
+
+fn wants_foo(f: Box<Foo>) -> i32 {
+    f(42)
+}
+
+fn main() {
+    let f = Box::new(|x| x);
+    assert_eq!(wants_foo(f), 42);
+}
diff --git a/src/test/run-pass/traits/trait-alias-object-type.rs b/src/test/run-pass/traits/trait-alias-object-type.rs
deleted file mode 100644 (file)
index 17e3092..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(trait_alias)]
-
-trait Foo = PartialEq<i32> + Send;
-trait Bar = Foo + Sync;
-
-trait I32Iterator = Iterator<Item = i32>;
-
-pub fn main() {
-    let a: &dyn Bar = &123;
-    assert!(*a == 123);
-    let b = Box::new(456) as Box<dyn Foo>;
-    assert!(*b == 456);
-
-    // FIXME(alexreg): associated type should be gotten from trait alias definition
-    // let c: &dyn I32Iterator = &vec![123].into_iter();
-    // assert_eq!(c.next(), Some(123));
-}
diff --git a/src/test/run-pass/traits/trait-alias-object.rs b/src/test/run-pass/traits/trait-alias-object.rs
new file mode 100644 (file)
index 0000000..adac28e
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(trait_alias)]
+
+trait Foo = PartialEq<i32> + Send;
+trait Bar = Foo + Sync;
+
+trait I32Iterator = Iterator<Item = i32>;
+
+pub fn main() {
+    let a: &dyn Bar = &123;
+    assert!(*a == 123);
+    let b = Box::new(456) as Box<dyn Foo>;
+    assert!(*b == 456);
+
+    let c: &mut dyn I32Iterator = &mut vec![123].into_iter();
+    assert_eq!(c.next(), Some(123));
+}
diff --git a/src/test/rustdoc/inline_cross/auxiliary/use_crate.rs b/src/test/rustdoc/inline_cross/auxiliary/use_crate.rs
new file mode 100644 (file)
index 0000000..55202de
--- /dev/null
@@ -0,0 +1,15 @@
+// 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.
+
+pub mod asdf {
+    pub struct SomeStruct;
+}
+
+pub trait SomeTrait {}
diff --git a/src/test/rustdoc/inline_cross/auxiliary/use_crate_2.rs b/src/test/rustdoc/inline_cross/auxiliary/use_crate_2.rs
new file mode 100644 (file)
index 0000000..1f11cbc
--- /dev/null
@@ -0,0 +1,11 @@
+// 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.
+
+pub struct SomethingElse;
diff --git a/src/test/rustdoc/inline_cross/use_crate.rs b/src/test/rustdoc/inline_cross/use_crate.rs
new file mode 100644 (file)
index 0000000..a987044
--- /dev/null
@@ -0,0 +1,37 @@
+// 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:use_crate.rs
+// aux-build:use_crate_2.rs
+// build-aux-docs
+// edition:2018
+// compile-flags:--extern use_crate --extern use_crate_2 -Z unstable-options
+
+// During the buildup to Rust 2018, rustdoc would eagerly inline `pub use some_crate;` as if it
+// were a module, so we changed it to make `pub use`ing crate roots remain as a `pub use` statement
+// in docs... unless you added `#[doc(inline)]`.
+
+#![crate_name = "local"]
+
+// @!has-dir local/use_crate
+// @has local/index.html
+// @has - '//code' 'pub use use_crate'
+pub use use_crate;
+
+// @has-dir local/asdf
+// @has local/asdf/index.html
+// @has local/index.html '//a/@href' 'asdf/index.html'
+pub use use_crate::asdf;
+
+// @has-dir local/use_crate_2
+// @has local/use_crate_2/index.html
+// @has local/index.html '//a/@href' 'use_crate_2/index.html'
+#[doc(inline)]
+pub use use_crate_2;
index d3307bb4d42c1076f23e1df42d9f9c4392bafb38..6cc7f1743ad07c440f9d63070ef479e4fcb0bac6 100644 (file)
@@ -18,6 +18,7 @@
 extern crate src_links_external;
 
 // @has foo/bar/index.html '//a/@href' '../../src/src_links_external/src-links-external.rs.html#11'
+#[doc(inline)]
 pub use src_links_external as bar;
 
 // @has foo/bar/struct.Foo.html '//a/@href' '../../src/src_links_external/src-links-external.rs.html#11'
diff --git a/src/test/ui/associated-types/associated-types-overridden-binding-2.rs b/src/test/ui/associated-types/associated-types-overridden-binding-2.rs
new file mode 100644 (file)
index 0000000..8d91561
--- /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.
+
+#![feature(trait_alias)]
+
+trait I32Iterator = Iterator<Item = i32>;
+
+fn main() {
+    let _: &I32Iterator<Item = u32> = &vec![42].into_iter();
+}
diff --git a/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr b/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr
new file mode 100644 (file)
index 0000000..536cd94
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0271]: type mismatch resolving `<std::vec::IntoIter<u32> as std::iter::Iterator>::Item == i32`
+  --> $DIR/associated-types-overridden-binding-2.rs:16:39
+   |
+LL |     let _: &I32Iterator<Item = u32> = &vec![42].into_iter();
+   |                                       ^^^^^^^^^^^^^^^^^^^^^ expected u32, found i32
+   |
+   = note: expected type `u32`
+              found type `i32`
+   = note: required for the cast to the object type `dyn I32Iterator<Item=u32, Item=i32>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/src/test/ui/associated-types/associated-types-overridden-binding.rs b/src/test/ui/associated-types/associated-types-overridden-binding.rs
new file mode 100644 (file)
index 0000000..ed2211e
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(trait_alias)]
+
+trait Foo: Iterator<Item = i32> {}
+trait Bar: Foo<Item = u32> {}
+
+trait I32Iterator = Iterator<Item = i32>;
+trait U32Iterator = I32Iterator<Item = u32>;
+
+fn main() {
+    let _: &I32Iterator<Item = u32>;
+}
diff --git a/src/test/ui/associated-types/associated-types-overridden-binding.stderr b/src/test/ui/associated-types/associated-types-overridden-binding.stderr
new file mode 100644 (file)
index 0000000..216aa09
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0284]: type annotations required: cannot resolve `<Self as std::iter::Iterator>::Item == i32`
+  --> $DIR/associated-types-overridden-binding.rs:14:1
+   |
+LL | trait Bar: Foo<Item = u32> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: required by `Foo`
+  --> $DIR/associated-types-overridden-binding.rs:13:1
+   |
+LL | trait Foo: Iterator<Item = i32> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0284`.
diff --git a/src/test/ui/borrowck/borrowck-box-insensitivity.ast.stderr b/src/test/ui/borrowck/borrowck-box-insensitivity.ast.stderr
new file mode 100644 (file)
index 0000000..95b26a5
--- /dev/null
@@ -0,0 +1,165 @@
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-box-insensitivity.rs:37:9
+   |
+LL |     let _x = a.x;
+   |         -- value moved here
+LL |     //[ast]~^ value moved here
+LL |     let _y = a.y; //[ast]~ ERROR use of moved
+   |         ^^ value used here after move
+   |
+   = note: move occurs because `a.x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-box-insensitivity.rs:46:9
+   |
+LL |     let _x = a.x;
+   |         -- value moved here
+LL |     //[ast]~^ value moved here
+LL |     let _y = a.y; //[ast]~ ERROR use of moved
+   |         ^^ value used here after move
+   |
+   = note: move occurs because `a.x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error[E0382]: use of moved value: `a`
+  --> $DIR/borrowck-box-insensitivity.rs:55:15
+   |
+LL |     let _x = a.x;
+   |         -- value moved here
+LL |     //[ast]~^ value moved here
+LL |     let _y = &a.y; //[ast]~ ERROR use of moved
+   |               ^^^ value used here after move
+   |
+   = note: move occurs because `a.x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error[E0505]: cannot move out of `a.y` because it is borrowed
+  --> $DIR/borrowck-box-insensitivity.rs:63:9
+   |
+LL |     let _x = &a.x;
+   |               --- borrow of `a.x` occurs here
+LL |     let _y = a.y;
+   |         ^^ move out of `a.y` occurs here
+
+error[E0503]: cannot use `a.y` because it was mutably borrowed
+  --> $DIR/borrowck-box-insensitivity.rs:71:9
+   |
+LL |     let _x = &mut a.x;
+   |                   --- borrow of `a.x` occurs here
+LL |     let _y = a.y; //[ast]~ ERROR cannot use
+   |         ^^ use of borrowed `a.x`
+
+error[E0505]: cannot move out of `a.y` because it is borrowed
+  --> $DIR/borrowck-box-insensitivity.rs:77:9
+   |
+LL |     let _x = &mut a.x;
+   |                   --- borrow of `a.x` occurs here
+LL |     let _y = a.y;
+   |         ^^ move out of `a.y` occurs here
+
+error[E0502]: cannot borrow `a` (via `a.y`) as immutable because `a` is also borrowed as mutable (via `a.x`)
+  --> $DIR/borrowck-box-insensitivity.rs:85:15
+   |
+LL |     let _x = &mut a.x;
+   |                   --- mutable borrow occurs here (via `a.x`)
+LL |     let _y = &a.y; //[ast]~ ERROR cannot borrow
+   |               ^^^ immutable borrow occurs here (via `a.y`)
+...
+LL | }
+   | - mutable borrow ends here
+
+error[E0502]: cannot borrow `a` (via `a.y`) as mutable because `a` is also borrowed as immutable (via `a.x`)
+  --> $DIR/borrowck-box-insensitivity.rs:92:19
+   |
+LL |     let _x = &a.x;
+   |               --- immutable borrow occurs here (via `a.x`)
+LL |     let _y = &mut a.y; //[ast]~ ERROR cannot borrow
+   |                   ^^^ mutable borrow occurs here (via `a.y`)
+...
+LL | }
+   | - immutable borrow ends here
+
+error[E0382]: use of collaterally moved value: `a.y`
+  --> $DIR/borrowck-box-insensitivity.rs:100:9
+   |
+LL |     let _x = a.x.x;
+   |         -- value moved here
+LL |     //[ast]~^ value moved here
+LL |     let _y = a.y; //[ast]~ ERROR use of collaterally moved
+   |         ^^ value used here after move
+   |
+   = note: move occurs because `a.x.x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error[E0382]: use of collaterally moved value: `a.y`
+  --> $DIR/borrowck-box-insensitivity.rs:108:9
+   |
+LL |     let _x = a.x.x;
+   |         -- value moved here
+LL |     //[ast]~^ value moved here
+LL |     let _y = a.y; //[ast]~ ERROR use of collaterally moved
+   |         ^^ value used here after move
+   |
+   = note: move occurs because `a.x.x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error[E0382]: use of collaterally moved value: `a.y`
+  --> $DIR/borrowck-box-insensitivity.rs:116:15
+   |
+LL |     let _x = a.x.x;
+   |         -- value moved here
+LL |     //[ast]~^ value moved here
+LL |     let _y = &a.y; //[ast]~ ERROR use of collaterally moved
+   |               ^^^ value used here after move
+   |
+   = note: move occurs because `a.x.x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+
+error[E0505]: cannot move out of `a.y` because it is borrowed
+  --> $DIR/borrowck-box-insensitivity.rs:124:9
+   |
+LL |     let _x = &a.x.x;
+   |               ----- borrow of `a.x.x` occurs here
+LL |     //[ast]~^ borrow of `a.x.x` occurs here
+LL |     let _y = a.y;
+   |         ^^ move out of `a.y` occurs here
+
+error[E0503]: cannot use `a.y` because it was mutably borrowed
+  --> $DIR/borrowck-box-insensitivity.rs:132:9
+   |
+LL |     let _x = &mut a.x.x;
+   |                   ----- borrow of `a.x.x` occurs here
+LL |     let _y = a.y; //[ast]~ ERROR cannot use
+   |         ^^ use of borrowed `a.x.x`
+
+error[E0505]: cannot move out of `a.y` because it is borrowed
+  --> $DIR/borrowck-box-insensitivity.rs:138:9
+   |
+LL |     let _x = &mut a.x.x;
+   |                   ----- borrow of `a.x.x` occurs here
+LL |     let _y = a.y;
+   |         ^^ move out of `a.y` occurs here
+
+error[E0502]: cannot borrow `a.y` as immutable because `a.x.x` is also borrowed as mutable
+  --> $DIR/borrowck-box-insensitivity.rs:147:15
+   |
+LL |     let _x = &mut a.x.x;
+   |                   ----- mutable borrow occurs here
+LL |     //[ast]~^ mutable borrow occurs here
+LL |     let _y = &a.y; //[ast]~ ERROR cannot borrow
+   |               ^^^ immutable borrow occurs here
+...
+LL | }
+   | - mutable borrow ends here
+
+error[E0502]: cannot borrow `a.y` as mutable because `a.x.x` is also borrowed as immutable
+  --> $DIR/borrowck-box-insensitivity.rs:155:19
+   |
+LL |     let _x = &a.x.x;
+   |               ----- immutable borrow occurs here
+LL |     //[ast]~^ immutable borrow occurs here
+LL |     let _y = &mut a.y; //[ast]~ ERROR cannot borrow
+   |                   ^^^ mutable borrow occurs here
+...
+LL | }
+   | - immutable borrow ends here
+
+error: aborting due to 16 previous errors
+
+Some errors occurred: E0382, E0502, E0503, E0505.
+For more information about an error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/borrowck-box-insensitivity.mir.stderr b/src/test/ui/borrowck/borrowck-box-insensitivity.mir.stderr
new file mode 100644 (file)
index 0000000..171e992
--- /dev/null
@@ -0,0 +1,14 @@
+error: compilation successful
+  --> $DIR/borrowck-box-insensitivity.rs:160:1
+   |
+LL | / fn main() { //[mir]~ ERROR compilation successful
+LL | |     copy_after_move();
+LL | |     move_after_move();
+LL | |     borrow_after_move();
+...  |
+LL | |     mut_borrow_after_borrow_nested();
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
index eabb8d7bca3fae511c73da3e4edd2f5d393e4041..2af97a9fc1d58718ed3e92eefa80f0549adbe68e 100644 (file)
@@ -1,13 +1,13 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
+// This test is an artifact of the old policy that `Box<T>` should not
+// be treated specially by the AST-borrowck.
 //
-// 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.
+// NLL goes back to treating `Box<T>` specially (namely, knowing that
+// it uniquely owns the data it holds). See rust-lang/rfcs#130.
 
+// revisions: ast mir
+//[ast] compile-flags: -Z borrowck=ast
+//[mir] compile-flags: -Z borrowck=mir
+// ignore-compare-mode-nll
 #![feature(box_syntax, rustc_attrs)]
 
 struct A {
@@ -33,131 +33,131 @@ struct D {
 fn copy_after_move() {
     let a: Box<_> = box A { x: box 0, y: 1 };
     let _x = a.x;
-    //~^ value moved here
-    let _y = a.y; //~ ERROR use of moved
-    //~^ move occurs because `a.x` has type `std::boxed::Box<isize>`
-    //~| value used here after move
+    //[ast]~^ value moved here
+    let _y = a.y; //[ast]~ ERROR use of moved
+    //[ast]~^ move occurs because `a.x` has type `std::boxed::Box<isize>`
+    //[ast]~| value used here after move
 }
 
 fn move_after_move() {
     let a: Box<_> = box B { x: box 0, y: box 1 };
     let _x = a.x;
-    //~^ value moved here
-    let _y = a.y; //~ ERROR use of moved
-    //~^ move occurs because `a.x` has type `std::boxed::Box<isize>`
-    //~| value used here after move
+    //[ast]~^ value moved here
+    let _y = a.y; //[ast]~ ERROR use of moved
+    //[ast]~^ move occurs because `a.x` has type `std::boxed::Box<isize>`
+    //[ast]~| value used here after move
 }
 
 fn borrow_after_move() {
     let a: Box<_> = box A { x: box 0, y: 1 };
     let _x = a.x;
-    //~^ value moved here
-    let _y = &a.y; //~ ERROR use of moved
-    //~^ move occurs because `a.x` has type `std::boxed::Box<isize>`
-    //~| value used here after move
+    //[ast]~^ value moved here
+    let _y = &a.y; //[ast]~ ERROR use of moved
+    //[ast]~^ move occurs because `a.x` has type `std::boxed::Box<isize>`
+    //[ast]~| value used here after move
 }
 
 fn move_after_borrow() {
     let a: Box<_> = box B { x: box 0, y: box 1 };
     let _x = &a.x;
     let _y = a.y;
-    //~^ ERROR cannot move
-    //~| move out of
+    //[ast]~^ ERROR cannot move
+    //[ast]~| move out of
+    use_imm(_x);
 }
-
 fn copy_after_mut_borrow() {
     let mut a: Box<_> = box A { x: box 0, y: 1 };
     let _x = &mut a.x;
-    let _y = a.y; //~ ERROR cannot use
+    let _y = a.y; //[ast]~ ERROR cannot use
+    use_mut(_x);
 }
-
 fn move_after_mut_borrow() {
     let mut a: Box<_> = box B { x: box 0, y: box 1 };
     let _x = &mut a.x;
     let _y = a.y;
-    //~^ ERROR cannot move
-    //~| move out of
+    //[ast]~^ ERROR cannot move
+    //[ast]~| move out of
+    use_mut(_x);
 }
-
 fn borrow_after_mut_borrow() {
     let mut a: Box<_> = box A { x: box 0, y: 1 };
     let _x = &mut a.x;
-    let _y = &a.y; //~ ERROR cannot borrow
-    //~^ immutable borrow occurs here (via `a.y`)
+    let _y = &a.y; //[ast]~ ERROR cannot borrow
+    //[ast]~^ immutable borrow occurs here (via `a.y`)
+    use_mut(_x);
 }
-
 fn mut_borrow_after_borrow() {
     let mut a: Box<_> = box A { x: box 0, y: 1 };
     let _x = &a.x;
-    let _y = &mut a.y; //~ ERROR cannot borrow
-    //~^ mutable borrow occurs here (via `a.y`)
+    let _y = &mut a.y; //[ast]~ ERROR cannot borrow
+    //[ast]~^ mutable borrow occurs here (via `a.y`)
+    use_imm(_x);
 }
-
 fn copy_after_move_nested() {
     let a: Box<_> = box C { x: box A { x: box 0, y: 1 }, y: 2 };
     let _x = a.x.x;
-    //~^ value moved here
-    let _y = a.y; //~ ERROR use of collaterally moved
-    //~| value used here after move
+    //[ast]~^ value moved here
+    let _y = a.y; //[ast]~ ERROR use of collaterally moved
+    //[ast]~| value used here after move
 }
 
 fn move_after_move_nested() {
     let a: Box<_> = box D { x: box A { x: box 0, y: 1 }, y: box 2 };
     let _x = a.x.x;
-    //~^ value moved here
-    let _y = a.y; //~ ERROR use of collaterally moved
-    //~| value used here after move
+    //[ast]~^ value moved here
+    let _y = a.y; //[ast]~ ERROR use of collaterally moved
+    //[ast]~| value used here after move
 }
 
 fn borrow_after_move_nested() {
     let a: Box<_> = box C { x: box A { x: box 0, y: 1 }, y: 2 };
     let _x = a.x.x;
-    //~^ value moved here
-    let _y = &a.y; //~ ERROR use of collaterally moved
-    //~| value used here after move
+    //[ast]~^ value moved here
+    let _y = &a.y; //[ast]~ ERROR use of collaterally moved
+    //[ast]~| value used here after move
 }
 
 fn move_after_borrow_nested() {
     let a: Box<_> = box D { x: box A { x: box 0, y: 1 }, y: box 2 };
     let _x = &a.x.x;
-    //~^ borrow of `a.x.x` occurs here
+    //[ast]~^ borrow of `a.x.x` occurs here
     let _y = a.y;
-    //~^ ERROR cannot move
-    //~| move out of
+    //[ast]~^ ERROR cannot move
+    //[ast]~| move out of
+    use_imm(_x);
 }
-
 fn copy_after_mut_borrow_nested() {
     let mut a: Box<_> = box C { x: box A { x: box 0, y: 1 }, y: 2 };
     let _x = &mut a.x.x;
-    let _y = a.y; //~ ERROR cannot use
+    let _y = a.y; //[ast]~ ERROR cannot use
+    use_mut(_x);
 }
-
 fn move_after_mut_borrow_nested() {
     let mut a: Box<_> = box D { x: box A { x: box 0, y: 1 }, y: box 2 };
     let _x = &mut a.x.x;
     let _y = a.y;
-    //~^ ERROR cannot move
-    //~| move out of
+    //[ast]~^ ERROR cannot move
+    //[ast]~| move out of
+    use_mut(_x);
 }
-
 fn borrow_after_mut_borrow_nested() {
     let mut a: Box<_> = box C { x: box A { x: box 0, y: 1 }, y: 2 };
     let _x = &mut a.x.x;
-    //~^ mutable borrow occurs here
-    let _y = &a.y; //~ ERROR cannot borrow
-    //~^ immutable borrow occurs here
+    //[ast]~^ mutable borrow occurs here
+    let _y = &a.y; //[ast]~ ERROR cannot borrow
+    //[ast]~^ immutable borrow occurs here
+    use_mut(_x);
 }
-
 fn mut_borrow_after_borrow_nested() {
     let mut a: Box<_> = box C { x: box A { x: box 0, y: 1 }, y: 2 };
     let _x = &a.x.x;
-    //~^ immutable borrow occurs here
-    let _y = &mut a.y; //~ ERROR cannot borrow
-    //~^ mutable borrow occurs here
+    //[ast]~^ immutable borrow occurs here
+    let _y = &mut a.y; //[ast]~ ERROR cannot borrow
+    //[ast]~^ mutable borrow occurs here
+    use_imm(_x);
 }
-
 #[rustc_error]
-fn main() {
+fn main() { //[mir]~ ERROR compilation successful
     copy_after_move();
     move_after_move();
     borrow_after_move();
@@ -180,3 +180,6 @@ fn main() {
     borrow_after_mut_borrow_nested();
     mut_borrow_after_borrow_nested();
 }
+
+fn use_mut<T>(_: &mut T) { }
+fn use_imm<T>(_: &T) { }
diff --git a/src/test/ui/borrowck/borrowck-box-insensitivity.stderr b/src/test/ui/borrowck/borrowck-box-insensitivity.stderr
deleted file mode 100644 (file)
index 5bf1fc0..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-box-insensitivity.rs:37:9
-   |
-LL |     let _x = a.x;
-   |         -- value moved here
-LL |     //~^ value moved here
-LL |     let _y = a.y; //~ ERROR use of moved
-   |         ^^ value used here after move
-   |
-   = note: move occurs because `a.x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
-
-error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-box-insensitivity.rs:46:9
-   |
-LL |     let _x = a.x;
-   |         -- value moved here
-LL |     //~^ value moved here
-LL |     let _y = a.y; //~ ERROR use of moved
-   |         ^^ value used here after move
-   |
-   = note: move occurs because `a.x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
-
-error[E0382]: use of moved value: `a`
-  --> $DIR/borrowck-box-insensitivity.rs:55:15
-   |
-LL |     let _x = a.x;
-   |         -- value moved here
-LL |     //~^ value moved here
-LL |     let _y = &a.y; //~ ERROR use of moved
-   |               ^^^ value used here after move
-   |
-   = note: move occurs because `a.x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
-
-error[E0505]: cannot move out of `a.y` because it is borrowed
-  --> $DIR/borrowck-box-insensitivity.rs:63:9
-   |
-LL |     let _x = &a.x;
-   |               --- borrow of `a.x` occurs here
-LL |     let _y = a.y;
-   |         ^^ move out of `a.y` occurs here
-
-error[E0503]: cannot use `a.y` because it was mutably borrowed
-  --> $DIR/borrowck-box-insensitivity.rs:71:9
-   |
-LL |     let _x = &mut a.x;
-   |                   --- borrow of `a.x` occurs here
-LL |     let _y = a.y; //~ ERROR cannot use
-   |         ^^ use of borrowed `a.x`
-
-error[E0505]: cannot move out of `a.y` because it is borrowed
-  --> $DIR/borrowck-box-insensitivity.rs:77:9
-   |
-LL |     let _x = &mut a.x;
-   |                   --- borrow of `a.x` occurs here
-LL |     let _y = a.y;
-   |         ^^ move out of `a.y` occurs here
-
-error[E0502]: cannot borrow `a` (via `a.y`) as immutable because `a` is also borrowed as mutable (via `a.x`)
-  --> $DIR/borrowck-box-insensitivity.rs:85:15
-   |
-LL |     let _x = &mut a.x;
-   |                   --- mutable borrow occurs here (via `a.x`)
-LL |     let _y = &a.y; //~ ERROR cannot borrow
-   |               ^^^ immutable borrow occurs here (via `a.y`)
-LL |     //~^ immutable borrow occurs here (via `a.y`)
-LL | }
-   | - mutable borrow ends here
-
-error[E0502]: cannot borrow `a` (via `a.y`) as mutable because `a` is also borrowed as immutable (via `a.x`)
-  --> $DIR/borrowck-box-insensitivity.rs:92:19
-   |
-LL |     let _x = &a.x;
-   |               --- immutable borrow occurs here (via `a.x`)
-LL |     let _y = &mut a.y; //~ ERROR cannot borrow
-   |                   ^^^ mutable borrow occurs here (via `a.y`)
-LL |     //~^ mutable borrow occurs here (via `a.y`)
-LL | }
-   | - immutable borrow ends here
-
-error[E0382]: use of collaterally moved value: `a.y`
-  --> $DIR/borrowck-box-insensitivity.rs:100:9
-   |
-LL |     let _x = a.x.x;
-   |         -- value moved here
-LL |     //~^ value moved here
-LL |     let _y = a.y; //~ ERROR use of collaterally moved
-   |         ^^ value used here after move
-   |
-   = note: move occurs because `a.x.x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
-
-error[E0382]: use of collaterally moved value: `a.y`
-  --> $DIR/borrowck-box-insensitivity.rs:108:9
-   |
-LL |     let _x = a.x.x;
-   |         -- value moved here
-LL |     //~^ value moved here
-LL |     let _y = a.y; //~ ERROR use of collaterally moved
-   |         ^^ value used here after move
-   |
-   = note: move occurs because `a.x.x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
-
-error[E0382]: use of collaterally moved value: `a.y`
-  --> $DIR/borrowck-box-insensitivity.rs:116:15
-   |
-LL |     let _x = a.x.x;
-   |         -- value moved here
-LL |     //~^ value moved here
-LL |     let _y = &a.y; //~ ERROR use of collaterally moved
-   |               ^^^ value used here after move
-   |
-   = note: move occurs because `a.x.x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
-
-error[E0505]: cannot move out of `a.y` because it is borrowed
-  --> $DIR/borrowck-box-insensitivity.rs:124:9
-   |
-LL |     let _x = &a.x.x;
-   |               ----- borrow of `a.x.x` occurs here
-LL |     //~^ borrow of `a.x.x` occurs here
-LL |     let _y = a.y;
-   |         ^^ move out of `a.y` occurs here
-
-error[E0503]: cannot use `a.y` because it was mutably borrowed
-  --> $DIR/borrowck-box-insensitivity.rs:132:9
-   |
-LL |     let _x = &mut a.x.x;
-   |                   ----- borrow of `a.x.x` occurs here
-LL |     let _y = a.y; //~ ERROR cannot use
-   |         ^^ use of borrowed `a.x.x`
-
-error[E0505]: cannot move out of `a.y` because it is borrowed
-  --> $DIR/borrowck-box-insensitivity.rs:138:9
-   |
-LL |     let _x = &mut a.x.x;
-   |                   ----- borrow of `a.x.x` occurs here
-LL |     let _y = a.y;
-   |         ^^ move out of `a.y` occurs here
-
-error[E0502]: cannot borrow `a.y` as immutable because `a.x.x` is also borrowed as mutable
-  --> $DIR/borrowck-box-insensitivity.rs:147:15
-   |
-LL |     let _x = &mut a.x.x;
-   |                   ----- mutable borrow occurs here
-LL |     //~^ mutable borrow occurs here
-LL |     let _y = &a.y; //~ ERROR cannot borrow
-   |               ^^^ immutable borrow occurs here
-LL |     //~^ immutable borrow occurs here
-LL | }
-   | - mutable borrow ends here
-
-error[E0502]: cannot borrow `a.y` as mutable because `a.x.x` is also borrowed as immutable
-  --> $DIR/borrowck-box-insensitivity.rs:155:19
-   |
-LL |     let _x = &a.x.x;
-   |               ----- immutable borrow occurs here
-LL |     //~^ immutable borrow occurs here
-LL |     let _y = &mut a.y; //~ ERROR cannot borrow
-   |                   ^^^ mutable borrow occurs here
-LL |     //~^ mutable borrow occurs here
-LL | }
-   | - immutable borrow ends here
-
-error: aborting due to 16 previous errors
-
-Some errors occurred: E0382, E0502, E0503, E0505.
-For more information about an error, try `rustc --explain E0382`.
index 423a44514db81525a229aac04a32ca4f7e08bf8d..a7125450e1c278ce9cc0166d995b2b6f3049ec83 100644 (file)
@@ -8,28 +8,6 @@ LL |             let a = u.a; //~ ERROR use of moved value: `u.a`
    |
    = note: move occurs because `u` has type `U`, which does not implement the `Copy` trait
 
-error[E0382]: use of moved value: `u`
-  --> $DIR/borrowck-union-move-assign.rs:33:21
-   |
-LL |             let a = u.a;
-   |                     --- value moved here
-LL |             u.a = A;
-LL |             let a = u.a; // OK
-   |                     ^^^ value used here after move
-   |
-   = note: move occurs because `u` has type `U`, which does not implement the `Copy` trait
-
-error[E0382]: use of moved value: `u`
-  --> $DIR/borrowck-union-move-assign.rs:39:21
-   |
-LL |             let a = u.a;
-   |                     --- value moved here
-LL |             u.b = B;
-LL |             let a = u.a; // OK
-   |                     ^^^ value used here after move
-   |
-   = note: move occurs because `u` has type `U`, which does not implement the `Copy` trait
-
-error: aborting due to 3 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0382`.
diff --git a/src/test/ui/borrowck/issue-55552-ascribe-wildcard-to-structured-pattern.rs b/src/test/ui/borrowck/issue-55552-ascribe-wildcard-to-structured-pattern.rs
new file mode 100644 (file)
index 0000000..6d91fd3
--- /dev/null
@@ -0,0 +1,31 @@
+// compile-pass
+
+// rust-lang/rust#55552: The strategy pnkfelix landed in PR #55274
+// (for ensuring that NLL respects user-provided lifetime annotations)
+// did not handle the case where the ascribed type has some expliit
+// wildcards (`_`) mixed in, and it caused an internal compiler error
+// (ICE).
+//
+// This test is just checking that we do not ICE when such things
+// occur.
+
+struct X;
+struct Y;
+struct Z;
+
+struct Pair { x: X, y: Y }
+
+pub fn join<A, B, RA, RB>(oper_a: A, oper_b: B) -> (RA, RB)
+where A: FnOnce() -> RA + Send,
+      B: FnOnce() -> RB + Send,
+      RA: Send,
+      RB: Send
+{
+    (oper_a(), oper_b())
+}
+
+fn main() {
+    let ((_x, _y), _z): (_, Z) = join(|| (X, Y), || Z);
+
+    let (Pair { x: _x, y: _y }, Z): (_, Z) = join(|| Pair { x: X, y: Y }, || Z);
+}
index 7da9dbfc088cb5a0f15ef80b27272f918117cc78..fb1fe27774064cb97ecd35dc1c47cea959a08259 100644 (file)
@@ -4,6 +4,16 @@ error[E0381]: assign to part of possibly uninitialized variable: `x`
 LL |     x.a = 1;  //~ ERROR
    |     ^^^^^^^ use of possibly uninitialized `x`
 
-error: aborting due to previous error
+error[E0594]: cannot assign to `x.b`, as `x` is not declared as mutable
+  --> $DIR/reassignment_immutable_fields_overlapping.rs:23:5
+   |
+LL |     let x: Foo;
+   |         - help: consider changing this to be mutable: `mut x`
+LL |     x.a = 1;  //~ ERROR
+LL |     x.b = 22; //~ ERROR
+   |     ^^^^^^^^ cannot assign
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0381`.
+Some errors occurred: E0381, E0594.
+For more information about an error, try `rustc --explain E0381`.
index 613ee0a269e70cd62a285e3a469da5cde0bad64c..dc417957795f5b3b6765e7ea37de569e47ee7cce 100644 (file)
@@ -14,7 +14,7 @@ LL | impl Copy for &'static NotSync {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: conflicting implementation in crate `core`:
-           - impl<'_, T> std::marker::Copy for &T
+           - impl<T> std::marker::Copy for &T
              where T: ?Sized;
 
 error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `&[NotSync]`:
@@ -24,7 +24,7 @@ LL | impl Copy for &'static [NotSync] {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: conflicting implementation in crate `core`:
-           - impl<'_, T> std::marker::Copy for &T
+           - impl<T> std::marker::Copy for &T
              where T: ?Sized;
 
 error[E0206]: the trait `Copy` may not be implemented for this type
diff --git a/src/test/ui/consts/auxiliary/promotable_const_fn_lib.rs b/src/test/ui/consts/auxiliary/promotable_const_fn_lib.rs
new file mode 100644 (file)
index 0000000..f6bbcc6
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Crate that exports a const fn. Used for testing cross-crate.
+
+#![feature(staged_api, rustc_attrs)]
+#![stable(since="1.0.0", feature = "mep")]
+
+#![crate_type="rlib"]
+
+#[rustc_promotable]
+#[stable(since="1.0.0", feature = "mep")]
+#[inline]
+pub const fn foo() -> usize { 22 }
+
+#[stable(since="1.0.0", feature = "mep")]
+pub struct Foo(usize);
+
+impl Foo {
+    #[stable(since="1.0.0", feature = "mep")]
+    #[inline]
+    #[rustc_promotable]
+    pub const fn foo() -> usize { 22 }
+}
index 4481b75840487440d363502b2ec0f832fce9164e..c8bed4a2b77e147c29913c9477b1edb6a9339e58 100644 (file)
@@ -10,8 +10,6 @@
 
 // compile-pass
 
-#![feature(duration_getters)]
-
 use std::time::Duration;
 
 fn main() {
index d6ffca09e96d84a2717d443efac48cd384ed76e9..4136a7b6a724f2416970fd87009541dfc377fe78 100644 (file)
@@ -23,13 +23,16 @@ unsafe impl Sync for Foo {}
 
 static FOO: Foo = Foo(UnsafeCell::new(42));
 
+fn foo() {}
+
 static BAR: () = unsafe {
     *FOO.0.get() = 5;
-    //~^ ERROR calls in statics are limited to constant functions, tuple structs and tuple variants
-
+    //~^ ERROR statements in statics are unstable (see issue #48821)
     // This error is caused by a separate bug that the feature gate error is reported
     // even though the feature gate "const_let" is active.
-    //~| statements in statics are unstable (see issue #48821)
+
+    foo();
+    //~^ ERROR calls in statics are limited to constant functions, tuple structs and tuple variants
 };
 
 fn main() {
index 8eaed1dcab116b099a8d952bd4475e17c0ec73f7..c2bba27e4d1e29992595d93cd3daef068e290857 100644 (file)
@@ -1,17 +1,17 @@
-error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
-  --> $DIR/mod-static-with-const-fn.rs:27:6
-   |
-LL |     *FOO.0.get() = 5;
-   |      ^^^^^^^^^^^
-
 error[E0658]: statements in statics are unstable (see issue #48821)
-  --> $DIR/mod-static-with-const-fn.rs:27:5
+  --> $DIR/mod-static-with-const-fn.rs:29:5
    |
 LL |     *FOO.0.get() = 5;
    |     ^^^^^^^^^^^^^^^^
    |
    = help: add #![feature(const_let)] to the crate attributes to enable
 
+error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
+  --> $DIR/mod-static-with-const-fn.rs:34:5
+   |
+LL |     foo();
+   |     ^^^^^
+
 error: aborting due to 2 previous errors
 
 Some errors occurred: E0015, E0658.
diff --git a/src/test/ui/consts/const-prop-ice.rs b/src/test/ui/consts/const-prop-ice.rs
new file mode 100644 (file)
index 0000000..13309f9
--- /dev/null
@@ -0,0 +1,3 @@
+fn main() {
+    [0; 3][3u64 as usize]; //~ ERROR the len is 3 but the index is 3
+}
diff --git a/src/test/ui/consts/const-prop-ice.stderr b/src/test/ui/consts/const-prop-ice.stderr
new file mode 100644 (file)
index 0000000..749ef95
--- /dev/null
@@ -0,0 +1,10 @@
+error: index out of bounds: the len is 3 but the index is 3
+  --> $DIR/const-prop-ice.rs:2:5
+   |
+LL |     [0; 3][3u64 as usize]; //~ ERROR the len is 3 but the index is 3
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: #[deny(const_err)] on by default
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/const-prop-ice2.rs b/src/test/ui/consts/const-prop-ice2.rs
new file mode 100644 (file)
index 0000000..e5fd79f
--- /dev/null
@@ -0,0 +1,5 @@
+fn main() {
+    enum Enum { One=1 }
+    let xs=[0;1 as usize];
+    println!("{}", xs[Enum::One as usize]); //~ ERROR the len is 1 but the index is 1
+}
diff --git a/src/test/ui/consts/const-prop-ice2.stderr b/src/test/ui/consts/const-prop-ice2.stderr
new file mode 100644 (file)
index 0000000..4febd0e
--- /dev/null
@@ -0,0 +1,10 @@
+error: index out of bounds: the len is 1 but the index is 1
+  --> $DIR/const-prop-ice2.rs:4:20
+   |
+LL |     println!("{}", xs[Enum::One as usize]); //~ ERROR the len is 1 but the index is 1
+   |                    ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: #[deny(const_err)] on by default
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/consts/promote_fn_calls.rs b/src/test/ui/consts/promote_fn_calls.rs
new file mode 100644 (file)
index 0000000..045322d
--- /dev/null
@@ -0,0 +1,13 @@
+// compile-pass
+// aux-build:promotable_const_fn_lib.rs
+
+#![feature(nll)]
+
+extern crate promotable_const_fn_lib;
+
+use promotable_const_fn_lib::{foo, Foo};
+
+fn main() {
+    let x: &'static usize = &foo();
+    let x: &'static usize = &Foo::foo();
+}
diff --git a/src/test/ui/consts/promote_fn_calls_std.rs b/src/test/ui/consts/promote_fn_calls_std.rs
new file mode 100644 (file)
index 0000000..0350708
--- /dev/null
@@ -0,0 +1,30 @@
+// compile-pass
+
+#![feature(nll)]
+
+fn main() {
+    let x: &'static u8 = &u8::max_value();
+    let x: &'static u16 = &u16::max_value();
+    let x: &'static u32 = &u32::max_value();
+    let x: &'static u64 = &u64::max_value();
+    let x: &'static u128 = &u128::max_value();
+    let x: &'static usize = &usize::max_value();
+    let x: &'static u8 = &u8::min_value();
+    let x: &'static u16 = &u16::min_value();
+    let x: &'static u32 = &u32::min_value();
+    let x: &'static u64 = &u64::min_value();
+    let x: &'static u128 = &u128::min_value();
+    let x: &'static usize = &usize::min_value();
+    let x: &'static i8 = &i8::max_value();
+    let x: &'static i16 = &i16::max_value();
+    let x: &'static i32 = &i32::max_value();
+    let x: &'static i64 = &i64::max_value();
+    let x: &'static i128 = &i128::max_value();
+    let x: &'static isize = &isize::max_value();
+    let x: &'static i8 = &i8::min_value();
+    let x: &'static i16 = &i16::min_value();
+    let x: &'static i32 = &i32::min_value();
+    let x: &'static i64 = &i64::min_value();
+    let x: &'static i128 = &i128::min_value();
+    let x: &'static isize = &isize::min_value();
+}
diff --git a/src/test/ui/consts/std/cell.rs b/src/test/ui/consts/std/cell.rs
new file mode 100644 (file)
index 0000000..cf6c0f2
--- /dev/null
@@ -0,0 +1,30 @@
+use std::cell::*;
+
+// not ok, because this would create a silent constant with interior mutability.
+// the rules could be relaxed in the future
+static FOO: Wrap<*mut u32> = Wrap(Cell::new(42).as_ptr());
+//~^ ERROR cannot borrow a constant which may contain interior mutability
+
+static FOO3: Wrap<Cell<u32>> = Wrap(Cell::new(42));
+// ok
+static FOO4: Wrap<*mut u32> = Wrap(FOO3.0.as_ptr());
+
+// not ok, because the `as_ptr` call takes a reference to a type with interior mutability
+// which is not allowed in constants
+const FOO2: *mut u32 = Cell::new(42).as_ptr();
+//~^ ERROR cannot borrow a constant which may contain interior mutability
+
+struct IMSafeTrustMe(UnsafeCell<u32>);
+unsafe impl Send for IMSafeTrustMe {}
+unsafe impl Sync for IMSafeTrustMe {}
+
+static BAR: IMSafeTrustMe = IMSafeTrustMe(UnsafeCell::new(5));
+
+
+struct Wrap<T>(T);
+unsafe impl<T> Send for Wrap<T> {}
+unsafe impl<T> Sync for Wrap<T> {}
+
+static BAR_PTR: Wrap<*mut u32> = Wrap(BAR.0.get());
+
+fn main() {}
diff --git a/src/test/ui/consts/std/cell.stderr b/src/test/ui/consts/std/cell.stderr
new file mode 100644 (file)
index 0000000..f75aadf
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+  --> $DIR/cell.rs:5:35
+   |
+LL | static FOO: Wrap<*mut u32> = Wrap(Cell::new(42).as_ptr());
+   |                                   ^^^^^^^^^^^^^
+
+error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
+  --> $DIR/cell.rs:14:24
+   |
+LL | const FOO2: *mut u32 = Cell::new(42).as_ptr();
+   |                        ^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0492`.
diff --git a/src/test/ui/consts/std/char.rs b/src/test/ui/consts/std/char.rs
new file mode 100644 (file)
index 0000000..fe79059
--- /dev/null
@@ -0,0 +1,9 @@
+// run-pass
+
+static X: bool = 'a'.is_ascii();
+static Y: bool = 'ä'.is_ascii();
+
+fn main() {
+    assert!(X);
+    assert!(!Y);
+}
diff --git a/src/test/ui/consts/std/iter.rs b/src/test/ui/consts/std/iter.rs
new file mode 100644 (file)
index 0000000..e9af781
--- /dev/null
@@ -0,0 +1,9 @@
+// run-pass
+
+const I: std::iter::Empty<u32> = std::iter::empty();
+
+fn main() {
+    for i in I {
+        panic!("magical value creation: {}", i);
+    }
+}
diff --git a/src/test/ui/consts/std/slice.rs b/src/test/ui/consts/std/slice.rs
new file mode 100644 (file)
index 0000000..ad38105
--- /dev/null
@@ -0,0 +1,10 @@
+// compile-pass
+
+struct Wrap<T>(T);
+unsafe impl<T> Send for Wrap<T> {}
+unsafe impl<T> Sync for Wrap<T> {}
+
+static FOO: Wrap<*const u32> = Wrap([42, 44, 46].as_ptr());
+static BAR: Wrap<*const u8> = Wrap("hello".as_ptr());
+
+fn main() {}
index 4886ad7717574e6eae004a6529139beccaac83d3..76ff88d6cc62346b52412741cd1026668d7b5627 100644 (file)
@@ -5,7 +5,7 @@ LL | impl<Foo> Deref for Foo { } //~ ERROR must be used
    | ^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: conflicting implementation in crate `core`:
-           - impl<'_, T> std::ops::Deref for &T
+           - impl<T> std::ops::Deref for &T
              where T: ?Sized;
 
 error[E0210]: type parameter `Foo` must be used as the type parameter for some local type (e.g. `MyStruct<Foo>`)
index 489ebb033f84e8133c98961750ff7530ba4878dc..c35c7e10f5a38500ab26cff4ab0cc8854964f397 100644 (file)
@@ -14,5 +14,4 @@ trait Trait {
 
 type Foo = Trait; //~ ERROR E0191
 
-fn main() {
-}
+fn main() {}
diff --git a/src/test/ui/error-codes/E0719.rs b/src/test/ui/error-codes/E0719.rs
new file mode 100644 (file)
index 0000000..c7bfa85
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Foo: Iterator<Item = i32, Item = i32> {}
+
+type Unit = ();
+
+fn test() -> Box<Iterator<Item = (), Item = Unit>> {
+    Box::new(None.into_iter())
+}
+
+fn main() {
+    let _: &Iterator<Item = i32, Item = i32>;
+    test();
+}
diff --git a/src/test/ui/error-codes/E0719.stderr b/src/test/ui/error-codes/E0719.stderr
new file mode 100644 (file)
index 0000000..3a908fc
--- /dev/null
@@ -0,0 +1,19 @@
+error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
+  --> $DIR/E0719.rs:11:33
+   |
+LL | trait Foo: Iterator<Item = i32, Item = i32> {}
+   |                     ----------  ^^^^^^^^^^ re-bound here
+   |                     |
+   |                     `Item` bound here first
+
+error[E0719]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) is already specified
+  --> $DIR/E0719.rs:15:38
+   |
+LL | fn test() -> Box<Iterator<Item = (), Item = Unit>> {
+   |                           ---------  ^^^^^^^^^^^ re-bound here
+   |                           |
+   |                           `Item` bound here first
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0719`.
diff --git a/src/test/ui/extern/extern-const.fixed b/src/test/ui/extern/extern-const.fixed
new file mode 100644 (file)
index 0000000..dca5698
--- /dev/null
@@ -0,0 +1,25 @@
+// Check extern items cannot be const + `rustfix` suggests using
+// extern static.
+//
+// #54388: an unused reference to an undefined static may or may not
+// compile. To sidestep this by using one that *is* defined.
+
+// run-rustfix
+// ignore-wasm32 no external library to link to.
+// compile-flags: -g -Z continue-parse-after-error
+#![feature(libc)]
+extern crate libc;
+
+#[link(name = "rust_test_helpers", kind = "static")]
+extern "C" {
+    static rust_dbg_static_mut: libc::c_int; //~ ERROR extern items cannot be `const`
+}
+
+fn main() {
+    // We suggest turning the (illegal) extern `const` into an extern `static`,
+    // but this also requires `unsafe` (a deny-by-default lint at comment time,
+    // future error; Issue #36247)
+    unsafe {
+        let _x = rust_dbg_static_mut;
+    }
+}
index d8a167311d55c12dbe389a2187607208fceff214..07dbe545a850a46c26fb7e68abd58a3e88e68752 100644 (file)
@@ -1,18 +1,18 @@
-// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
+// Check extern items cannot be const + `rustfix` suggests using
+// extern static.
 //
-// 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.
+// #54388: an unused reference to an undefined static may or may not
+// compile. To sidestep this by using one that *is* defined.
 
-// FIXME(#54388): re-enable rustfix later, when this test has consistent output across targets
-// compile-flags: -Z continue-parse-after-error
+// run-rustfix
+// ignore-wasm32 no external library to link to.
+// compile-flags: -g -Z continue-parse-after-error
+#![feature(libc)]
+extern crate libc;
 
+#[link(name = "rust_test_helpers", kind = "static")]
 extern "C" {
-    const C: u8; //~ ERROR extern items cannot be `const`
+    const rust_dbg_static_mut: libc::c_int; //~ ERROR extern items cannot be `const`
 }
 
 fn main() {
@@ -20,6 +20,6 @@ fn main() {
     // but this also requires `unsafe` (a deny-by-default lint at comment time,
     // future error; Issue #36247)
     unsafe {
-        let _x = C;
+        let _x = rust_dbg_static_mut;
     }
 }
index cbed5e56c76c4523c42e39712d30cfc575bd2416..7ebaec0368e3d46f53c4f429a6fc3aad5e0f0343 100644 (file)
@@ -1,7 +1,7 @@
 error: extern items cannot be `const`
   --> $DIR/extern-const.rs:15:5
    |
-LL |     const C: u8; //~ ERROR extern items cannot be `const`
+LL |     const rust_dbg_static_mut: libc::c_int; //~ ERROR extern items cannot be `const`
    |     ^^^^^ help: try using a static value: `static`
 
 error: aborting due to previous error
diff --git a/src/test/ui/hygiene/no_implicit_prelude-2018.rs b/src/test/ui/hygiene/no_implicit_prelude-2018.rs
new file mode 100644 (file)
index 0000000..3ad7435
--- /dev/null
@@ -0,0 +1,11 @@
+// edition:2018
+
+#[no_implicit_prelude]
+mod bar {
+    fn f() {
+        ::std::print!(""); // OK
+        print!(); //~ ERROR cannot find macro `print!` in this scope
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/hygiene/no_implicit_prelude-2018.stderr b/src/test/ui/hygiene/no_implicit_prelude-2018.stderr
new file mode 100644 (file)
index 0000000..370fc97
--- /dev/null
@@ -0,0 +1,10 @@
+error: cannot find macro `print!` in this scope
+  --> $DIR/no_implicit_prelude-2018.rs:7:9
+   |
+LL |         print!(); //~ ERROR cannot find macro `print!` in this scope
+   |         ^^^^^
+   |
+   = help: have you added the `#[macro_use]` on the module/import?
+
+error: aborting due to previous error
+
index bf07bc05491cc3752afd543338b08af9a5ff4c09..5b6041945abea76a2f9d57e39d0b591a66ab9798 100644 (file)
@@ -21,7 +21,10 @@ mod bar {
         Vec::new(); //~ ERROR failed to resolve
         ().clone() //~ ERROR no method named `clone` found
     }
-    fn f() { ::foo::m!(); }
+    fn f() {
+        ::foo::m!();
+        println!(); // OK on 2015 edition (at least for now)
+    }
 }
 
 fn main() {}
diff --git a/src/test/ui/impl-trait/issue-55608-captures-empty-region.rs b/src/test/ui/impl-trait/issue-55608-captures-empty-region.rs
new file mode 100644 (file)
index 0000000..7ebc348
--- /dev/null
@@ -0,0 +1,22 @@
+// This used to ICE because it creates an `impl Trait` that captures a
+// hidden empty region.
+
+#![feature(conservative_impl_trait)]
+
+fn server() -> impl FilterBase2 { //~ ERROR [E0700]
+    segment2(|| { loop { } }).map2(|| "")
+}
+
+trait FilterBase2 {
+    fn map2<F>(self, _fn: F) -> Map2<F> where Self: Sized { loop { } }
+}
+
+struct Map2<F> { _func: F }
+
+impl<F> FilterBase2 for Map2<F> { }
+
+fn segment2<F>(_fn: F) -> Map2<F> where F: Fn() -> Result<(), ()> {
+    loop { }
+}
+
+fn main() { server(); }
diff --git a/src/test/ui/impl-trait/issue-55608-captures-empty-region.stderr b/src/test/ui/impl-trait/issue-55608-captures-empty-region.stderr
new file mode 100644 (file)
index 0000000..d1f1478
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+  --> $DIR/issue-55608-captures-empty-region.rs:6:16
+   |
+LL | fn server() -> impl FilterBase2 { //~ ERROR [E0700]
+   |                ^^^^^^^^^^^^^^^^
+   |
+   = note: hidden type `Map2<[closure@$DIR/issue-55608-captures-empty-region.rs:7:36: 7:41]>` captures an empty lifetime
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0700`.
index 654f230741e96f6e9b5cef5e55fe92cec7da9b56..5a08a097fd02faf3c60ec92bdbe04261c0af0105 100644 (file)
@@ -10,6 +10,8 @@
 
 // Test that the compiler will catch invalid inline assembly constraints.
 
+// ignore-emscripten
+
 #![feature(asm)]
 
 extern "C" {
index ce1f274749f1f70b67e5c70bfe67cdca050b9aa2..44facff080543aa8ea85917ae04c546126a25e90 100644 (file)
@@ -1,17 +1,17 @@
 error[E0668]: malformed inline assembly
-  --> $DIR/inline-asm-bad-constraint.rs:29:9
+  --> $DIR/inline-asm-bad-constraint.rs:31:9
    |
 LL |         asm!("" :"={rax"(rax)) //~ ERROR E0668
    |         ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0668]: malformed inline assembly
-  --> $DIR/inline-asm-bad-constraint.rs:37:9
+  --> $DIR/inline-asm-bad-constraint.rs:39:9
    |
 LL |         asm!("callq $0" : : "0"(foo)) //~ ERROR E0668
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0668]: malformed inline assembly
-  --> $DIR/inline-asm-bad-constraint.rs:44:9
+  --> $DIR/inline-asm-bad-constraint.rs:46:9
    |
 LL |         asm!("addb $1, $0" : "={rax}"((0i32, rax))); //~ ERROR E0668
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
index bbfb14b8d9d22d5e4ed00523bf0351610f394cba..0ee4080fd0cb1c4adefdb901d703881bf8619489 100644 (file)
@@ -11,6 +11,8 @@
 // Test that the compiler will catch passing invalid values to inline assembly
 // operands.
 
+// ignore-emscripten
+
 #![feature(asm)]
 
 #[repr(C)]
index 2f650bfcab7b52ac1ef27f4f8fe196da1909a2ca..1a99aa28f584ada4105e95324569404c7b9d5a28 100644 (file)
@@ -1,41 +1,41 @@
 error[E0669]: invalid value for constraint in inline assembly
-  --> $DIR/inline-asm-bad-operand.rs:29:24
+  --> $DIR/inline-asm-bad-operand.rs:31:24
    |
 LL |         asm!("" :: "r"("")); //~ ERROR E0669
    |                        ^^
 
 error[E0669]: invalid value for constraint in inline assembly
-  --> $DIR/inline-asm-bad-operand.rs:34:32
+  --> $DIR/inline-asm-bad-operand.rs:36:32
    |
 LL |         asm!("ret" : : "{rdi}"(target)); //~ ERROR E0669
    |                                ^^^^^^
 
 error[E0669]: invalid value for constraint in inline assembly
-  --> $DIR/inline-asm-bad-operand.rs:41:29
+  --> $DIR/inline-asm-bad-operand.rs:43:29
    |
 LL |     unsafe { asm!("" :: "i"(hello)) }; //~ ERROR E0669
    |                             ^^^^^
 
 error[E0669]: invalid value for constraint in inline assembly
-  --> $DIR/inline-asm-bad-operand.rs:49:38
+  --> $DIR/inline-asm-bad-operand.rs:51:38
    |
 LL |         asm!("movups $1, %xmm0"::"m"(arr)); //~ ERROR E0669
    |                                      ^^^
 
 error[E0669]: invalid value for constraint in inline assembly
-  --> $DIR/inline-asm-bad-operand.rs:56:32
+  --> $DIR/inline-asm-bad-operand.rs:58:32
    |
 LL |         asm!("mov sp, $0"::"r"(addr)); //~ ERROR E0669
    |                                ^^^^
 
 error[E0669]: invalid value for constraint in inline assembly
-  --> $DIR/inline-asm-bad-operand.rs:63:32
+  --> $DIR/inline-asm-bad-operand.rs:65:32
    |
 LL |         asm!("mov sp, $0"::"r"(addr), //~ ERROR E0669
    |                                ^^^^
 
 error[E0669]: invalid value for constraint in inline assembly
-  --> $DIR/inline-asm-bad-operand.rs:64:32
+  --> $DIR/inline-asm-bad-operand.rs:66:32
    |
 LL |                            "r"("hello e0669")); //~ ERROR E0669
    |                                ^^^^^^^^^^^^^
diff --git a/src/test/ui/issue-51947.rs b/src/test/ui/issue-51947.rs
deleted file mode 100644 (file)
index 7b79807..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// compile-pass
-
-#![crate_type = "lib"]
-#![feature(linkage)]
-
-// MergeFunctions will merge these via an anonymous internal
-// backing function, which must be named if ThinLTO buffers are used
-
-#[linkage = "weak"]
-pub fn fn1(a: u32, b: u32, c: u32) -> u32 {
-    a + b + c
-}
-
-#[linkage = "weak"]
-pub fn fn2(a: u32, b: u32, c: u32) -> u32 {
-    a + b + c
-}
index c43f8d778239771a7478c6daac54feab38304b66..9620f89338620c3bd715c9066d90e65d812c88f4 100644 (file)
@@ -1,10 +1,11 @@
-error[E0275]: overflow evaluating the requirement `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next`
+error[E0275]: overflow evaluating the requirement `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next: std::marker::Sized`
   --> $DIR/issue-23122-2.rs:17:15
    |
 LL | impl<T: Next> Next for GetNext<T> {
    |               ^^^^
    |
    = help: consider adding a `#![recursion_limit="128"]` attribute to your crate
+   = note: required because of the requirements on the impl of `Next` for `GetNext<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>`
 
 error: aborting due to previous error
 
index e4e97c58d8aa3f1703bcfd3e8015123b5b180bfd..83ebc92315552a291ef1722f3ba5f304c716f3f6 100644 (file)
@@ -8,8 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
 // compile-pass
+// ignore-emscripten no i128 support
 
 #![feature(nll)]
 
diff --git a/src/test/ui/issues/issue-51947.rs b/src/test/ui/issues/issue-51947.rs
new file mode 100644 (file)
index 0000000..3e0c3c0
--- /dev/null
@@ -0,0 +1,27 @@
+// 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
+
+#![crate_type = "lib"]
+#![feature(linkage)]
+
+// MergeFunctions will merge these via an anonymous internal
+// backing function, which must be named if ThinLTO buffers are used
+
+#[linkage = "weak"]
+pub fn fn1(a: u32, b: u32, c: u32) -> u32 {
+    a + b + c
+}
+
+#[linkage = "weak"]
+pub fn fn2(a: u32, b: u32, c: u32) -> u32 {
+    a + b + c
+}
diff --git a/src/test/ui/issues/issue-55796.rs b/src/test/ui/issues/issue-55796.rs
new file mode 100644 (file)
index 0000000..b48d4a9
--- /dev/null
@@ -0,0 +1,22 @@
+pub trait EdgeTrait<N> {
+    fn target(&self) -> N;
+}
+
+pub trait Graph<'a> {
+    type Node;
+    type Edge: EdgeTrait<Self::Node>;
+    type NodesIter: Iterator<Item = Self::Node> + 'a;
+    type EdgesIter: Iterator<Item = Self::Edge> + 'a;
+
+    fn nodes(&'a self) -> Self::NodesIter;
+    fn out_edges(&'a self, u: &Self::Node) -> Self::EdgesIter;
+    fn in_edges(&'a self, u: &Self::Node) -> Self::EdgesIter;
+
+    fn out_neighbors(&'a self, u: &Self::Node) -> Box<Iterator<Item = Self::Node>> {
+        Box::new(self.out_edges(u).map(|e| e.target()))
+    }
+
+    fn in_neighbors(&'a self, u: &Self::Node) -> Box<Iterator<Item = Self::Node>> {
+        Box::new(self.in_edges(u).map(|e| e.target()))
+    }
+}
diff --git a/src/test/ui/issues/issue-55796.stderr b/src/test/ui/issues/issue-55796.stderr
new file mode 100644 (file)
index 0000000..60ce829
--- /dev/null
@@ -0,0 +1,50 @@
+error[E0601]: `main` function not found in crate `issue_55796`
+   |
+   = note: consider adding a `main` function to `$DIR/issue-55796.rs`
+
+error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
+  --> $DIR/issue-55796.rs:16:9
+   |
+LL |         Box::new(self.out_edges(u).map(|e| e.target()))
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: first, the lifetime cannot outlive the lifetime 'a as defined on the trait at 5:17...
+  --> $DIR/issue-55796.rs:5:17
+   |
+LL | pub trait Graph<'a> {
+   |                 ^^
+note: ...so that the type `std::iter::Map<<Self as Graph<'a>>::EdgesIter, [closure@$DIR/issue-55796.rs:16:40: 16:54]>` will meet its required lifetime bounds
+  --> $DIR/issue-55796.rs:16:9
+   |
+LL |         Box::new(self.out_edges(u).map(|e| e.target()))
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: but, the lifetime must be valid for the static lifetime...
+   = note: ...so that the expression is assignable:
+           expected std::boxed::Box<(dyn std::iter::Iterator<Item=<Self as Graph<'a>>::Node> + 'static)>
+              found std::boxed::Box<dyn std::iter::Iterator<Item=<Self as Graph<'a>>::Node>>
+
+error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
+  --> $DIR/issue-55796.rs:20:9
+   |
+LL |         Box::new(self.in_edges(u).map(|e| e.target()))
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: first, the lifetime cannot outlive the lifetime 'a as defined on the trait at 5:17...
+  --> $DIR/issue-55796.rs:5:17
+   |
+LL | pub trait Graph<'a> {
+   |                 ^^
+note: ...so that the type `std::iter::Map<<Self as Graph<'a>>::EdgesIter, [closure@$DIR/issue-55796.rs:20:39: 20:53]>` will meet its required lifetime bounds
+  --> $DIR/issue-55796.rs:20:9
+   |
+LL |         Box::new(self.in_edges(u).map(|e| e.target()))
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: but, the lifetime must be valid for the static lifetime...
+   = note: ...so that the expression is assignable:
+           expected std::boxed::Box<(dyn std::iter::Iterator<Item=<Self as Graph<'a>>::Node> + 'static)>
+              found std::boxed::Box<dyn std::iter::Iterator<Item=<Self as Graph<'a>>::Node>>
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0495, E0601.
+For more information about an error, try `rustc --explain E0495`.
diff --git a/src/test/ui/lint/issue-50589-multiple-associated-types.rs b/src/test/ui/lint/issue-50589-multiple-associated-types.rs
deleted file mode 100644 (file)
index 2c789a1..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// 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
-
-use std::iter::Iterator;
-
-type Unit = ();
-
-fn test() ->  Box<Iterator<Item = (), Item = Unit>> {
-    Box::new(None.into_iter())
-}
-
-fn main() {
-    test();
-}
diff --git a/src/test/ui/lint/issue-50589-multiple-associated-types.stderr b/src/test/ui/lint/issue-50589-multiple-associated-types.stderr
deleted file mode 100644 (file)
index 7f0a1ee..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-warning: associated type binding `Item` specified more than once
-  --> $DIR/issue-50589-multiple-associated-types.rs:17:39
-   |
-LL | fn test() ->  Box<Iterator<Item = (), Item = Unit>> {
-   |                            ---------  ^^^^^^^^^^^ used more than once
-   |                            |
-   |                            first use of `Item`
-   |
-   = note: #[warn(duplicate_associated_type_bindings)] on by default
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #50589 <https://github.com/rust-lang/rust/issues/50589>
-
-warning: associated type binding `Item` specified more than once
-  --> $DIR/issue-50589-multiple-associated-types.rs:17:39
-   |
-LL | fn test() ->  Box<Iterator<Item = (), Item = Unit>> {
-   |                            ---------  ^^^^^^^^^^^ used more than once
-   |                            |
-   |                            first use of `Item`
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #50589 <https://github.com/rust-lang/rust/issues/50589>
-
diff --git a/src/test/ui/lint/lint-unused-mut-variables.lexical.stderr b/src/test/ui/lint/lint-unused-mut-variables.lexical.stderr
deleted file mode 100644 (file)
index 40f68c6..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:59:14
-   |
-LL |     let x = |mut y: isize| 10; //[lexical]~ ERROR: variable does not need to be mutable
-   |              ----^
-   |              |
-   |              help: remove this `mut`
-   |
-note: lint level defined here
-  --> $DIR/lint-unused-mut-variables.rs:19:9
-   |
-LL | #![deny(unused_mut)]
-   |         ^^^^^^^^^^
-
-error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:24:9
-   |
-LL |     let mut a = 3; //[lexical]~ ERROR: variable does not need to be mutable
-   |         ----^
-   |         |
-   |         help: remove this `mut`
-
-error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:26:9
-   |
-LL |     let mut a = 2; //[lexical]~ ERROR: variable does not need to be mutable
-   |         ----^
-   |         |
-   |         help: remove this `mut`
-
-error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:28:9
-   |
-LL |     let mut b = 3; //[lexical]~ ERROR: variable does not need to be mutable
-   |         ----^
-   |         |
-   |         help: remove this `mut`
-
-error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:30:9
-   |
-LL |     let mut a = vec![3]; //[lexical]~ ERROR: variable does not need to be mutable
-   |         ----^
-   |         |
-   |         help: remove this `mut`
-
-error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:32:10
-   |
-LL |     let (mut a, b) = (1, 2); //[lexical]~ ERROR: variable does not need to be mutable
-   |          ----^
-   |          |
-   |          help: remove this `mut`
-
-error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:34:9
-   |
-LL |     let mut a; //[lexical]~ ERROR: variable does not need to be mutable
-   |         ----^
-   |         |
-   |         help: remove this `mut`
-
-error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:38:9
-   |
-LL |     let mut b; //[lexical]~ ERROR: variable does not need to be mutable
-   |         ----^
-   |         |
-   |         help: remove this `mut`
-
-error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:47:9
-   |
-LL |         mut x => {} //[lexical]~ ERROR: variable does not need to be mutable
-   |         ----^
-   |         |
-   |         help: remove this `mut`
-
-error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:51:8
-   |
-LL |       (mut x, 1) | //[lexical]~ ERROR: variable does not need to be mutable
-   |        ----^
-   |        |
-   |        help: remove this `mut`
-
-error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:64:9
-   |
-LL |     let mut a = &mut 5; //[lexical]~ ERROR: variable does not need to be mutable
-   |         ----^
-   |         |
-   |         help: remove this `mut`
-
-error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:69:9
-   |
-LL |     let mut b = (&mut a,); //[lexical]~ ERROR: variable does not need to be mutable
-   |         ----^
-   |         |
-   |         help: remove this `mut`
-
-error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:72:9
-   |
-LL |     let mut x = &mut 1; //[lexical]~ ERROR: variable does not need to be mutable
-   |         ----^
-   |         |
-   |         help: remove this `mut`
-
-error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:84:9
-   |
-LL |     let mut v : &mut Vec<()> = &mut vec![]; //[lexical]~ ERROR: variable does not need to be mutable
-   |         ----^
-   |         |
-   |         help: remove this `mut`
-
-error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:61:13
-   |
-LL |     fn what(mut foo: isize) {} //[lexical]~ ERROR: variable does not need to be mutable
-   |             ----^^^
-   |             |
-   |             help: remove this `mut`
-
-error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:79:20
-   |
-LL |     fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] {
-   |                    ----^^^
-   |                    |
-   |                    help: remove this `mut`
-
-error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:143:9
-   |
-LL |     let mut b = vec![2]; //[lexical]~ ERROR: variable does not need to be mutable
-   |         ----^
-   |         |
-   |         help: remove this `mut`
-   |
-note: lint level defined here
-  --> $DIR/lint-unused-mut-variables.rs:139:8
-   |
-LL | #[deny(unused_mut)]
-   |        ^^^^^^^^^^
-
-error: aborting due to 17 previous errors
-
diff --git a/src/test/ui/lint/lint-unused-mut-variables.nll.stderr b/src/test/ui/lint/lint-unused-mut-variables.nll.stderr
deleted file mode 100644 (file)
index 40f68c6..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:59:14
-   |
-LL |     let x = |mut y: isize| 10; //[lexical]~ ERROR: variable does not need to be mutable
-   |              ----^
-   |              |
-   |              help: remove this `mut`
-   |
-note: lint level defined here
-  --> $DIR/lint-unused-mut-variables.rs:19:9
-   |
-LL | #![deny(unused_mut)]
-   |         ^^^^^^^^^^
-
-error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:24:9
-   |
-LL |     let mut a = 3; //[lexical]~ ERROR: variable does not need to be mutable
-   |         ----^
-   |         |
-   |         help: remove this `mut`
-
-error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:26:9
-   |
-LL |     let mut a = 2; //[lexical]~ ERROR: variable does not need to be mutable
-   |         ----^
-   |         |
-   |         help: remove this `mut`
-
-error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:28:9
-   |
-LL |     let mut b = 3; //[lexical]~ ERROR: variable does not need to be mutable
-   |         ----^
-   |         |
-   |         help: remove this `mut`
-
-error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:30:9
-   |
-LL |     let mut a = vec![3]; //[lexical]~ ERROR: variable does not need to be mutable
-   |         ----^
-   |         |
-   |         help: remove this `mut`
-
-error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:32:10
-   |
-LL |     let (mut a, b) = (1, 2); //[lexical]~ ERROR: variable does not need to be mutable
-   |          ----^
-   |          |
-   |          help: remove this `mut`
-
-error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:34:9
-   |
-LL |     let mut a; //[lexical]~ ERROR: variable does not need to be mutable
-   |         ----^
-   |         |
-   |         help: remove this `mut`
-
-error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:38:9
-   |
-LL |     let mut b; //[lexical]~ ERROR: variable does not need to be mutable
-   |         ----^
-   |         |
-   |         help: remove this `mut`
-
-error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:47:9
-   |
-LL |         mut x => {} //[lexical]~ ERROR: variable does not need to be mutable
-   |         ----^
-   |         |
-   |         help: remove this `mut`
-
-error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:51:8
-   |
-LL |       (mut x, 1) | //[lexical]~ ERROR: variable does not need to be mutable
-   |        ----^
-   |        |
-   |        help: remove this `mut`
-
-error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:64:9
-   |
-LL |     let mut a = &mut 5; //[lexical]~ ERROR: variable does not need to be mutable
-   |         ----^
-   |         |
-   |         help: remove this `mut`
-
-error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:69:9
-   |
-LL |     let mut b = (&mut a,); //[lexical]~ ERROR: variable does not need to be mutable
-   |         ----^
-   |         |
-   |         help: remove this `mut`
-
-error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:72:9
-   |
-LL |     let mut x = &mut 1; //[lexical]~ ERROR: variable does not need to be mutable
-   |         ----^
-   |         |
-   |         help: remove this `mut`
-
-error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:84:9
-   |
-LL |     let mut v : &mut Vec<()> = &mut vec![]; //[lexical]~ ERROR: variable does not need to be mutable
-   |         ----^
-   |         |
-   |         help: remove this `mut`
-
-error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:61:13
-   |
-LL |     fn what(mut foo: isize) {} //[lexical]~ ERROR: variable does not need to be mutable
-   |             ----^^^
-   |             |
-   |             help: remove this `mut`
-
-error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:79:20
-   |
-LL |     fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] {
-   |                    ----^^^
-   |                    |
-   |                    help: remove this `mut`
-
-error: variable does not need to be mutable
-  --> $DIR/lint-unused-mut-variables.rs:143:9
-   |
-LL |     let mut b = vec![2]; //[lexical]~ ERROR: variable does not need to be mutable
-   |         ----^
-   |         |
-   |         help: remove this `mut`
-   |
-note: lint level defined here
-  --> $DIR/lint-unused-mut-variables.rs:139:8
-   |
-LL | #[deny(unused_mut)]
-   |        ^^^^^^^^^^
-
-error: aborting due to 17 previous errors
-
index 14d836074dca377123a891ccae19858d03dab41c..a2005ba9f72e02db8b82d3d3736c3d6756d9d9a2 100644 (file)
@@ -8,8 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// revisions: lexical nll
-#![cfg_attr(nll, feature(nll))]
+
+
 
 // Exercise the unused_mut attribute in some positive and negative cases
 
 
 fn main() {
     // negative cases
-    let mut a = 3; //[lexical]~ ERROR: variable does not need to be mutable
-                   //[nll]~^ ERROR: variable does not need to be mutable
-    let mut a = 2; //[lexical]~ ERROR: variable does not need to be mutable
-                   //[nll]~^ ERROR: variable does not need to be mutable
-    let mut b = 3; //[lexical]~ ERROR: variable does not need to be mutable
-                   //[nll]~^ ERROR: variable does not need to be mutable
-    let mut a = vec![3]; //[lexical]~ ERROR: variable does not need to be mutable
-                         //[nll]~^ ERROR: variable does not need to be mutable
-    let (mut a, b) = (1, 2); //[lexical]~ ERROR: variable does not need to be mutable
-                             //[nll]~^ ERROR: variable does not need to be mutable
-    let mut a; //[lexical]~ ERROR: variable does not need to be mutable
-               //[nll]~^ ERROR: variable does not need to be mutable
+    let mut a = 3; //~ ERROR: variable does not need to be mutable
+
+    let mut a = 2; //~ ERROR: variable does not need to be mutable
+
+    let mut b = 3; //~ ERROR: variable does not need to be mutable
+
+    let mut a = vec![3]; //~ ERROR: variable does not need to be mutable
+
+    let (mut a, b) = (1, 2); //~ ERROR: variable does not need to be mutable
+
+    let mut a; //~ ERROR: variable does not need to be mutable
+
     a = 3;
 
-    let mut b; //[lexical]~ ERROR: variable does not need to be mutable
-               //[nll]~^ ERROR: variable does not need to be mutable
+    let mut b; //~ ERROR: variable does not need to be mutable
+
     if true {
         b = 3;
     } else {
@@ -44,45 +44,45 @@ fn main() {
     }
 
     match 30 {
-        mut x => {} //[lexical]~ ERROR: variable does not need to be mutable
-                    //[nll]~^ ERROR: variable does not need to be mutable
+        mut x => {} //~ ERROR: variable does not need to be mutable
+
     }
     match (30, 2) {
-      (mut x, 1) | //[lexical]~ ERROR: variable does not need to be mutable
-                   //[nll]~^ ERROR: variable does not need to be mutable
+      (mut x, 1) | //~ ERROR: variable does not need to be mutable
+
       (mut x, 2) |
       (mut x, 3) => {
       }
       _ => {}
     }
 
-    let x = |mut y: isize| 10; //[lexical]~ ERROR: variable does not need to be mutable
-                               //[nll]~^ ERROR: variable does not need to be mutable
-    fn what(mut foo: isize) {} //[lexical]~ ERROR: variable does not need to be mutable
-                               //[nll]~^ ERROR: variable does not need to be mutable
+    let x = |mut y: isize| 10; //~ ERROR: variable does not need to be mutable
+
+    fn what(mut foo: isize) {} //~ ERROR: variable does not need to be mutable
+
+
+    let mut a = &mut 5; //~ ERROR: variable does not need to be mutable
 
-    let mut a = &mut 5; //[lexical]~ ERROR: variable does not need to be mutable
-                        //[nll]~^ ERROR: variable does not need to be mutable
     *a = 4;
 
     let mut a = 5;
-    let mut b = (&mut a,); //[lexical]~ ERROR: variable does not need to be mutable
-    *b.0 = 4;              //[nll]~^ ERROR: variable does not need to be mutable
+    let mut b = (&mut a,); //~ ERROR: variable does not need to be mutable
+    *b.0 = 4;
+
+    let mut x = &mut 1; //~ ERROR: variable does not need to be mutable
 
-    let mut x = &mut 1; //[lexical]~ ERROR: variable does not need to be mutable
-                        //[nll]~^ ERROR: variable does not need to be mutable
     let mut f = || {
       *x += 1;
     };
     f();
 
     fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] {
-        &mut arg[..] //[lexical]~^ ERROR: variable does not need to be mutable
-                     //[nll]~^^ ERROR: variable does not need to be mutable
+        &mut arg[..] //~^ ERROR: variable does not need to be mutable
+
     }
 
-    let mut v : &mut Vec<()> = &mut vec![]; //[lexical]~ ERROR: variable does not need to be mutable
-                                            //[nll]~^ ERROR: variable does not need to be mutable
+    let mut v : &mut Vec<()> = &mut vec![]; //~ ERROR: variable does not need to be mutable
+
     v.push(());
 
     // positive cases
@@ -140,6 +140,6 @@ fn foo(mut a: isize) {
 fn bar() {
     #[allow(unused_mut)]
     let mut a = 3;
-    let mut b = vec![2]; //[lexical]~ ERROR: variable does not need to be mutable
-                         //[nll]~^ ERROR: variable does not need to be mutable
+    let mut b = vec![2]; //~ ERROR: variable does not need to be mutable
+
 }
diff --git a/src/test/ui/lint/lint-unused-mut-variables.stderr b/src/test/ui/lint/lint-unused-mut-variables.stderr
new file mode 100644 (file)
index 0000000..60e8400
--- /dev/null
@@ -0,0 +1,150 @@
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:59:14
+   |
+LL |     let x = |mut y: isize| 10; //~ ERROR: variable does not need to be mutable
+   |              ----^
+   |              |
+   |              help: remove this `mut`
+   |
+note: lint level defined here
+  --> $DIR/lint-unused-mut-variables.rs:19:9
+   |
+LL | #![deny(unused_mut)]
+   |         ^^^^^^^^^^
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:24:9
+   |
+LL |     let mut a = 3; //~ ERROR: variable does not need to be mutable
+   |         ----^
+   |         |
+   |         help: remove this `mut`
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:26:9
+   |
+LL |     let mut a = 2; //~ ERROR: variable does not need to be mutable
+   |         ----^
+   |         |
+   |         help: remove this `mut`
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:28:9
+   |
+LL |     let mut b = 3; //~ ERROR: variable does not need to be mutable
+   |         ----^
+   |         |
+   |         help: remove this `mut`
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:30:9
+   |
+LL |     let mut a = vec![3]; //~ ERROR: variable does not need to be mutable
+   |         ----^
+   |         |
+   |         help: remove this `mut`
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:32:10
+   |
+LL |     let (mut a, b) = (1, 2); //~ ERROR: variable does not need to be mutable
+   |          ----^
+   |          |
+   |          help: remove this `mut`
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:34:9
+   |
+LL |     let mut a; //~ ERROR: variable does not need to be mutable
+   |         ----^
+   |         |
+   |         help: remove this `mut`
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:38:9
+   |
+LL |     let mut b; //~ ERROR: variable does not need to be mutable
+   |         ----^
+   |         |
+   |         help: remove this `mut`
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:47:9
+   |
+LL |         mut x => {} //~ ERROR: variable does not need to be mutable
+   |         ----^
+   |         |
+   |         help: remove this `mut`
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:51:8
+   |
+LL |       (mut x, 1) | //~ ERROR: variable does not need to be mutable
+   |        ----^
+   |        |
+   |        help: remove this `mut`
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:64:9
+   |
+LL |     let mut a = &mut 5; //~ ERROR: variable does not need to be mutable
+   |         ----^
+   |         |
+   |         help: remove this `mut`
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:69:9
+   |
+LL |     let mut b = (&mut a,); //~ ERROR: variable does not need to be mutable
+   |         ----^
+   |         |
+   |         help: remove this `mut`
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:72:9
+   |
+LL |     let mut x = &mut 1; //~ ERROR: variable does not need to be mutable
+   |         ----^
+   |         |
+   |         help: remove this `mut`
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:84:9
+   |
+LL |     let mut v : &mut Vec<()> = &mut vec![]; //~ ERROR: variable does not need to be mutable
+   |         ----^
+   |         |
+   |         help: remove this `mut`
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:61:13
+   |
+LL |     fn what(mut foo: isize) {} //~ ERROR: variable does not need to be mutable
+   |             ----^^^
+   |             |
+   |             help: remove this `mut`
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:79:20
+   |
+LL |     fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] {
+   |                    ----^^^
+   |                    |
+   |                    help: remove this `mut`
+
+error: variable does not need to be mutable
+  --> $DIR/lint-unused-mut-variables.rs:143:9
+   |
+LL |     let mut b = vec![2]; //~ ERROR: variable does not need to be mutable
+   |         ----^
+   |         |
+   |         help: remove this `mut`
+   |
+note: lint level defined here
+  --> $DIR/lint-unused-mut-variables.rs:139:8
+   |
+LL | #[deny(unused_mut)]
+   |        ^^^^^^^^^^
+
+error: aborting due to 17 previous errors
+
diff --git a/src/test/ui/match/match-fn-call.rs b/src/test/ui/match/match-fn-call.rs
new file mode 100644 (file)
index 0000000..d9c50e7
--- /dev/null
@@ -0,0 +1,12 @@
+use std::path::Path;
+
+fn main() {
+    let path = Path::new("foo");
+    match path {
+        Path::new("foo") => println!("foo"),
+        //~^ ERROR expected tuple struct/variant
+        Path::new("bar") => println!("bar"),
+        //~^ ERROR expected tuple struct/variant
+        _ => (),
+    }
+}
diff --git a/src/test/ui/match/match-fn-call.stderr b/src/test/ui/match/match-fn-call.stderr
new file mode 100644 (file)
index 0000000..4e24621
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0164]: expected tuple struct/variant, found method `<Path>::new`
+  --> $DIR/match-fn-call.rs:6:9
+   |
+LL |         Path::new("foo") => println!("foo"),
+   |         ^^^^^^^^^^^^^^^^ not a tuple variant or struct
+
+error[E0164]: expected tuple struct/variant, found method `<Path>::new`
+  --> $DIR/match-fn-call.rs:8:9
+   |
+LL |         Path::new("bar") => println!("bar"),
+   |         ^^^^^^^^^^^^^^^^ not a tuple variant or struct
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0164`.
diff --git a/src/test/ui/nll/issue-55344.rs b/src/test/ui/nll/issue-55344.rs
new file mode 100644 (file)
index 0000000..131c979
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-pass
+
+#![feature(nll)]
+#![allow(unreachable_code)]
+#![deny(unused_mut)]
+
+pub fn foo() {
+    return;
+
+    let mut v = 0;
+    assert_eq!(v, 0);
+    v = 1;
+    assert_eq!(v, 1);
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/issue-55394.rs b/src/test/ui/nll/issue-55394.rs
new file mode 100644 (file)
index 0000000..452fc88
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(nll)]
+
+struct Bar;
+
+struct Foo<'s> {
+    bar: &'s mut Bar,
+}
+
+impl Foo<'_> {
+    fn new(bar: &mut Bar) -> Self {
+        Foo { bar }
+    }
+}
+
+fn main() { }
diff --git a/src/test/ui/nll/issue-55394.stderr b/src/test/ui/nll/issue-55394.stderr
new file mode 100644 (file)
index 0000000..284d7af
--- /dev/null
@@ -0,0 +1,12 @@
+error: unsatisfied lifetime constraints
+  --> $DIR/issue-55394.rs:21:9
+   |
+LL |     fn new(bar: &mut Bar) -> Self {
+   |                 -            ---- return type is Foo<'2>
+   |                 |
+   |                 let's call the lifetime of this reference `'1`
+LL |         Foo { bar }
+   |         ^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/nll/issue-55651.rs b/src/test/ui/nll/issue-55651.rs
new file mode 100644 (file)
index 0000000..b977783
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-pass
+
+#![feature(untagged_unions)]
+
+struct A;
+struct B;
+
+union U {
+    a: A,
+    b: B,
+}
+
+fn main() {
+    unsafe {
+        {
+            let mut u = U { a: A };
+            let a = u.a;
+            u.a = A;
+            let a = u.a; // OK
+        }
+        {
+            let mut u = U { a: A };
+            let a = u.a;
+            u.b = B;
+            let a = u.a; // OK
+        }
+    }
+}
index 1915fd82899aa2669898059cf37cce77d0bcc945..22cf15fb2e4a1458b8bab26e645ac6b833540627 100644 (file)
@@ -11,7 +11,7 @@
 
 use core::ops::RangeBounds;
 
-#[cfg(not(target_arch = "wasm32"))]
+#[cfg(any(not(target_arch = "wasm32"), target_os = "emscripten"))]
 #[lang = "eh_personality"]
 extern fn eh_personality() {}
 
diff --git a/src/test/ui/rfc-2306/convert-id-const-no-gate.rs b/src/test/ui/rfc-2306/convert-id-const-no-gate.rs
deleted file mode 100644 (file)
index 545c179..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// 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.
-
-// This test should fail since identity is not stable as a const fn yet.
-
-#![feature(convert_id)]
-
-fn main() {
-    const _FOO: u8 = ::std::convert::identity(42u8);
-}
diff --git a/src/test/ui/rfc-2306/convert-id-const-no-gate.stderr b/src/test/ui/rfc-2306/convert-id-const-no-gate.stderr
deleted file mode 100644 (file)
index dfd8619..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-error: `std::convert::identity` is not yet stable as a const fn
-  --> $DIR/convert-id-const-no-gate.rs:16:22
-   |
-LL |     const _FOO: u8 = ::std::convert::identity(42u8);
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: in Nightly builds, add `#![feature(const_convert_id)]` to the crate attributes to enable
-
-error: aborting due to previous error
-
index c546f11914f814eacf7e734a1bedaf632a6ed031..2e71aee57c2f18abcf1b5f014b0537cf2310c2cd 100644 (file)
@@ -8,12 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// This test should pass since we've opted into 'identity' as an
-// unstable const fn.
+// This test should pass since 'identity' is const fn.
 
 // compile-pass
 
-#![feature(convert_id, const_convert_id)]
+#![feature(convert_id)]
 
 fn main() {
     const _FOO: u8 = ::std::convert::identity(42u8);
diff --git a/src/test/ui/rfc1445/phantom-data-is-structurally-matchable.rs b/src/test/ui/rfc1445/phantom-data-is-structurally-matchable.rs
new file mode 100644 (file)
index 0000000..af025b9
--- /dev/null
@@ -0,0 +1,53 @@
+// run-pass
+
+// This file checks that `PhantomData` is considered structurally matchable.
+
+use std::marker::PhantomData;
+
+fn main() {
+    let mut count = 0;
+
+    // A type which is not structurally matchable:
+    struct NotSM;
+
+    // And one that is:
+    #[derive(PartialEq, Eq)]
+    struct SM;
+
+    // Check that SM is #[structural_match]:
+    const CSM: SM = SM;
+    match SM {
+        CSM => count += 1,
+    };
+
+    // Check that PhantomData<T> is #[structural_match] even if T is not.
+    const CPD1: PhantomData<NotSM> = PhantomData;
+    match PhantomData {
+        CPD1 => count += 1,
+    };
+
+    // Check that PhantomData<T> is #[structural_match] when T is.
+    const CPD2: PhantomData<SM> = PhantomData;
+    match PhantomData {
+        CPD2 => count += 1,
+    };
+
+    // Check that a type which has a PhantomData is `#[structural_match]`.
+    #[derive(PartialEq, Eq, Default)]
+    struct Foo {
+        alpha: PhantomData<NotSM>,
+        beta: PhantomData<SM>,
+    }
+
+    const CFOO: Foo = Foo {
+        alpha: PhantomData,
+        beta: PhantomData,
+    };
+
+    match Foo::default() {
+        CFOO => count += 1,
+    };
+
+    // Final count must be 4 now if all
+    assert_eq!(count, 4);
+}
diff --git a/src/test/ui/traits/trait-alias-object.rs b/src/test/ui/traits/trait-alias-object.rs
new file mode 100644 (file)
index 0000000..3adcd84
--- /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.
+
+#![feature(trait_alias)]
+
+trait EqAlias = Eq;
+trait IteratorAlias = Iterator;
+
+fn main() {
+    let _: &dyn EqAlias = &123;
+    let _: &dyn IteratorAlias = &vec![123].into_iter();
+}
diff --git a/src/test/ui/traits/trait-alias-object.stderr b/src/test/ui/traits/trait-alias-object.stderr
new file mode 100644 (file)
index 0000000..6b7b322
--- /dev/null
@@ -0,0 +1,18 @@
+error[E0038]: the trait `EqAlias` cannot be made into an object
+  --> $DIR/trait-alias-object.rs:17:13
+   |
+LL |     let _: &dyn EqAlias = &123;
+   |             ^^^^^^^^^^^ the trait `EqAlias` cannot be made into an object
+   |
+   = note: the trait cannot use `Self` as a type parameter in the supertraits or where-clauses
+
+error[E0191]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) must be specified
+  --> $DIR/trait-alias-object.rs:18:13
+   |
+LL |     let _: &dyn IteratorAlias = &vec![123].into_iter();
+   |             ^^^^^^^^^^^^^^^^^ missing associated type `Item` value
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0038, E0191.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/src/test/ui/traits/trait-alias-objects.rs b/src/test/ui/traits/trait-alias-objects.rs
deleted file mode 100644 (file)
index 3adcd84..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(trait_alias)]
-
-trait EqAlias = Eq;
-trait IteratorAlias = Iterator;
-
-fn main() {
-    let _: &dyn EqAlias = &123;
-    let _: &dyn IteratorAlias = &vec![123].into_iter();
-}
diff --git a/src/test/ui/traits/trait-alias-objects.stderr b/src/test/ui/traits/trait-alias-objects.stderr
deleted file mode 100644 (file)
index 8f9681e..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-error[E0038]: the trait `EqAlias` cannot be made into an object
-  --> $DIR/trait-alias-objects.rs:17:13
-   |
-LL |     let _: &dyn EqAlias = &123;
-   |             ^^^^^^^^^^^ the trait `EqAlias` cannot be made into an object
-   |
-   = note: the trait cannot use `Self` as a type parameter in the supertraits or where-clauses
-
-error[E0191]: the value of the associated type `Item` (from the trait `std::iter::Iterator`) must be specified
-  --> $DIR/trait-alias-objects.rs:18:13
-   |
-LL |     let _: &dyn IteratorAlias = &vec![123].into_iter();
-   |             ^^^^^^^^^^^^^^^^^ missing associated type `Item` value
-
-error: aborting due to 2 previous errors
-
-Some errors occurred: E0038, E0191.
-For more information about an error, try `rustc --explain E0038`.
diff --git a/src/test/ui/typeck/issue-55810-must-typeck-match-pats-before-guards.rs b/src/test/ui/typeck/issue-55810-must-typeck-match-pats-before-guards.rs
new file mode 100644 (file)
index 0000000..9eed80a
--- /dev/null
@@ -0,0 +1,23 @@
+// compile-pass
+
+// rust-lang/rust#55810: types for a binding in a match arm can be
+// inferred from arms that come later in the match.
+
+struct S;
+
+impl S {
+    fn method(&self) -> bool {
+        unimplemented!()
+    }
+}
+
+fn get<T>() -> T {
+    unimplemented!()
+}
+
+fn main() {
+    match get() {
+        x if x.method() => {}
+        &S => {}
+    }
+}
index 1fa30882067703202d13ad0bd53d630bc2c1de66..241fac0e3933063fa48a1a01f5d577e40af12e4d 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 1fa30882067703202d13ad0bd53d630bc2c1de66
+Subproject commit 241fac0e3933063fa48a1a01f5d577e40af12e4d
index a80bbd401ab43c70fcc305fea79db444e755069e..399f9f577edf5b8a08fefa295ac15129135cb8f2 100644 (file)
@@ -1870,11 +1870,9 @@ fn make_run_args(&self) -> ProcArgs {
             } else {
                 self.fatal("no NodeJS binary found (--nodejs)");
             }
-        }
-
-        // If this is otherwise wasm , then run tests under nodejs with our
+        // If this is otherwise wasm, then run tests under nodejs with our
         // shim
-        if self.config.target.contains("wasm32") {
+        } else if self.config.target.contains("wasm32") {
             if let Some(ref p) = self.config.nodejs {
                 args.push(p.clone());
             } else {
index ee14c62df30720138da3b28cd029f5b02b162d37..f2b08f8e0bbdd4bd840e6ba53c440602036d2717 100644 (file)
@@ -59,4 +59,4 @@ openssl = { version = "0.10.12", optional = true }
 
 
 [features]
-all-static = ['openssl/vendored', 'curl-sys/static-curl']
+all-static = ['openssl/vendored', 'curl-sys/static-curl', 'curl-sys/force-system-lib-on-osx']
index e8f197ba78afe1f83d4f7a158d1443ed2efa0a6c..12e9a54da52819939fcaccecb2fd1e549796ac7a 100644 (file)
@@ -27,7 +27,6 @@
 //!
 //! - core may not have platform-specific code
 //! - libcompiler_builtins may have platform-specific code
-//! - liballoc_system may have platform-specific code
 //! - libpanic_abort may have platform-specific code
 //! - libpanic_unwind may have platform-specific code
 //! - libunwind may have platform-specific code
@@ -51,7 +50,6 @@
 // Paths that may contain platform-specific code
 const EXCEPTION_PATHS: &[&str] = &[
     // std crates
-    "src/liballoc_system",
     "src/libcompiler_builtins",
     "src/liblibc",
     "src/libpanic_abort",