]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #52712 - oli-obk:const_eval_cleanups, r=RalfJung
authorbors <bors@rust-lang.org>
Fri, 3 Aug 2018 14:28:12 +0000 (14:28 +0000)
committerbors <bors@rust-lang.org>
Fri, 3 Aug 2018 14:28:12 +0000 (14:28 +0000)
Reintroduce `Undef` and properly check constant value sizes

r? @RalfJung

cc @eddyb

basically all kinds of silent failures that never occurred are assertions now

179 files changed:
RELEASES.md
config.toml.example
src/Cargo.lock
src/Cargo.toml
src/bootstrap/channel.rs
src/bootstrap/config.rs
src/bootstrap/test.rs
src/bootstrap/tool.rs
src/ci/docker/dist-various-1/Dockerfile
src/liballoc/lib.rs
src/liballoc/task.rs
src/liballoc/vec.rs
src/liballoc_jemalloc/build.rs
src/libcore/alloc.rs
src/libcore/char/methods.rs
src/libcore/intrinsics.rs
src/libcore/manually_drop_stage0.rs [deleted file]
src/libcore/mem.rs
src/libcore/slice/memchr.rs
src/libcore/slice/mod.rs
src/libcore/sync/atomic.rs
src/libcore/tests/char.rs
src/libcore/tests/slice.rs
src/libcore/unicode/tables.rs
src/libcore/unicode/unicode.py
src/librustc/hir/def.rs
src/librustc/hir/lowering.rs
src/librustc/ich/impls_hir.rs
src/librustc/ich/impls_syntax.rs
src/librustc/lib.rs
src/librustc/mir/traversal.rs
src/librustc/session/config.rs
src/librustc/session/mod.rs
src/librustc/traits/select.rs
src/librustc/ty/context.rs
src/librustc/ty/query/config.rs
src/librustc/ty/query/mod.rs
src/librustc/ty/query/plumbing.rs
src/librustc/util/profiling.rs [new file with mode: 0644]
src/librustc_codegen_llvm/back/linker.rs
src/librustc_codegen_llvm/back/lto.rs
src/librustc_codegen_llvm/back/write.rs
src/librustc_codegen_llvm/base.rs
src/librustc_codegen_llvm/debuginfo/create_scope_map.rs
src/librustc_codegen_llvm/lib.rs
src/librustc_codegen_llvm/llvm/diagnostic.rs
src/librustc_codegen_llvm/llvm/ffi.rs
src/librustc_codegen_llvm/mir/analyze.rs
src/librustc_codegen_llvm/mir/mod.rs
src/librustc_data_structures/bitvec.rs
src/librustc_data_structures/graph/implementation/mod.rs
src/librustc_data_structures/small_vec.rs
src/librustc_driver/driver.rs
src/librustc_lint/builtin.rs
src/librustc_lint/lib.rs
src/librustc_llvm/build.rs
src/librustc_llvm/lib.rs
src/librustc_mir/borrow_check/mod.rs
src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
src/librustc_mir/borrow_check/places_conflict.rs
src/librustc_mir/build/matches/mod.rs
src/librustc_mir/build/matches/test.rs
src/librustc_mir/dataflow/impls/borrowed_locals.rs
src/librustc_mir/monomorphize/collector.rs
src/librustc_mir/transform/generator.rs
src/librustc_mir/transform/inline.rs
src/librustc_mir/transform/qualify_consts.rs
src/librustc_mir/transform/remove_noop_landing_pads.rs
src/librustc_mir/transform/simplify.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/check_unused.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/macros.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_save_analysis/lib.rs
src/librustc_target/abi/call/mod.rs
src/librustc_target/abi/call/riscv.rs [new file with mode: 0644]
src/librustc_target/spec/mod.rs
src/librustc_target/spec/riscv32imac_unknown_none_elf.rs [new file with mode: 0644]
src/librustc_typeck/lib.rs
src/librustdoc/clean/mod.rs
src/librustdoc/visit_ast.rs
src/libstd/alloc.rs
src/libstd/io/mod.rs
src/libstd/macros.rs
src/libstd/sys/windows/c.rs
src/libstd/sys/windows/thread.rs
src/libsyntax/ast.rs
src/libsyntax/attr/mod.rs
src/libsyntax/ext/base.rs
src/libsyntax/ext/expand.rs
src/libsyntax/feature_gate.rs
src/libsyntax/lib.rs
src/libsyntax/parse/token.rs
src/libsyntax_pos/hygiene.rs
src/rustllvm/PassWrapper.cpp
src/rustllvm/RustWrapper.cpp
src/stage0.txt
src/test/codegen/vec-clear.rs [new file with mode: 0644]
src/test/compile-fail/auxiliary/issue-52489.rs [new file with mode: 0644]
src/test/compile-fail/auxiliary/lto-duplicate-symbols1.rs [new file with mode: 0644]
src/test/compile-fail/auxiliary/lto-duplicate-symbols2.rs [new file with mode: 0644]
src/test/compile-fail/feature-gate-tool_attributes.rs [deleted file]
src/test/compile-fail/issue-52489.rs [new file with mode: 0644]
src/test/compile-fail/lto-duplicate-symbols.rs [new file with mode: 0644]
src/test/compile-fail/unknown-tool-name.rs
src/test/compile-fail/unknown_tool_attributes-1.rs [deleted file]
src/test/run-pass-fulldeps/proc-macro/issue-42708.rs
src/test/run-pass-fulldeps/proc-macro/issue-50061.rs
src/test/run-pass/generator/yield-in-initializer.rs [new file with mode: 0644]
src/test/run-pass/issue-52557.rs [new file with mode: 0644]
src/test/rustdoc-ui/intra-doc-alias-ice.rs [new file with mode: 0644]
src/test/rustdoc-ui/intra-doc-alias-ice.stderr [new file with mode: 0644]
src/test/ui-fulldeps/proc-macro/parent-source-spans.rs
src/test/ui/asm-out-assign-imm.nll.stderr
src/test/ui/asm-out-assign-imm.rs
src/test/ui/asm-out-assign-imm.stderr
src/test/ui/async-matches-expr.rs [new file with mode: 0644]
src/test/ui/auxiliary/macro-in-other-crate.rs
src/test/ui/borrowck/issue-52967-edition-2018-needs-two-phase-borrows.rs [new file with mode: 0644]
src/test/ui/borrowck/mut-borrow-outside-loop.nll.stderr
src/test/ui/feature-gate-macros_in_extern.stderr
src/test/ui/feature-gate-tool_attributes.rs
src/test/ui/feature-gate-tool_attributes.stderr
src/test/ui/generator/dropck.nll.stderr
src/test/ui/issue-11692-1.rs
src/test/ui/issue-11692-1.stderr
src/test/ui/issue-11692-2.rs
src/test/ui/issue-11692-2.stderr
src/test/ui/issue-45696-long-live-borrows-in-boxes.rs [new file with mode: 0644]
src/test/ui/issue-45696-no-variant-box-recur.rs [new file with mode: 0644]
src/test/ui/issue-45696-scribble-on-boxed-borrow.ast.stderr [new file with mode: 0644]
src/test/ui/issue-45696-scribble-on-boxed-borrow.migrate.stderr [new file with mode: 0644]
src/test/ui/issue-45696-scribble-on-boxed-borrow.nll.stderr [new file with mode: 0644]
src/test/ui/issue-45696-scribble-on-boxed-borrow.rs [new file with mode: 0644]
src/test/ui/issue-49579.rs [new file with mode: 0644]
src/test/ui/issue-49824.nll.stderr [new file with mode: 0644]
src/test/ui/issue-49824.rs [new file with mode: 0644]
src/test/ui/issue-49824.stderr [new file with mode: 0644]
src/test/ui/issue-50187.rs
src/test/ui/issue-52126-assign-op-invariance.nll.stderr
src/test/ui/macro-path-prelude-fail-1.rs [new file with mode: 0644]
src/test/ui/macro-path-prelude-fail-1.stderr [new file with mode: 0644]
src/test/ui/macro-path-prelude-fail-2.rs [new file with mode: 0644]
src/test/ui/macro-path-prelude-fail-2.stderr [new file with mode: 0644]
src/test/ui/macro-path-prelude-fail-3.rs [new file with mode: 0644]
src/test/ui/macro-path-prelude-fail-3.stderr [new file with mode: 0644]
src/test/ui/macro-path-prelude-pass.rs [new file with mode: 0644]
src/test/ui/macro-path-prelude-shadowing.rs [new file with mode: 0644]
src/test/ui/macro-path-prelude-shadowing.stderr [new file with mode: 0644]
src/test/ui/macros/trace-macro.stderr
src/test/ui/nll/promotable-mutable-zst-doesnt-conflict.rs [new file with mode: 0644]
src/test/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.nll.stderr
src/test/ui/rust-2018/macro-use-warned-against.rs
src/test/ui/rust-2018/macro-use-warned-against.stderr
src/test/ui/span/dropck-object-cycle.nll.stderr
src/test/ui/span/regions-escape-loop-via-variable.nll.stderr
src/test/ui/span/regions-escape-loop-via-vec.nll.stderr
src/test/ui/target-feature-gate.rs
src/test/ui/target-feature-gate.stderr
src/test/ui/target-feature-wrong.rs
src/test/ui/target-feature-wrong.stderr
src/test/ui/tool-attributes-disabled-1.rs [new file with mode: 0644]
src/test/ui/tool-attributes-disabled-1.stderr [new file with mode: 0644]
src/test/ui/tool-attributes-disabled-2.rs [new file with mode: 0644]
src/test/ui/tool-attributes-misplaced-1.rs [new file with mode: 0644]
src/test/ui/tool-attributes-misplaced-1.stderr [new file with mode: 0644]
src/test/ui/tool-attributes-misplaced-2.rs [new file with mode: 0644]
src/test/ui/tool-attributes-misplaced-2.stderr [new file with mode: 0644]
src/test/ui/tool-attributes-shadowing.rs [new file with mode: 0644]
src/test/ui/tool-attributes-shadowing.stderr [new file with mode: 0644]
src/tools/build-manifest/src/main.rs
src/tools/cargo
src/tools/clippy
src/tools/rls
src/tools/rustc-workspace-hack/Cargo.toml [new file with mode: 0644]
src/tools/rustc-workspace-hack/README.md [new file with mode: 0644]
src/tools/rustc-workspace-hack/lib.rs [new file with mode: 0644]
src/tools/rustfmt

index 13042ab07e2175178d1d57574ec592fbb0a96821..e969b91b2b6435dcbc1003bbdc173de9c5912719 100644 (file)
@@ -216,7 +216,7 @@ Language
 
 Compiler
 --------
-- [Added the `armv5te-unknown-linux-musl` target.][50423]
+- [Added the `armv5te-unknown-linux-musleabi` target.][50423]
 
 Libraries
 ---------
index 99073416334f59ef7b02fcae69c7ac276c3084d3..eb7cd61a1b07e7a936e126db5f9e622421d291a5 100644 (file)
@@ -61,8 +61,8 @@
 # the same format as above, but since these targets are experimental, they are
 # not built by default and the experimental Rust compilation targets that depend
 # on them will not work unless the user opts in to building them. By default the
-# `WebAssembly` target is enabled when compiling LLVM from scratch.
-#experimental-targets = "WebAssembly"
+# `WebAssembly` and `RISCV` targets are enabled when compiling LLVM from scratch.
+#experimental-targets = "WebAssembly;RISCV"
 
 # Cap the number of parallel linker invocations when compiling LLVM.
 # This can be useful when building LLVM with debug info, which significantly
index b2e41589893cc4a55827e0fe3d67dce390defa7c..8a94faf2c5294608ab0b0c372fc24e125a9c3fac 100644 (file)
@@ -80,8 +80,8 @@ dependencies = [
  "colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "environment 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -183,7 +183,7 @@ dependencies = [
  "crypto-hash 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "curl 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "failure 0.1.1 (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)",
  "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -226,11 +226,11 @@ dependencies = [
  "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "crates-io 0.18.0",
- "crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "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.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "failure 0.1.1 (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)",
  "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -247,9 +247,9 @@ dependencies = [
  "libgit2-sys 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "miow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustfix 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-workspace-hack 1.0.0",
+ "rustfix 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -351,20 +351,18 @@ name = "clippy"
 version = "0.0.212"
 dependencies = [
  "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "cargo_metadata 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "clippy-mini-macro-test 0.2.0",
  "clippy_lints 0.0.212",
  "compiletest_rs 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-workspace-hack 1.0.0",
  "rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -452,7 +450,7 @@ dependencies = [
  "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "miow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustfix 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustfix 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -521,7 +519,7 @@ version = "0.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "curl 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "failure 0.1.1 (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.70 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -533,7 +531,7 @@ name = "crates-io"
 version = "0.18.0"
 dependencies = [
  "curl 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "failure 0.1.1 (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.70 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -606,6 +604,11 @@ name = "crossbeam-utils"
 version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "crossbeam-utils"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "crypto-hash"
 version = "0.3.1"
@@ -763,21 +766,22 @@ dependencies = [
 
 [[package]]
 name = "failure"
-version = "0.1.1"
+version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "failure_derive"
-version = "0.1.1"
+version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
- "synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "synstructure 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1773,7 +1777,7 @@ dependencies = [
  "clippy_lints 0.0.212",
  "crossbeam-channel 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "languageserver-types 0.45.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1790,6 +1794,7 @@ dependencies = [
  "rls-rustc 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-vfs 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-workspace-hack 1.0.0",
  "rustfmt-nightly 0.9.0",
  "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1848,7 +1853,6 @@ name = "rls-vfs"
 version = "0.4.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "racer 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1899,6 +1903,14 @@ dependencies = [
  "rustc-ap-rustc_data_structures 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "rustc-ap-arena"
+version = "211.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rustc-ap-rustc_data_structures 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "rustc-ap-rustc_cratesio_shim"
 version = "209.0.0"
@@ -1908,6 +1920,15 @@ dependencies = [
  "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "rustc-ap-rustc_cratesio_shim"
+version = "211.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "rustc-ap-rustc_data_structures"
 version = "209.0.0"
@@ -1926,6 +1947,24 @@ dependencies = [
  "stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "rustc-ap-rustc_data_structures"
+version = "211.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ena 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_cratesio_shim 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "rustc-ap-rustc_errors"
 version = "209.0.0"
@@ -1939,6 +1978,19 @@ dependencies = [
  "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "rustc-ap-rustc_errors"
+version = "211.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "rustc-ap-rustc_target"
 version = "209.0.0"
@@ -1950,11 +2002,27 @@ dependencies = [
  "rustc-ap-serialize 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "rustc-ap-rustc_target"
+version = "211.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_cratesio_shim 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "rustc-ap-serialize"
 version = "209.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "rustc-ap-serialize"
+version = "211.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "rustc-ap-syntax"
 version = "209.0.0"
@@ -1970,6 +2038,21 @@ dependencies = [
  "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "rustc-ap-syntax"
+version = "211.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_errors 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_target 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "rustc-ap-syntax_pos"
 version = "209.0.0"
@@ -1983,6 +2066,19 @@ dependencies = [
  "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "rustc-ap-syntax_pos"
+version = "211.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-arena 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "rustc-demangle"
 version = "0.1.8"
@@ -2030,6 +2126,14 @@ name = "rustc-serialize"
 version = "0.3.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "rustc-workspace-hack"
+version = "1.0.0"
+dependencies = [
+ "syn 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "rustc_allocator"
 version = "0.0.0"
@@ -2438,10 +2542,10 @@ dependencies = [
 
 [[package]]
 name = "rustfix"
-version = "0.4.1"
+version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2457,16 +2561,16 @@ dependencies = [
  "derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "isatty 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_target 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax_pos 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_target 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2706,11 +2810,13 @@ dependencies = [
 
 [[package]]
 name = "synstructure"
-version = "0.6.1"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc-macro2 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "syn 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -3119,6 +3225,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum crossbeam-epoch 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "285987a59c4d91388e749850e3cb7b3a92299668528caaacd08005b8f238c0ea"
 "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9"
 "checksum crossbeam-utils 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ea52fab26a99d96cdff39d0ca75c9716125937f5dba2ab83923aaaf5928f684a"
+"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.13 (registry+https://github.com/rust-lang/crates.io-index)" = "893713db705eab9847e050268507b0e2a2aad64e90a831874bd4e8e0d67f9523"
 "checksum curl-sys 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "de9cf174efdf90b5887c4e2e900769373c89c5e18152e8f3ed75b501a6f1c0fb"
@@ -3135,8 +3242,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum environment 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f4b14e20978669064c33b4c1e0fb4083412e40fe56cbea2eae80fd7591503ee"
 "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
 "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02"
-"checksum failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "934799b6c1de475a012a02dab0ace1ace43789ee4b99bcfbf1a2e3e8ced5de82"
-"checksum failure_derive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c7cdda555bb90c9bb67a3b670a0f42de8e73f5981524123ad8578aafec8ddb8b"
+"checksum failure 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7efb22686e4a466b1ec1a15c2898f91fa9cb340452496dca654032de20ff95b9"
+"checksum failure_derive 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "946d0e98a50d9831f5d589038d2ca7f8f455b1c21028c0db0e84116a12696426"
 "checksum filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "da4b9849e77b13195302c174324b5ba73eec9b236b24c221a61000daefb95c5f"
 "checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33"
 "checksum flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fac2277e84e5e858483756647a9d0aa8d9a2b7cba517fd84325a0aaa69a0909"
@@ -3248,20 +3355,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a"
 "checksum rls-vfs 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ecbc8541b4c341d6271eae10f869dd9d36db871afe184f5b6f9bffbd6ed0373f"
 "checksum rustc-ap-arena 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b098827864368459cbc7a79fbc54eafb92df7e00a46c0cda352b5a21583ee436"
+"checksum rustc-ap-arena 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eec75ed880706dd9a05bc770c327ed142fa7d4b648d9757fbc71d821d68448a5"
 "checksum rustc-ap-rustc_cratesio_shim 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef4d923dea14fb085bca743fb982f6a3bc11c0d5d30b822bcf6fa16e9464a56c"
+"checksum rustc-ap-rustc_cratesio_shim 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0f5d54615bedbae65a976e0835edf0de90dd962ec818c0149fe181d5cd81da9e"
 "checksum rustc-ap-rustc_data_structures 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18c6a5c9edc6b4ae035cdc03af7d8662d39fad7879c5501d103e7087dfaebc80"
+"checksum rustc-ap-rustc_data_structures 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7c51cc6e79eab25c7ea84a7e104e81e6f44cca32709df54c2cdb4e7059d7843"
 "checksum rustc-ap-rustc_errors 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9a1e9bdc597abd95cebce0c14c1da58943a9e5b8255530a0fec30659d144eb0b"
+"checksum rustc-ap-rustc_errors 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff050095b7afb254506591ee7d3a5d0fb9c03c16f8c2741b588178085e563d49"
 "checksum rustc-ap-rustc_target 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "142ddef3dc12dda2bcd3412f0d96d3745413a8fbc2f224f0cc97afa04c071d89"
+"checksum rustc-ap-rustc_target 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "53c7a8c21c3b05f24998fa6ab9ded6269810a2f3ae12ff301c432c1e9fa8e111"
 "checksum rustc-ap-serialize 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8b08f8f175b038a82caa7e51fc52b72ff96cfe8c1429755da30380dbd4199c7f"
+"checksum rustc-ap-serialize 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad4713c2c0c26a45ead8fb16fee88e16fecf999588ae6920847cbaeb19565b7f"
 "checksum rustc-ap-syntax 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4c802e0e1fbc64eddc21e0798527eb1f5fdbd5781d119bd2c44b6130afdc81cc"
+"checksum rustc-ap-syntax 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "768e2698f912913be2ccd355b2dea62c978efc356f75db1400605f3642905d53"
 "checksum rustc-ap-syntax_pos 209.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "008d47cc54ed12a2784217b9e6630a7fa1c8dc3591a283f65ad4b7fa307d49d5"
+"checksum rustc-ap-syntax_pos 211.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a280dc8919aa7f684832ba3eeab2f6c96dbe2e2e4f6a922f7f0bdb3a9dd9e641"
 "checksum rustc-demangle 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "76d7ba1feafada44f2d38eed812bd2489a03c0f5abb975799251518b68848649"
 "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8"
 "checksum rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c6d5a683c6ba4ed37959097e88d71c9e8e26659a3cb5be8b389078e7ad45306"
 "checksum rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40f06724db71e18d68b3b946fdf890ca8c921d9edccc1404fdfdb537b0d12649"
 "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
 "checksum rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a54aa04a10c68c1c4eacb4337fd883b435997ede17a9385784b990777686b09a"
-"checksum rustfix 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "86f77b09d42bae4adfbcd105a8914e2d9fb46b63612c1a765b824a2b4a4bb814"
+"checksum rustfix 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "756567f00f7d89c9f89a5c401b8b1caaa122e27240b9eaadd0bb52ee0b680b1b"
 "checksum same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cfb6eded0b06a0b512c8ddbcf04089138c9b4362c2f696f3c3d76039d68f3637"
 "checksum schannel 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "dc1fabf2a7b6483a141426e1afd09ad543520a77ac49bd03c286e7696ccfd77f"
 "checksum scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28"
@@ -3288,7 +3403,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum syn 0.13.11 (registry+https://github.com/rust-lang/crates.io-index)" = "14f9bf6292f3a61d2c716723fdb789a41bbe104168e6f496dc6497e531ea1b9b"
 "checksum syn 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)" = "2beff8ebc3658f07512a413866875adddd20f4fd47b2a4e6c9da65cd281baaea"
 "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
-"checksum synstructure 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a761d12e6d8dcb4dcf952a7a89b475e3a9d69e4a69307e01a470977642914bd"
+"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 tempfile 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "47776f63b85777d984a50ce49d6b9e58826b6a3766a449fc95bc66cd5663c15b"
 "checksum tendril 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9de21546595a0873061940d994bbbc5c35f024ae4fd61ec5c5b159115684f508"
index 62403700f3a4010a9acf93754a59bdfdffb2a00e..01663487f92e12459857cecd4135d2272d2bfa14 100644 (file)
@@ -52,11 +52,15 @@ debug-assertions = false
 [patch."https://github.com/rust-lang/cargo"]
 cargo = { path = "tools/cargo" }
 
-[patch."https://github.com/rust-lang-nursery/rustfmt"]
+[patch.crates-io]
 # Similar to Cargo above we want the RLS to use a vendored version of `rustfmt`
 # that we're shipping as well (to ensure that the rustfmt in RLS and the
 # `rustfmt` executable are the same exact version).
 rustfmt-nightly = { path = "tools/rustfmt" }
 
+# See comments in `tools/rustc-workspace-hack/README.md` for what's going on
+# here
+rustc-workspace-hack = { path = 'tools/rustc-workspace-hack' }
+
 [patch."https://github.com/rust-lang-nursery/rust-clippy"]
 clippy_lints = { path = "tools/clippy/clippy_lints" }
index 04d576df95546b98d58bac8316e69ae280b221d0..fa2b58fb2daa711714407124900514f49798d31b 100644 (file)
@@ -24,7 +24,7 @@
 use config::Config;
 
 // The version number
-pub const CFG_RELEASE_NUM: &str = "1.29.0";
+pub const CFG_RELEASE_NUM: &str = "1.30.0";
 
 pub struct GitInfo {
     inner: Option<Info>,
index 0a8a5c87d0da1a4b1a90cbd5aad26b634f02ae34..1a94d597ef895d6e5ba8b0cdc0ceab073ca1ffec 100644 (file)
@@ -507,7 +507,7 @@ pub fn parse(args: &[String]) -> Config {
             set(&mut config.llvm_link_shared, llvm.link_shared);
             config.llvm_targets = llvm.targets.clone();
             config.llvm_experimental_targets = llvm.experimental_targets.clone()
-                .unwrap_or("WebAssembly".to_string());
+                .unwrap_or("WebAssembly;RISCV".to_string());
             config.llvm_link_jobs = llvm.link_jobs;
             config.llvm_clang_cl = llvm.clang_cl.clone();
         }
index 24a1dbbde66396c756df043a78cc62974fe27ad0..c86010379f495fe56e89a31ff1eed0106bd5a513 100644 (file)
@@ -298,6 +298,8 @@ fn run(self, builder: &Builder) {
         cargo.env("RLS_TEST_WORKSPACE_DIR", test_workspace_path);
 
         builder.add_rustc_lib_path(compiler, &mut cargo);
+        cargo.arg("--")
+            .args(builder.config.cmd.test_args());
 
         if try_run(builder, &mut cargo) {
             builder.save_toolstate("rls", ToolState::TestPass);
index 5e68b797b3d54fe4a80b7e8a5724e410e29e6a12..eaa316494477e73eb6ac8934fb22c6bd4c96a0c6 100644 (file)
@@ -221,6 +221,10 @@ fn run(self, builder: &Builder) -> Option<PathBuf> {
                          prev.0, &prev_features - &cur_features, prev.1);
             }
             println!("");
+            println!("to fix this you will probably want to edit the local \
+                      src/tools/rustc-workspace-hack/Cargo.toml crate, as \
+                      that will update the dependency graph to ensure that \
+                      these crates all share the same feature set");
             panic!("tools should not compile multiple copies of the same crate");
         }
 
index 6302f550091ad6285df2584ed6a26022f462cf18..bfc5e712f76c3aa1802e5a66fe45472454728b9b 100644 (file)
@@ -102,6 +102,7 @@ ENV TARGETS=$TARGETS,thumbv6m-none-eabi
 ENV TARGETS=$TARGETS,thumbv7m-none-eabi
 ENV TARGETS=$TARGETS,thumbv7em-none-eabi
 ENV TARGETS=$TARGETS,thumbv7em-none-eabihf
+ENV TARGETS=$TARGETS,riscv32imac-unknown-none-elf
 
 ENV CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \
     CC_mips_unknown_linux_musl=mips-openwrt-linux-gcc \
index ef619527e064a34d2f8f387881619570393cde5d..ca1b7507b5e9b0dcc8062c632dd785883b7ae4c3 100644 (file)
@@ -162,10 +162,7 @@ mod boxed {
 #[cfg(test)]
 mod boxed_test;
 pub mod collections;
-#[cfg(any(
-    all(stage0, target_has_atomic = "ptr"),
-    all(not(stage0), target_has_atomic = "ptr", target_has_atomic = "cas")
-))]
+#[cfg(all(target_has_atomic = "ptr", target_has_atomic = "cas"))]
 pub mod sync;
 pub mod rc;
 pub mod raw_vec;
index 9792d52dd66d26c658bc5e3fbcb380f0f5022081..7a4eda21a601a61442dd1d4fbf6d68295cb29526 100644 (file)
 
 pub use core::task::*;
 
-#[cfg(any(
-    all(stage0, target_has_atomic = "ptr"),
-    all(not(stage0), target_has_atomic = "ptr", target_has_atomic = "cas")
-))]
+#[cfg(all(target_has_atomic = "ptr", target_has_atomic = "cas"))]
 pub use self::if_arc::*;
 
-#[cfg(any(
-    all(stage0, target_has_atomic = "ptr"),
-    all(not(stage0), target_has_atomic = "ptr", target_has_atomic = "cas")
-))]
+#[cfg(all(target_has_atomic = "ptr", target_has_atomic = "cas"))]
 mod if_arc {
     use super::*;
     use core::marker::PhantomData;
@@ -53,10 +47,7 @@ unsafe fn wake_local(arc_self: &Arc<Self>) {
         }
     }
 
-    #[cfg(any(
-        all(stage0, target_has_atomic = "ptr"),
-        all(not(stage0), target_has_atomic = "ptr", target_has_atomic = "cas")
-    ))]
+    #[cfg(all(target_has_atomic = "ptr", target_has_atomic = "cas"))]
     struct ArcWrapped<T>(PhantomData<T>);
 
     unsafe impl<T: Wake + 'static> UnsafeWake for ArcWrapped<T> {
index 5efe1e23309a7d7a84e96796149be522763511c9..cc913dfbb4b01e140abb47403998f7a65c224f3a 100644 (file)
@@ -690,14 +690,20 @@ pub fn into_boxed_slice(mut self) -> Box<[T]> {
     /// [`drain`]: #method.drain
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn truncate(&mut self, len: usize) {
+        let current_len = self.len;
         unsafe {
+            let mut ptr = self.as_mut_ptr().offset(self.len as isize);
+            // Set the final length at the end, keeping in mind that
+            // dropping an element might panic. Works around a missed
+            // optimization, as seen in the following issue:
+            // https://github.com/rust-lang/rust/issues/51802
+            let mut local_len = SetLenOnDrop::new(&mut self.len);
+
             // drop any extra elements
-            while len < self.len {
-                // decrement len before the drop_in_place(), so a panic on Drop
-                // doesn't re-drop the just-failed value.
-                self.len -= 1;
-                let len = self.len;
-                ptr::drop_in_place(self.get_unchecked_mut(len));
+            for _ in len..current_len {
+                local_len.decrement_len(1);
+                ptr = ptr.offset(-1);
+                ptr::drop_in_place(ptr);
             }
         }
     }
@@ -1512,6 +1518,11 @@ fn new(len: &'a mut usize) -> Self {
     fn increment_len(&mut self, increment: usize) {
         self.local_len += increment;
     }
+
+    #[inline]
+    fn decrement_len(&mut self, decrement: usize) {
+        self.local_len -= decrement;
+    }
 }
 
 impl<'a> Drop for SetLenOnDrop<'a> {
index 0aa46dc6d205fa0976caf5a7bbd005abcd4b26e7..fbda425a70bf5d6388455a4a0014e58a0a13d1d0 100644 (file)
@@ -105,11 +105,10 @@ fn main() {
         cmd.arg("--with-jemalloc-prefix=je_");
     }
 
-    // FIXME: building with jemalloc assertions is currently broken.
-    // See <https://github.com/rust-lang/rust/issues/44152>.
-    //if cfg!(feature = "debug") {
-    //    cmd.arg("--enable-debug");
-    //}
+    if cfg!(feature = "debug") {
+        // Enable jemalloc assertions.
+        cmd.arg("--enable-debug");
+    }
 
     cmd.arg(format!("--host={}", build_helper::gnu_target(&target)));
     cmd.arg(format!("--build={}", build_helper::gnu_target(&host)));
index b6ac248b79f8666331ab77c82d7aa9d311b188ff..39ec5d6411c16c26b3161414426cc6722f18e809 100644 (file)
 use ptr::{self, NonNull};
 use num::NonZeroUsize;
 
-#[unstable(feature = "alloc_internals", issue = "0")]
-#[cfg(stage0)]
-pub type Opaque = u8;
-
 /// Represents the combination of a starting address and
 /// a total capacity of the returned block.
 #[unstable(feature = "allocator_api", issue = "32838")]
@@ -48,7 +44,7 @@ fn size_align<T>() -> (usize, usize) {
 /// use specific allocators with looser requirements.)
 #[stable(feature = "alloc_layout", since = "1.28.0")]
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
-#[cfg_attr(not(stage0), lang = "alloc_layout")]
+#[lang = "alloc_layout"]
 pub struct Layout {
     // size of the requested block of memory, measured in bytes.
     size_: usize,
index eee78de903628cee1514f40a0dc86315637dc210..33fd6947c1e4b6471d978a13bd69058695cf33e6 100644 (file)
@@ -673,11 +673,11 @@ pub fn is_whitespace(self) -> bool {
     /// assert!('٣'.is_alphanumeric());
     /// assert!('7'.is_alphanumeric());
     /// assert!('৬'.is_alphanumeric());
+    /// assert!('¾'.is_alphanumeric());
+    /// assert!('①'.is_alphanumeric());
     /// assert!('K'.is_alphanumeric());
     /// assert!('و'.is_alphanumeric());
     /// assert!('藏'.is_alphanumeric());
-    /// assert!(!'¾'.is_alphanumeric());
-    /// assert!(!'①'.is_alphanumeric());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -727,11 +727,11 @@ pub(crate) fn is_grapheme_extended(self) -> bool {
     /// assert!('٣'.is_numeric());
     /// assert!('7'.is_numeric());
     /// assert!('৬'.is_numeric());
+    /// assert!('¾'.is_numeric());
+    /// assert!('①'.is_numeric());
     /// assert!(!'K'.is_numeric());
     /// assert!(!'و'.is_numeric());
     /// assert!(!'藏'.is_numeric());
-    /// assert!(!'¾'.is_numeric());
-    /// assert!(!'①'.is_numeric());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
index 854cb5f4e3b3f77a1791896e3f8df6d0eaba57dd..9ddf902349dd2e633ae87aa2c03ebebb0e28e96f 100644 (file)
@@ -1087,11 +1087,9 @@ pub fn volatile_copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T,
 
     /// Perform a volatile load from the `src` pointer
     /// The pointer is not required to be aligned.
-    #[cfg(not(stage0))]
     pub fn unaligned_volatile_load<T>(src: *const T) -> T;
     /// Perform a volatile store to the `dst` pointer.
     /// The pointer is not required to be aligned.
-    #[cfg(not(stage0))]
     pub fn unaligned_volatile_store<T>(dst: *mut T, val: T);
 
     /// Returns the square root of an `f32`
diff --git a/src/libcore/manually_drop_stage0.rs b/src/libcore/manually_drop_stage0.rs
deleted file mode 100644 (file)
index 8643219..0000000
+++ /dev/null
@@ -1,195 +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.
-
-/// A wrapper to inhibit compiler from automatically calling `T`’s destructor.
-///
-/// This wrapper is 0-cost.
-///
-/// # Examples
-///
-/// This wrapper helps with explicitly documenting the drop order dependencies between fields of
-/// the type:
-///
-/// ```rust
-/// use std::mem::ManuallyDrop;
-/// struct Peach;
-/// struct Banana;
-/// struct Melon;
-/// struct FruitBox {
-///     // Immediately clear there’s something non-trivial going on with these fields.
-///     peach: ManuallyDrop<Peach>,
-///     melon: Melon, // Field that’s independent of the other two.
-///     banana: ManuallyDrop<Banana>,
-/// }
-///
-/// impl Drop for FruitBox {
-///     fn drop(&mut self) {
-///         unsafe {
-///             // Explicit ordering in which field destructors are run specified in the intuitive
-///             // location – the destructor of the structure containing the fields.
-///             // Moreover, one can now reorder fields within the struct however much they want.
-///             ManuallyDrop::drop(&mut self.peach);
-///             ManuallyDrop::drop(&mut self.banana);
-///         }
-///         // After destructor for `FruitBox` runs (this function), the destructor for Melon gets
-///         // invoked in the usual manner, as it is not wrapped in `ManuallyDrop`.
-///     }
-/// }
-/// ```
-#[stable(feature = "manually_drop", since = "1.20.0")]
-#[allow(unions_with_drop_fields)]
-#[derive(Copy)]
-pub union ManuallyDrop<T>{ value: T }
-
-impl<T> ManuallyDrop<T> {
-    /// Wrap a value to be manually dropped.
-    ///
-    /// # Examples
-    ///
-    /// ```rust
-    /// use std::mem::ManuallyDrop;
-    /// 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: value }
-    }
-
-    /// Extract the value from the ManuallyDrop container.
-    ///
-    /// # Examples
-    ///
-    /// ```rust
-    /// use std::mem::ManuallyDrop;
-    /// let x = ManuallyDrop::new(Box::new(()));
-    /// let _: Box<()> = ManuallyDrop::into_inner(x);
-    /// ```
-    #[stable(feature = "manually_drop", since = "1.20.0")]
-    #[inline]
-    pub fn into_inner(slot: ManuallyDrop<T>) -> T {
-        unsafe {
-            slot.value
-        }
-    }
-
-    /// Manually drops the contained value.
-    ///
-    /// # Safety
-    ///
-    /// This function runs the destructor of the contained value and thus the wrapped value
-    /// now represents uninitialized data. It is up to the user of this method to ensure the
-    /// uninitialized data is not actually used.
-    #[stable(feature = "manually_drop", since = "1.20.0")]
-    #[inline]
-    pub unsafe fn drop(slot: &mut ManuallyDrop<T>) {
-        ptr::drop_in_place(&mut slot.value)
-    }
-}
-
-#[stable(feature = "manually_drop", since = "1.20.0")]
-impl<T> Deref for ManuallyDrop<T> {
-    type Target = T;
-    #[inline]
-    fn deref(&self) -> &Self::Target {
-        unsafe {
-            &self.value
-        }
-    }
-}
-
-#[stable(feature = "manually_drop", since = "1.20.0")]
-impl<T> DerefMut for ManuallyDrop<T> {
-    #[inline]
-    fn deref_mut(&mut self) -> &mut Self::Target {
-        unsafe {
-            &mut self.value
-        }
-    }
-}
-
-#[stable(feature = "manually_drop", since = "1.20.0")]
-impl<T: ::fmt::Debug> ::fmt::Debug for ManuallyDrop<T> {
-    fn fmt(&self, fmt: &mut ::fmt::Formatter) -> ::fmt::Result {
-        unsafe {
-            fmt.debug_tuple("ManuallyDrop").field(&self.value).finish()
-        }
-    }
-}
-
-#[stable(feature = "manually_drop_impls", since = "1.22.0")]
-impl<T: Clone> Clone for ManuallyDrop<T> {
-    fn clone(&self) -> Self {
-        ManuallyDrop::new(self.deref().clone())
-    }
-
-    fn clone_from(&mut self, source: &Self) {
-        self.deref_mut().clone_from(source);
-    }
-}
-
-#[stable(feature = "manually_drop_impls", since = "1.22.0")]
-impl<T: Default> Default for ManuallyDrop<T> {
-    fn default() -> Self {
-        ManuallyDrop::new(Default::default())
-    }
-}
-
-#[stable(feature = "manually_drop_impls", since = "1.22.0")]
-impl<T: PartialEq> PartialEq for ManuallyDrop<T> {
-    fn eq(&self, other: &Self) -> bool {
-        self.deref().eq(other)
-    }
-
-    fn ne(&self, other: &Self) -> bool {
-        self.deref().ne(other)
-    }
-}
-
-#[stable(feature = "manually_drop_impls", since = "1.22.0")]
-impl<T: Eq> Eq for ManuallyDrop<T> {}
-
-#[stable(feature = "manually_drop_impls", since = "1.22.0")]
-impl<T: PartialOrd> PartialOrd for ManuallyDrop<T> {
-    fn partial_cmp(&self, other: &Self) -> Option<::cmp::Ordering> {
-        self.deref().partial_cmp(other)
-    }
-
-    fn lt(&self, other: &Self) -> bool {
-        self.deref().lt(other)
-    }
-
-    fn le(&self, other: &Self) -> bool {
-        self.deref().le(other)
-    }
-
-    fn gt(&self, other: &Self) -> bool {
-        self.deref().gt(other)
-    }
-
-    fn ge(&self, other: &Self) -> bool {
-        self.deref().ge(other)
-    }
-}
-
-#[stable(feature = "manually_drop_impls", since = "1.22.0")]
-impl<T: Ord> Ord for ManuallyDrop<T> {
-    fn cmp(&self, other: &Self) -> ::cmp::Ordering {
-        self.deref().cmp(other)
-    }
-}
-
-#[stable(feature = "manually_drop_impls", since = "1.22.0")]
-impl<T: ::hash::Hash> ::hash::Hash for ManuallyDrop<T> {
-    fn hash<H: ::hash::Hasher>(&self, state: &mut H) {
-        self.deref().hash(state);
-    }
-}
index 1a54f03bb00673ed2c2a431e7e76ef2a3ffd333f..8a74e7c6f1cc66d628432457eee60f26acb62fa8 100644 (file)
@@ -953,7 +953,6 @@ pub fn discriminant<T>(v: &T) -> Discriminant<T> {
 ///     }
 /// }
 /// ```
-#[cfg(not(stage0))]
 #[stable(feature = "manually_drop", since = "1.20.0")]
 #[lang = "manually_drop"]
 #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
@@ -961,10 +960,6 @@ pub struct ManuallyDrop<T> {
     value: T,
 }
 
-#[cfg(stage0)]
-include!("manually_drop_stage0.rs");
-
-#[cfg(not(stage0))]
 impl<T> ManuallyDrop<T> {
     /// Wrap a value to be manually dropped.
     ///
@@ -1010,7 +1005,6 @@ pub unsafe fn drop(slot: &mut ManuallyDrop<T>) {
     }
 }
 
-#[cfg(not(stage0))]
 #[stable(feature = "manually_drop", since = "1.20.0")]
 impl<T> Deref for ManuallyDrop<T> {
     type Target = T;
@@ -1020,7 +1014,6 @@ fn deref(&self) -> &Self::Target {
     }
 }
 
-#[cfg(not(stage0))]
 #[stable(feature = "manually_drop", since = "1.20.0")]
 impl<T> DerefMut for ManuallyDrop<T> {
     #[inline]
index 72e7b57a6cb3cee63e87b970f026d946e9c40ee8..c9d3c7fea9839e1ed3da89ae8b61971ff69c493f 100644 (file)
@@ -100,24 +100,30 @@ pub fn memrchr(x: u8, text: &[u8]) -> Option<usize> {
     // - the first remaining bytes, < 2 word size
     let len = text.len();
     let ptr = text.as_ptr();
-    let usize_bytes = mem::size_of::<usize>();
+    type Chunk = usize;
 
-    let mut offset = {
-        // We call this just to obtain the length of the suffix
-        let (_, _, suffix) = unsafe { text.align_to::<usize>() };
-        len - suffix.len()
+    let (min_aligned_offset, max_aligned_offset) = {
+        // We call this just to obtain the length of the prefix and suffix.
+        // In the middle we always process two chunks at once.
+        let (prefix, _, suffix) = unsafe { text.align_to::<(Chunk, Chunk)>() };
+        (prefix.len(), len - suffix.len())
     };
+
+    let mut offset = max_aligned_offset;
     if let Some(index) = text[offset..].iter().rposition(|elt| *elt == x) {
         return Some(offset + index);
     }
 
-    // search the body of the text
+    // search the body of the text, make sure we don't cross min_aligned_offset.
+    // offset is always aligned, so just testing `>` is sufficient and avoids possible
+    // overflow.
     let repeated_x = repeat_byte(x);
+    let chunk_bytes = mem::size_of::<Chunk>();
 
-    while offset >= 2 * usize_bytes {
+    while offset > min_aligned_offset {
         unsafe {
-            let u = *(ptr.offset(offset as isize - 2 * usize_bytes as isize) as *const usize);
-            let v = *(ptr.offset(offset as isize - usize_bytes as isize) as *const usize);
+            let u = *(ptr.offset(offset as isize - 2 * chunk_bytes as isize) as *const Chunk);
+            let v = *(ptr.offset(offset as isize - chunk_bytes as isize) as *const Chunk);
 
             // break if there is a matching byte
             let zu = contains_zero_byte(u ^ repeated_x);
@@ -126,7 +132,7 @@ pub fn memrchr(x: u8, text: &[u8]) -> Option<usize> {
                 break;
             }
         }
-        offset -= 2 * usize_bytes;
+        offset -= 2 * chunk_bytes;
     }
 
     // find the byte before the point the body loop stopped
index b766140ffe99a1e37f292e729df55ecb4850ad57..a4dde38cb7bb636abb201cbd26c056a0b4cd21f5 100644 (file)
@@ -75,44 +75,6 @@ struct FatPtr<T> {
 // Extension traits
 //
 
-// Use macros to be generic over const/mut
-macro_rules! slice_offset {
-    ($ptr:expr, $by:expr) => {{
-        let ptr = $ptr;
-        if size_from_ptr(ptr) == 0 {
-            (ptr as *mut i8).wrapping_offset($by) as _
-        } else {
-            ptr.offset($by)
-        }
-    }};
-}
-
-// make a &T from a *const T
-macro_rules! make_ref {
-    ($ptr:expr) => {{
-        let ptr = $ptr;
-        if size_from_ptr(ptr) == 0 {
-            // Use a non-null pointer value
-            &*(1 as *mut _)
-        } else {
-            &*ptr
-        }
-    }};
-}
-
-// make a &mut T from a *mut T
-macro_rules! make_ref_mut {
-    ($ptr:expr) => {{
-        let ptr = $ptr;
-        if size_from_ptr(ptr) == 0 {
-            // Use a non-null pointer value
-            &mut *(1 as *mut _)
-        } else {
-            &mut *ptr
-        }
-    }};
-}
-
 #[lang = "slice"]
 #[cfg(not(test))]
 impl<T> [T] {
@@ -580,17 +542,18 @@ pub fn reverse(&mut self) {
     #[inline]
     pub fn iter(&self) -> Iter<T> {
         unsafe {
-            let p = if mem::size_of::<T>() == 0 {
-                1 as *const _
+            let ptr = self.as_ptr();
+            assume(!ptr.is_null());
+
+            let end = if mem::size_of::<T>() == 0 {
+                (ptr as *const u8).wrapping_offset(self.len() as isize) as *const T
             } else {
-                let p = self.as_ptr();
-                assume(!p.is_null());
-                p
+                ptr.offset(self.len() as isize)
             };
 
             Iter {
-                ptr: p,
-                end: slice_offset!(p, self.len() as isize),
+                ptr,
+                end,
                 _marker: marker::PhantomData
             }
         }
@@ -611,17 +574,18 @@ pub fn iter(&self) -> Iter<T> {
     #[inline]
     pub fn iter_mut(&mut self) -> IterMut<T> {
         unsafe {
-            let p = if mem::size_of::<T>() == 0 {
-                1 as *mut _
+            let ptr = self.as_mut_ptr();
+            assume(!ptr.is_null());
+
+            let end = if mem::size_of::<T>() == 0 {
+                (ptr as *mut u8).wrapping_offset(self.len() as isize) as *mut T
             } else {
-                let p = self.as_mut_ptr();
-                assume(!p.is_null());
-                p
+                ptr.offset(self.len() as isize)
             };
 
             IterMut {
-                ptr: p,
-                end: slice_offset!(p, self.len() as isize),
+                ptr,
+                end,
                 _marker: marker::PhantomData
             }
         }
@@ -2373,14 +2337,88 @@ fn into_iter(self) -> IterMut<'a, T> {
     }
 }
 
-#[inline]
+// Macro helper functions
+#[inline(always)]
 fn size_from_ptr<T>(_: *const T) -> usize {
     mem::size_of::<T>()
 }
 
+// Inlining is_empty and len makes a huge performance difference
+macro_rules! is_empty {
+    // The way we encode the length of a ZST iterator, this works both for ZST
+    // and non-ZST.
+    ($self: ident) => {$self.ptr == $self.end}
+}
+// To get rid of some bounds checks (see `position`), we compute the length in a somewhat
+// unexpected way. (Tested by `codegen/slice-position-bounds-check`.)
+macro_rules! len {
+    ($self: ident) => {{
+        let start = $self.ptr;
+        let diff = ($self.end as usize).wrapping_sub(start as usize);
+        let size = size_from_ptr(start);
+        if size == 0 {
+            diff
+        } else {
+            // Using division instead of `offset_from` helps LLVM remove bounds checks
+            diff / size
+        }
+    }}
+}
+
 // The shared definition of the `Iter` and `IterMut` iterators
 macro_rules! iterator {
-    (struct $name:ident -> $ptr:ty, $elem:ty, $mkref:ident) => {
+    (struct $name:ident -> $ptr:ty, $elem:ty, $raw_mut:tt, $( $mut_:tt )*) => {
+        impl<'a, T> $name<'a, T> {
+            // Helper function for creating a slice from the iterator.
+            #[inline(always)]
+            fn make_slice(&self) -> &'a [T] {
+                unsafe { from_raw_parts(self.ptr, len!(self)) }
+            }
+
+            // Helper function for moving the start of the iterator forwards by `offset` elements,
+            // returning the old start.
+            // Unsafe because the offset must be in-bounds or one-past-the-end.
+            #[inline(always)]
+            unsafe fn post_inc_start(&mut self, offset: isize) -> * $raw_mut T {
+                if mem::size_of::<T>() == 0 {
+                    // This is *reducing* the length.  `ptr` never changes with ZST.
+                    self.end = (self.end as * $raw_mut u8).wrapping_offset(-offset) as * $raw_mut T;
+                    self.ptr
+                } else {
+                    let old = self.ptr;
+                    self.ptr = self.ptr.offset(offset);
+                    old
+                }
+            }
+
+            // Helper function for moving the end of the iterator backwards by `offset` elements,
+            // returning the new end.
+            // Unsafe because the offset must be in-bounds or one-past-the-end.
+            #[inline(always)]
+            unsafe fn pre_dec_end(&mut self, offset: isize) -> * $raw_mut T {
+                if mem::size_of::<T>() == 0 {
+                    self.end = (self.end as * $raw_mut u8).wrapping_offset(-offset) as * $raw_mut T;
+                    self.ptr
+                } else {
+                    self.end = self.end.offset(-offset);
+                    self.end
+                }
+            }
+        }
+
+        #[stable(feature = "rust1", since = "1.0.0")]
+        impl<'a, T> ExactSizeIterator for $name<'a, T> {
+            #[inline(always)]
+            fn len(&self) -> usize {
+                len!(self)
+            }
+
+            #[inline(always)]
+            fn is_empty(&self) -> bool {
+                is_empty!(self)
+            }
+        }
+
         #[stable(feature = "rust1", since = "1.0.0")]
         impl<'a, T> Iterator for $name<'a, T> {
             type Item = $elem;
@@ -2389,33 +2427,48 @@ impl<'a, T> Iterator for $name<'a, T> {
             fn next(&mut self) -> Option<$elem> {
                 // could be implemented with slices, but this avoids bounds checks
                 unsafe {
+                    assume(!self.ptr.is_null());
                     if mem::size_of::<T>() != 0 {
-                        assume(!self.ptr.is_null());
                         assume(!self.end.is_null());
                     }
-                    if self.ptr == self.end {
+                    if is_empty!(self) {
                         None
                     } else {
-                        Some($mkref!(self.ptr.post_inc()))
+                        Some(& $( $mut_ )* *self.post_inc_start(1))
                     }
                 }
             }
 
             #[inline]
             fn size_hint(&self) -> (usize, Option<usize>) {
-                let exact = unsafe { ptrdistance(self.ptr, self.end) };
+                let exact = len!(self);
                 (exact, Some(exact))
             }
 
             #[inline]
             fn count(self) -> usize {
-                self.len()
+                len!(self)
             }
 
             #[inline]
             fn nth(&mut self, n: usize) -> Option<$elem> {
-                // Call helper method. Can't put the definition here because mut versus const.
-                self.iter_nth(n)
+                if n >= len!(self) {
+                    // This iterator is now empty.
+                    if mem::size_of::<T>() == 0 {
+                        // We have to do it this way as `ptr` may never be 0, but `end`
+                        // could be (due to wrapping).
+                        self.end = self.ptr;
+                    } else {
+                        self.ptr = self.end;
+                    }
+                    return None;
+                }
+                // We are in bounds. `offset` does the right thing even for ZSTs.
+                unsafe {
+                    let elem = Some(& $( $mut_ )* *self.ptr.offset(n as isize));
+                    self.post_inc_start((n as isize).wrapping_add(1));
+                    elem
+                }
             }
 
             #[inline]
@@ -2430,14 +2483,14 @@ fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R where
                 // manual unrolling is needed when there are conditional exits from the loop
                 let mut accum = init;
                 unsafe {
-                    while ptrdistance(self.ptr, self.end) >= 4 {
-                        accum = f(accum, $mkref!(self.ptr.post_inc()))?;
-                        accum = f(accum, $mkref!(self.ptr.post_inc()))?;
-                        accum = f(accum, $mkref!(self.ptr.post_inc()))?;
-                        accum = f(accum, $mkref!(self.ptr.post_inc()))?;
+                    while len!(self) >= 4 {
+                        accum = f(accum, & $( $mut_ )* *self.post_inc_start(1))?;
+                        accum = f(accum, & $( $mut_ )* *self.post_inc_start(1))?;
+                        accum = f(accum, & $( $mut_ )* *self.post_inc_start(1))?;
+                        accum = f(accum, & $( $mut_ )* *self.post_inc_start(1))?;
                     }
-                    while self.ptr != self.end {
-                        accum = f(accum, $mkref!(self.ptr.post_inc()))?;
+                    while !is_empty!(self) {
+                        accum = f(accum, & $( $mut_ )* *self.post_inc_start(1))?;
                     }
                 }
                 Try::from_ok(accum)
@@ -2462,9 +2515,8 @@ fn position<P>(&mut self, mut predicate: P) -> Option<usize> where
                 Self: Sized,
                 P: FnMut(Self::Item) -> bool,
             {
-                // The addition might panic on overflow
-                // Use the len of the slice to hint optimizer to remove result index bounds check.
-                let n = make_slice!(self.ptr, self.end).len();
+                // The addition might panic on overflow.
+                let n = len!(self);
                 self.try_fold(0, move |i, x| {
                     if predicate(x) { Err(i) }
                     else { Ok(i + 1) }
@@ -2481,9 +2533,7 @@ fn rposition<P>(&mut self, mut predicate: P) -> Option<usize> where
                 Self: Sized + ExactSizeIterator + DoubleEndedIterator
             {
                 // No need for an overflow check here, because `ExactSizeIterator`
-                // implies that the number of elements fits into a `usize`.
-                // Use the len of the slice to hint optimizer to remove result index bounds check.
-                let n = make_slice!(self.ptr, self.end).len();
+                let n = len!(self);
                 self.try_rfold(n, move |i, x| {
                     let i = i - 1;
                     if predicate(x) { Err(i) }
@@ -2502,14 +2552,14 @@ impl<'a, T> DoubleEndedIterator for $name<'a, T> {
             fn next_back(&mut self) -> Option<$elem> {
                 // could be implemented with slices, but this avoids bounds checks
                 unsafe {
+                    assume(!self.ptr.is_null());
                     if mem::size_of::<T>() != 0 {
-                        assume(!self.ptr.is_null());
                         assume(!self.end.is_null());
                     }
-                    if self.end == self.ptr {
+                    if is_empty!(self) {
                         None
                     } else {
-                        Some($mkref!(self.end.pre_dec()))
+                        Some(& $( $mut_ )* *self.pre_dec_end(1))
                     }
                 }
             }
@@ -2521,14 +2571,15 @@ fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R where
                 // manual unrolling is needed when there are conditional exits from the loop
                 let mut accum = init;
                 unsafe {
-                    while ptrdistance(self.ptr, self.end) >= 4 {
-                        accum = f(accum, $mkref!(self.end.pre_dec()))?;
-                        accum = f(accum, $mkref!(self.end.pre_dec()))?;
-                        accum = f(accum, $mkref!(self.end.pre_dec()))?;
-                        accum = f(accum, $mkref!(self.end.pre_dec()))?;
+                    while len!(self) >= 4 {
+                        accum = f(accum, & $( $mut_ )* *self.pre_dec_end(1))?;
+                        accum = f(accum, & $( $mut_ )* *self.pre_dec_end(1))?;
+                        accum = f(accum, & $( $mut_ )* *self.pre_dec_end(1))?;
+                        accum = f(accum, & $( $mut_ )* *self.pre_dec_end(1))?;
                     }
-                    while self.ptr != self.end {
-                        accum = f(accum, $mkref!(self.end.pre_dec()))?;
+                    // inlining is_empty everywhere makes a huge performance difference
+                    while !is_empty!(self) {
+                        accum = f(accum, & $( $mut_ )* *self.pre_dec_end(1))?;
                     }
                 }
                 Try::from_ok(accum)
@@ -2556,34 +2607,6 @@ unsafe impl<'a, T> TrustedLen for $name<'a, T> {}
     }
 }
 
-macro_rules! make_slice {
-    ($start: expr, $end: expr) => {{
-        let start = $start;
-        let diff = ($end as usize).wrapping_sub(start as usize);
-        if size_from_ptr(start) == 0 {
-            // use a non-null pointer value
-            unsafe { from_raw_parts(1 as *const _, diff) }
-        } else {
-            let len = diff / size_from_ptr(start);
-            unsafe { from_raw_parts(start, len) }
-        }
-    }}
-}
-
-macro_rules! make_mut_slice {
-    ($start: expr, $end: expr) => {{
-        let start = $start;
-        let diff = ($end as usize).wrapping_sub(start as usize);
-        if size_from_ptr(start) == 0 {
-            // use a non-null pointer value
-            unsafe { from_raw_parts_mut(1 as *mut _, diff) }
-        } else {
-            let len = diff / size_from_ptr(start);
-            unsafe { from_raw_parts_mut(start, len) }
-        }
-    }}
-}
-
 /// Immutable slice iterator
 ///
 /// This struct is created by the [`iter`] method on [slices].
@@ -2607,7 +2630,9 @@ macro_rules! make_mut_slice {
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Iter<'a, T: 'a> {
     ptr: *const T,
-    end: *const T,
+    end: *const T, // If T is a ZST, this is actually ptr+len.  This encoding is picked so that
+                   // ptr == end is a quick test for the Iterator being empty, that works
+                   // for both ZST and non-ZST.
     _marker: marker::PhantomData<&'a T>,
 }
 
@@ -2652,32 +2677,11 @@ impl<'a, T> Iter<'a, T> {
     /// ```
     #[stable(feature = "iter_to_slice", since = "1.4.0")]
     pub fn as_slice(&self) -> &'a [T] {
-        make_slice!(self.ptr, self.end)
-    }
-
-    // Helper function for Iter::nth
-    fn iter_nth(&mut self, n: usize) -> Option<&'a T> {
-        match self.as_slice().get(n) {
-            Some(elem_ref) => unsafe {
-                self.ptr = slice_offset!(self.ptr, (n as isize).wrapping_add(1));
-                Some(elem_ref)
-            },
-            None => {
-                self.ptr = self.end;
-                None
-            }
-        }
+        self.make_slice()
     }
 }
 
-iterator!{struct Iter -> *const T, &'a T, make_ref}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> ExactSizeIterator for Iter<'a, T> {
-    fn is_empty(&self) -> bool {
-        self.ptr == self.end
-    }
-}
+iterator!{struct Iter -> *const T, &'a T, const, /* no mut */}
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> Clone for Iter<'a, T> {
@@ -2718,7 +2722,9 @@ fn as_ref(&self) -> &[T] {
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct IterMut<'a, T: 'a> {
     ptr: *mut T,
-    end: *mut T,
+    end: *mut T, // If T is a ZST, this is actually ptr+len.  This encoding is picked so that
+                 // ptr == end is a quick test for the Iterator being empty, that works
+                 // for both ZST and non-ZST.
     _marker: marker::PhantomData<&'a mut T>,
 }
 
@@ -2726,7 +2732,7 @@ pub struct IterMut<'a, T: 'a> {
 impl<'a, T: 'a + fmt::Debug> fmt::Debug for IterMut<'a, T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_tuple("IterMut")
-            .field(&make_slice!(self.ptr, self.end))
+            .field(&self.make_slice())
             .finish()
     }
 }
@@ -2772,77 +2778,11 @@ impl<'a, T> IterMut<'a, T> {
     /// ```
     #[stable(feature = "iter_to_slice", since = "1.4.0")]
     pub fn into_slice(self) -> &'a mut [T] {
-        make_mut_slice!(self.ptr, self.end)
-    }
-
-    // Helper function for IterMut::nth
-    fn iter_nth(&mut self, n: usize) -> Option<&'a mut T> {
-        match make_mut_slice!(self.ptr, self.end).get_mut(n) {
-            Some(elem_ref) => unsafe {
-                self.ptr = slice_offset!(self.ptr, (n as isize).wrapping_add(1));
-                Some(elem_ref)
-            },
-            None => {
-                self.ptr = self.end;
-                None
-            }
-        }
-    }
-}
-
-iterator!{struct IterMut -> *mut T, &'a mut T, make_ref_mut}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> ExactSizeIterator for IterMut<'a, T> {
-    fn is_empty(&self) -> bool {
-        self.ptr == self.end
+        unsafe { from_raw_parts_mut(self.ptr, len!(self)) }
     }
 }
 
-// Return the number of elements of `T` from `start` to `end`.
-// Return the arithmetic difference if `T` is zero size.
-#[inline(always)]
-unsafe fn ptrdistance<T>(start: *const T, end: *const T) -> usize {
-    if mem::size_of::<T>() == 0 {
-        (end as usize).wrapping_sub(start as usize)
-    } else {
-        end.offset_from(start) as usize
-    }
-}
-
-// Extension methods for raw pointers, used by the iterators
-trait PointerExt : Copy {
-    unsafe fn slice_offset(self, i: isize) -> Self;
-
-    /// Increments `self` by 1, but returns the old value.
-    #[inline(always)]
-    unsafe fn post_inc(&mut self) -> Self {
-        let current = *self;
-        *self = self.slice_offset(1);
-        current
-    }
-
-    /// Decrements `self` by 1, and returns the new value.
-    #[inline(always)]
-    unsafe fn pre_dec(&mut self) -> Self {
-        *self = self.slice_offset(-1);
-        *self
-    }
-}
-
-impl<T> PointerExt for *const T {
-    #[inline(always)]
-    unsafe fn slice_offset(self, i: isize) -> Self {
-        slice_offset!(self, i)
-    }
-}
-
-impl<T> PointerExt for *mut T {
-    #[inline(always)]
-    unsafe fn slice_offset(self, i: isize) -> Self {
-        slice_offset!(self, i)
-    }
-}
+iterator!{struct IterMut -> *mut T, &'a mut T, mut, mut}
 
 /// An internal abstraction over the splitting iterators, so that
 /// splitn, splitn_mut etc can be implemented once.
@@ -3927,12 +3867,11 @@ fn may_have_side_effect() -> bool { false }
 /// ```
 /// use std::slice;
 ///
-/// // manifest a slice out of thin air!
-/// let ptr = 0x1234 as *const usize;
-/// let amt = 10;
-/// unsafe {
-///     let slice = slice::from_raw_parts(ptr, amt);
-/// }
+/// // manifest a slice for a single element
+/// let x = 42;
+/// let ptr = &x as *const _;
+/// let slice = unsafe { slice::from_raw_parts(ptr, 1) };
+/// assert_eq!(slice[0], 42);
 /// ```
 ///
 /// [`NonNull::dangling()`]: ../../std/ptr/struct.NonNull.html#method.dangling
index 1e2b18bf9b038fc83fa0485474db7aecaca1e232..e98194c17c8851204520a0123b29722f25fba42d 100644 (file)
@@ -373,7 +373,7 @@ pub fn store(&self, val: bool, order: Ordering) {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[cfg(any(stage0, target_has_atomic = "cas"))]
+    #[cfg(target_has_atomic = "cas")]
     pub fn swap(&self, val: bool, order: Ordering) -> bool {
         unsafe { atomic_swap(self.v.get(), val as u8, order) != 0 }
     }
@@ -404,7 +404,7 @@ pub fn swap(&self, val: bool, order: Ordering) -> bool {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[cfg(any(stage0, target_has_atomic = "cas"))]
+    #[cfg(target_has_atomic = "cas")]
     pub fn compare_and_swap(&self, current: bool, new: bool, order: Ordering) -> bool {
         match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) {
             Ok(x) => x,
@@ -450,7 +450,7 @@ pub fn compare_and_swap(&self, current: bool, new: bool, order: Ordering) -> boo
     /// ```
     #[inline]
     #[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
-    #[cfg(any(stage0, target_has_atomic = "cas"))]
+    #[cfg(target_has_atomic = "cas")]
     pub fn compare_exchange(&self,
                             current: bool,
                             new: bool,
@@ -542,7 +542,7 @@ pub fn compare_exchange_weak(&self,
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[cfg(any(stage0, target_has_atomic = "cas"))]
+    #[cfg(target_has_atomic = "cas")]
     pub fn fetch_and(&self, val: bool, order: Ordering) -> bool {
         unsafe { atomic_and(self.v.get(), val as u8, order) != 0 }
     }
@@ -574,7 +574,7 @@ pub fn fetch_and(&self, val: bool, order: Ordering) -> bool {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[cfg(any(stage0, target_has_atomic = "cas"))]
+    #[cfg(target_has_atomic = "cas")]
     pub fn fetch_nand(&self, val: bool, order: Ordering) -> bool {
         // We can't use atomic_nand here because it can result in a bool with
         // an invalid value. This happens because the atomic operation is done
@@ -617,7 +617,7 @@ pub fn fetch_nand(&self, val: bool, order: Ordering) -> bool {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[cfg(any(stage0, target_has_atomic = "cas"))]
+    #[cfg(target_has_atomic = "cas")]
     pub fn fetch_or(&self, val: bool, order: Ordering) -> bool {
         unsafe { atomic_or(self.v.get(), val as u8, order) != 0 }
     }
@@ -648,7 +648,7 @@ pub fn fetch_or(&self, val: bool, order: Ordering) -> bool {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[cfg(any(stage0, target_has_atomic = "cas"))]
+    #[cfg(target_has_atomic = "cas")]
     pub fn fetch_xor(&self, val: bool, order: Ordering) -> bool {
         unsafe { atomic_xor(self.v.get(), val as u8, order) != 0 }
     }
@@ -795,7 +795,7 @@ pub fn store(&self, ptr: *mut T, order: Ordering) {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[cfg(any(stage0, target_has_atomic = "cas"))]
+    #[cfg(target_has_atomic = "cas")]
     pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T {
         unsafe { atomic_swap(self.p.get() as *mut usize, ptr as usize, order) as *mut T }
     }
@@ -825,7 +825,7 @@ pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[cfg(any(stage0, target_has_atomic = "cas"))]
+    #[cfg(target_has_atomic = "cas")]
     pub fn compare_and_swap(&self, current: *mut T, new: *mut T, order: Ordering) -> *mut T {
         match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) {
             Ok(x) => x,
@@ -864,7 +864,7 @@ pub fn compare_and_swap(&self, current: *mut T, new: *mut T, order: Ordering) ->
     /// ```
     #[inline]
     #[stable(feature = "extended_compare_and_swap", since = "1.10.0")]
-    #[cfg(any(stage0, target_has_atomic = "cas"))]
+    #[cfg(target_has_atomic = "cas")]
     pub fn compare_exchange(&self,
                             current: *mut T,
                             new: *mut T,
@@ -1151,7 +1151,7 @@ pub fn store(&self, val: $int_type, order: Ordering) {
 ```"),
                 #[inline]
                 #[$stable]
-                #[cfg(any(stage0, target_has_atomic = "cas"))]
+                #[cfg(target_has_atomic = "cas")]
                 pub fn swap(&self, val: $int_type, order: Ordering) -> $int_type {
                     unsafe { atomic_swap(self.v.get(), val, order) }
                 }
@@ -1184,7 +1184,7 @@ pub fn swap(&self, val: $int_type, order: Ordering) -> $int_type {
 ```"),
                 #[inline]
                 #[$stable]
-                #[cfg(any(stage0, target_has_atomic = "cas"))]
+                #[cfg(target_has_atomic = "cas")]
                 pub fn compare_and_swap(&self,
                                         current: $int_type,
                                         new: $int_type,
@@ -1238,7 +1238,7 @@ pub fn compare_and_swap(&self,
 ```"),
                 #[inline]
                 #[$stable_cxchg]
-                #[cfg(any(stage0, target_has_atomic = "cas"))]
+                #[cfg(target_has_atomic = "cas")]
                 pub fn compare_exchange(&self,
                                         current: $int_type,
                                         new: $int_type,
@@ -1693,7 +1693,7 @@ pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type {
 }
 
 #[inline]
-#[cfg(any(stage0, target_has_atomic = "cas"))]
+#[cfg(target_has_atomic = "cas")]
 fn strongest_failure_ordering(order: Ordering) -> Ordering {
     match order {
         Release => Relaxed,
@@ -1730,7 +1730,7 @@ unsafe fn atomic_load<T>(dst: *const T, order: Ordering) -> T {
 }
 
 #[inline]
-#[cfg(any(stage0, target_has_atomic = "cas"))]
+#[cfg(target_has_atomic = "cas")]
 unsafe fn atomic_swap<T>(dst: *mut T, val: T, order: Ordering) -> T {
     match order {
         Acquire => intrinsics::atomic_xchg_acq(dst, val),
@@ -1769,7 +1769,7 @@ unsafe fn atomic_sub<T>(dst: *mut T, val: T, order: Ordering) -> T {
 }
 
 #[inline]
-#[cfg(any(stage0, target_has_atomic = "cas"))]
+#[cfg(target_has_atomic = "cas")]
 unsafe fn atomic_compare_exchange<T>(dst: *mut T,
                                      old: T,
                                      new: T,
index 46c54056e2cc9e67b8f4882e294c1ef110d1dcaf..3d99c8ea9e22913aaac335c25d52ab08d33bad63 100644 (file)
@@ -148,9 +148,10 @@ fn test_is_control() {
 }
 
 #[test]
-fn test_is_digit() {
+fn test_is_numeric() {
    assert!('2'.is_numeric());
    assert!('7'.is_numeric());
+   assert!('¾'.is_numeric());
    assert!(!'c'.is_numeric());
    assert!(!'i'.is_numeric());
    assert!(!'z'.is_numeric());
index 2b37acdfe3e81386d4a4c3b5d6a7bb606df29e3d..7968521f7b461ee841d5747a524cf2777c67413b 100644 (file)
@@ -390,6 +390,132 @@ fn test_windows_zip() {
     assert_eq!(res, [14, 18, 22, 26]);
 }
 
+#[test]
+#[allow(const_err)]
+fn test_iter_ref_consistency() {
+    use std::fmt::Debug;
+
+    fn test<T : Copy + Debug + PartialEq>(x : T) {
+        let v : &[T] = &[x, x, x];
+        let v_ptrs : [*const T; 3] = match v {
+            [ref v1, ref v2, ref v3] => [v1 as *const _, v2 as *const _, v3 as *const _],
+            _ => unreachable!()
+        };
+        let len = v.len();
+
+        // nth(i)
+        for i in 0..len {
+            assert_eq!(&v[i] as *const _, v_ptrs[i]); // check the v_ptrs array, just to be sure
+            let nth = v.iter().nth(i).unwrap();
+            assert_eq!(nth as *const _, v_ptrs[i]);
+        }
+        assert_eq!(v.iter().nth(len), None, "nth(len) should return None");
+
+        // stepping through with nth(0)
+        {
+            let mut it = v.iter();
+            for i in 0..len {
+                let next = it.nth(0).unwrap();
+                assert_eq!(next as *const _, v_ptrs[i]);
+            }
+            assert_eq!(it.nth(0), None);
+        }
+
+        // next()
+        {
+            let mut it = v.iter();
+            for i in 0..len {
+                let remaining = len - i;
+                assert_eq!(it.size_hint(), (remaining, Some(remaining)));
+
+                let next = it.next().unwrap();
+                assert_eq!(next as *const _, v_ptrs[i]);
+            }
+            assert_eq!(it.size_hint(), (0, Some(0)));
+            assert_eq!(it.next(), None, "The final call to next() should return None");
+        }
+
+        // next_back()
+        {
+            let mut it = v.iter();
+            for i in 0..len {
+                let remaining = len - i;
+                assert_eq!(it.size_hint(), (remaining, Some(remaining)));
+
+                let prev = it.next_back().unwrap();
+                assert_eq!(prev as *const _, v_ptrs[remaining-1]);
+            }
+            assert_eq!(it.size_hint(), (0, Some(0)));
+            assert_eq!(it.next_back(), None, "The final call to next_back() should return None");
+        }
+    }
+
+    fn test_mut<T : Copy + Debug + PartialEq>(x : T) {
+        let v : &mut [T] = &mut [x, x, x];
+        let v_ptrs : [*mut T; 3] = match v {
+            [ref v1, ref v2, ref v3] =>
+              [v1 as *const _ as *mut _, v2 as *const _ as *mut _, v3 as *const _ as *mut _],
+            _ => unreachable!()
+        };
+        let len = v.len();
+
+        // nth(i)
+        for i in 0..len {
+            assert_eq!(&mut v[i] as *mut _, v_ptrs[i]); // check the v_ptrs array, just to be sure
+            let nth = v.iter_mut().nth(i).unwrap();
+            assert_eq!(nth as *mut _, v_ptrs[i]);
+        }
+        assert_eq!(v.iter().nth(len), None, "nth(len) should return None");
+
+        // stepping through with nth(0)
+        {
+            let mut it = v.iter();
+            for i in 0..len {
+                let next = it.nth(0).unwrap();
+                assert_eq!(next as *const _, v_ptrs[i]);
+            }
+            assert_eq!(it.nth(0), None);
+        }
+
+        // next()
+        {
+            let mut it = v.iter_mut();
+            for i in 0..len {
+                let remaining = len - i;
+                assert_eq!(it.size_hint(), (remaining, Some(remaining)));
+
+                let next = it.next().unwrap();
+                assert_eq!(next as *mut _, v_ptrs[i]);
+            }
+            assert_eq!(it.size_hint(), (0, Some(0)));
+            assert_eq!(it.next(), None, "The final call to next() should return None");
+        }
+
+        // next_back()
+        {
+            let mut it = v.iter_mut();
+            for i in 0..len {
+                let remaining = len - i;
+                assert_eq!(it.size_hint(), (remaining, Some(remaining)));
+
+                let prev = it.next_back().unwrap();
+                assert_eq!(prev as *mut _, v_ptrs[remaining-1]);
+            }
+            assert_eq!(it.size_hint(), (0, Some(0)));
+            assert_eq!(it.next_back(), None, "The final call to next_back() should return None");
+        }
+    }
+
+    // Make sure iterators and slice patterns yield consistent addresses for various types,
+    // including ZSTs.
+    test(0u32);
+    test(());
+    test([0u32; 0]); // ZST with alignment > 0
+    test_mut(0u32);
+    test_mut(());
+    test_mut([0u32; 0]); // ZST with alignment > 0
+}
+
 // The current implementation of SliceIndex fails to handle methods
 // orthogonally from range types; therefore, it is worth testing
 // all of the indexing operations on each input.
index 32668ea93dd8c18a62df7a8cc59d844a52aa93a9..3de855ac943157091696c035096c70399d5bd96e 100644 (file)
@@ -40,7 +40,7 @@ pub fn Cc(c: char) -> bool {
 
     pub const N_table: &super::BoolTrie = &super::BoolTrie {
         r1: [
-            0x03ff000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
+            0x03ff000000000000, 0x0000000000000000, 0x720c000000000000, 0x0000000000000000,
             0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
             0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
             0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000,
@@ -50,12 +50,14 @@ pub fn Cc(c: char) -> bool {
             0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x00000000000003ff
         ],
         r2: [
-            0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 2, 0, 2, 3,
-            0, 0, 0, 0, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 5, 0, 0, 0, 3, 2, 0, 0, 0, 0, 6, 0, 2, 0, 0, 7, 0, 0, 2, 8, 0, 0, 7, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 1, 0, 2, 0, 1, 0, 1, 0, 3, 0, 4, 0, 5, 0, 1, 0, 6, 0, 1, 0, 7, 0, 7, 8,
+            0, 0, 0, 0, 9, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 11, 0, 0, 0, 12, 7, 0, 0, 0, 0, 13, 0, 14, 0, 0, 15, 0, 0, 7, 16, 0, 0, 15, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 9, 0, 0, 18, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            20, 21, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 23, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 0, 0, 0, 0, 0, 27, 0, 28,
+            29, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -69,10 +71,10 @@ pub fn Cc(c: char) -> bool {
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28,
+            0, 0, 1, 0, 0, 0, 0, 31, 0, 0, 7, 9, 0, 0, 32, 0, 7, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 0, 0,
-            0, 0, 0, 0, 0, 2, 4, 0, 0, 12, 0, 2, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -82,18 +84,21 @@ pub fn Cc(c: char) -> bool {
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 2, 0, 0, 0
+            0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0
         ],
         r3: &[
-            0x0000000000000000, 0x0000ffc000000000, 0x0000000003ff0000, 0x000003ff00000000,
-            0x00000000000003ff, 0x0001c00000000000, 0x000000000000ffc0, 0x0000000003ff03ff,
-            0x03ff000000000000, 0xffffffff00000000, 0x00000000000001e7, 0x070003fe00000080,
+            0x0000000000000000, 0x0000ffc000000000, 0x03f0ffc000000000, 0x00fcffc000000000,
+            0x0007ffc000000000, 0x7f00ffc000000000, 0x01ffffc07f000000, 0x0000000003ff0000,
+            0x000fffff00000000, 0x00000000000003ff, 0x1ffffe0000000000, 0x0001c00000000000,
+            0x03ff03ff00000000, 0x000000000000ffc0, 0x0000000007ff0000, 0x0000000003ff03ff,
+            0x03ff000000000000, 0x03f1000000000000, 0xffffffffffff0000, 0x00000000000003e7,
+            0xffffffff00000000, 0x000000000fffffff, 0xfffffc0000000000, 0xffc0000000000000,
+            0x00000000000fffff, 0x2000000000000000, 0x070003fe00000080, 0x00000000003c0000,
+            0x000003ff00000000, 0x00000000fffeff00, 0xfffe0000000003ff, 0x003f000000000000,
             0x03ff000003ff0000
         ],
         r4: [
-            0, 1, 2, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 5, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+            0, 1, 2, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 5, 6, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
             3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
             3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
             3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
@@ -104,28 +109,37 @@ pub fn Cc(c: char) -> bool {
             3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
         ],
         r5: &[
-            0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 3, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 6, 0, 5, 7, 0, 0, 8, 0, 0, 0, 5, 0, 0, 0, 0, 0, 8, 0, 8, 0, 0, 0,
-            0, 0, 8, 0, 9, 5, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0,
-            0, 8, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10,
-            11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 1, 2, 3, 0, 0, 0, 0, 4, 5, 6, 0, 7, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 9, 10, 11, 12, 0, 13, 14, 0, 15, 16, 17, 0, 18, 19, 0, 0, 0, 0, 20, 21, 0,
+            0, 0, 0, 22, 0, 0, 23, 24, 0, 0, 0, 25, 0, 21, 26, 0, 0, 27, 0, 0, 0, 21, 0, 0, 0, 0, 0,
+            28, 0, 28, 0, 0, 0, 0, 0, 28, 0, 29, 30, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 32, 0, 0, 0, 28, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 33, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 38, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 0, 28, 0, 0, 0, 0,
+            0, 0, 0, 0, 0, 0, 0, 41, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 0,
             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
         ],
         r6: &[
-            0x0000000000000000, 0x001fffffffffffff, 0x0000000000000402, 0x00000000003e0000,
-            0x000003ff00000000, 0x03ff000000000000, 0x0000ffc000000000, 0xffc0000000000000,
-            0x0000000003ff0000, 0x00000000000003ff, 0xffffffffffffffff, 0x00007fffffffffff,
-            0xffffffffffffc000
+            0x0000000000000000, 0x000fffffffffff80, 0x01ffffffffffffff, 0x0000000000000c00,
+            0x0ffffffe00000000, 0x0000000f00000000, 0x0000000000000402, 0x00000000003e0000,
+            0x000003ff00000000, 0xfe000000ff000000, 0x0000ff8000000000, 0xf800000000000000,
+            0x000000000fc00000, 0x3000000000000000, 0xfffffffffffcffff, 0x60000000000001ff,
+            0x00000000e0000000, 0x0000f80000000000, 0xff000000ff000000, 0x0000fe0000000000,
+            0xfc00000000000000, 0x03ff000000000000, 0x7fffffff00000000, 0x0000007fe0000000,
+            0x00000000001e0000, 0x0000fffffffc0000, 0xffc0000000000000, 0x001ffffe03ff0000,
+            0x0000000003ff0000, 0x00000000000003ff, 0x0fff000000000000, 0x0007ffff00000000,
+            0x00001fffffff0000, 0xffffffffffffffff, 0x00007fffffffffff, 0x00000003fbff0000,
+            0x00000000007fffff, 0x000fffff00000000, 0x01ffffff00000000, 0xffffffffffffc000,
+            0x000000000000ff80, 0xfffe000000000000, 0x001eefffffffffff, 0x0000000000001fff
         ],
     };
 
index be0970b544406e5ac9cfe6e2d0b41bb4aa76217a..28a1e01805e46d9a502cb3b84ac6c2f0a02fb8dc 100755 (executable)
@@ -52,7 +52,7 @@ expanded_categories = {
     'Lu': ['LC', 'L'], 'Ll': ['LC', 'L'], 'Lt': ['LC', 'L'],
     'Lm': ['L'], 'Lo': ['L'],
     'Mn': ['M'], 'Mc': ['M'], 'Me': ['M'],
-    'Nd': ['N'], 'Nl': ['N'], 'No': ['No'],
+    'Nd': ['N'], 'Nl': ['N'], 'No': ['N'],
     'Pc': ['P'], 'Pd': ['P'], 'Ps': ['P'], 'Pe': ['P'],
     'Pi': ['P'], 'Pf': ['P'], 'Po': ['P'],
     'Sm': ['S'], 'Sc': ['S'], 'Sk': ['S'], 'So': ['S'],
index 1c355e35fd6eafffbc048e23c6fe21dae2874291..cb5e1e600d3d2e8659b21d7bdcc8cc84231dd5a3 100644 (file)
@@ -49,6 +49,7 @@ pub enum Def {
     PrimTy(hir::PrimTy),
     TyParam(DefId),
     SelfTy(Option<DefId> /* trait */, Option<DefId> /* impl */),
+    ToolMod, // e.g. `rustfmt` in `#[rustfmt::skip]`
 
     // Value namespace
     Fn(DefId),
@@ -67,6 +68,7 @@ pub enum Def {
 
     // Macro namespace
     Macro(DefId, MacroKind),
+    NonMacroAttr, // e.g. `#[inline]` or `#[rustfmt::skip]`
 
     GlobalAsm(DefId),
 
@@ -259,6 +261,8 @@ pub fn def_id(&self) -> DefId {
             Def::Label(..)  |
             Def::PrimTy(..) |
             Def::SelfTy(..) |
+            Def::ToolMod |
+            Def::NonMacroAttr |
             Def::Err => {
                 bug!("attempted .def_id() on invalid def: {:?}", self)
             }
@@ -299,6 +303,8 @@ pub fn kind_name(&self) -> &'static str {
             Def::SelfTy(..) => "self type",
             Def::Macro(.., macro_kind) => macro_kind.descr(),
             Def::GlobalAsm(..) => "global asm",
+            Def::ToolMod => "tool module",
+            Def::NonMacroAttr => "non-macro attribute",
             Def::Err => "unresolved item",
         }
     }
index 63755bcea5e62f293d923be13efc7fb8d22ecbd6..4b69e3b6bc70db8d0db5ba99597f68e0b9f649d6 100644 (file)
@@ -3753,16 +3753,14 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
             }
             // Desugar `<start>..=<end>` to `std::ops::RangeInclusive::new(<start>, <end>)`
             ExprKind::Range(Some(ref e1), Some(ref e2), RangeLimits::Closed) => {
-                // FIXME: Use e.span directly after RangeInclusive::new() is stabilized in stage0.
-                let span = self.allow_internal_unstable(CompilerDesugaringKind::DotFill, e.span);
                 let id = self.next_id();
                 let e1 = self.lower_expr(e1);
                 let e2 = self.lower_expr(e2);
-                let ty_path = P(self.std_path(span, &["ops", "RangeInclusive"], None, false));
-                let ty = P(self.ty_path(id, span, hir::QPath::Resolved(None, ty_path)));
+                let ty_path = P(self.std_path(e.span, &["ops", "RangeInclusive"], None, false));
+                let ty = P(self.ty_path(id, e.span, hir::QPath::Resolved(None, ty_path)));
                 let new_seg = P(hir::PathSegment::from_ident(Ident::from_str("new")));
                 let new_path = hir::QPath::TypeRelative(ty, new_seg);
-                let new = P(self.expr(span, hir::ExprKind::Path(new_path), ThinVec::new()));
+                let new = P(self.expr(e.span, hir::ExprKind::Path(new_path), ThinVec::new()));
                 hir::ExprKind::Call(new, hir_vec![e1, e2])
             }
             ExprKind::Range(ref e1, ref e2, lims) => {
@@ -3785,20 +3783,16 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                     .chain(e2.iter().map(|e| ("end", e)))
                     .map(|(s, e)| {
                         let expr = P(self.lower_expr(&e));
-                        let unstable_span =
-                            self.allow_internal_unstable(CompilerDesugaringKind::DotFill, e.span);
-                        let ident = Ident::new(Symbol::intern(s), unstable_span);
-                        self.field(ident, expr, unstable_span)
+                        let ident = Ident::new(Symbol::intern(s), e.span);
+                        self.field(ident, expr, e.span)
                     })
                     .collect::<P<[hir::Field]>>();
 
                 let is_unit = fields.is_empty();
-                let unstable_span =
-                    self.allow_internal_unstable(CompilerDesugaringKind::DotFill, e.span);
                 let struct_path = iter::once("ops")
                     .chain(iter::once(path))
                     .collect::<Vec<_>>();
-                let struct_path = self.std_path(unstable_span, &struct_path, None, is_unit);
+                let struct_path = self.std_path(e.span, &struct_path, None, is_unit);
                 let struct_path = hir::QPath::Resolved(None, P(struct_path));
 
                 let LoweredNodeId { node_id, hir_id } = self.lower_node_id(e.id);
@@ -3811,7 +3805,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                     } else {
                         hir::ExprKind::Struct(struct_path, fields, None)
                     },
-                    span: unstable_span,
+                    span: e.span,
                     attrs: e.attrs.clone(),
                 };
             }
index 410d578d4044c9524101d400402e9fd53e9ffe37..cac0d182d3a48923c43ad897e4c7ab32dc0cf4a1 100644 (file)
@@ -1016,6 +1016,8 @@ fn to_stable_hash_key(&self,
     Label(node_id),
     Macro(def_id, macro_kind),
     GlobalAsm(def_id),
+    ToolMod,
+    NonMacroAttr,
     Err
 });
 
index c106966fb70be0041ef576f32d1ff6d220d39a11..2ab0124397bbb1b1a8749e153e5ef6057a77f9a2 100644 (file)
@@ -409,7 +409,6 @@ fn hash_token<'a, 'gcx, W: StableHasherResult>(
 
 impl_stable_hash_for!(enum ::syntax_pos::hygiene::CompilerDesugaringKind {
     Async,
-    DotFill,
     QuestionMark,
     ExistentialReturnType,
     ForLoop,
index 8e71df3c34b0b42b998aeb7a8d24e477cda6249d..bac511aac1fe10108f01adb76258d4df01fdcbdf 100644 (file)
@@ -165,6 +165,7 @@ pub mod util {
     pub mod nodemap;
     pub mod fs;
     pub mod time_graph;
+    pub mod profiling;
 }
 
 // A private module so that macro-expanded idents like
index 86fd825850fc54444fccd80957f2b87cdc9ad9cf..c178a9063c9acd09fa1131c52e44831ed6e6ed33 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use rustc_data_structures::bitvec::BitVector;
+use rustc_data_structures::bitvec::BitArray;
 
 use super::*;
 
@@ -32,7 +32,7 @@
 #[derive(Clone)]
 pub struct Preorder<'a, 'tcx: 'a> {
     mir: &'a Mir<'tcx>,
-    visited: BitVector<BasicBlock>,
+    visited: BitArray<BasicBlock>,
     worklist: Vec<BasicBlock>,
 }
 
@@ -42,7 +42,7 @@ pub fn new(mir: &'a Mir<'tcx>, root: BasicBlock) -> Preorder<'a, 'tcx> {
 
         Preorder {
             mir,
-            visited: BitVector::new(mir.basic_blocks().len()),
+            visited: BitArray::new(mir.basic_blocks().len()),
             worklist,
         }
     }
@@ -104,7 +104,7 @@ impl<'a, 'tcx> ExactSizeIterator for Preorder<'a, 'tcx> {}
 /// A Postorder traversal of this graph is `D B C A` or `D C B A`
 pub struct Postorder<'a, 'tcx: 'a> {
     mir: &'a Mir<'tcx>,
-    visited: BitVector<BasicBlock>,
+    visited: BitArray<BasicBlock>,
     visit_stack: Vec<(BasicBlock, Successors<'a>)>
 }
 
@@ -112,7 +112,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {
     pub fn new(mir: &'a Mir<'tcx>, root: BasicBlock) -> Postorder<'a, 'tcx> {
         let mut po = Postorder {
             mir,
-            visited: BitVector::new(mir.basic_blocks().len()),
+            visited: BitArray::new(mir.basic_blocks().len()),
             visit_stack: Vec::new()
         };
 
index e0532a3320bc4294673744eb8ec007d90eee6eea..dda4a2d2418d7bc09784b39907b747c08b11f091 100644 (file)
@@ -65,7 +65,7 @@ pub enum Sanitizer {
     Thread,
 }
 
-#[derive(Clone, Copy, PartialEq, Hash)]
+#[derive(Clone, Copy, Debug, PartialEq, Hash)]
 pub enum OptLevel {
     No,         // -O0
     Less,       // -O1
@@ -1367,6 +1367,10 @@ fn parse_cross_lang_lto(slot: &mut CrossLangLto, v: Option<&str>) -> bool {
         "disables the 'leak check' for subtyping; unsound, but useful for tests"),
     crate_attr: Vec<String> = (Vec::new(), parse_string_push, [TRACKED],
         "inject the given attribute in the crate"),
+    self_profile: bool = (false, parse_bool, [UNTRACKED],
+          "run the self profiler"),
+    profile_json: bool = (false, parse_bool, [UNTRACKED],
+          "output a json file with profiler results"),
 }
 
 pub fn default_lib_output() -> CrateType {
index 7b8bbbf4a10e061eb83becc03886f980e460ff5f..0ab482c89a125813b85150cf4a4eb810892f60df 100644 (file)
@@ -40,6 +40,7 @@
 use syntax::{ast, codemap};
 use syntax::feature_gate::AttributeType;
 use syntax_pos::{MultiSpan, Span};
+use util::profiling::SelfProfiler;
 
 use rustc_target::spec::{LinkerFlavor, PanicStrategy};
 use rustc_target::spec::{Target, TargetTriple};
@@ -133,6 +134,9 @@ pub struct Session {
     /// Used by -Z profile-queries in util::common
     pub profile_channel: Lock<Option<mpsc::Sender<ProfileQueriesMsg>>>,
 
+    /// Used by -Z self-profile
+    pub self_profiling: Lock<SelfProfiler>,
+
     /// Some measurements that are being gathered during compilation.
     pub perf_stats: PerfStats,
 
@@ -825,6 +829,21 @@ pub fn incr_comp_session_dir_opt(&self) -> Option<cell::Ref<PathBuf>> {
         }
     }
 
+    pub fn profiler<F: FnOnce(&mut SelfProfiler) -> ()>(&self, f: F) {
+        let mut profiler = self.self_profiling.borrow_mut();
+        f(&mut profiler);
+    }
+
+    pub fn print_profiler_results(&self) {
+        let mut profiler = self.self_profiling.borrow_mut();
+        profiler.print_results(&self.opts);
+    }
+
+    pub fn save_json_results(&self) {
+        let profiler = self.self_profiling.borrow();
+        profiler.save_results(&self.opts);
+    }
+
     pub fn print_perf_stats(&self) {
         println!(
             "Total time spent computing symbol hashes:      {}",
@@ -1125,6 +1144,7 @@ pub fn build_session_(
         imported_macro_spans: OneThread::new(RefCell::new(HashMap::new())),
         incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)),
         ignored_attr_names: ich::compute_ignored_attr_names(),
+        self_profiling: Lock::new(SelfProfiler::new()),
         profile_channel: Lock::new(None),
         perf_stats: PerfStats {
             symbol_hash_time: Lock::new(Duration::from_secs(0)),
index 40171345f558b6b2210364c22cbb582fe1454815..35184ca6a2559cc3c3f2527db555a3addb414fc3 100644 (file)
@@ -45,7 +45,7 @@
 use mir::interpret::{GlobalId};
 
 use rustc_data_structures::sync::Lock;
-use rustc_data_structures::bitvec::BitVector;
+use rustc_data_structures::bitvec::BitArray;
 use std::iter;
 use std::cmp;
 use std::fmt;
@@ -3056,7 +3056,7 @@ fn confirm_builtin_unsize_candidate(&mut self,
                 } else {
                     return Err(Unimplemented);
                 };
-                let mut ty_params = BitVector::new(substs_a.types().count());
+                let mut ty_params = BitArray::new(substs_a.types().count());
                 let mut found = false;
                 for ty in field.walk() {
                     if let ty::TyParam(p) = ty.sty {
index 98568f860a4fdd62ee33a4728de581a85a31612e..89f3d7c30db92a3d177d450e82cfe83c1f27c305 100644 (file)
@@ -1395,10 +1395,18 @@ pub fn all_pat_vars_are_implicit_refs_within_guards(self) -> bool {
     }
 
     /// If true, we should enable two-phase borrows checks. This is
-    /// done with either `-Ztwo-phase-borrows` or with
-    /// `#![feature(nll)]`.
+    /// done with either: `-Ztwo-phase-borrows`, `#![feature(nll)]`,
+    /// or by opting into an edition after 2015.
     pub fn two_phase_borrows(self) -> bool {
-        self.features().nll || self.sess.opts.debugging_opts.two_phase_borrows
+        if self.features().nll || self.sess.opts.debugging_opts.two_phase_borrows {
+            return true;
+        }
+
+        match self.sess.edition() {
+            Edition::Edition2015 => false,
+            Edition::Edition2018 => true,
+            _ => true,
+        }
     }
 
     /// What mode(s) of borrowck should we run? AST? MIR? both?
index fedf090b9e915a5f91779fff0dc9f560d8fc347b..d2648cad55ee9fa11dd03372af55cc510952b906 100644 (file)
@@ -21,6 +21,7 @@
 use ty::query::queries;
 use ty::query::Query;
 use ty::query::QueryCache;
+use util::profiling::ProfileCategory;
 
 use std::hash::Hash;
 use std::fmt::Debug;
@@ -33,6 +34,7 @@
 
 pub trait QueryConfig<'tcx> {
     const NAME: &'static str;
+    const CATEGORY: ProfileCategory;
 
     type Key: Eq + Hash + Clone + Debug;
     type Value: Clone + for<'a> HashStable<StableHashingContext<'a>>;
index 1b1020c9bd86dbe47d18eb8d3c466909451e6d7c..ab9bdd82e01ebf6cb97aa00f404f6810c93d571e 100644 (file)
@@ -46,6 +46,7 @@
 use ty::subst::Substs;
 use util::nodemap::{DefIdSet, DefIdMap, ItemLocalSet};
 use util::common::{ErrorReported};
+use util::profiling::ProfileCategory::*;
 
 use rustc_data_structures::indexed_set::IdxSetBuf;
 use rustc_target::spec::PanicStrategy;
index 7a9827b50a176ec35910d2429fdd370f5ac2ec5d..0fa643d796e0e1c7a3451ad84c35b9f133bcd78e 100644 (file)
@@ -118,6 +118,11 @@ pub(super) fn try_get(
             let mut lock = cache.borrow_mut();
             if let Some(value) = lock.results.get(key) {
                 profq_msg!(tcx, ProfileQueriesMsg::CacheHit);
+                tcx.sess.profiler(|p| {
+                    p.record_query(Q::CATEGORY);
+                    p.record_query_hit(Q::CATEGORY);
+                });
+
                 let result = Ok((value.value.clone(), value.index));
                 return TryGetJob::JobCompleted(result);
             }
@@ -358,10 +363,13 @@ fn try_get_with<Q: QueryDescription<'gcx>>(
             )
         );
 
+        self.sess.profiler(|p| p.record_query(Q::CATEGORY));
+
         let job = match JobOwner::try_get(self, span, &key) {
             TryGetJob::NotYetStarted(job) => job,
             TryGetJob::JobCompleted(result) => {
                 return result.map(|(v, index)| {
+                    self.sess.profiler(|p| p.record_query_hit(Q::CATEGORY));
                     self.dep_graph.read_index(index);
                     v
                 })
@@ -379,6 +387,7 @@ fn try_get_with<Q: QueryDescription<'gcx>>(
 
         if dep_node.kind.is_anon() {
             profq_msg!(self, ProfileQueriesMsg::ProviderBegin);
+            self.sess.profiler(|p| p.start_activity(Q::CATEGORY));
 
             let res = job.start(self, |tcx| {
                 tcx.dep_graph.with_anon_task(dep_node.kind, || {
@@ -386,6 +395,7 @@ fn try_get_with<Q: QueryDescription<'gcx>>(
                 })
             });
 
+            self.sess.profiler(|p| p.end_activity(Q::CATEGORY));
             profq_msg!(self, ProfileQueriesMsg::ProviderEnd);
             let ((result, dep_node_index), diagnostics) = res;
 
@@ -402,6 +412,8 @@ fn try_get_with<Q: QueryDescription<'gcx>>(
         if !dep_node.kind.is_input() {
             if let Some(dep_node_index) = self.try_mark_green_and_read(&dep_node) {
                 profq_msg!(self, ProfileQueriesMsg::CacheHit);
+                self.sess.profiler(|p| p.record_query_hit(Q::CATEGORY));
+
                 return self.load_from_disk_and_cache_in_memory::<Q>(key,
                                                                     job,
                                                                     dep_node_index,
@@ -523,6 +535,11 @@ fn force_query_with_job<Q: QueryDescription<'gcx>>(
                 key, dep_node);
 
         profq_msg!(self, ProfileQueriesMsg::ProviderBegin);
+        self.sess.profiler(|p| {
+            p.start_activity(Q::CATEGORY);
+            p.record_query(Q::CATEGORY);
+        });
+
         let res = job.start(self, |tcx| {
             if dep_node.kind.is_eval_always() {
                 tcx.dep_graph.with_eval_always_task(dep_node,
@@ -536,6 +553,8 @@ fn force_query_with_job<Q: QueryDescription<'gcx>>(
                                         Q::compute)
             }
         });
+
+        self.sess.profiler(|p| p.end_activity(Q::CATEGORY));
         profq_msg!(self, ProfileQueriesMsg::ProviderEnd);
 
         let ((result, dep_node_index), diagnostics) = res;
@@ -574,7 +593,15 @@ pub(super) fn ensure_query<Q: QueryDescription<'gcx>>(self, key: Q::Key) -> () {
             // DepNodeIndex. We must invoke the query itself. The performance cost
             // this introduces should be negligible as we'll immediately hit the
             // in-memory cache, or another query down the line will.
+
+            self.sess.profiler(|p| {
+                p.start_activity(Q::CATEGORY);
+                p.record_query(Q::CATEGORY);
+            });
+
             let _ = self.get_query::<Q>(DUMMY_SP, key);
+
+            self.sess.profiler(|p| p.end_activity(Q::CATEGORY));
         }
     }
 
@@ -655,6 +682,7 @@ macro_rules! define_queries_inner {
             rustc_data_structures::stable_hasher::StableHasher,
             ich::StableHashingContext
         };
+        use util::profiling::ProfileCategory;
 
         define_queries_struct! {
             tcx: $tcx,
@@ -768,6 +796,7 @@ pub fn $name<F: FnOnce() -> R, R>(f: F) -> R {
             type Value = $V;
 
             const NAME: &'static str = stringify!($name);
+            const CATEGORY: ProfileCategory = $category;
         }
 
         impl<$tcx> QueryAccessors<$tcx> for queries::$name<$tcx> {
diff --git a/src/librustc/util/profiling.rs b/src/librustc/util/profiling.rs
new file mode 100644 (file)
index 0000000..447b75e
--- /dev/null
@@ -0,0 +1,248 @@
+// 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 session::config::Options;
+
+use std::fs;
+use std::io::{self, StdoutLock, Write};
+use std::time::Instant;
+
+macro_rules! define_categories {
+    ($($name:ident,)*) => {
+        #[derive(Clone, Copy, Debug, PartialEq, Eq)]
+        pub enum ProfileCategory {
+            $($name),*
+        }
+
+        #[allow(bad_style)]
+        struct Categories<T> {
+            $($name: T),*
+        }
+
+        impl<T: Default> Categories<T> {
+            fn new() -> Categories<T> {
+                Categories {
+                    $($name: T::default()),*
+                }
+            }
+        }
+
+        impl<T> Categories<T> {
+            fn get(&self, category: ProfileCategory) -> &T {
+                match category {
+                    $(ProfileCategory::$name => &self.$name),*
+                }
+            }
+
+            fn set(&mut self, category: ProfileCategory, value: T) {
+                match category {
+                    $(ProfileCategory::$name => self.$name = value),*
+                }
+            }
+        }
+
+        struct CategoryData {
+            times: Categories<u64>,
+            query_counts: Categories<(u64, u64)>,
+        }
+
+        impl CategoryData {
+            fn new() -> CategoryData {
+                CategoryData {
+                    times: Categories::new(),
+                    query_counts: Categories::new(),
+                }
+            }
+
+            fn print(&self, lock: &mut StdoutLock) {
+                writeln!(lock, "| Phase            | Time (ms)      | Queries        | Hits (%) |")
+                    .unwrap();
+                writeln!(lock, "| ---------------- | -------------- | -------------- | -------- |")
+                    .unwrap();
+
+                $(
+                    let (hits, total) = self.query_counts.$name;
+                    let (hits, total) = if total > 0 {
+                        (format!("{:.2}",
+                        (((hits as f32) / (total as f32)) * 100.0)), total.to_string())
+                    } else {
+                        ("".into(), "".into())
+                    };
+
+                    writeln!(
+                        lock,
+                        "| {0: <16} | {1: <14} | {2: <14} | {3: <8} |",
+                        stringify!($name),
+                        self.times.$name / 1_000_000,
+                        total,
+                        hits
+                    ).unwrap();
+                )*
+            }
+
+            fn json(&self) -> String {
+                let mut json = String::from("[");
+
+                $(
+                    let (hits, total) = self.query_counts.$name;
+
+                    json.push_str(&format!(
+                        "{{ \"category\": {}, \"time_ms\": {},
+                            \"query_count\": {}, \"query_hits\": {} }}",
+                        stringify!($name),
+                        self.times.$name / 1_000_000,
+                        total,
+                        format!("{:.2}", (((hits as f32) / (total as f32)) * 100.0))
+                    ));
+                )*
+
+                json.push(']');
+
+                json
+            }
+        }
+    }
+}
+
+define_categories! {
+    Parsing,
+    Expansion,
+    TypeChecking,
+    BorrowChecking,
+    Codegen,
+    Linking,
+    Other,
+}
+
+pub struct SelfProfiler {
+    timer_stack: Vec<ProfileCategory>,
+    data: CategoryData,
+    current_timer: Instant,
+}
+
+impl SelfProfiler {
+    pub fn new() -> SelfProfiler {
+        let mut profiler = SelfProfiler {
+            timer_stack: Vec::new(),
+            data: CategoryData::new(),
+            current_timer: Instant::now(),
+        };
+
+        profiler.start_activity(ProfileCategory::Other);
+
+        profiler
+    }
+
+    pub fn start_activity(&mut self, category: ProfileCategory) {
+        match self.timer_stack.last().cloned() {
+            None => {
+                self.current_timer = Instant::now();
+            },
+            Some(current_category) if current_category == category => {
+                //since the current category is the same as the new activity's category,
+                //we don't need to do anything with the timer, we just need to push it on the stack
+            }
+            Some(current_category) => {
+                let elapsed = self.stop_timer();
+
+                //record the current category's time
+                let new_time = self.data.times.get(current_category) + elapsed;
+                self.data.times.set(current_category, new_time);
+            }
+        }
+
+        //push the new category
+        self.timer_stack.push(category);
+    }
+
+    pub fn record_query(&mut self, category: ProfileCategory) {
+        let (hits, total) = *self.data.query_counts.get(category);
+        self.data.query_counts.set(category, (hits, total + 1));
+    }
+
+    pub fn record_query_hit(&mut self, category: ProfileCategory) {
+        let (hits, total) = *self.data.query_counts.get(category);
+        self.data.query_counts.set(category, (hits + 1, total));
+    }
+
+    pub fn end_activity(&mut self, category: ProfileCategory) {
+        match self.timer_stack.pop() {
+            None => bug!("end_activity() was called but there was no running activity"),
+            Some(c) =>
+                assert!(
+                    c == category,
+                    "end_activity() was called but a different activity was running"),
+        }
+
+        //check if the new running timer is in the same category as this one
+        //if it is, we don't need to do anything
+        if let Some(c) = self.timer_stack.last() {
+            if *c == category {
+                return;
+            }
+        }
+
+        //the new timer is different than the previous,
+        //so record the elapsed time and start a new timer
+        let elapsed = self.stop_timer();
+        let new_time = self.data.times.get(category) + elapsed;
+        self.data.times.set(category, new_time);
+    }
+
+    fn stop_timer(&mut self) -> u64 {
+        let elapsed = self.current_timer.elapsed();
+
+        self.current_timer = Instant::now();
+
+        (elapsed.as_secs() * 1_000_000_000) + (elapsed.subsec_nanos() as u64)
+    }
+
+    pub fn print_results(&mut self, opts: &Options) {
+        self.end_activity(ProfileCategory::Other);
+
+        assert!(
+            self.timer_stack.is_empty(),
+            "there were timers running when print_results() was called");
+
+        let out = io::stdout();
+        let mut lock = out.lock();
+
+        let crate_name =
+            opts.crate_name
+            .as_ref()
+            .map(|n| format!(" for {}", n))
+            .unwrap_or_default();
+
+        writeln!(lock, "Self profiling results{}:", crate_name).unwrap();
+        writeln!(lock).unwrap();
+
+        self.data.print(&mut lock);
+
+        writeln!(lock).unwrap();
+        writeln!(lock, "Optimization level: {:?}", opts.optimize).unwrap();
+
+        let incremental = if opts.incremental.is_some() { "on" } else { "off" };
+        writeln!(lock, "Incremental: {}", incremental).unwrap();
+    }
+
+    pub fn save_results(&self, opts: &Options) {
+        let category_data = self.data.json();
+        let compilation_options =
+            format!("{{ \"optimization_level\": \"{:?}\", \"incremental\": {} }}",
+                    opts.optimize,
+                    if opts.incremental.is_some() { "true" } else { "false" });
+
+        let json = format!("{{ \"category_data\": {}, \"compilation_options\": {} }}",
+                        category_data,
+                        compilation_options);
+
+        fs::write("self_profiler_results.json", json).unwrap();
+    }
+}
index 5f2f3733ec7f0df434ed9f2e01ea3e5912ea0528..7253b5346b9ab79a1cdbb13a1ae438221010dc6e 100644 (file)
@@ -1006,6 +1006,18 @@ fn optimize(&mut self) {
             OptLevel::Size => "-O2",
             OptLevel::SizeMin => "-O2"
         });
+        match self.sess.opts.optimize {
+            OptLevel::No => (),
+            OptLevel::Less |
+            OptLevel::Default |
+            OptLevel::Aggressive |
+            OptLevel::Size |
+            OptLevel::SizeMin => {
+                // LLD generates incorrect debugging information when
+                // optimization is applied: strip debug sections.
+                self.cmd.arg("--strip-debug");
+            }
+        }
     }
 
     fn pgo_gen(&mut self) {
index daa2fb05280649793a50ac3831c7352cd8b1f5df..b644422e79532a4aba355813fff735f5d2f88a90 100644 (file)
@@ -11,7 +11,7 @@
 use back::bytecode::{DecodedBytecode, RLIB_BYTECODE_EXTENSION};
 use back::symbol_export;
 use back::write::{ModuleConfig, with_llvm_pmb, CodegenContext};
-use back::write;
+use back::write::{self, DiagnosticHandlers};
 use errors::{FatalError, Handler};
 use llvm::archive_ro::ArchiveRO;
 use llvm::{True, False};
@@ -234,9 +234,17 @@ fn fat_lto(cgcx: &CodegenContext,
     let module = modules.remove(costliest_module);
     let mut serialized_bitcode = Vec::new();
     {
-        let llmod = module.llvm().expect("can't lto pre-codegened modules").llmod();
+        let (llcx, llmod) = {
+            let llvm = module.llvm().expect("can't lto pre-codegened modules");
+            (&llvm.llcx, llvm.llmod())
+        };
         info!("using {:?} as a base module", module.llmod_id);
 
+        // The linking steps below may produce errors and diagnostics within LLVM
+        // which we'd like to handle and print, so set up our diagnostic handlers
+        // (which get unregistered when they go out of scope below).
+        let _handler = DiagnosticHandlers::new(cgcx, diag_handler, llcx);
+
         // For all other modules we codegened we'll need to link them into our own
         // bitcode. All modules were codegened in their own LLVM context, however,
         // and we want to move everything to the same LLVM context. Currently the
index db044878fe745e194b12d215cc0adc1453337e53..209c3a23c5cc35e1f6a97350825b3d61b4e5bae1 100644 (file)
@@ -397,15 +397,15 @@ pub(crate) fn save_temp_bitcode(&self, module: &ModuleCodegen, name: &str) {
     }
 }
 
-struct DiagnosticHandlers<'a> {
+pub struct DiagnosticHandlers<'a> {
     data: *mut (&'a CodegenContext, &'a Handler),
     llcx: &'a llvm::Context,
 }
 
 impl<'a> DiagnosticHandlers<'a> {
-    fn new(cgcx: &'a CodegenContext,
-           handler: &'a Handler,
-           llcx: &'a llvm::Context) -> Self {
+    pub fn new(cgcx: &'a CodegenContext,
+               handler: &'a Handler,
+               llcx: &'a llvm::Context) -> Self {
         let data = Box::into_raw(Box::new((cgcx, handler)));
         unsafe {
             llvm::LLVMRustSetInlineAsmDiagnosticHandler(llcx, inline_asm_handler, data as *mut _);
@@ -475,10 +475,11 @@ fn drop(&mut self) {
                                                 opt.message));
             }
         }
-        llvm::diagnostic::PGO(diagnostic_ref) => {
+        llvm::diagnostic::PGO(diagnostic_ref) |
+        llvm::diagnostic::Linker(diagnostic_ref) => {
             let msg = llvm::build_string(|s| {
                 llvm::LLVMRustWriteDiagnosticInfoToString(diagnostic_ref, s)
-            }).expect("non-UTF8 PGO diagnostic");
+            }).expect("non-UTF8 diagnostic");
             diag_handler.warn(&msg);
         }
         llvm::diagnostic::UnknownDiagnostic(..) => {},
index 8278b443a4c83a9e1394f16783b44ee00ca42e1c..34cd3998f83cc689b0b278bcfa35d367daf48614 100644 (file)
@@ -45,6 +45,7 @@
 use rustc::middle::cstore::{self, LinkMeta, LinkagePreference};
 use rustc::middle::exported_symbols;
 use rustc::util::common::{time, print_time_passes_entry};
+use rustc::util::profiling::ProfileCategory;
 use rustc::session::config::{self, NoDebugInfo};
 use rustc::session::Session;
 use rustc_incremental;
@@ -741,11 +742,13 @@ pub fn codegen_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let link_meta = link::build_link_meta(crate_hash);
 
     // Codegen the metadata.
+    tcx.sess.profiler(|p| p.start_activity(ProfileCategory::Codegen));
     let llmod_id = "metadata";
     let metadata_llvm_module = ModuleLlvm::new(tcx.sess, llmod_id);
     let metadata = time(tcx.sess, "write metadata", || {
         write_metadata(tcx, &metadata_llvm_module, &link_meta)
     });
+    tcx.sess.profiler(|p| p.end_activity(ProfileCategory::Codegen));
 
     let metadata_module = ModuleCodegen {
         name: link::METADATA_MODULE_NAME.to_string(),
index 5273032f2d7f5fd8d68a4f760b4a19fbbcb1a216..a76f1d50fa7bf89551717ec1eb9164b44837c1f8 100644 (file)
@@ -21,7 +21,7 @@
 
 use syntax_pos::Pos;
 
-use rustc_data_structures::bitvec::BitVector;
+use rustc_data_structures::bitvec::BitArray;
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 
 use syntax_pos::BytePos;
@@ -64,7 +64,7 @@ pub fn create_mir_scopes(
     };
 
     // Find all the scopes with variables defined in them.
-    let mut has_variables = BitVector::new(mir.source_scopes.len());
+    let mut has_variables = BitArray::new(mir.source_scopes.len());
     for var in mir.vars_iter() {
         let decl = &mir.local_decls[var];
         has_variables.insert(decl.visibility_scope);
@@ -81,7 +81,7 @@ pub fn create_mir_scopes(
 
 fn make_mir_scope(cx: &CodegenCx<'ll, '_>,
                   mir: &Mir,
-                  has_variables: &BitVector<SourceScope>,
+                  has_variables: &BitArray<SourceScope>,
                   debug_context: &FunctionDebugContextData<'ll>,
                   scope: SourceScope,
                   scopes: &mut IndexVec<SourceScope, MirDebugScope<'ll>>) {
index 724a2e3e65f4247a7a12c6936af79e58638fb46c..c01ef37d1b8cca664653b8e90d249c09f51d2680 100644 (file)
@@ -84,6 +84,7 @@
 use rustc::ty::{self, TyCtxt};
 use rustc::util::time_graph;
 use rustc::util::nodemap::{FxHashSet, FxHashMap};
+use rustc::util::profiling::ProfileCategory;
 use rustc_mir::monomorphize;
 use rustc_codegen_utils::codegen_backend::CodegenBackend;
 
@@ -240,10 +241,12 @@ fn join_codegen_and_link(
 
         // Run the linker on any artifacts that resulted from the LLVM run.
         // This should produce either a finished executable or library.
+        sess.profiler(|p| p.start_activity(ProfileCategory::Linking));
         time(sess, "linking", || {
             back::link::link_binary(sess, &ongoing_codegen,
                                     outputs, &ongoing_codegen.crate_name.as_str());
         });
+        sess.profiler(|p| p.end_activity(ProfileCategory::Linking));
 
         // Now that we won't touch anything in the incremental compilation directory
         // any more, we can finalize it (which involves renaming it)
index 7f2a9d6984a1577fbca34234f932f2b250e253d7..c41a5f74ae30282a598717aaa843f95fb9c348c9 100644 (file)
@@ -126,6 +126,7 @@ pub enum Diagnostic<'ll> {
     Optimization(OptimizationDiagnostic<'ll>),
     InlineAsm(InlineAsmDiagnostic<'ll>),
     PGO(&'ll DiagnosticInfo),
+    Linker(&'ll DiagnosticInfo),
 
     /// LLVM has other types that we do not wrap here.
     UnknownDiagnostic(&'ll DiagnosticInfo),
@@ -168,6 +169,9 @@ pub unsafe fn unpack(di: &'ll DiagnosticInfo) -> Self {
             Dk::PGOProfile => {
                 PGO(di)
             }
+            Dk::Linker => {
+                Linker(di)
+            }
 
             _ => UnknownDiagnostic(di),
         }
index 898d3d67353634b1ece65bfd1e2dd74fea44f9c8..989498ea92bcefd770af80cee557ac8f6741648b 100644 (file)
@@ -332,6 +332,7 @@ pub enum DiagnosticKind {
     OptimizationRemarkOther,
     OptimizationFailure,
     PGOProfile,
+    Linker,
 }
 
 /// LLVMRustArchiveKind
index 2c2058035241f5207b6ade9a111ec33005195e9b..993138aee1cec90e9560c9a5859baec62c96f3bf 100644 (file)
@@ -11,7 +11,7 @@
 //! An analysis to determine which locals require allocas and
 //! which do not.
 
-use rustc_data_structures::bitvec::BitVector;
+use rustc_data_structures::bitvec::BitArray;
 use rustc_data_structures::graph::dominators::Dominators;
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use rustc::mir::{self, Location, TerminatorKind};
@@ -22,7 +22,7 @@
 use type_of::LayoutLlvmExt;
 use super::FunctionCx;
 
-pub fn non_ssa_locals(fx: &FunctionCx<'a, 'll, 'tcx>) -> BitVector<mir::Local> {
+pub fn non_ssa_locals(fx: &FunctionCx<'a, 'll, 'tcx>) -> BitArray<mir::Local> {
     let mir = fx.mir;
     let mut analyzer = LocalAnalyzer::new(fx);
 
@@ -54,7 +54,7 @@ pub fn non_ssa_locals(fx: &FunctionCx<'a, 'll, 'tcx>) -> BitVector<mir::Local> {
 struct LocalAnalyzer<'mir, 'a: 'mir, 'll: 'a, 'tcx: 'll> {
     fx: &'mir FunctionCx<'a, 'll, 'tcx>,
     dominators: Dominators<mir::BasicBlock>,
-    non_ssa_locals: BitVector<mir::Local>,
+    non_ssa_locals: BitArray<mir::Local>,
     // The location of the first visited direct assignment to each
     // local, or an invalid location (out of bounds `block` index).
     first_assignment: IndexVec<mir::Local, Location>
@@ -67,7 +67,7 @@ fn new(fx: &'mir FunctionCx<'a, 'll, 'tcx>) -> Self {
         let mut analyzer = LocalAnalyzer {
             fx,
             dominators: fx.mir.dominators(),
-            non_ssa_locals: BitVector::new(fx.mir.local_decls.len()),
+            non_ssa_locals: BitArray::new(fx.mir.local_decls.len()),
             first_assignment: IndexVec::from_elem(invalid_location, &fx.mir.local_decls)
         };
 
index 8cdd0398eff96d02e28dfea807c8523429dc968b..a099cb5c64b211fcf1087717dfe5325db1e15099 100644 (file)
@@ -31,7 +31,7 @@
 
 use std::iter;
 
-use rustc_data_structures::bitvec::BitVector;
+use rustc_data_structures::bitvec::BitArray;
 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
 
 pub use self::constant::codegen_static_initializer;
@@ -323,7 +323,7 @@ pub fn codegen_mir(
     debuginfo::start_emitting_source_locations(&fx.debug_context);
 
     let rpo = traversal::reverse_postorder(&mir);
-    let mut visited = BitVector::new(mir.basic_blocks().len());
+    let mut visited = BitArray::new(mir.basic_blocks().len());
 
     // Codegen the body of each block using reverse postorder
     for (bb, _) in rpo {
@@ -417,7 +417,7 @@ fn arg_local_refs(
     bx: &Builder<'a, 'll, 'tcx>,
     fx: &FunctionCx<'a, 'll, 'tcx>,
     scopes: &IndexVec<mir::SourceScope, debuginfo::MirDebugScope<'ll>>,
-    memory_locals: &BitVector<mir::Local>,
+    memory_locals: &BitArray<mir::Local>,
 ) -> Vec<LocalRef<'ll, 'tcx>> {
     let mir = fx.mir;
     let tcx = bx.tcx();
index 04d6cb5e2a6d24ce87f57bdc0ac309fe42cd63e6..6e8a45d034250e2d4f7b195aa45c11d564c1561d 100644 (file)
@@ -9,24 +9,74 @@
 // except according to those terms.
 
 use indexed_vec::{Idx, IndexVec};
-use std::iter::FromIterator;
 use std::marker::PhantomData;
 
 type Word = u128;
 const WORD_BITS: usize = 128;
 
-/// A very simple BitVector type.
+/// A very simple BitArray type.
+///
+/// It does not support resizing after creation; use `BitVector` for that.
 #[derive(Clone, Debug, PartialEq)]
-pub struct BitVector<C: Idx> {
+pub struct BitArray<C: Idx> {
     data: Vec<Word>,
     marker: PhantomData<C>,
 }
 
+#[derive(Clone, Debug, PartialEq)]
+pub struct BitVector<C: Idx> {
+    data: BitArray<C>,
+}
+
 impl<C: Idx> BitVector<C> {
+    pub fn grow(&mut self, num_bits: C) {
+        self.data.grow(num_bits)
+    }
+
+    pub fn new() -> BitVector<C> {
+        BitVector {
+            data: BitArray::new(0),
+        }
+    }
+
+    pub fn with_capacity(bits: usize) -> BitVector<C> {
+        BitVector {
+            data: BitArray::new(bits),
+        }
+    }
+
+    /// Returns true if the bit has changed.
+    #[inline]
+    pub fn insert(&mut self, bit: C) -> bool {
+        self.grow(bit);
+        self.data.insert(bit)
+    }
+
     #[inline]
-    pub fn new(num_bits: usize) -> BitVector<C> {
+    pub fn contains(&self, bit: C) -> bool {
+        let (word, mask) = word_mask(bit);
+        if let Some(word) = self.data.data.get(word) {
+            (word & mask) != 0
+        } else {
+            false
+        }
+    }
+}
+
+impl<C: Idx> BitArray<C> {
+    // Do not make this method public, instead switch your use case to BitVector.
+    #[inline]
+    fn grow(&mut self, num_bits: C) {
         let num_words = words(num_bits);
-        BitVector {
+        if self.data.len() <= num_words {
+            self.data.resize(num_words + 1, 0)
+        }
+    }
+
+    #[inline]
+    pub fn new(num_bits: usize) -> BitArray<C> {
+        let num_words = words(num_bits);
+        BitArray {
             data: vec![0; num_words],
             marker: PhantomData,
         }
@@ -54,7 +104,7 @@ pub fn contains(&self, bit: C) -> bool {
     ///
     /// The two vectors must have the same length.
     #[inline]
-    pub fn contains_all(&self, other: &BitVector<C>) -> bool {
+    pub fn contains_all(&self, other: &BitArray<C>) -> bool {
         assert_eq!(self.data.len(), other.data.len());
         self.data.iter().zip(&other.data).all(|(a, b)| (a & b) == *b)
     }
@@ -94,7 +144,7 @@ pub fn remove(&mut self, bit: C) -> bool {
     }
 
     #[inline]
-    pub fn merge(&mut self, all: &BitVector<C>) -> bool {
+    pub fn merge(&mut self, all: &BitArray<C>) -> bool {
         assert!(self.data.len() == all.data.len());
         let mut changed = false;
         for (i, j) in self.data.iter_mut().zip(&all.data) {
@@ -107,18 +157,10 @@ pub fn merge(&mut self, all: &BitVector<C>) -> bool {
         changed
     }
 
-    #[inline]
-    pub fn grow(&mut self, num_bits: C) {
-        let num_words = words(num_bits);
-        if self.data.len() < num_words {
-            self.data.resize(num_words, 0)
-        }
-    }
-
     /// Iterates over indexes of set bits in a sorted order
     #[inline]
-    pub fn iter<'a>(&'a self) -> BitVectorIter<'a, C> {
-        BitVectorIter {
+    pub fn iter<'a>(&'a self) -> BitIter<'a, C> {
+        BitIter {
             iter: self.data.iter(),
             current: 0,
             idx: 0,
@@ -127,14 +169,14 @@ pub fn iter<'a>(&'a self) -> BitVectorIter<'a, C> {
     }
 }
 
-pub struct BitVectorIter<'a, C: Idx> {
+pub struct BitIter<'a, C: Idx> {
     iter: ::std::slice::Iter<'a, Word>,
     current: Word,
     idx: usize,
     marker: PhantomData<C>
 }
 
-impl<'a, C: Idx> Iterator for BitVectorIter<'a, C> {
+impl<'a, C: Idx> Iterator for BitIter<'a, C> {
     type Item = C;
     fn next(&mut self) -> Option<C> {
         while self.current == 0 {
@@ -163,30 +205,6 @@ fn size_hint(&self) -> (usize, Option<usize>) {
     }
 }
 
-impl<C: Idx> FromIterator<bool> for BitVector<C> {
-    fn from_iter<I>(iter: I) -> BitVector<C>
-    where
-        I: IntoIterator<Item = bool>,
-    {
-        let iter = iter.into_iter();
-        let (len, _) = iter.size_hint();
-        // Make the minimum length for the bitvector WORD_BITS bits since that's
-        // the smallest non-zero size anyway.
-        let len = if len < WORD_BITS { WORD_BITS } else { len };
-        let mut bv = BitVector::new(len);
-        for (idx, val) in iter.enumerate() {
-            if idx > len {
-                bv.grow(C::new(idx));
-            }
-            if val {
-                bv.insert(C::new(idx));
-            }
-        }
-
-        bv
-    }
-}
-
 /// A "bit matrix" is basically a matrix of booleans represented as
 /// one gigantic bitvector. In other words, it is as if you have
 /// `rows` bitvectors, each of length `columns`.
@@ -288,9 +306,9 @@ pub fn merge(&mut self, read: R, write: R) -> bool {
 
     /// Iterates through all the columns set to true in a given row of
     /// the matrix.
-    pub fn iter<'a>(&'a self, row: R) -> BitVectorIter<'a, C> {
+    pub fn iter<'a>(&'a self, row: R) -> BitIter<'a, C> {
         let (start, end) = self.range(row);
-        BitVectorIter {
+        BitIter {
             iter: self.vector[start..end].iter(),
             current: 0,
             idx: 0,
@@ -308,7 +326,7 @@ pub struct SparseBitMatrix<R, C>
     C: Idx,
 {
     columns: usize,
-    vector: IndexVec<R, BitVector<C>>,
+    vector: IndexVec<R, BitArray<C>>,
 }
 
 impl<R: Idx, C: Idx> SparseBitMatrix<R, C> {
@@ -323,7 +341,7 @@ pub fn new(columns: usize) -> Self {
     fn ensure_row(&mut self, row: R) {
         let columns = self.columns;
         self.vector
-            .ensure_contains_elem(row, || BitVector::new(columns));
+            .ensure_contains_elem(row, || BitArray::new(columns));
     }
 
     /// Sets the cell at `(row, column)` to true. Put another way, insert
@@ -361,7 +379,7 @@ pub fn merge(&mut self, read: R, write: R) -> bool {
     }
 
     /// Merge a row, `from`, into the `into` row.
-    pub fn merge_into(&mut self, into: R, from: &BitVector<C>) -> bool {
+    pub fn merge_into(&mut self, into: R, from: &BitArray<C>) -> bool {
         self.ensure_row(into);
         self.vector[into].merge(from)
     }
@@ -388,11 +406,11 @@ pub fn iter<'a>(&'a self, row: R) -> impl Iterator<Item = C> + 'a {
     }
 
     /// Iterates through each row and the accompanying bit set.
-    pub fn iter_enumerated<'a>(&'a self) -> impl Iterator<Item = (R, &'a BitVector<C>)> + 'a {
+    pub fn iter_enumerated<'a>(&'a self) -> impl Iterator<Item = (R, &'a BitArray<C>)> + 'a {
         self.vector.iter_enumerated()
     }
 
-    pub fn row(&self, row: R) -> Option<&BitVector<C>> {
+    pub fn row(&self, row: R) -> Option<&BitArray<C>> {
         self.vector.get(row)
     }
 }
@@ -412,7 +430,7 @@ fn word_mask<C: Idx>(index: C) -> (usize, Word) {
 
 #[test]
 fn bitvec_iter_works() {
-    let mut bitvec: BitVector<usize> = BitVector::new(100);
+    let mut bitvec: BitArray<usize> = BitArray::new(100);
     bitvec.insert(1);
     bitvec.insert(10);
     bitvec.insert(19);
@@ -430,7 +448,7 @@ fn bitvec_iter_works() {
 
 #[test]
 fn bitvec_iter_works_2() {
-    let mut bitvec: BitVector<usize> = BitVector::new(319);
+    let mut bitvec: BitArray<usize> = BitArray::new(319);
     bitvec.insert(0);
     bitvec.insert(127);
     bitvec.insert(191);
@@ -441,8 +459,8 @@ fn bitvec_iter_works_2() {
 
 #[test]
 fn union_two_vecs() {
-    let mut vec1: BitVector<usize> = BitVector::new(65);
-    let mut vec2: BitVector<usize> = BitVector::new(65);
+    let mut vec1: BitArray<usize> = BitArray::new(65);
+    let mut vec2: BitArray<usize> = BitArray::new(65);
     assert!(vec1.insert(3));
     assert!(!vec1.insert(3));
     assert!(vec2.insert(5));
@@ -458,7 +476,7 @@ fn union_two_vecs() {
 
 #[test]
 fn grow() {
-    let mut vec1: BitVector<usize> = BitVector::new(65);
+    let mut vec1: BitVector<usize> = BitVector::with_capacity(65);
     for index in 0..65 {
         assert!(vec1.insert(index));
         assert!(!vec1.insert(index));
index dbfc09116bbaa281bbe5c076ecc21bdf7422c80f..cf9403db658f4fa9fcb5a6dcb4cec900de1b5b76 100644 (file)
@@ -30,7 +30,7 @@
 //! the field `next_edge`). Each of those fields is an array that should
 //! be indexed by the direction (see the type `Direction`).
 
-use bitvec::BitVector;
+use bitvec::BitArray;
 use std::fmt::Debug;
 use std::usize;
 use snapshot_vec::{SnapshotVec, SnapshotVecDelegate};
@@ -266,7 +266,7 @@ pub fn nodes_in_postorder<'a>(
         direction: Direction,
         entry_node: NodeIndex,
     ) -> Vec<NodeIndex> {
-        let mut visited = BitVector::new(self.len_nodes());
+        let mut visited = BitArray::new(self.len_nodes());
         let mut stack = vec![];
         let mut result = Vec::with_capacity(self.len_nodes());
         let mut push_node = |stack: &mut Vec<_>, node: NodeIndex| {
@@ -348,7 +348,7 @@ pub struct DepthFirstTraversal<'g, N, E>
 {
     graph: &'g Graph<N, E>,
     stack: Vec<NodeIndex>,
-    visited: BitVector<usize>,
+    visited: BitArray<usize>,
     direction: Direction,
 }
 
@@ -358,7 +358,7 @@ pub fn with_start_node(
         start_node: NodeIndex,
         direction: Direction,
     ) -> Self {
-        let mut visited = BitVector::new(graph.len_nodes());
+        let mut visited = BitArray::new(graph.len_nodes());
         visited.insert(start_node.node_id());
         DepthFirstTraversal {
             graph,
index b5f52d54ae471bd7bca2569b46a3eea2283a8332..76b01beb4bad3dbcd524fb2c07bee6ccb210f434 100644 (file)
@@ -169,18 +169,11 @@ fn from_iter<I>(iter: I) -> Self where I: IntoIterator<Item=A::Element> {
 
 impl<A: Array> Extend<A::Element> for SmallVec<A> {
     fn extend<I: IntoIterator<Item=A::Element>>(&mut self, iter: I) {
-        if self.is_array() {
-            let iter = iter.into_iter();
-            self.reserve(iter.size_hint().0);
-
-            for el in iter {
-                self.push(el);
-            }
-        } else {
-            match self.0 {
-                AccumulateVec::Heap(ref mut vec) => vec.extend(iter),
-                _ => unreachable!()
-            }
+        let iter = iter.into_iter();
+        self.reserve(iter.size_hint().0);
+        match self.0 {
+            AccumulateVec::Heap(ref mut vec) => vec.extend(iter),
+            _ => iter.for_each(|el| self.push(el))
         }
     }
 }
index 24a2354775cb55299822f048e1bc421d6ed7c7cd..f178f847aa51e21858f17929d60107f4b756405f 100644 (file)
@@ -25,6 +25,7 @@
 use rustc::ty::{self, AllArenas, Resolutions, TyCtxt};
 use rustc::traits;
 use rustc::util::common::{install_panic_hook, time, ErrorReported};
+use rustc::util::profiling::ProfileCategory;
 use rustc_allocator as allocator;
 use rustc_borrowck as borrowck;
 use rustc_incremental;
@@ -352,6 +353,14 @@ macro_rules! controller_entry_point {
         sess.print_perf_stats();
     }
 
+    if sess.opts.debugging_opts.self_profile {
+        sess.print_profiler_results();
+
+        if sess.opts.debugging_opts.profile_json {
+            sess.save_json_results();
+        }
+    }
+
     controller_entry_point!(
         compilation_done,
         sess,
@@ -667,6 +676,7 @@ pub fn phase_1_parse_input<'a>(
         profile::begin(sess);
     }
 
+    sess.profiler(|p| p.start_activity(ProfileCategory::Parsing));
     let krate = time(sess, "parsing", || match *input {
         Input::File(ref file) => parse::parse_crate_from_file(file, &sess.parse_sess),
         Input::Str {
@@ -674,6 +684,7 @@ pub fn phase_1_parse_input<'a>(
             ref name,
         } => parse::parse_crate_from_source_str(name.clone(), input.clone(), &sess.parse_sess),
     })?;
+    sess.profiler(|p| p.end_activity(ProfileCategory::Parsing));
 
     sess.diagnostic().set_continue_after_error(true);
 
@@ -944,6 +955,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(
     syntax_ext::register_builtins(&mut resolver, syntax_exts, sess.features_untracked().quote);
 
     // Expand all macros
+    sess.profiler(|p| p.start_activity(ProfileCategory::Expansion));
     krate = time(sess, "expansion", || {
         // Windows dlls do not have rpaths, so they don't know how to find their
         // dependencies. It's up to us to tell the system where to find all the
@@ -1021,6 +1033,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(
         }
         krate
     });
+    sess.profiler(|p| p.end_activity(ProfileCategory::Expansion));
 
     krate = time(sess, "maybe building test harness", || {
         syntax::test::modify_for_testing(
@@ -1350,7 +1363,9 @@ pub fn phase_4_codegen<'a, 'tcx>(
         ::rustc::middle::dependency_format::calculate(tcx)
     });
 
+    tcx.sess.profiler(|p| p.start_activity(ProfileCategory::Codegen));
     let codegen = time(tcx.sess, "codegen", move || codegen_backend.codegen_crate(tcx, rx));
+    tcx.sess.profiler(|p| p.end_activity(ProfileCategory::Codegen));
     if tcx.sess.profile_queries() {
         profile::dump(&tcx.sess, "profile_queries".to_string())
     }
index 561f5fbf5c41e5a809f59257b5ebdf93626b4fa4..8481f738adc7b5f94573a53d021d6b713c51bd0f 100644 (file)
@@ -1630,7 +1630,13 @@ fn validate_const<'a, 'tcx>(
 
 fn check_const(cx: &LateContext, body_id: hir::BodyId, what: &str) {
     let def_id = cx.tcx.hir.body_owner_def_id(body_id);
-    let param_env = cx.tcx.param_env(def_id);
+    let is_static = cx.tcx.is_static(def_id).is_some();
+    let param_env = if is_static {
+        // Use the same param_env as `codegen_static_initializer`, to reuse the cache.
+        ty::ParamEnv::reveal_all()
+    } else {
+        cx.tcx.param_env(def_id)
+    };
     let cid = ::rustc::mir::interpret::GlobalId {
         instance: ty::Instance::mono(cx.tcx, def_id),
         promoted: None
@@ -1638,8 +1644,8 @@ fn check_const(cx: &LateContext, body_id: hir::BodyId, what: &str) {
     match cx.tcx.const_eval(param_env.and(cid)) {
         Ok(val) => validate_const(cx.tcx, val, param_env, cid, what),
         Err(err) => {
-            // errors for statics are already reported directly in the query
-            if cx.tcx.is_static(def_id).is_none() {
+            // errors for statics are already reported directly in the query, avoid duplicates
+            if !is_static {
                 let span = cx.tcx.def_span(def_id);
                 err.report_as_lint(
                     cx.tcx.at(span),
index 78a8c494f48c53e5d4f09c85199608a5921d6c76..b92ac0ff57bd88478b5fb40c95520c55e884173a 100644 (file)
@@ -45,7 +45,6 @@
 use rustc::lint::builtin::{
     BARE_TRAIT_OBJECTS,
     ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
-    MACRO_USE_EXTERN_CRATE,
     ELIDED_LIFETIMES_IN_PATHS,
     parser::QUESTION_MARK_MACRO_SEP
 };
@@ -195,11 +194,18 @@ macro_rules! add_lint_group {
     add_lint_group!(sess,
                     "rust_2018_idioms",
                     BARE_TRAIT_OBJECTS,
-                    UNREACHABLE_PUB,
                     UNUSED_EXTERN_CRATES,
-                    MACRO_USE_EXTERN_CRATE,
-                    ELIDED_LIFETIMES_IN_PATHS,
-                    ELLIPSIS_INCLUSIVE_RANGE_PATTERNS);
+                    ELLIPSIS_INCLUSIVE_RANGE_PATTERNS,
+                    ELIDED_LIFETIMES_IN_PATHS
+
+                    // FIXME(#52665, #47816) not always applicable and not all
+                    // macros are ready for this yet.
+                    // UNREACHABLE_PUB,
+
+                    // FIXME macro crates are not up for this yet, too much
+                    // breakage is seen if we try to encourage this lint.
+                    // MACRO_USE_EXTERN_CRATE,
+                    );
 
     // Guidelines for creating a future incompatibility lint:
     //
index 5910e55def39690c3e6d5b6a19fedd97721d8010..4e24a26983d48754a9a84dd78cb2d1b083f18866 100644 (file)
@@ -100,6 +100,10 @@ fn main() {
         optional_components.push("hexagon");
     }
 
+    if major > 6 {
+        optional_components.push("riscv");
+    }
+
     // FIXME: surely we don't need all these components, right? Stuff like mcjit
     //        or interpreter the compiler itself never uses.
     let required_components = &["ipo",
index 05f6b5b5fbd289fc60c4f7cdf6408f7d7c16c4fa..ffa97bd6fa59d3a385d5738440a54d8527134871 100644 (file)
@@ -90,6 +90,12 @@ fn init() { }
                  LLVMInitializeMSP430Target,
                  LLVMInitializeMSP430TargetMC,
                  LLVMInitializeMSP430AsmPrinter);
+    init_target!(llvm_component = "riscv",
+                 LLVMInitializeRISCVTargetInfo,
+                 LLVMInitializeRISCVTarget,
+                 LLVMInitializeRISCVTargetMC,
+                 LLVMInitializeRISCVAsmPrinter,
+                 LLVMInitializeRISCVAsmParser);
     init_target!(llvm_component = "sparc",
                  LLVMInitializeSparcTargetInfo,
                  LLVMInitializeSparcTarget,
index 27221296ff31fc467856f7f46c0525f76d327576..4596c7be1c557b728402a4e23b4420225220f4a6 100644 (file)
@@ -22,7 +22,7 @@
 use rustc::mir::{Field, Projection, ProjectionElem, Rvalue, Statement, StatementKind};
 use rustc::mir::{Terminator, TerminatorKind};
 use rustc::ty::query::Providers;
-use rustc::ty::{self, ParamEnv, TyCtxt};
+use rustc::ty::{self, ParamEnv, TyCtxt, Ty};
 
 use rustc_errors::{Diagnostic, DiagnosticBuilder, Level};
 use rustc_data_structures::graph::dominators::Dominators;
@@ -598,7 +598,12 @@ fn visit_terminator_entry(
                 // that is useful later.
                 let drop_place_ty = gcx.lift(&drop_place_ty).unwrap();
 
-                self.visit_terminator_drop(loc, term, flow_state, drop_place, drop_place_ty, span);
+                debug!("visit_terminator_drop \
+                        loc: {:?} term: {:?} drop_place: {:?} drop_place_ty: {:?} span: {:?}",
+                       loc, term, drop_place, drop_place_ty, span);
+
+                self.visit_terminator_drop(
+                    loc, term, flow_state, drop_place, drop_place_ty, span, SeenTy(None));
             }
             TerminatorKind::DropAndReplace {
                 location: ref drop_place,
@@ -832,6 +837,35 @@ fn as_verb_in_past_tense(self) -> &'static str {
     }
 }
 
+/// A simple linked-list threaded up the stack of recursive calls in `visit_terminator_drop`.
+#[derive(Copy, Clone, Debug)]
+struct SeenTy<'a, 'gcx: 'a>(Option<(Ty<'gcx>, &'a SeenTy<'a, 'gcx>)>);
+
+impl<'a, 'gcx> SeenTy<'a, 'gcx> {
+    /// Return a new list with `ty` prepended to the front of `self`.
+    fn cons(&'a self, ty: Ty<'gcx>) -> Self {
+        SeenTy(Some((ty, self)))
+    }
+
+    /// True if and only if `ty` occurs on the linked list `self`.
+    fn have_seen(self, ty: Ty) -> bool {
+        let mut this = self.0;
+        loop {
+            match this {
+                None => return false,
+                Some((seen_ty, recur)) => {
+                    if seen_ty == ty {
+                        return true;
+                    } else {
+                        this = recur.0;
+                        continue;
+                    }
+                }
+            }
+        }
+    }
+}
+
 impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
     /// Invokes `access_place` as appropriate for dropping the value
     /// at `drop_place`. Note that the *actual* `Drop` in the MIR is
@@ -847,14 +881,57 @@ fn visit_terminator_drop(
         drop_place: &Place<'tcx>,
         erased_drop_place_ty: ty::Ty<'gcx>,
         span: Span,
+        prev_seen: SeenTy<'_, 'gcx>,
     ) {
+        if prev_seen.have_seen(erased_drop_place_ty) {
+            // if we have directly seen the input ty `T`, then we must
+            // have had some *direct* ownership loop between `T` and
+            // some directly-owned (as in, actually traversed by
+            // recursive calls below) part that is also of type `T`.
+            //
+            // Note: in *all* such cases, the data in question cannot
+            // be constructed (nor destructed) in finite time/space.
+            //
+            // Proper examples, some of which are statically rejected:
+            //
+            // * `struct A { field: A, ... }`:
+            //   statically rejected as infinite size
+            //
+            // * `type B = (B, ...);`:
+            //   statically rejected as cyclic
+            //
+            // * `struct C { field: Box<C>, ... }`
+            // * `struct D { field: Box<(D, D)>, ... }`:
+            //   *accepted*, though impossible to construct
+            //
+            // Here is *NOT* an example:
+            // * `struct Z { field: Option<Box<Z>>, ... }`:
+            //   Here, the type is both representable in finite space (due to the boxed indirection)
+            //   and constructable in finite time (since the recursion can bottom out with `None`).
+            //   This is an obvious instance of something the compiler must accept.
+            //
+            // Since some of the above impossible cases like `C` and
+            // `D` are accepted by the compiler, we must take care not
+            // to infinite-loop while processing them. But since such
+            // cases cannot actually arise, it is sound for us to just
+            // skip them during drop. If the developer uses unsafe
+            // code to construct them, they should not be surprised by
+            // weird drop behavior in their resulting code.
+            debug!("visit_terminator_drop previously seen \
+                    erased_drop_place_ty: {:?} on prev_seen: {:?}; returning early.",
+                   erased_drop_place_ty, prev_seen);
+            return;
+        }
+
         let gcx = self.tcx.global_tcx();
         let drop_field = |mir: &mut MirBorrowckCtxt<'cx, 'gcx, 'tcx>,
                           (index, field): (usize, ty::Ty<'gcx>)| {
             let field_ty = gcx.normalize_erasing_regions(mir.param_env, field);
             let place = drop_place.clone().field(Field::new(index), field_ty);
 
-            mir.visit_terminator_drop(loc, term, flow_state, &place, field_ty, span);
+            debug!("visit_terminator_drop drop_field place: {:?} field_ty: {:?}", place, field_ty);
+            let seen = prev_seen.cons(erased_drop_place_ty);
+            mir.visit_terminator_drop(loc, term, flow_state, &place, field_ty, span, seen);
         };
 
         match erased_drop_place_ty.sty {
@@ -899,13 +976,42 @@ fn visit_terminator_drop(
                     .enumerate()
                     .for_each(|field| drop_field(self, field));
             }
+
+            // #45696: special-case Box<T> by treating its dtor as
+            // only deep *across owned content*. Namely, we know
+            // dropping a box does not touch data behind any
+            // references it holds; if we were to instead fall into
+            // the base case below, we would have a Deep Write due to
+            // the box being `needs_drop`, and that Deep Write would
+            // touch `&mut` data in the box.
+            ty::TyAdt(def, _) if def.is_box() => {
+                // When/if we add a `&own T` type, this action would
+                // be like running the destructor of the `&own T`.
+                // (And the owner of backing storage referenced by the
+                // `&own T` would be responsible for deallocating that
+                // backing storage.)
+
+                // we model dropping any content owned by the box by
+                // recurring on box contents. This catches cases like
+                // `Box<Box<ScribbleWhenDropped<&mut T>>>`, while
+                // still restricting Write to *owned* content.
+                let ty = erased_drop_place_ty.boxed_ty();
+                let deref_place = drop_place.clone().deref();
+                debug!("visit_terminator_drop drop-box-content deref_place: {:?} ty: {:?}",
+                       deref_place, ty);
+                let seen = prev_seen.cons(erased_drop_place_ty);
+                self.visit_terminator_drop(
+                    loc, term, flow_state, &deref_place, ty, span, seen);
+            }
+
             _ => {
                 // We have now refined the type of the value being
                 // dropped (potentially) to just the type of a
                 // subfield; so check whether that field's type still
-                // "needs drop". If so, we assume that the destructor
-                // may access any data it likes (i.e., a Deep Write).
+                // "needs drop".
                 if erased_drop_place_ty.needs_drop(gcx, self.param_env) {
+                    // If so, we assume that the destructor may access
+                    // any data it likes (i.e., a Deep Write).
                     self.access_place(
                         ContextKind::Drop.new(loc),
                         (drop_place, span),
@@ -913,6 +1019,41 @@ fn visit_terminator_drop(
                         LocalMutationIsAllowed::Yes,
                         flow_state,
                     );
+                } else {
+                    // If there is no destructor, we still include a
+                    // *shallow* write.  This essentially ensures that
+                    // borrows of the memory directly at `drop_place`
+                    // cannot continue to be borrowed across the drop.
+                    //
+                    // If we were to use a Deep Write here, then any
+                    // `&mut T` that is reachable from `drop_place`
+                    // would get invalidated; fixing that is the
+                    // essence of resolving issue #45696.
+                    //
+                    // * Note: In the compiler today, doing a Deep
+                    //   Write here would not actually break
+                    //   anything beyond #45696; for example it does not
+                    //   break this example:
+                    //
+                    //   ```rust
+                    //   fn reborrow(x: &mut i32) -> &mut i32 { &mut *x }
+                    //   ```
+                    //
+                    //   Why? Because we do not schedule/emit
+                    //   `Drop(x)` in the MIR unless `x` needs drop in
+                    //   the first place.
+                    //
+                    // FIXME: Its possible this logic actually should
+                    // be attached to the `StorageDead` statement
+                    // rather than the `Drop`. See discussion on PR
+                    // #52782.
+                    self.access_place(
+                        ContextKind::Drop.new(loc),
+                        (drop_place, span),
+                        (Shallow(None), Write(WriteKind::StorageDeadOrDrop)),
+                        LocalMutationIsAllowed::Yes,
+                        flow_state,
+                    );
                 }
             }
         }
index cdb0351d9a8f08ca7f9faf95fb2e6a12205c7b51..d98bba72f7a33be06f10e0d31ac90e7aae263e65 100644 (file)
@@ -11,7 +11,7 @@
 use borrow_check::borrow_set::BorrowData;
 use borrow_check::nll::region_infer::Cause;
 use borrow_check::{Context, MirBorrowckCtxt, WriteKind};
-use rustc::mir::Place;
+use rustc::mir::{Location, Place, TerminatorKind};
 use rustc_errors::DiagnosticBuilder;
 
 mod find_use;
@@ -63,10 +63,17 @@ pub(in borrow_check) fn explain_why_borrow_contains_point(
 
         match find_use::find(mir, regioncx, tcx, region_sub, context.loc) {
             Some(Cause::LiveVar(_local, location)) => {
-                err.span_label(
-                    mir.source_info(location).span,
-                    "borrow later used here".to_string(),
-                );
+                if self.is_borrow_location_in_loop(context.loc) {
+                    err.span_label(
+                        mir.source_info(location).span,
+                        "borrow used here in later iteration of loop".to_string(),
+                    );
+                } else {
+                    err.span_label(
+                        mir.source_info(location).span,
+                        "borrow later used here".to_string(),
+                    );
+                }
             }
 
             Some(Cause::DropVar(local, location)) => match &mir.local_decls[local].name {
@@ -107,4 +114,76 @@ pub(in borrow_check) fn explain_why_borrow_contains_point(
             }
         }
     }
+
+    /// Check if a borrow location is within a loop.
+    fn is_borrow_location_in_loop(
+        &self,
+        borrow_location: Location,
+    ) -> bool {
+        let mut visited_locations = Vec::new();
+        let mut pending_locations = vec![ borrow_location ];
+        debug!("is_in_loop: borrow_location={:?}", borrow_location);
+
+        while let Some(location) = pending_locations.pop() {
+            debug!("is_in_loop: location={:?} pending_locations={:?} visited_locations={:?}",
+                   location, pending_locations, visited_locations);
+            if location == borrow_location && visited_locations.contains(&borrow_location) {
+                // We've managed to return to where we started (and this isn't the start of the
+                // search).
+                debug!("is_in_loop: found!");
+                return true;
+            }
+
+            // Skip locations we've been.
+            if visited_locations.contains(&location) { continue; }
+
+            let block = &self.mir.basic_blocks()[location.block];
+            if location.statement_index ==  block.statements.len() {
+                // Add start location of the next blocks to pending locations.
+                match block.terminator().kind {
+                    TerminatorKind::Goto { target } => {
+                        pending_locations.push(target.start_location());
+                    },
+                    TerminatorKind::SwitchInt { ref targets, .. } => {
+                        for target in targets {
+                            pending_locations.push(target.start_location());
+                        }
+                    },
+                    TerminatorKind::Drop { target, unwind, .. } |
+                    TerminatorKind::DropAndReplace { target, unwind, .. } |
+                    TerminatorKind::Assert { target, cleanup: unwind, .. } |
+                    TerminatorKind::Yield { resume: target, drop: unwind, .. } |
+                    TerminatorKind::FalseUnwind { real_target: target, unwind, .. } => {
+                        pending_locations.push(target.start_location());
+                        if let Some(unwind) = unwind {
+                            pending_locations.push(unwind.start_location());
+                        }
+                    },
+                    TerminatorKind::Call { ref destination, cleanup, .. } => {
+                        if let Some((_, destination)) = destination {
+                            pending_locations.push(destination.start_location());
+                        }
+                        if let Some(cleanup) = cleanup {
+                            pending_locations.push(cleanup.start_location());
+                        }
+                    },
+                    TerminatorKind::FalseEdges { real_target, ref imaginary_targets, .. } => {
+                        pending_locations.push(real_target.start_location());
+                        for target in imaginary_targets {
+                            pending_locations.push(target.start_location());
+                        }
+                    },
+                    _ => {},
+                }
+            } else {
+                // Add the next statement to pending locations.
+                pending_locations.push(location.successor_within_block());
+            }
+
+            // Keep track of where we have visited.
+            visited_locations.push(location);
+        }
+
+        false
+    }
 }
index c44af0036547966e4f390cca6334c72425ef2225..640ae31d45b349db89028614c438daca19eca80e 100644 (file)
@@ -329,6 +329,13 @@ fn place_element_conflict<'a, 'gcx: 'tcx, 'tcx>(
         }
         (Place::Promoted(p1), Place::Promoted(p2)) => {
             if p1.0 == p2.0 {
+                if let ty::TyArray(_, size) = p1.1.sty {
+                    if size.unwrap_usize(tcx) == 0 {
+                        // Ignore conflicts with promoted [T; 0].
+                        debug!("place_element_conflict: IGNORE-LEN-0-PROMOTED");
+                        return Overlap::Disjoint;
+                    }
+                }
                 // the same promoted - base case, equal
                 debug!("place_element_conflict: DISJOINT-OR-EQ-PROMOTED");
                 Overlap::EqualOrDisjoint
index 6a447d81dc3cb5f92f549b63621f1e5081df975a..6b6ec749bcbe6efd1124d6f529264564a4aab661 100644 (file)
@@ -18,7 +18,7 @@
 use build::ForGuard::{self, OutsideGuard, RefWithinGuard, ValWithinGuard};
 use build::scope::{CachedBlock, DropKind};
 use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::bitvec::BitVector;
+use rustc_data_structures::bitvec::BitArray;
 use rustc::ty::{self, Ty};
 use rustc::mir::*;
 use rustc::hir;
@@ -496,7 +496,7 @@ enum TestKind<'tcx> {
     // test the branches of enum
     Switch {
         adt_def: &'tcx ty::AdtDef,
-        variants: BitVector<usize>,
+        variants: BitArray<usize>,
     },
 
     // test the branches of enum
index f8bfb5b48ba99fdc18ec18087d1a7c703d1d4a2f..7106e02284da3888cd219b61d17fe23ce5076bb6 100644 (file)
@@ -19,7 +19,7 @@
 use build::matches::{Candidate, MatchPair, Test, TestKind};
 use hair::*;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::bitvec::BitVector;
+use rustc_data_structures::bitvec::BitArray;
 use rustc::ty::{self, Ty};
 use rustc::ty::util::IntTypeExt;
 use rustc::mir::*;
@@ -38,7 +38,7 @@ pub fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<'tcx> {
                     span: match_pair.pattern.span,
                     kind: TestKind::Switch {
                         adt_def: adt_def.clone(),
-                        variants: BitVector::new(adt_def.variants.len()),
+                        variants: BitArray::new(adt_def.variants.len()),
                     },
                 }
             }
@@ -149,7 +149,7 @@ pub fn add_cases_to_switch<'pat>(&mut self,
     pub fn add_variants_to_switch<'pat>(&mut self,
                                         test_place: &Place<'tcx>,
                                         candidate: &Candidate<'pat, 'tcx>,
-                                        variants: &mut BitVector<usize>)
+                                        variants: &mut BitArray<usize>)
                                         -> bool
     {
         let match_pair = match candidate.match_pairs.iter().find(|mp| mp.place == *test_place) {
index 96f4c6b60f511648627799e684ecbacc91a95fcc..c8c41c13b0fbb684fbaa8967689f6fb12f9a3508 100644 (file)
@@ -15,9 +15,9 @@
 use dataflow::BitDenotation;
 
 /// This calculates if any part of a MIR local could have previously been borrowed.
-/// This means that once a local has been borrowed, its bit will always be set
-/// from that point and onwards, even if the borrow ends. You could also think of this
-/// as computing the lifetimes of infinite borrows.
+/// This means that once a local has been borrowed, its bit will be set
+/// from that point and onwards, until we see a StorageDead statement for the local,
+/// at which points there is no memory associated with the local, so it cannot be borrowed.
 /// This is used to compute which locals are live during a yield expression for
 /// immovable generators.
 #[derive(Copy, Clone)]
@@ -50,9 +50,17 @@ fn start_block_effect(&self, _sets: &mut IdxSet<Local>) {
     fn statement_effect(&self,
                         sets: &mut BlockSets<Local>,
                         loc: Location) {
+        let stmt = &self.mir[loc.block].statements[loc.statement_index];
+
         BorrowedLocalsVisitor {
             sets,
-        }.visit_statement(loc.block, &self.mir[loc.block].statements[loc.statement_index], loc);
+        }.visit_statement(loc.block, stmt, loc);
+
+        // StorageDead invalidates all borrows and raw pointers to a local
+        match stmt.kind {
+            StatementKind::StorageDead(l) => sets.kill(&l),
+            _ => (),
+        }
     }
 
     fn terminator_effect(&self,
index bd90b308fabe80e2ac9fc5263e2bf86d2d7194ca..97f1f2a76ca2b71ef2b346aafa812604ecdd5ed5 100644 (file)
@@ -240,7 +240,7 @@ fn new() -> InliningMap<'tcx> {
         InliningMap {
             index: FxHashMap(),
             targets: Vec::new(),
-            inlines: BitVector::new(1024),
+            inlines: BitVector::with_capacity(1024),
         }
     }
 
index 6a9258fe2c918eb5d4ae9b1574fdb8420c819ac0..a3647edd155d3d71b105891b4e16b16d7400a683 100644 (file)
@@ -433,7 +433,8 @@ fn locals_live_across_suspend_points<'a, 'tcx,>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 // The `liveness` variable contains the liveness of MIR locals ignoring borrows.
                 // This is correct for movable generators since borrows cannot live across
                 // suspension points. However for immovable generators we need to account for
-                // borrows, so we conseratively assume that all borrowed locals live forever.
+                // borrows, so we conseratively assume that all borrowed locals are live until
+                // we find a StorageDead statement referencing the locals.
                 // To do this we just union our `liveness` result with `borrowed_locals`, which
                 // contains all the locals which has been borrowed before this suspension point.
                 // If a borrow is converted to a raw reference, we must also assume that it lives
index 46fab544aafe98bf3430f3babc0e41ea463e0a29..85115427edae9dc00d0cfd7bf8e4f90f3ad79eb5 100644 (file)
@@ -14,7 +14,7 @@
 use rustc::hir::CodegenFnAttrFlags;
 use rustc::hir::def_id::DefId;
 
-use rustc_data_structures::bitvec::BitVector;
+use rustc_data_structures::bitvec::BitArray;
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 
 use rustc::mir::*;
@@ -271,7 +271,7 @@ fn should_inline(&self,
         // Traverse the MIR manually so we can account for the effects of
         // inlining on the CFG.
         let mut work_list = vec![START_BLOCK];
-        let mut visited = BitVector::new(callee_mir.basic_blocks().len());
+        let mut visited = BitArray::new(callee_mir.basic_blocks().len());
         while let Some(bb) = work_list.pop() {
             if !visited.insert(bb.index()) { continue; }
             let blk = &callee_mir.basic_blocks()[bb];
index 8a12a604ef2023156870e908ddcf9e3447019959..208679d2aa08adf3aa50a4c66c13b475c27ed8ea 100644 (file)
@@ -14,7 +14,7 @@
 //! The Qualif flags below can be used to also provide better
 //! diagnostics as to why a constant rvalue wasn't promoted.
 
-use rustc_data_structures::bitvec::BitVector;
+use rustc_data_structures::bitvec::BitArray;
 use rustc_data_structures::indexed_set::IdxSetBuf;
 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
 use rustc_data_structures::fx::FxHashSet;
@@ -116,7 +116,7 @@ struct Qualifier<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     param_env: ty::ParamEnv<'tcx>,
     local_qualif: IndexVec<Local, Option<Qualif>>,
     qualif: Qualif,
-    const_fn_arg_vars: BitVector<Local>,
+    const_fn_arg_vars: BitArray<Local>,
     temp_promotion_state: IndexVec<Local, TempState>,
     promotion_candidates: Vec<Candidate>
 }
@@ -150,7 +150,7 @@ fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             param_env,
             local_qualif,
             qualif: Qualif::empty(),
-            const_fn_arg_vars: BitVector::new(mir.local_decls.len()),
+            const_fn_arg_vars: BitArray::new(mir.local_decls.len()),
             temp_promotion_state: temps,
             promotion_candidates: vec![]
         }
@@ -284,7 +284,7 @@ fn qualify_const(&mut self) -> (Qualif, Lrc<IdxSetBuf<Local>>) {
 
         let mir = self.mir;
 
-        let mut seen_blocks = BitVector::new(mir.basic_blocks().len());
+        let mut seen_blocks = BitArray::new(mir.basic_blocks().len());
         let mut bb = START_BLOCK;
         loop {
             seen_blocks.insert(bb.index());
index a7ef93eaec6b97c6fd814b996b692c3af7bdecc0..04a7a81eb126fc7f6e492ec6887e613fc678818c 100644 (file)
@@ -10,7 +10,7 @@
 
 use rustc::ty::TyCtxt;
 use rustc::mir::*;
-use rustc_data_structures::bitvec::BitVector;
+use rustc_data_structures::bitvec::BitArray;
 use transform::{MirPass, MirSource};
 use util::patch::MirPatch;
 
@@ -45,7 +45,7 @@ fn is_nop_landing_pad(
         &self,
         bb: BasicBlock,
         mir: &Mir,
-        nop_landing_pads: &BitVector<BasicBlock>,
+        nop_landing_pads: &BitArray<BasicBlock>,
     ) -> bool {
         for stmt in &mir[bb].statements {
             match stmt.kind {
@@ -111,7 +111,7 @@ fn remove_nop_landing_pads(&self, mir: &mut Mir) {
 
         let mut jumps_folded = 0;
         let mut landing_pads_removed = 0;
-        let mut nop_landing_pads = BitVector::new(mir.basic_blocks().len());
+        let mut nop_landing_pads = BitArray::new(mir.basic_blocks().len());
 
         // This is a post-order traversal, so that if A post-dominates B
         // then A will be visited before B.
index 6b8d5a1489388403fa25a5f42d7f25cbc5d6590b..6e8471c672934e127bac884eeefcc7066bd9d584 100644 (file)
@@ -37,7 +37,7 @@
 //! naively generate still contains the `_a = ()` write in the unreachable block "after" the
 //! return.
 
-use rustc_data_structures::bitvec::BitVector;
+use rustc_data_structures::bitvec::BitArray;
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use rustc::ty::TyCtxt;
 use rustc::mir::*;
@@ -249,7 +249,7 @@ fn strip_nops(&mut self) {
 }
 
 pub fn remove_dead_blocks(mir: &mut Mir) {
-    let mut seen = BitVector::new(mir.basic_blocks().len());
+    let mut seen = BitArray::new(mir.basic_blocks().len());
     for (bb, _) in traversal::preorder(mir) {
         seen.insert(bb.index());
     }
@@ -285,7 +285,7 @@ fn run_pass<'a, 'tcx>(&self,
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           _: MirSource,
                           mir: &mut Mir<'tcx>) {
-        let mut marker = DeclMarker { locals: BitVector::new(mir.local_decls.len()) };
+        let mut marker = DeclMarker { locals: BitArray::new(mir.local_decls.len()) };
         marker.visit_mir(mir);
         // Return pointer and arguments are always live
         marker.locals.insert(RETURN_PLACE);
@@ -310,7 +310,7 @@ fn run_pass<'a, 'tcx>(&self,
 /// Construct the mapping while swapping out unused stuff out from the `vec`.
 fn make_local_map<'tcx, V>(
     vec: &mut IndexVec<Local, V>,
-    mask: BitVector<Local>,
+    mask: BitArray<Local>,
 ) -> IndexVec<Local, Option<Local>> {
     let mut map: IndexVec<Local, Option<Local>> = IndexVec::from_elem(None, &*vec);
     let mut used = Local::new(0);
@@ -326,7 +326,7 @@ fn make_local_map<'tcx, V>(
 }
 
 struct DeclMarker {
-    pub locals: BitVector<Local>,
+    pub locals: BitArray<Local>,
 }
 
 impl<'tcx> Visitor<'tcx> for DeclMarker {
index 4553a2ab5779f6e972600ee119c72812f7c22ba2..ab4d15d0b9040413aa2e3f459c6d82811a145f46 100644 (file)
@@ -629,7 +629,8 @@ pub fn macro_def_scope(&mut self, expansion: Mark) -> Module<'a> {
     pub fn get_macro(&mut self, def: Def) -> Lrc<SyntaxExtension> {
         let def_id = match def {
             Def::Macro(def_id, ..) => def_id,
-            _ => panic!("Expected Def::Macro(..)"),
+            Def::NonMacroAttr => return Lrc::new(SyntaxExtension::NonMacroAttr),
+            _ => panic!("Expected Def::Macro(..) or Def::NonMacroAttr"),
         };
         if let Some(ext) = self.macro_map.get(&def_id) {
             return ext.clone();
index ec067a6477b6d84a7f12c5b738dd27f90fac2f4a..4c12591c83207d8b5479a05cd55a85dc1a76b175 100644 (file)
@@ -131,8 +131,7 @@ pub fn check_crate(resolver: &mut Resolver, krate: &ast::Crate) {
                  directive.vis.get() == ty::Visibility::Public ||
                  directive.span.is_dummy() => {
                 if let ImportDirectiveSubclass::MacroUse = directive.subclass {
-                    if resolver.session.features_untracked().use_extern_macros &&
-                        !directive.span.is_dummy() {
+                    if resolver.use_extern_macros && !directive.span.is_dummy() {
                         resolver.session.buffer_lint(
                             lint::builtin::MACRO_USE_EXTERN_CRATE,
                             directive.id,
index ca42cf6dace2efac9ac7d7cf86f8b7ab9eca5017..9c58d2c1f0b0ccaa46f2ad4b730e71d090a0794b 100644 (file)
 mod build_reduced_graph;
 mod resolve_imports;
 
+fn is_known_tool(name: Name) -> bool {
+    ["clippy", "rustfmt"].contains(&&*name.as_str())
+}
+
 /// A free importable items suggested in case of resolution failure.
 struct ImportSuggestion {
     path: Path,
@@ -200,15 +204,10 @@ fn resolve_struct_error<'sess, 'a>(resolver: &'sess Resolver,
                         err.span_label(typaram_span, "type variable from outer function");
                     }
                 },
-                Def::Mod(..) | Def::Struct(..) | Def::Union(..) | Def::Enum(..) | Def::Variant(..) |
-                Def::Trait(..) | Def::TyAlias(..) | Def::TyForeign(..) | Def::TraitAlias(..) |
-                Def::AssociatedTy(..) | Def::PrimTy(..) | Def::Fn(..) | Def::Const(..) |
-                Def::Static(..) | Def::StructCtor(..) | Def::VariantCtor(..) | Def::Method(..) |
-                Def::AssociatedConst(..) | Def::Local(..) | Def::Upvar(..) | Def::Label(..) |
-                Def::Existential(..) | Def::AssociatedExistential(..) |
-                Def::Macro(..) | Def::GlobalAsm(..) | Def::Err =>
+                _ => {
                     bug!("TypeParametersFromOuterFunction should only be used with Def::SelfTy or \
                          Def::TyParam")
+                }
             }
 
             // Try to retrieve the span of the function signature and generate a new message with
@@ -1711,9 +1710,7 @@ pub fn new(session: &'a Session,
                 vis: ty::Visibility::Public,
             }),
 
-            // The `proc_macro` and `decl_macro` features imply `use_extern_macros`
-            use_extern_macros:
-                features.use_extern_macros || features.decl_macro,
+            use_extern_macros: features.use_extern_macros(),
 
             crate_loader,
             macro_names: FxHashSet(),
@@ -1846,6 +1843,7 @@ fn resolve_ident_in_lexical_scope(&mut self,
                                       path_span: Span)
                                       -> Option<LexicalScopeBinding<'a>> {
         let record_used = record_used_id.is_some();
+        assert!(ns == TypeNS  || ns == ValueNS);
         if ns == TypeNS {
             ident.span = if ident.name == keywords::SelfType.name() {
                 // FIXME(jseyfried) improve `Self` hygiene
@@ -1922,8 +1920,9 @@ fn resolve_ident_in_lexical_scope(&mut self,
                     return Some(LexicalScopeBinding::Item(binding))
                 }
                 _ if poisoned.is_some() => break,
-                Err(Undetermined) => return None,
-                Err(Determined) => {}
+                Err(Determined) => continue,
+                Err(Undetermined) =>
+                    span_bug!(ident.span, "undetermined resolution during main resolution pass"),
             }
         }
 
@@ -1945,6 +1944,11 @@ fn resolve_ident_in_lexical_scope(&mut self,
                                ident.span, Mark::root()).to_name_binding(self.arenas);
                 return Some(LexicalScopeBinding::Item(binding));
             }
+            if ns == TypeNS && is_known_tool(ident.name) {
+                let binding = (Def::ToolMod, ty::Visibility::Public,
+                               ident.span, Mark::root()).to_name_binding(self.arenas);
+                return Some(LexicalScopeBinding::Item(binding));
+            }
             if let Some(prelude) = self.prelude {
                 if let Ok(binding) = self.resolve_ident_in_module_unadjusted(prelude, ident, ns,
                                                                         false, false, path_span) {
@@ -3505,6 +3509,8 @@ fn resolve_path(
                     let maybe_assoc = opt_ns != Some(MacroNS) && PathSource::Type.is_expected(def);
                     if let Some(next_module) = binding.module() {
                         module = Some(next_module);
+                    } else if def == Def::ToolMod && i + 1 != path.len() {
+                        return PathResult::NonModule(PathResolution::new(Def::NonMacroAttr))
                     } else if def == Def::Err {
                         return PathResult::NonModule(err_path_resolution());
                     } else if opt_ns.is_some() && (is_last || maybe_assoc) {
index 1d42ad4e4902e2336302c376237cfb8d38fa419e..60a6bcf499db4aa735fbf5f06f3618ad65f02534 100644 (file)
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use {AmbiguityError, CrateLint, Resolver, ResolutionError, resolve_error};
-use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult};
-use Namespace::{self, MacroNS};
+use {AmbiguityError, CrateLint, Resolver, ResolutionError, is_known_tool, resolve_error};
+use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult, ToNameBinding};
+use Namespace::{self, TypeNS, MacroNS};
 use build_reduced_graph::{BuildReducedGraphVisitor, IsMacroExport};
 use resolve_imports::ImportResolver;
 use rustc::hir::def_id::{DefId, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, DefIndex,
@@ -27,7 +27,7 @@
 use syntax::ext::hygiene::{self, Mark};
 use syntax::ext::placeholders::placeholder;
 use syntax::ext::tt::macro_rules;
-use syntax::feature_gate::{self, emit_feature_err, GateIssue};
+use syntax::feature_gate::{self, feature_err, emit_feature_err, is_builtin_attr_name, GateIssue};
 use syntax::fold::{self, Folder};
 use syntax::parse::parser::PathStyle;
 use syntax::parse::token::{self, Token};
@@ -326,6 +326,18 @@ fn resolve_invoc(&mut self, invoc: &mut Invocation, scope: Mark, force: bool)
         if let Def::Macro(_, MacroKind::ProcMacroStub) = def {
             self.report_proc_macro_stub(invoc.span());
             return Err(Determinacy::Determined);
+        } else if let Def::NonMacroAttr = def {
+            if let InvocationKind::Attr { .. } = invoc.kind {
+                if !self.session.features_untracked().tool_attributes {
+                    feature_err(&self.session.parse_sess, "tool_attributes",
+                                invoc.span(), GateIssue::Language,
+                                "tool attributes are unstable").emit();
+                }
+                return Ok(Some(Lrc::new(SyntaxExtension::NonMacroAttr)));
+            } else {
+                self.report_non_macro_attr(invoc.path_span());
+                return Err(Determinacy::Determined);
+            }
         }
         let def_id = def.def_id();
 
@@ -348,6 +360,9 @@ fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, forc
             if let Def::Macro(_, MacroKind::ProcMacroStub) = def {
                 self.report_proc_macro_stub(path.span);
                 return Err(Determinacy::Determined);
+            } else if let Def::NonMacroAttr = def {
+                self.report_non_macro_attr(path.span);
+                return Err(Determinacy::Determined);
             }
             self.unused_macros.remove(&def.def_id());
             Ok(self.get_macro(def))
@@ -378,6 +393,11 @@ fn report_proc_macro_stub(&self, span: Span) {
                               "can't use a procedural macro from the same crate that defines it");
     }
 
+    fn report_non_macro_attr(&self, span: Span) {
+        self.session.span_err(span,
+                              "expected a macro, found non-macro attribute");
+    }
+
     fn resolve_invoc_to_def(&mut self, invoc: &mut Invocation, scope: Mark, force: bool)
                             -> Result<Def, Determinacy> {
         let (attr, traits, item) = match invoc.kind {
@@ -450,7 +470,15 @@ fn resolve_invoc_to_def(&mut self, invoc: &mut Invocation, scope: Mark, force: b
 
     fn resolve_macro_to_def(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool)
                             -> Result<Def, Determinacy> {
-        if kind != MacroKind::Bang && path.segments.len() > 1 {
+        let def = self.resolve_macro_to_def_inner(scope, path, kind, force);
+        if def != Err(Determinacy::Undetermined) {
+            // Do not report duplicated errors on every undetermined resolution.
+            path.segments.iter().find(|segment| segment.args.is_some()).map(|segment| {
+                self.session.span_err(segment.args.as_ref().unwrap().span(),
+                                      "generic arguments in macro path");
+            });
+        }
+        if kind != MacroKind::Bang && path.segments.len() > 1 && def != Ok(Def::NonMacroAttr) {
             if !self.session.features_untracked().proc_macro_path_invoc {
                 emit_feature_err(
                     &self.session.parse_sess,
@@ -462,15 +490,6 @@ fn resolve_macro_to_def(&mut self, scope: Mark, path: &ast::Path, kind: MacroKin
                 );
             }
         }
-
-        let def = self.resolve_macro_to_def_inner(scope, path, kind, force);
-        if def != Err(Determinacy::Undetermined) {
-            // Do not report duplicated errors on every undetermined resolution.
-            path.segments.iter().find(|segment| segment.args.is_some()).map(|segment| {
-                self.session.span_err(segment.args.as_ref().unwrap().span(),
-                                      "generic arguments in macro path");
-            });
-        }
         def
     }
 
@@ -544,67 +563,226 @@ pub fn resolve_macro_to_def_inner(&mut self, scope: Mark, path: &ast::Path,
         result
     }
 
-    // Resolve the initial segment of a non-global macro path (e.g. `foo` in `foo::bar!();`)
+    // Resolve the initial segment of a non-global macro path
+    // (e.g. `foo` in `foo::bar!(); or `foo!();`).
+    // This is a variation of `fn resolve_ident_in_lexical_scope` that can be run during
+    // expansion and import resolution (perhaps they can be merged in the future).
     pub fn resolve_lexical_macro_path_segment(&mut self,
                                               mut ident: Ident,
                                               ns: Namespace,
                                               record_used: bool,
                                               path_span: Span)
                                               -> Result<MacroBinding<'a>, Determinacy> {
+        // General principles:
+        // 1. Not controlled (user-defined) names should have higher priority than controlled names
+        //    built into the language or standard library. This way we can add new names into the
+        //    language or standard library without breaking user code.
+        // 2. "Closed set" below means new names can appear after the current resolution attempt.
+        // Places to search (in order of decreasing priority):
+        // (Type NS)
+        // 1. FIXME: Ribs (type parameters), there's no necessary infrastructure yet
+        //    (open set, not controlled).
+        // 2. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents
+        //    (open, not controlled).
+        // 3. Extern prelude (closed, not controlled).
+        // 4. Tool modules (closed, controlled right now, but not in the future).
+        // 5. Standard library prelude (de-facto closed, controlled).
+        // 6. Language prelude (closed, controlled).
+        // (Macro NS)
+        // 1. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents
+        //    (open, not controlled).
+        // 2. Macro prelude (language, standard library, user-defined legacy plugins lumped into
+        //    one set) (open, the open part is from macro expansions, not controlled).
+        // 2a. User-defined prelude from macro-use
+        //    (open, the open part is from macro expansions, not controlled).
+        // 2b. Standard library prelude, currently just a macro-use (closed, controlled)
+        // 2c. Language prelude, perhaps including builtin attributes
+        //    (closed, controlled, except for legacy plugins).
+        // 3. Builtin attributes (closed, controlled).
+
+        assert!(ns == TypeNS  || ns == MacroNS);
         ident = ident.modern();
-        let mut module = Some(self.current_module);
-        let mut potential_illegal_shadower = Err(Determinacy::Determined);
-        let determinacy =
-            if record_used { Determinacy::Determined } else { Determinacy::Undetermined };
+
+        // Names from inner scope that can't shadow names from outer scopes, e.g.
+        // mod m { ... }
+        // {
+        //     use prefix::*; // if this imports another `m`, then it can't shadow the outer `m`
+        //                    // and we have and ambiguity error
+        //     m::mac!();
+        // }
+        // This includes names from globs and from macro expansions.
+        let mut potentially_ambiguous_result: Option<MacroBinding> = None;
+
+        enum WhereToResolve<'a> {
+            Module(Module<'a>),
+            MacroPrelude,
+            BuiltinAttrs,
+            ExternPrelude,
+            ToolPrelude,
+            StdLibPrelude,
+            PrimitiveTypes,
+        }
+
+        // Go through all the scopes and try to resolve the name.
+        let mut where_to_resolve = WhereToResolve::Module(self.current_module);
+        let mut use_prelude = !self.current_module.no_implicit_prelude;
         loop {
-            let orig_current_module = self.current_module;
-            let result = if let Some(module) = module {
-                self.current_module = module; // Lexical resolutions can never be a privacy error.
-                // Since expanded macros may not shadow the lexical scope and
-                // globs may not shadow global macros (both enforced below),
-                // we resolve with restricted shadowing (indicated by the penultimate argument).
-                self.resolve_ident_in_module_unadjusted(
-                    module, ident, ns, true, record_used, path_span,
-                ).map(MacroBinding::Modern)
-            } else {
-                self.macro_prelude.get(&ident.name).cloned().ok_or(determinacy)
-                    .map(MacroBinding::Global)
+            let result = match where_to_resolve {
+                WhereToResolve::Module(module) => {
+                    let orig_current_module = mem::replace(&mut self.current_module, module);
+                    let binding = self.resolve_ident_in_module_unadjusted(
+                            module, ident, ns, true, record_used, path_span,
+                    );
+                    self.current_module = orig_current_module;
+                    binding.map(MacroBinding::Modern)
+                }
+                WhereToResolve::MacroPrelude => {
+                    match self.macro_prelude.get(&ident.name).cloned() {
+                        Some(binding) => Ok(MacroBinding::Global(binding)),
+                        None => Err(Determinacy::Determined),
+                    }
+                }
+                WhereToResolve::BuiltinAttrs => {
+                    if is_builtin_attr_name(ident.name) {
+                        let binding = (Def::NonMacroAttr, ty::Visibility::Public,
+                                       ident.span, Mark::root()).to_name_binding(self.arenas);
+                        Ok(MacroBinding::Global(binding))
+                    } else {
+                        Err(Determinacy::Determined)
+                    }
+                }
+                WhereToResolve::ExternPrelude => {
+                    if use_prelude && self.extern_prelude.contains(&ident.name) {
+                        if !self.session.features_untracked().extern_prelude &&
+                           !self.ignore_extern_prelude_feature {
+                            feature_err(&self.session.parse_sess, "extern_prelude",
+                                        ident.span, GateIssue::Language,
+                                        "access to extern crates through prelude is experimental")
+                                        .emit();
+                        }
+
+                        let crate_id =
+                            self.crate_loader.process_path_extern(ident.name, ident.span);
+                        let crate_root =
+                            self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX });
+                        self.populate_module_if_necessary(crate_root);
+
+                        let binding = (crate_root, ty::Visibility::Public,
+                                       ident.span, Mark::root()).to_name_binding(self.arenas);
+                        Ok(MacroBinding::Global(binding))
+                    } else {
+                        Err(Determinacy::Determined)
+                    }
+                }
+                WhereToResolve::ToolPrelude => {
+                    if use_prelude && is_known_tool(ident.name) {
+                        let binding = (Def::ToolMod, ty::Visibility::Public,
+                                       ident.span, Mark::root()).to_name_binding(self.arenas);
+                        Ok(MacroBinding::Global(binding))
+                    } else {
+                        Err(Determinacy::Determined)
+                    }
+                }
+                WhereToResolve::StdLibPrelude => {
+                    let mut result = Err(Determinacy::Determined);
+                    if use_prelude {
+                        if let Some(prelude) = self.prelude {
+                            if let Ok(binding) =
+                                    self.resolve_ident_in_module_unadjusted(prelude, ident, ns,
+                                                                          false, false, path_span) {
+                                result = Ok(MacroBinding::Global(binding));
+                            }
+                        }
+                    }
+                    result
+                }
+                WhereToResolve::PrimitiveTypes => {
+                    if let Some(prim_ty) =
+                            self.primitive_type_table.primitive_types.get(&ident.name).cloned() {
+                        let binding = (Def::PrimTy(prim_ty), ty::Visibility::Public,
+                                       ident.span, Mark::root()).to_name_binding(self.arenas);
+                        Ok(MacroBinding::Global(binding))
+                    } else {
+                        Err(Determinacy::Determined)
+                    }
+                }
             };
-            self.current_module = orig_current_module;
 
-            match result.map(MacroBinding::binding) {
-                Ok(binding) => {
+            macro_rules! continue_search { () => {
+                where_to_resolve = match where_to_resolve {
+                    WhereToResolve::Module(module) => {
+                        match self.hygienic_lexical_parent(module, &mut ident.span) {
+                            Some(parent_module) => WhereToResolve::Module(parent_module),
+                            None => {
+                                use_prelude = !module.no_implicit_prelude;
+                                if ns == MacroNS {
+                                    WhereToResolve::MacroPrelude
+                                } else {
+                                    WhereToResolve::ExternPrelude
+                                }
+                            }
+                        }
+                    }
+                    WhereToResolve::MacroPrelude => WhereToResolve::BuiltinAttrs,
+                    WhereToResolve::BuiltinAttrs => break, // nowhere else to search
+                    WhereToResolve::ExternPrelude => WhereToResolve::ToolPrelude,
+                    WhereToResolve::ToolPrelude => WhereToResolve::StdLibPrelude,
+                    WhereToResolve::StdLibPrelude => WhereToResolve::PrimitiveTypes,
+                    WhereToResolve::PrimitiveTypes => break, // nowhere else to search
+                };
+
+                continue;
+            }}
+
+            match result {
+                Ok(result) => {
                     if !record_used {
-                        return result;
+                        return Ok(result);
                     }
-                    if let Ok(MacroBinding::Modern(shadower)) = potential_illegal_shadower {
-                        if shadower.def() != binding.def() {
-                            let name = ident.name;
+
+                    let binding = result.binding();
+
+                    // Found a solution that is ambiguous with a previously found solution.
+                    // Push an ambiguity error for later reporting and
+                    // return something for better recovery.
+                    if let Some(previous_result) = potentially_ambiguous_result {
+                        if binding.def() != previous_result.binding().def() {
                             self.ambiguity_errors.push(AmbiguityError {
                                 span: path_span,
-                                name,
-                                b1: shadower,
+                                name: ident.name,
+                                b1: previous_result.binding(),
                                 b2: binding,
                                 lexical: true,
                             });
-                            return potential_illegal_shadower;
+                            return Ok(previous_result);
                         }
                     }
+
+                    // Found a solution that's not an ambiguity yet, but is "suspicious" and
+                    // can participate in ambiguities later on.
+                    // Remember it and go search for other solutions in outer scopes.
                     if binding.is_glob_import() || binding.expansion != Mark::root() {
-                        potential_illegal_shadower = result;
-                    } else {
-                        return result;
+                        potentially_ambiguous_result = Some(result);
+
+                        continue_search!();
                     }
+
+                    // Found a solution that can't be ambiguous, great success.
+                    return Ok(result);
                 },
+                Err(Determinacy::Determined) => {
+                    continue_search!();
+                }
                 Err(Determinacy::Undetermined) => return Err(Determinacy::Undetermined),
-                Err(Determinacy::Determined) => {}
             }
+        }
 
-            module = match module {
-                Some(module) => self.hygienic_lexical_parent(module, &mut ident.span),
-                None => return potential_illegal_shadower,
-            }
+        // Previously found potentially ambiguous result turned out to not be ambiguous after all.
+        if let Some(previous_result) = potentially_ambiguous_result {
+            return Ok(previous_result);
         }
+
+        if record_used { Err(Determinacy::Determined) } else { Err(Determinacy::Undetermined) }
     }
 
     pub fn resolve_legacy_scope(&mut self,
index 260179de99b801b87a89a39bfdce67171c12ac1d..b6ad2f316a0a257fe8c45114cc153ff486611274 100644 (file)
@@ -691,6 +691,8 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<(Spa
                             expansion: directive.expansion,
                         });
                         let _ = self.try_define(directive.parent, target, TypeNS, binding);
+                        let import = self.import_map.entry(directive.id).or_default();
+                        import[TypeNS] = Some(PathResolution::new(binding.def()));
                         return None;
                     }
                 }
index 761521c8807ca3f42147433202222d816b42590b..240b33c3c9478ca50ae950f9d1d11c361e0bd51f 100644 (file)
@@ -811,6 +811,8 @@ fn fn_type(path: &ast::Path) -> bool {
             HirDef::Label(..) |
             HirDef::Macro(..) |
             HirDef::GlobalAsm(..) |
+            HirDef::ToolMod |
+            HirDef::NonMacroAttr |
             HirDef::Err => None,
         }
     }
index ca5aba5b6420a36bbfe1c1a18cbaf0248f3de947..f65fa341231e3893facf13ff9de9fe84b373a5d5 100644 (file)
@@ -23,6 +23,7 @@
 mod nvptx64;
 mod powerpc;
 mod powerpc64;
+mod riscv;
 mod s390x;
 mod sparc;
 mod sparc64;
@@ -500,6 +501,8 @@ pub fn adjust_for_cabi<C>(&mut self, cx: C, abi: ::spec::abi::Abi) -> Result<(),
             "nvptx" => nvptx::compute_abi_info(self),
             "nvptx64" => nvptx64::compute_abi_info(self),
             "hexagon" => hexagon::compute_abi_info(self),
+            "riscv32" => riscv::compute_abi_info(self, 32),
+            "riscv64" => riscv::compute_abi_info(self, 64),
             a => return Err(format!("unrecognized arch \"{}\" in target specification", a))
         }
 
diff --git a/src/librustc_target/abi/call/riscv.rs b/src/librustc_target/abi/call/riscv.rs
new file mode 100644 (file)
index 0000000..fe0d748
--- /dev/null
@@ -0,0 +1,59 @@
+// Copyright 2012-2013 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.
+
+// Reference: RISC-V ELF psABI specification
+// https://github.com/riscv/riscv-elf-psabi-doc
+
+use abi::call::{ArgType, FnType};
+
+fn classify_ret_ty<Ty>(arg: &mut ArgType<Ty>, xlen: u64) {
+    // "Scalars wider than 2✕XLEN are passed by reference and are replaced in
+    // the argument list with the address."
+    // "Aggregates larger than 2✕XLEN bits are passed by reference and are
+    // replaced in the argument list with the address, as are C++ aggregates
+    // with nontrivial copy constructors, destructors, or vtables."
+    if arg.layout.size.bits() > 2 * xlen {
+        arg.make_indirect();
+    }
+
+    // "When passed in registers, scalars narrower than XLEN bits are widened
+    // according to the sign of their type up to 32 bits, then sign-extended to
+    // XLEN bits."
+    arg.extend_integer_width_to(xlen); // this method only affects integer scalars
+}
+
+fn classify_arg_ty<Ty>(arg: &mut ArgType<Ty>, xlen: u64) {
+    // "Scalars wider than 2✕XLEN are passed by reference and are replaced in
+    // the argument list with the address."
+    // "Aggregates larger than 2✕XLEN bits are passed by reference and are
+    // replaced in the argument list with the address, as are C++ aggregates
+    // with nontrivial copy constructors, destructors, or vtables."
+    if arg.layout.size.bits() > 2 * xlen {
+        arg.make_indirect();
+    }
+
+    // "When passed in registers, scalars narrower than XLEN bits are widened
+    // according to the sign of their type up to 32 bits, then sign-extended to
+    // XLEN bits."
+    arg.extend_integer_width_to(xlen); // this method only affects integer scalars
+}
+
+pub fn compute_abi_info<Ty>(fty: &mut FnType<Ty>, xlen: u64) {
+    if !fty.ret.is_ignore() {
+        classify_ret_ty(&mut fty.ret, xlen);
+    }
+
+    for arg in &mut fty.args {
+        if arg.is_ignore() {
+            continue;
+        }
+        classify_arg_ty(arg, xlen);
+    }
+}
index 6c2d16d6a17eb7d9298fbf1582c498db30ca41e2..6faab77d7709f3cc7d320f12f742f928dde72e6c 100644 (file)
@@ -377,6 +377,8 @@ fn $module() {
 
     ("aarch64-unknown-hermit", aarch64_unknown_hermit),
     ("x86_64-unknown-hermit", x86_64_unknown_hermit),
+
+    ("riscv32imac-unknown-none-elf", riscv32imac_unknown_none_elf),
 }
 
 /// Everything `rustc` knows about how to compile for a specific target.
diff --git a/src/librustc_target/spec/riscv32imac_unknown_none_elf.rs b/src/librustc_target/spec/riscv32imac_unknown_none_elf.rs
new file mode 100644 (file)
index 0000000..cfd73e3
--- /dev/null
@@ -0,0 +1,52 @@
+// 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 spec::{LinkerFlavor, PanicStrategy, Target, TargetOptions, TargetResult};
+use spec::abi::{Abi};
+
+pub fn target() -> TargetResult {
+    Ok(Target {
+        data_layout: "e-m:e-p:32:32-i64:64-n32-S128".to_string(),
+        llvm_target: "riscv32".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "32".to_string(),
+        target_c_int_width: "32".to_string(),
+        target_os: "none".to_string(),
+        target_env: "".to_string(),
+        target_vendor: "unknown".to_string(),
+        arch: "riscv32".to_string(),
+        linker_flavor: LinkerFlavor::Ld,
+
+        options: TargetOptions {
+            linker: Some("riscv32-unknown-elf-ld".to_string()),
+            cpu: "generic-rv32".to_string(),
+            max_atomic_width: Some(32),
+            atomic_cas: false, // incomplete +a extension
+            features: "+m,+a".to_string(), // disable +c extension
+            executables: true,
+            panic_strategy: PanicStrategy::Abort,
+            relocation_model: "static".to_string(),
+            abi_blacklist: vec![
+                Abi::Cdecl,
+                Abi::Stdcall,
+                Abi::Fastcall,
+                Abi::Vectorcall,
+                Abi::Thiscall,
+                Abi::Aapcs,
+                Abi::Win64,
+                Abi::SysV64,
+                Abi::PtxKernel,
+                Abi::Msp430Interrupt,
+                Abi::X86Interrupt,
+            ],
+            .. Default::default()
+        },
+    })
+}
index 0cc1f6333afa002859d3404f5511e1606e66bb8e..4f1609455178b0cbbafc53d4c26a57fa988691c6 100644 (file)
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::query::Providers;
 use rustc::traits::{ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt};
+use rustc::util::profiling::ProfileCategory;
 use session::{CompileIncomplete, config};
 use util::common::time;
 
@@ -334,6 +335,8 @@ pub fn provide(providers: &mut Providers) {
 pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
                              -> Result<(), CompileIncomplete>
 {
+    tcx.sess.profiler(|p| p.start_activity(ProfileCategory::TypeChecking));
+
     // this ensures that later parts of type checking can assume that items
     // have valid types and not error
     tcx.sess.track_errors(|| {
@@ -371,6 +374,8 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
     check_unused::check_crate(tcx);
     check_for_entry_fn(tcx);
 
+    tcx.sess.profiler(|p| p.end_activity(ProfileCategory::TypeChecking));
+
     tcx.sess.compile_status()
 }
 
index 7454f79ed6bbb6f9b50905f332330c905dcbacbe..45566230fdaae29cdcb5f88a40f229779756bab8 100644 (file)
@@ -1194,7 +1194,8 @@ fn resolve(cx: &DocContext, path_str: &str, is_val: bool) -> Result<(Def, Option
         })?;
         match ty.def {
             Def::Struct(did) | Def::Union(did) | Def::Enum(did) | Def::TyAlias(did) => {
-                let item = cx.tcx.inherent_impls(did).iter()
+                let item = cx.tcx.inherent_impls(did)
+                                 .iter()
                                  .flat_map(|imp| cx.tcx.associated_items(*imp))
                                  .find(|item| item.ident.name == item_name);
                 if let Some(item) = item {
@@ -1205,26 +1206,29 @@ fn resolve(cx: &DocContext, path_str: &str, is_val: bool) -> Result<(Def, Option
                     };
                     Ok((ty.def, Some(format!("{}.{}", out, item_name))))
                 } else {
-                    let is_enum = match ty.def {
-                        Def::Enum(_) => true,
-                        _ => false,
-                    };
-                    let elem = if is_enum {
-                        cx.tcx.adt_def(did).all_fields().find(|item| item.ident.name == item_name)
-                    } else {
-                        cx.tcx.adt_def(did)
-                              .non_enum_variant()
-                              .fields
-                              .iter()
-                              .find(|item| item.ident.name == item_name)
-                    };
-                    if let Some(item) = elem {
-                        Ok((ty.def,
-                            Some(format!("{}.{}",
-                                         if is_enum { "variant" } else { "structfield" },
-                                         item.ident))))
-                    } else {
-                        Err(())
+                    match cx.tcx.type_of(did).sty {
+                        ty::TyAdt(def, _) => {
+                            if let Some(item) = if def.is_enum() {
+                                def.all_fields().find(|item| item.ident.name == item_name)
+                            } else {
+                                def.non_enum_variant()
+                                   .fields
+                                   .iter()
+                                   .find(|item| item.ident.name == item_name)
+                            } {
+                                Ok((ty.def,
+                                    Some(format!("{}.{}",
+                                                 if def.is_enum() {
+                                                     "variant"
+                                                 } else {
+                                                     "structfield"
+                                                 },
+                                                 item.ident))))
+                            } else {
+                                Err(())
+                            }
+                        }
+                        _ => Err(()),
                     }
                 }
             }
index 09d304b71a2c1627adb424e0742b253b256945f3..287913d2cc9b88f7e06ac25b0eaa6173949c725d 100644 (file)
@@ -105,8 +105,8 @@ pub fn visit(&mut self, krate: &hir::Crate) {
     }
 
     pub fn visit_variant_data(&mut self, item: &hir::Item,
-                            name: ast::Name, sd: &hir::VariantData,
-                            generics: &hir::Generics) -> Struct {
+                              name: ast::Name, sd: &hir::VariantData,
+                              generics: &hir::Generics) -> Struct {
         debug!("Visiting struct");
         let struct_type = struct_type_from_def(&*sd);
         Struct {
index 8db365cd21d67938be2bbca12cfee14a3fded4cd..b9aba1e9cab321d979430c921d3960cfacf38ac3 100644 (file)
@@ -125,8 +125,7 @@ fn default_alloc_error_hook(layout: Layout) {
 
 #[cfg(not(test))]
 #[doc(hidden)]
-#[cfg_attr(stage0, lang = "oom")]
-#[cfg_attr(not(stage0), alloc_error_handler)]
+#[alloc_error_handler]
 #[unstable(feature = "alloc_internals", issue = "0")]
 pub fn rust_oom(layout: Layout) -> ! {
     let hook = HOOK.load(Ordering::SeqCst);
index 5e89ad45f81d24031ec06999eb8b2acfd101e84f..b83f3fbe7a59cd94673791f7d3af7ec2bd3836fe 100644 (file)
@@ -354,19 +354,26 @@ fn append_to_string<F>(buf: &mut String, f: F) -> Result<usize>
 // avoid paying to allocate and zero a huge chunk of memory if the reader only
 // has 4 bytes while still making large reads if the reader does have a ton
 // of data to return. Simply tacking on an extra DEFAULT_BUF_SIZE space every
-// time is 4,500 times (!) slower than this if the reader has a very small
-// amount of data to return.
+// time is 4,500 times (!) slower than a default reservation size of 32 if the
+// reader has a very small amount of data to return.
 //
 // Because we're extending the buffer with uninitialized data for trusted
 // readers, we need to make sure to truncate that if any of this panics.
 fn read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize> {
+    read_to_end_with_reservation(r, buf, 32)
+}
+
+fn read_to_end_with_reservation<R: Read + ?Sized>(r: &mut R,
+                                                  buf: &mut Vec<u8>,
+                                                  reservation_size: usize) -> Result<usize>
+{
     let start_len = buf.len();
     let mut g = Guard { len: buf.len(), buf: buf };
     let ret;
     loop {
         if g.len == g.buf.len() {
             unsafe {
-                g.buf.reserve(32);
+                g.buf.reserve(reservation_size);
                 let capacity = g.buf.capacity();
                 g.buf.set_len(capacity);
                 r.initializer().initialize(&mut g.buf[g.len..]);
@@ -1899,6 +1906,12 @@ fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
     unsafe fn initializer(&self) -> Initializer {
         self.inner.initializer()
     }
+
+    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> {
+        let reservation_size = cmp::min(self.limit, 32) as usize;
+
+        read_to_end_with_reservation(self, buf, reservation_size)
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
index 0025f21da22a887cca799674c555d61e6c1608ad..a96e2ba21345b4f66b4b29c69cdb03eb0057aab0 100644 (file)
@@ -157,12 +157,7 @@ macro_rules! print {
 macro_rules! println {
     () => (print!("\n"));
     ($($arg:tt)*) => ({
-        #[cfg(not(stage0))] {
-            ($crate::io::_print(format_args_nl!($($arg)*)));
-        }
-        #[cfg(stage0)] {
-            print!("{}\n", format_args!($($arg)*))
-        }
+        $crate::io::_print(format_args_nl!($($arg)*));
     })
 }
 
@@ -221,12 +216,7 @@ macro_rules! eprint {
 macro_rules! eprintln {
     () => (eprint!("\n"));
     ($($arg:tt)*) => ({
-        #[cfg(all(not(stage0), not(stage1)))] {
-            ($crate::io::_eprint(format_args_nl!($($arg)*)));
-        }
-        #[cfg(any(stage0, stage1))] {
-            eprint!("{}\n", format_args!($($arg)*))
-        }
+        $crate::io::_eprint(format_args_nl!($($arg)*));
     })
 }
 
index 30aba2f400f2f8059fd6680105833d5f0d77d827..6f81afe66f95b694ae1123d9da74bfd501103a43 100644 (file)
@@ -296,6 +296,8 @@ pub struct ipv6_mreq {
 
 pub const FD_SETSIZE: usize = 64;
 
+pub const STACK_SIZE_PARAM_IS_A_RESERVATION: DWORD = 0x00010000;
+
 #[repr(C)]
 #[cfg(not(target_pointer_width = "64"))]
 pub struct WSADATA {
index 44ec872b2446b956d85677a5e5d28f60a4a2bc44..85588cc6c8e85e074e3d3d52c085a9defbb46a16 100644 (file)
@@ -42,7 +42,8 @@ pub unsafe fn new<'a>(stack: usize, p: Box<dyn FnBox() + 'a>)
         let stack_size = (stack + 0xfffe) & (!0xfffe);
         let ret = c::CreateThread(ptr::null_mut(), stack_size,
                                   thread_start, &*p as *const _ as *mut _,
-                                  0, ptr::null_mut());
+                                  c::STACK_SIZE_PARAM_IS_A_RESERVATION,
+                                  ptr::null_mut());
 
         return if ret as usize == 0 {
             Err(io::Error::last_os_error())
index d59c9dd6b53e8fbc5399984ec1d81a0ec40ae4d6..28c1e4324de7a3070c90f2c4cce5a694dc3ce2e8 100644 (file)
@@ -23,6 +23,7 @@
 use print::pprust;
 use ptr::P;
 use rustc_data_structures::indexed_vec;
+use rustc_data_structures::indexed_vec::Idx;
 use symbol::{Symbol, keywords};
 use tokenstream::{ThinTokenStream, TokenStream};
 
@@ -1910,9 +1911,18 @@ pub enum AttrStyle {
     Inner,
 }
 
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
+#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, PartialOrd, Ord, Copy)]
 pub struct AttrId(pub usize);
 
+impl Idx for AttrId {
+    fn new(idx: usize) -> Self {
+        AttrId(idx)
+    }
+    fn index(self) -> usize {
+        self.0
+    }
+}
+
 /// Meta-data associated with an item
 /// Doc-comments are promoted to attributes that have is_sugared_doc = true
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
index 137b94230a3cd251ccdb9864499de835daaa15c7..b3b173db70b8906649f300f7cbdc9060abfad849 100644 (file)
 
 pub fn mark_used(attr: &Attribute) {
     debug!("Marking {:?} as used.", attr);
-    let AttrId(id) = attr.id;
     GLOBALS.with(|globals| {
-        let mut slot = globals.used_attrs.lock();
-        let idx = (id / 64) as usize;
-        let shift = id % 64;
-        if slot.len() <= idx {
-            slot.resize(idx + 1, 0);
-        }
-        slot[idx] |= 1 << shift;
+        globals.used_attrs.lock().insert(attr.id);
     });
 }
 
 pub fn is_used(attr: &Attribute) -> bool {
-    let AttrId(id) = attr.id;
     GLOBALS.with(|globals| {
-        let slot = globals.used_attrs.lock();
-        let idx = (id / 64) as usize;
-        let shift = id % 64;
-        slot.get(idx).map(|bits| bits & (1 << shift) != 0)
-            .unwrap_or(false)
+        globals.used_attrs.lock().contains(attr.id)
     })
 }
 
 pub fn mark_known(attr: &Attribute) {
     debug!("Marking {:?} as known.", attr);
-    let AttrId(id) = attr.id;
     GLOBALS.with(|globals| {
-        let mut slot = globals.known_attrs.lock();
-        let idx = (id / 64) as usize;
-        let shift = id % 64;
-        if slot.len() <= idx {
-            slot.resize(idx + 1, 0);
-        }
-        slot[idx] |= 1 << shift;
+        globals.known_attrs.lock().insert(attr.id);
     });
 }
 
 pub fn is_known(attr: &Attribute) -> bool {
-    let AttrId(id) = attr.id;
     GLOBALS.with(|globals| {
-        let slot = globals.known_attrs.lock();
-        let idx = (id / 64) as usize;
-        let shift = id % 64;
-        slot.get(idx).map(|bits| bits & (1 << shift) != 0)
-            .unwrap_or(false)
+        globals.known_attrs.lock().contains(attr.id)
     })
 }
 
-const RUST_KNOWN_TOOL: &[&str] = &["clippy", "rustfmt"];
-const RUST_KNOWN_LINT_TOOL: &[&str] = &["clippy"];
-
-pub fn is_known_tool(attr: &Attribute) -> bool {
-    let tool_name =
-        attr.path.segments.iter().next().expect("empty path in attribute").ident.name;
-    RUST_KNOWN_TOOL.contains(&tool_name.as_str().as_ref())
-}
-
 pub fn is_known_lint_tool(m_item: Ident) -> bool {
-    RUST_KNOWN_LINT_TOOL.contains(&m_item.as_str().as_ref())
+    ["clippy"].contains(&m_item.as_str().as_ref())
 }
 
 impl NestedMetaItem {
@@ -245,10 +212,6 @@ pub fn is_meta_item_list(&self) -> bool {
     pub fn is_value_str(&self) -> bool {
         self.value_str().is_some()
     }
-
-    pub fn is_scoped(&self) -> bool {
-        self.path.segments.len() > 1
-    }
 }
 
 impl MetaItem {
index b55c4f99206c4204858092501e30d0c39d6e579e..8450daa3f7c943fc93dc1de90f9f97730c8aaa2a 100644 (file)
@@ -588,6 +588,9 @@ pub fn descr(self) -> &'static str {
 
 /// An enum representing the different kinds of syntax extensions.
 pub enum SyntaxExtension {
+    /// A trivial "extension" that does nothing, only keeps the attribute and marks it as known.
+    NonMacroAttr,
+
     /// A syntax extension that is attached to an item and creates new items
     /// based upon it.
     ///
@@ -667,6 +670,7 @@ pub fn kind(&self) -> MacroKind {
             SyntaxExtension::IdentTT(..) |
             SyntaxExtension::ProcMacro { .. } =>
                 MacroKind::Bang,
+            SyntaxExtension::NonMacroAttr |
             SyntaxExtension::MultiDecorator(..) |
             SyntaxExtension::MultiModifier(..) |
             SyntaxExtension::AttrProcMacro(..) =>
@@ -696,6 +700,7 @@ pub fn edition(&self) -> Edition {
             SyntaxExtension::AttrProcMacro(.., edition) |
             SyntaxExtension::ProcMacroDerive(.., edition) => edition,
             // Unstable legacy stuff
+            SyntaxExtension::NonMacroAttr |
             SyntaxExtension::IdentTT(..) |
             SyntaxExtension::MultiDecorator(..) |
             SyntaxExtension::MultiModifier(..) |
index 9f8909e16264e601b6b2ba7184820715e75d0e8b..8bd30e434767be5a3397e1cf8c78ffd9450e2a64 100644 (file)
@@ -15,6 +15,7 @@
 use config::{is_test_or_bench, StripUnconfigured};
 use errors::{Applicability, FatalError};
 use ext::base::*;
+use ext::build::AstBuilder;
 use ext::derive::{add_derived_markers, collect_derives};
 use ext::hygiene::{self, Mark, SyntaxContext};
 use ext::placeholders::{placeholder, PlaceholderExpander};
@@ -36,7 +37,7 @@
 use std::collections::HashMap;
 use std::fs::File;
 use std::io::Read;
-use std::mem;
+use std::{iter, mem};
 use std::rc::Rc;
 use std::path::PathBuf;
 
@@ -243,6 +244,15 @@ pub fn span(&self) -> Span {
         }
     }
 
+    pub fn path_span(&self) -> Span {
+        match self.kind {
+            InvocationKind::Bang { ref mac, .. } => mac.node.path.span,
+            InvocationKind::Attr { attr: Some(ref attr), .. } => attr.path.span,
+            InvocationKind::Attr { attr: None, .. } => DUMMY_SP,
+            InvocationKind::Derive { ref path, .. } => path.span,
+        }
+    }
+
     pub fn attr_id(&self) -> Option<ast::AttrId> {
         match self.kind {
             InvocationKind::Attr { attr: Some(ref attr), .. } => Some(attr.id),
@@ -474,6 +484,7 @@ fn collect_invocations(&mut self, fragment: AstFragment, derives: &[Mark])
                 cx: self.cx,
                 invocations: Vec::new(),
                 monotonic: self.monotonic,
+                tests_nameable: true,
             };
             (fragment.fold_with(&mut collector), collector.invocations)
         };
@@ -566,6 +577,11 @@ fn expand_attr_invoc(&mut self,
         });
 
         match *ext {
+            NonMacroAttr => {
+                attr::mark_known(&attr);
+                let item = item.map_attrs(|mut attrs| { attrs.push(attr); attrs });
+                Some(invoc.fragment_kind.expect_from_annotatables(iter::once(item)))
+            }
             MultiModifier(ref mac) => {
                 let meta = attr.parse_meta(self.cx.parse_sess)
                                .map_err(|mut e| { e.emit(); }).ok()?;
@@ -810,7 +826,8 @@ fn expand_bang_invoc(&mut self,
                 }
             }
 
-            MultiDecorator(..) | MultiModifier(..) | AttrProcMacro(..) => {
+            MultiDecorator(..) | MultiModifier(..) |
+            AttrProcMacro(..) | SyntaxExtension::NonMacroAttr => {
                 self.cx.span_err(path.span,
                                  &format!("`{}` can only be used in attributes", path));
                 self.cx.trace_macros_diag();
@@ -1049,6 +1066,11 @@ struct InvocationCollector<'a, 'b: 'a> {
     cfg: StripUnconfigured<'a>,
     invocations: Vec<Invocation>,
     monotonic: bool,
+
+    /// Test functions need to be nameable. Tests inside functions or in other
+    /// unnameable locations need to be ignored. `tests_nameable` tracks whether
+    /// any test functions found in the current context would be nameable.
+    tests_nameable: bool,
 }
 
 impl<'a, 'b> InvocationCollector<'a, 'b> {
@@ -1066,6 +1088,20 @@ fn collect(&mut self, fragment_kind: AstFragmentKind, kind: InvocationKind) -> A
         placeholder(fragment_kind, NodeId::placeholder_from_mark(mark))
     }
 
+    /// Folds the item allowing tests to be expanded because they are still nameable.
+    /// This should probably only be called with module items
+    fn fold_nameable(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
+        fold::noop_fold_item(item, self)
+    }
+
+    /// Folds the item but doesn't allow tests to occur within it
+    fn fold_unnameable(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
+        let was_nameable = mem::replace(&mut self.tests_nameable, false);
+        let items = fold::noop_fold_item(item, self);
+        self.tests_nameable = was_nameable;
+        items
+    }
+
     fn collect_bang(&mut self, mac: ast::Mac, span: Span, kind: AstFragmentKind) -> AstFragment {
         self.collect(kind, InvocationKind::Bang { mac: mac, ident: None, span: span })
     }
@@ -1306,7 +1342,7 @@ fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
             }
             ast::ItemKind::Mod(ast::Mod { inner, .. }) => {
                 if item.ident == keywords::Invalid.ident() {
-                    return noop_fold_item(item, self);
+                    return self.fold_nameable(item);
                 }
 
                 let orig_directory_ownership = self.cx.current_expansion.directory_ownership;
@@ -1346,22 +1382,58 @@ fn fold_item(&mut self, item: P<ast::Item>) -> SmallVector<P<ast::Item>> {
 
                 let orig_module =
                     mem::replace(&mut self.cx.current_expansion.module, Rc::new(module));
-                let result = noop_fold_item(item, self);
+                let result = self.fold_nameable(item);
                 self.cx.current_expansion.module = orig_module;
                 self.cx.current_expansion.directory_ownership = orig_directory_ownership;
                 result
             }
             // Ensure that test functions are accessible from the test harness.
+            // #[test] fn foo() {}
+            // becomes:
+            // #[test] pub fn foo_gensym(){}
+            // #[allow(unused)]
+            // use foo_gensym as foo;
             ast::ItemKind::Fn(..) if self.cx.ecfg.should_test => {
-                if item.attrs.iter().any(|attr| is_test_or_bench(attr)) {
+                if self.tests_nameable && item.attrs.iter().any(|attr| is_test_or_bench(attr)) {
+                    let orig_ident = item.ident;
+                    let orig_vis   = item.vis.clone();
+
+                    // Publicize the item under gensymed name to avoid pollution
                     item = item.map(|mut item| {
                         item.vis = respan(item.vis.span, ast::VisibilityKind::Public);
+                        item.ident = item.ident.gensym();
                         item
                     });
+
+                    // Use the gensymed name under the item's original visibility
+                    let mut use_item = self.cx.item_use_simple_(
+                        item.ident.span,
+                        orig_vis,
+                        Some(orig_ident),
+                        self.cx.path(item.ident.span,
+                            vec![keywords::SelfValue.ident(), item.ident]));
+
+                    // #[allow(unused)] because the test function probably isn't being referenced
+                    use_item = use_item.map(|mut ui| {
+                        ui.attrs.push(
+                            self.cx.attribute(DUMMY_SP, attr::mk_list_item(DUMMY_SP,
+                                Ident::from_str("allow"), vec![
+                                    attr::mk_nested_word_item(Ident::from_str("unused"))
+                                ]
+                            ))
+                        );
+
+                        ui
+                    });
+
+                    SmallVector::many(
+                        self.fold_unnameable(item).into_iter()
+                            .chain(self.fold_unnameable(use_item)))
+                } else {
+                    self.fold_unnameable(item)
                 }
-                noop_fold_item(item, self)
             }
-            _ => noop_fold_item(item, self),
+            _ => self.fold_unnameable(item),
         }
     }
 
@@ -1612,13 +1684,16 @@ fn enable_trace_macros = trace_macros,
         fn enable_allow_internal_unstable = allow_internal_unstable,
         fn enable_custom_derive = custom_derive,
         fn enable_format_args_nl = format_args_nl,
-        fn use_extern_macros_enabled = use_extern_macros,
         fn macros_in_extern_enabled = macros_in_extern,
         fn proc_macro_mod = proc_macro_mod,
         fn proc_macro_gen = proc_macro_gen,
         fn proc_macro_expr = proc_macro_expr,
         fn proc_macro_non_items = proc_macro_non_items,
     }
+
+    pub fn use_extern_macros_enabled(&self) -> bool {
+        self.features.map_or(false, |features| features.use_extern_macros())
+    }
 }
 
 // A Marker adds the given mark to the syntax context.
index 37a021a95291437578f3bb80b33d8b69fba20297..77e3faa5b1faca25b7d386c1e0f44eb394009626 100644 (file)
@@ -80,6 +80,11 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
             {
                 $(f(stringify!($feature), self.$feature);)+
             }
+
+            pub fn use_extern_macros(&self) -> bool {
+                // The `decl_macro` and `tool_attributes` features imply `use_extern_macros`.
+                self.use_extern_macros || self.decl_macro || self.tool_attributes
+            }
         }
     };
 
@@ -689,6 +694,10 @@ pub fn deprecated_attributes() -> Vec<&'static (&'static str, AttributeType, Att
     BUILTIN_ATTRIBUTES.iter().filter(|a| a.2.is_deprecated()).collect()
 }
 
+pub fn is_builtin_attr_name(name: ast::Name) -> bool {
+    BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| name == builtin_name)
+}
+
 pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
     BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| attr.check_name(builtin_name)) ||
     attr.name().as_str().starts_with("rustc_")
@@ -1198,28 +1207,9 @@ fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) {
             // before the plugin attributes are registered
             // so we skip this then
             if !is_macro {
-                if attr.is_scoped() {
-                    gate_feature!(self, tool_attributes, attr.span,
-                                  &format!("scoped attribute `{}` is experimental", attr.path));
-                    if attr::is_known_tool(attr) {
-                        attr::mark_used(attr);
-                    } else {
-                        span_err!(
-                            self.parse_sess.span_diagnostic,
-                            attr.span,
-                            E0694,
-                            "an unknown tool name found in scoped attribute: `{}`.",
-                            attr.path
-                        );
-                    }
-                } else {
-                    gate_feature!(self, custom_attribute, attr.span,
-                                  &format!("The attribute `{}` is currently \
-                                            unknown to the compiler and \
-                                            may have meaning \
-                                            added to it in the future",
-                                           attr.path));
-                }
+                let msg = format!("The attribute `{}` is currently unknown to the compiler and \
+                                   may have meaning added to it in the future", attr.path);
+                gate_feature!(self, custom_attribute, attr.span, &msg);
             }
         }
     }
@@ -1529,7 +1519,7 @@ fn visit_attribute(&mut self, attr: &ast::Attribute) {
             }
         }
 
-        if self.context.features.use_extern_macros && attr::is_known(attr) {
+        if self.context.features.use_extern_macros() && attr::is_known(attr) {
             return
         }
 
@@ -2004,7 +1994,7 @@ impl FeatureChecker {
     // the branching can be eliminated by modifying `set!()` to set these spans
     // only for the features that need to be checked for mutual exclusion.
     fn collect(&mut self, features: &Features, span: Span) {
-        if features.use_extern_macros {
+        if features.use_extern_macros() {
             // If self.use_extern_macros is None, set to Some(span)
             self.use_extern_macros = self.use_extern_macros.or(Some(span));
         }
index 60de94821bba0ba7b87a9a634ab74c36a4d5fa22..0c105865e0c2e13e3c916d8c1a7f0b9af7d55d8f 100644 (file)
@@ -43,6 +43,8 @@
 extern crate serialize as rustc_serialize; // used by deriving
 
 use rustc_data_structures::sync::Lock;
+use rustc_data_structures::bitvec::BitVector;
+use ast::AttrId;
 
 // A variant of 'try!' that panics on an Err. This is used as a crutch on the
 // way towards a non-panic!-prone parser. It should be used for fatal parsing
@@ -75,16 +77,18 @@ macro_rules! unwrap_or {
 }
 
 pub struct Globals {
-    used_attrs: Lock<Vec<u64>>,
-    known_attrs: Lock<Vec<u64>>,
+    used_attrs: Lock<BitVector<AttrId>>,
+    known_attrs: Lock<BitVector<AttrId>>,
     syntax_pos_globals: syntax_pos::Globals,
 }
 
 impl Globals {
     fn new() -> Globals {
         Globals {
-            used_attrs: Lock::new(Vec::new()),
-            known_attrs: Lock::new(Vec::new()),
+            // We have no idea how many attributes their will be, so just
+            // initiate the vectors with 0 bits. We'll grow them as necessary.
+            used_attrs: Lock::new(BitVector::new()),
+            known_attrs: Lock::new(BitVector::new()),
             syntax_pos_globals: syntax_pos::Globals::new(),
         }
     }
index fd8f394a600f09b456b97774f2a208d7b2783642..c449cc0a6525a9bdcb41136908f536706311a421 100644 (file)
@@ -104,6 +104,7 @@ pub(crate) fn ident_can_begin_expr(ident: ast::Ident, is_raw: bool) -> bool {
     !ident_token.is_reserved_ident() ||
     ident_token.is_path_segment_keyword() ||
     [
+        keywords::Async.name(),
         keywords::Do.name(),
         keywords::Box.name(),
         keywords::Break.name(),
index 1531f030127e302516fe924b350571ac3d5e3675..670fd5b872d92f96b5736378399c87333e14de0a 100644 (file)
@@ -594,7 +594,6 @@ pub fn name(&self) -> Symbol {
 /// The kind of compiler desugaring.
 #[derive(Clone, Copy, Hash, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
 pub enum CompilerDesugaringKind {
-    DotFill,
     QuestionMark,
     Catch,
     /// Desugaring of an `impl Trait` in return type position
@@ -609,7 +608,6 @@ impl CompilerDesugaringKind {
     pub fn name(self) -> Symbol {
         Symbol::intern(match self {
             CompilerDesugaringKind::Async => "async",
-            CompilerDesugaringKind::DotFill => "...",
             CompilerDesugaringKind::QuestionMark => "?",
             CompilerDesugaringKind::Catch => "do catch",
             CompilerDesugaringKind::ExistentialReturnType => "existential type",
index a13e4ffa8f8295cc50da40d3c3fe3b0735c6128a..7305dc71cbf63fa5bd14fc2b8d6e7edb74e4b832 100644 (file)
@@ -171,6 +171,12 @@ bool LLVMRustPassManagerBuilderPopulateThinLTOPassManager(
 #define SUBTARGET_MSP430
 #endif
 
+#ifdef LLVM_COMPONENT_RISCV
+#define SUBTARGET_RISCV SUBTARGET(RISCV)
+#else
+#define SUBTARGET_RISCV
+#endif
+
 #ifdef LLVM_COMPONENT_SPARC
 #define SUBTARGET_SPARC SUBTARGET(Sparc)
 #else
@@ -192,7 +198,8 @@ bool LLVMRustPassManagerBuilderPopulateThinLTOPassManager(
   SUBTARGET_SYSTEMZ                                                            \
   SUBTARGET_MSP430                                                             \
   SUBTARGET_SPARC                                                              \
-  SUBTARGET_HEXAGON
+  SUBTARGET_HEXAGON                                                            \
+  SUBTARGET_RISCV                                                              \
 
 #define SUBTARGET(x)                                                           \
   namespace llvm {                                                             \
index f2b5297285ca79623d4ccad6e3b13d69625dda09..4bcb4fd7ad385a4ec1c0db8593a65cb578d248e6 100644 (file)
@@ -984,6 +984,7 @@ enum class LLVMRustDiagnosticKind {
   OptimizationRemarkOther,
   OptimizationFailure,
   PGOProfile,
+  Linker,
 };
 
 static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) {
@@ -1008,6 +1009,8 @@ static LLVMRustDiagnosticKind toRust(DiagnosticKind Kind) {
     return LLVMRustDiagnosticKind::OptimizationRemarkAnalysisAliasing;
   case DK_PGOProfile:
     return LLVMRustDiagnosticKind::PGOProfile;
+  case DK_Linker:
+    return LLVMRustDiagnosticKind::Linker;
   default:
     return (Kind >= DK_FirstRemark && Kind <= DK_LastRemark)
                ? LLVMRustDiagnosticKind::OptimizationRemarkOther
index aa6339c852221ed7a37f75357c37323bb0ec8302..a93b25607eb3ad2ab9da4555750dd4bbd533a7f4 100644 (file)
@@ -12,7 +12,7 @@
 # source tarball for a stable release you'll likely see `1.x.0` for rustc and
 # `0.x.0` for Cargo where they were released on `date`.
 
-date: 2018-07-27
+date: 2018-08-01
 rustc: beta
 cargo: beta
 
diff --git a/src/test/codegen/vec-clear.rs b/src/test/codegen/vec-clear.rs
new file mode 100644 (file)
index 0000000..a73dd07
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -O
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @vec_clear
+#[no_mangle]
+pub fn vec_clear(x: &mut Vec<u32>) {
+    // CHECK-NOT: load
+    // CHECK-NOT: icmp
+    x.clear()
+}
diff --git a/src/test/compile-fail/auxiliary/issue-52489.rs b/src/test/compile-fail/auxiliary/issue-52489.rs
new file mode 100644 (file)
index 0000000..68d1ef8
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type = "lib"]
+#![unstable(feature = "issue_52489_unstable", issue = "0")]
+#![feature(staged_api)]
diff --git a/src/test/compile-fail/auxiliary/lto-duplicate-symbols1.rs b/src/test/compile-fail/auxiliary/lto-duplicate-symbols1.rs
new file mode 100644 (file)
index 0000000..ea09327
--- /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.
+
+// no-prefer-dynamic
+
+#![crate_type = "rlib"]
+
+#[no_mangle]
+pub extern fn foo() {}
diff --git a/src/test/compile-fail/auxiliary/lto-duplicate-symbols2.rs b/src/test/compile-fail/auxiliary/lto-duplicate-symbols2.rs
new file mode 100644 (file)
index 0000000..ea09327
--- /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.
+
+// no-prefer-dynamic
+
+#![crate_type = "rlib"]
+
+#[no_mangle]
+pub extern fn foo() {}
diff --git a/src/test/compile-fail/feature-gate-tool_attributes.rs b/src/test/compile-fail/feature-gate-tool_attributes.rs
deleted file mode 100644 (file)
index 5a7536c..0000000
+++ /dev/null
@@ -1,15 +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.
-
-fn main() {
-    #[rustfmt::skip] //~ ERROR scoped attribute `rustfmt::skip` is experimental
-    let x =
-        3;
-}
diff --git a/src/test/compile-fail/issue-52489.rs b/src/test/compile-fail/issue-52489.rs
new file mode 100644 (file)
index 0000000..c43cc12
--- /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.
+
+// edition:2018
+// aux-build:issue-52489.rs
+
+use issue_52489;
+//~^ ERROR use of unstable library feature 'issue_52489_unstable'
+
+fn main() {}
diff --git a/src/test/compile-fail/lto-duplicate-symbols.rs b/src/test/compile-fail/lto-duplicate-symbols.rs
new file mode 100644 (file)
index 0000000..9c1dbfc
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:lto-duplicate-symbols1.rs
+// aux-build:lto-duplicate-symbols2.rs
+// error-pattern:Linking globals named 'foo': symbol multiply defined!
+// compile-flags: -C lto
+// no-prefer-dynamic
+
+extern crate lto_duplicate_symbols1;
+extern crate lto_duplicate_symbols2;
+
+fn main() {}
index c2192a21d90501026685cdeadd82c30dff2e3086..c4d22e6d392102ab9489797e4e844d04ecc31663 100644 (file)
@@ -8,9 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(tool_attributes)]
+#![feature(use_extern_macros, proc_macro_path_invoc)]
 
-#![foo::bar] //~ ERROR an unknown tool name found in scoped attribute: `foo::bar`. [E0694]
-
-#[foo::bar] //~ ERROR an unknown tool name found in scoped attribute: `foo::bar`. [E0694]
+#[foo::bar] //~ ERROR failed to resolve. Use of undeclared type or module `foo`
 fn main() {}
diff --git a/src/test/compile-fail/unknown_tool_attributes-1.rs b/src/test/compile-fail/unknown_tool_attributes-1.rs
deleted file mode 100644 (file)
index ba38c29..0000000
+++ /dev/null
@@ -1,18 +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.
-
-// Make sure that 'custom_attributes' feature does not allow scoped attributes.
-
-#![feature(custom_attributes)]
-
-#[foo::bar]
-//~^ ERROR scoped attribute `foo::bar` is experimental (see issue #44690) [E0658]
-//~^^ ERROR an unknown tool name found in scoped attribute: `foo::bar`. [E0694]
-fn main() {}
index df4a1d8994b5481b7c219f726026d71b12992345..d4af99f97c5c82001c5394169a6530cbce193145 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:issue-42708.rs
 // ignore-stage1
 
-#![feature(decl_macro, use_extern_macros, proc_macro_path_invoc)]
+#![feature(decl_macro, proc_macro_path_invoc)]
 #![allow(unused)]
 
 extern crate issue_42708;
index 15dff94c88c180b1e11e468ec3dada2c9c9aefff..53783e7fedb2929ed865eed6dd49ae66a22e1fc7 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:issue-50061.rs
 // ignore-stage1
 
-#![feature(use_extern_macros, proc_macro_path_invoc, decl_macro)]
+#![feature(proc_macro_path_invoc, decl_macro)]
 
 extern crate issue_50061;
 
diff --git a/src/test/run-pass/generator/yield-in-initializer.rs b/src/test/run-pass/generator/yield-in-initializer.rs
new file mode 100644 (file)
index 0000000..3042061
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(generators)]
+
+fn main() {
+    static || {
+        loop {
+            // Test that `opt` is not live across the yield, even when borrowed in a loop
+            // See https://github.com/rust-lang/rust/issues/52792
+            let opt = {
+                yield;
+                true
+            };
+            &opt;
+        }
+    };
+}
diff --git a/src/test/run-pass/issue-52557.rs b/src/test/run-pass/issue-52557.rs
new file mode 100644 (file)
index 0000000..2b8dfe1
--- /dev/null
@@ -0,0 +1,38 @@
+// 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.
+
+// This test checks for namespace pollution by private tests.
+// Tests used to marked as public causing name conflicts with normal
+// functions only in test builds.
+
+// compile-flags: --test
+
+mod a {
+    pub fn foo() -> bool {
+        true
+    }
+}
+
+mod b {
+    #[test]
+    fn foo() {
+        local_name(); // ensure the local name still works
+    }
+
+    #[test]
+    fn local_name() {}
+}
+
+use a::*;
+use b::*;
+
+pub fn conflict() {
+    let _: bool = foo();
+}
diff --git a/src/test/rustdoc-ui/intra-doc-alias-ice.rs b/src/test/rustdoc-ui/intra-doc-alias-ice.rs
new file mode 100644 (file)
index 0000000..a459ab5
--- /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.
+
+#![deny(intra_doc_link_resolution_failure)]
+
+pub type TypeAlias = usize;
+
+/// [broken cross-reference](TypeAlias::hoge) //~ ERROR
+pub fn some_public_item() {}
diff --git a/src/test/rustdoc-ui/intra-doc-alias-ice.stderr b/src/test/rustdoc-ui/intra-doc-alias-ice.stderr
new file mode 100644 (file)
index 0000000..2319639
--- /dev/null
@@ -0,0 +1,13 @@
+error: `[TypeAlias::hoge]` cannot be resolved, ignoring it...
+  --> $DIR/intra-doc-alias-ice.rs:15:30
+   |
+15 | /// [broken cross-reference](TypeAlias::hoge) //~ ERROR
+   |                              ^^^^^^^^^^^^^^^ cannot be resolved, ignoring
+   |
+note: lint level defined here
+  --> $DIR/intra-doc-alias-ice.rs:11:9
+   |
+11 | #![deny(intra_doc_link_resolution_failure)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: to escape `[` and `]` characters, just add '/' before them like `/[` or `/]`
+
index a60841d848c16363ac56f08e03cd04abf7d2e858..18f5b0f506cc2f7b9e78aa49ec730ff4b6fcac4c 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:parent-source-spans.rs
 // ignore-stage1
 
-#![feature(use_extern_macros, decl_macro, proc_macro_non_items)]
+#![feature(decl_macro, proc_macro_non_items)]
 
 extern crate parent_source_spans;
 
index fbd58cd4c2260adc3212068169d9ba3ee27672a7..45b0c84275be46ef203595a015511bd35870a775 100644 (file)
@@ -1,5 +1,5 @@
 error[E0384]: cannot assign twice to immutable variable `x`
-  --> $DIR/asm-out-assign-imm.rs:33:9
+  --> $DIR/asm-out-assign-imm.rs:34:9
    |
 LL |     let x: isize;
    |         - consider changing this to `mut x`
index f5bb07a9b35aacb265ef2655c43fc9fffd15b2e7..73143f1154631be50106dbf82ee28d79e985a0f7 100644 (file)
@@ -16,6 +16,7 @@
 // ignore-sparc
 // ignore-sparc64
 // ignore-mips
+// ignore-mips64
 
 #![feature(asm)]
 
index 7075914fa04bd35cfdff6e5278841bc941fcfb25..83cb8092e16a29e7174f5e24a616e8bbfa610ba6 100644 (file)
@@ -1,5 +1,5 @@
 error[E0384]: cannot assign twice to immutable variable `x`
-  --> $DIR/asm-out-assign-imm.rs:33:9
+  --> $DIR/asm-out-assign-imm.rs:34:9
    |
 LL |     x = 1;
    |     ----- first assignment to `x`
diff --git a/src/test/ui/async-matches-expr.rs b/src/test/ui/async-matches-expr.rs
new file mode 100644 (file)
index 0000000..d6959f9
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-pass
+// edition:2018
+
+#![feature(async_await, await_macro)]
+
+macro_rules! match_expr {
+    ($x:expr) => {}
+}
+
+fn main() {
+    match_expr!(async {});
+    match_expr!(async || {});
+}
index 01282f2ad24b2daf57af8ae346e724947a3e9a4b..c787cedc2d0ea10b5880ac5a76139858fb377427 100644 (file)
@@ -12,3 +12,8 @@
 macro_rules! mac {
     ($ident:ident) => { let $ident = 42; }
 }
+
+#[macro_export]
+macro_rules! inline {
+    () => ()
+}
diff --git a/src/test/ui/borrowck/issue-52967-edition-2018-needs-two-phase-borrows.rs b/src/test/ui/borrowck/issue-52967-edition-2018-needs-two-phase-borrows.rs
new file mode 100644 (file)
index 0000000..c39fff2
--- /dev/null
@@ -0,0 +1,32 @@
+// 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 a regression test for #52967, where we discovered that in
+// the initial deployment of NLL for the 2018 edition, I forgot to
+// turn on two-phase-borrows in addition to `-Z borrowck=migrate`.
+
+// revisions: ast zflags edition
+//[zflags]compile-flags: -Z borrowck=migrate -Z two-phase-borrows
+//[edition]compile-flags: --edition 2018
+
+// run-pass
+
+fn the_bug() {
+    let mut stuff = ("left", "right");
+    match stuff {
+        (ref mut left, _) if *left == "left" => { *left = "new left"; }
+        _ => {}
+    }
+    assert_eq!(stuff, ("new left", "right"));
+}
+
+fn main() {
+    the_bug();
+}
index 55f57e97ba4fa3c968a2e634009437cdba15b206..02e5b44c17c4acc0baf53689129655a108654e41 100644 (file)
@@ -17,7 +17,7 @@ LL |         let inner_second = &mut inner_void; //~ ERROR cannot borrow
    |                            ^^^^^^^^^^^^^^^ second mutable borrow occurs here
 LL |         inner_second.use_mut();
 LL |         inner_first.use_mut();
-   |         ----------- borrow later used here
+   |         ----------- borrow used here in later iteration of loop
 
 error: aborting due to 2 previous errors
 
index 748adc390d8bbf3025e911461c388a5ffe7db99c..5d7e01fbbb752d895d42b4468c9abfffaa5cefb5 100644 (file)
@@ -1,4 +1,4 @@
-error[E0658]: macro invocations in `extern {}` blocks are experimental. (see issue #49476)
+error[E0658]: macro and proc-macro invocations in `extern {}` blocks are experimental. (see issue #49476)
   --> $DIR/feature-gate-macros_in_extern.rs:29:5
    |
 LL |     returns_isize!(rust_get_test_int);
@@ -6,7 +6,7 @@ LL |     returns_isize!(rust_get_test_int);
    |
    = help: add #![feature(macros_in_extern)] to the crate attributes to enable
 
-error[E0658]: macro invocations in `extern {}` blocks are experimental. (see issue #49476)
+error[E0658]: macro and proc-macro invocations in `extern {}` blocks are experimental. (see issue #49476)
   --> $DIR/feature-gate-macros_in_extern.rs:31:5
    |
 LL |     takes_u32_returns_u32!(rust_dbg_extern_identity_u32);
@@ -14,7 +14,7 @@ LL |     takes_u32_returns_u32!(rust_dbg_extern_identity_u32);
    |
    = help: add #![feature(macros_in_extern)] to the crate attributes to enable
 
-error[E0658]: macro invocations in `extern {}` blocks are experimental. (see issue #49476)
+error[E0658]: macro and proc-macro invocations in `extern {}` blocks are experimental. (see issue #49476)
   --> $DIR/feature-gate-macros_in_extern.rs:33:5
    |
 LL |     emits_nothing!();
index 2b7cf56d9381291f1aed2a4fa13af3dc1a0677c4..47c623574ec90ef84e77f3357dbcb6ae588967d1 100644 (file)
@@ -8,8 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(use_extern_macros)]
+
 fn main() {
-    #[rustfmt::skip] //~ ERROR scoped attribute `rustfmt::skip` is experimental
+    #[rustfmt::skip] //~ ERROR tool attributes are unstable
     let x = 3
         ;
 }
index da89c4a5ef692634badba632f031afb2c0009dcb..ebc266e004ecceaf293e746e76cadd471d4e4f79 100644 (file)
@@ -1,7 +1,7 @@
-error[E0658]: scoped attribute `rustfmt::skip` is experimental (see issue #44690)
-  --> $DIR/feature-gate-tool_attributes.rs:12:5
+error[E0658]: tool attributes are unstable (see issue #44690)
+  --> $DIR/feature-gate-tool_attributes.rs:14:5
    |
-LL |     #[rustfmt::skip] //~ ERROR scoped attribute `rustfmt::skip` is experimental
+LL |     #[rustfmt::skip] //~ ERROR tool attributes are unstable
    |     ^^^^^^^^^^^^^^^^
    |
    = help: add #![feature(tool_attributes)] to the crate attributes to enable
index ef7e64ffd97ae251494a68b10e5b8548955c115b..b49bf81715079006535a47584eeeb1917b104e59 100644 (file)
@@ -9,8 +9,6 @@ LL | }
    | |
    | `*cell` dropped here while still borrowed
    | borrow later used here, when `gen` is dropped
-   |
-   = note: values in a scope are dropped in the opposite order they are defined
 
 error[E0597]: `ref_` does not live long enough
   --> $DIR/dropck.rs:22:11
index f577aad04e620bf0c7e02bedb9ebdc60167a529c..ff6009da72fd96920bf3a2dd59d0fe5327b37783 100644 (file)
@@ -9,6 +9,6 @@
 // except according to those terms.
 
 fn main() {
-    print!(test!());
+    print!(testo!());
     //~^ ERROR: format argument must be a string literal
 }
index bee73e9f568b60e0e508cb3244a69d9cf16b52e0..61ff455d16ca587ec008a390b7fe470bfc8e5ea5 100644 (file)
@@ -1,11 +1,11 @@
 error: format argument must be a string literal
   --> $DIR/issue-11692-1.rs:12:12
    |
-LL |     print!(test!());
-   |            ^^^^^^^
+LL |     print!(testo!());
+   |            ^^^^^^^^
 help: you might be missing a string literal to format with
    |
-LL |     print!("{}", test!());
+LL |     print!("{}", testo!());
    |            ^^^^^
 
 error: aborting due to previous error
index acac2d151fe9ad5ef8008d3caf10f1a5de111bf7..c595b0fb2c2d8ea9d59f17f785153c7edd09190a 100644 (file)
@@ -10,5 +10,5 @@
 
 fn main() {
     concat!(test!());
-    //~^ ERROR cannot find macro `test!` in this scope
+    //~^ ERROR expected a macro, found non-macro attribute
 }
index 51d6041e92220e356b6f873a9ec54c9c8e5ca952..3d080bd46dcc967012c6a2a2a6b407519297f960 100644 (file)
@@ -1,4 +1,4 @@
-error: cannot find macro `test!` in this scope
+error: expected a macro, found non-macro attribute
   --> $DIR/issue-11692-2.rs:12:13
    |
 LL |     concat!(test!());
diff --git a/src/test/ui/issue-45696-long-live-borrows-in-boxes.rs b/src/test/ui/issue-45696-long-live-borrows-in-boxes.rs
new file mode 100644 (file)
index 0000000..881f37c
--- /dev/null
@@ -0,0 +1,133 @@
+// 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.
+
+// rust-lang/rust#45696: This test is checking that we can return
+// mutable borrows owned by boxes even when the boxes are dropped.
+//
+// We will explicitly test AST-borrowck, NLL, and migration modes;
+// thus we will also skip the automated compare-mode=nll.
+
+// revisions: ast nll migrate
+// ignore-compare-mode-nll
+
+#![cfg_attr(nll, feature(nll))]
+//[migrate]compile-flags: -Z borrowck=migrate -Z two-phase-borrows
+
+// run-pass
+
+// This function shows quite directly what is going on: We have a
+// reborrow of contents within the box.
+fn return_borrow_from_dropped_box_1(x: Box<&mut u32>) -> &mut u32 { &mut **x }
+
+// This function is the way you'll probably see this in practice (the
+// reborrow is now implicit).
+fn return_borrow_from_dropped_box_2(x: Box<&mut u32>) -> &mut u32 { *x }
+
+// For the remaining tests we just add some fields or other
+// indirection to ensure that the compiler isn't just special-casing
+// the above `Box<&mut T>` as the only type that would work.
+
+// Here we add a tuple of indirection between the box and the
+// reference.
+type BoxedTup<'a, 'b> = Box<(&'a mut u32, &'b mut u32)>;
+
+fn return_borrow_of_field_from_dropped_box_1<'a>(x: BoxedTup<'a, '_>) -> &'a mut u32 {
+    &mut *x.0
+}
+
+fn return_borrow_of_field_from_dropped_box_2<'a>(x: BoxedTup<'a, '_>) -> &'a mut u32 {
+    x.0
+}
+
+fn return_borrow_from_dropped_tupled_box_1<'a>(x: (BoxedTup<'a, '_>, &mut u32)) -> &'a mut u32 {
+    &mut *(x.0).0
+}
+
+fn return_borrow_from_dropped_tupled_box_2<'a>(x: (BoxedTup<'a, '_>, &mut u32)) -> &'a mut u32 {
+    (x.0).0
+}
+
+fn basic_tests() {
+    let mut x = 2;
+    let mut y = 3;
+    let mut z = 4;
+    *return_borrow_from_dropped_box_1(Box::new(&mut x)) += 10;
+    assert_eq!((x, y, z), (12, 3, 4));
+    *return_borrow_from_dropped_box_2(Box::new(&mut x)) += 10;
+    assert_eq!((x, y, z), (22, 3, 4));
+    *return_borrow_of_field_from_dropped_box_1(Box::new((&mut x, &mut y))) += 10;
+    assert_eq!((x, y, z), (32, 3, 4));
+    *return_borrow_of_field_from_dropped_box_2(Box::new((&mut x, &mut y))) += 10;
+    assert_eq!((x, y, z), (42, 3, 4));
+    *return_borrow_from_dropped_tupled_box_1((Box::new((&mut x, &mut y)), &mut z)) += 10;
+    assert_eq!((x, y, z), (52, 3, 4));
+    *return_borrow_from_dropped_tupled_box_2((Box::new((&mut x, &mut y)), &mut z)) += 10;
+    assert_eq!((x, y, z), (62, 3, 4));
+}
+
+// These scribbling tests have been transcribed from
+// issue-45696-scribble-on-boxed-borrow.rs
+//
+// In the context of that file, these tests are meant to show cases
+// that should be *accepted* by the compiler, so here we are actually
+// checking that the code we get when they are compiled matches our
+// expectations.
+
+struct Scribble<'a>(&'a mut u32);
+
+impl<'a> Drop for Scribble<'a> { fn drop(&mut self) { *self.0 = 42; } }
+
+// this is okay, in both AST-borrowck and NLL: The `Scribble` here *has*
+// to strictly outlive `'a`
+fn borrowed_scribble<'a>(s: &'a mut Scribble) -> &'a mut u32 {
+    &mut *s.0
+}
+
+// this, by analogy to previous case, is also okay.
+fn boxed_borrowed_scribble<'a>(s: Box<&'a mut Scribble>) -> &'a mut u32 {
+    &mut *(*s).0
+}
+
+// this, by analogy to previous case, is also okay.
+fn boxed_boxed_borrowed_scribble<'a>(s: Box<Box<&'a mut Scribble>>) -> &'a mut u32 {
+    &mut *(**s).0
+}
+
+fn scribbling_tests() {
+    let mut x = 1;
+    {
+        let mut long_lived = Scribble(&mut x);
+        *borrowed_scribble(&mut long_lived) += 10;
+        assert_eq!(*long_lived.0, 11);
+        // (Scribble dtor runs here, after `&mut`-borrow above ends)
+    }
+    assert_eq!(x, 42);
+    x = 1;
+    {
+        let mut long_lived = Scribble(&mut x);
+        *boxed_borrowed_scribble(Box::new(&mut long_lived)) += 10;
+        assert_eq!(*long_lived.0, 11);
+        // (Scribble dtor runs here, after `&mut`-borrow above ends)
+    }
+    assert_eq!(x, 42);
+    x = 1;
+    {
+        let mut long_lived = Scribble(&mut x);
+        *boxed_boxed_borrowed_scribble(Box::new(Box::new(&mut long_lived))) += 10;
+        assert_eq!(*long_lived.0, 11);
+        // (Scribble dtor runs here, after `&mut`-borrow above ends)
+    }
+    assert_eq!(x, 42);
+}
+
+fn main() {
+    basic_tests();
+    scribbling_tests();
+}
diff --git a/src/test/ui/issue-45696-no-variant-box-recur.rs b/src/test/ui/issue-45696-no-variant-box-recur.rs
new file mode 100644 (file)
index 0000000..da42e17
--- /dev/null
@@ -0,0 +1,66 @@
+// 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.
+
+// rust-lang/rust#45696: This test checks the compiler won't infinite
+// loop when you declare a variable of type `struct A(Box<A>, ...);`
+// (which is impossible to construct but *is* possible to declare; see
+// also issues #4287, #44933, and #52852).
+//
+// We will explicitly test AST-borrowck, NLL, and migration modes;
+// thus we will also skip the automated compare-mode=nll.
+
+// revisions: ast nll migrate
+// ignore-compare-mode-nll
+
+#![cfg_attr(nll, feature(nll))]
+//[migrate]compile-flags: -Z borrowck=migrate -Z two-phase-borrows
+
+// run-pass
+
+// This test has structs and functions that are by definiton unusable
+// all over the place, so just go ahead and allow dead_code
+#![allow(dead_code)]
+
+// direct regular recursion with indirect ownership via box
+struct C { field: Box<C> }
+
+// direct non-regular recursion with indirect ownership via box
+struct D { field: Box<(D, D)> }
+
+// indirect regular recursion with indirect ownership via box.
+struct E { field: F }
+struct F { field: Box<E> }
+
+// indirect non-regular recursion with indirect ownership via box.
+struct G { field: (H, H) }
+struct H { field: Box<G> }
+
+// These enums are cases that are not currently hit by the
+// `visit_terminator_drop` recursion down a type's structural
+// definition.
+//
+// But it seems prudent to include them in this test as variants on
+// the above, in that they are similarly non-constructable data types
+// with destructors that would diverge.
+enum I { One(Box<I>) }
+enum J { One(Box<J>), Two(Box<J>) }
+
+fn impossible_to_call_c(_c: C) { }
+fn impossible_to_call_d(_d: D) { }
+fn impossible_to_call_e(_e: E) { }
+fn impossible_to_call_f(_f: F) { }
+fn impossible_to_call_g(_g: G) { }
+fn impossible_to_call_h(_h: H) { }
+fn impossible_to_call_i(_i: I) { }
+fn impossible_to_call_j(_j: J) { }
+
+fn main() {
+
+}
diff --git a/src/test/ui/issue-45696-scribble-on-boxed-borrow.ast.stderr b/src/test/ui/issue-45696-scribble-on-boxed-borrow.ast.stderr
new file mode 100644 (file)
index 0000000..6172a5e
--- /dev/null
@@ -0,0 +1,14 @@
+error: compilation successful
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:89:1
+   |
+LL | / fn main() { //[ast]~ ERROR compilation successful
+LL | |      //[migrate]~^ ERROR compilation successful
+LL | |     let mut x = 1;
+LL | |     {
+...  |
+LL | |     *boxed_boxed_scribbled(Box::new(Box::new(Scribble(&mut x)))) += 10;
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issue-45696-scribble-on-boxed-borrow.migrate.stderr b/src/test/ui/issue-45696-scribble-on-boxed-borrow.migrate.stderr
new file mode 100644 (file)
index 0000000..da0dfac
--- /dev/null
@@ -0,0 +1,69 @@
+warning[E0597]: `*s.0` does not live long enough
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:63:5
+   |
+LL |     &mut *s.0 //[nll]~ ERROR `*s.0` does not live long enough [E0597]
+   |     ^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `*s.0` dropped here while still borrowed
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 62:14...
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:62:14
+   |
+LL | fn scribbled<'a>(s: Scribble<'a>) -> &'a mut u32 {
+   |              ^^
+   = warning: This error has been downgraded to a warning for backwards compatibility with previous releases.
+           It represents potential unsoundness in your code.
+           This warning will become a hard error in the future.
+
+warning[E0597]: `*s.0` does not live long enough
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:73:5
+   |
+LL |     &mut *(*s).0 //[nll]~ ERROR `*s.0` does not live long enough [E0597]
+   |     ^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `*s.0` dropped here while still borrowed
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 72:20...
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:72:20
+   |
+LL | fn boxed_scribbled<'a>(s: Box<Scribble<'a>>) -> &'a mut u32 {
+   |                    ^^
+   = warning: This error has been downgraded to a warning for backwards compatibility with previous releases.
+           It represents potential unsoundness in your code.
+           This warning will become a hard error in the future.
+
+warning[E0597]: `*s.0` does not live long enough
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:83:5
+   |
+LL |     &mut *(**s).0 //[nll]~ ERROR `*s.0` does not live long enough [E0597]
+   |     ^^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `*s.0` dropped here while still borrowed
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 82:26...
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:82:26
+   |
+LL | fn boxed_boxed_scribbled<'a>(s: Box<Box<Scribble<'a>>>) -> &'a mut u32 {
+   |                          ^^
+   = warning: This error has been downgraded to a warning for backwards compatibility with previous releases.
+           It represents potential unsoundness in your code.
+           This warning will become a hard error in the future.
+
+error: compilation successful
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:89:1
+   |
+LL | / fn main() { //[ast]~ ERROR compilation successful
+LL | |      //[migrate]~^ ERROR compilation successful
+LL | |     let mut x = 1;
+LL | |     {
+...  |
+LL | |     *boxed_boxed_scribbled(Box::new(Box::new(Scribble(&mut x)))) += 10;
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/issue-45696-scribble-on-boxed-borrow.nll.stderr b/src/test/ui/issue-45696-scribble-on-boxed-borrow.nll.stderr
new file mode 100644 (file)
index 0000000..09cbc2f
--- /dev/null
@@ -0,0 +1,48 @@
+error[E0597]: `*s.0` does not live long enough
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:63:5
+   |
+LL |     &mut *s.0 //[nll]~ ERROR `*s.0` does not live long enough [E0597]
+   |     ^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `*s.0` dropped here while still borrowed
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 62:14...
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:62:14
+   |
+LL | fn scribbled<'a>(s: Scribble<'a>) -> &'a mut u32 {
+   |              ^^
+
+error[E0597]: `*s.0` does not live long enough
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:73:5
+   |
+LL |     &mut *(*s).0 //[nll]~ ERROR `*s.0` does not live long enough [E0597]
+   |     ^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `*s.0` dropped here while still borrowed
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 72:20...
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:72:20
+   |
+LL | fn boxed_scribbled<'a>(s: Box<Scribble<'a>>) -> &'a mut u32 {
+   |                    ^^
+
+error[E0597]: `*s.0` does not live long enough
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:83:5
+   |
+LL |     &mut *(**s).0 //[nll]~ ERROR `*s.0` does not live long enough [E0597]
+   |     ^^^^^^^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `*s.0` dropped here while still borrowed
+   |
+note: borrowed value must be valid for the lifetime 'a as defined on the function body at 82:26...
+  --> $DIR/issue-45696-scribble-on-boxed-borrow.rs:82:26
+   |
+LL | fn boxed_boxed_scribbled<'a>(s: Box<Box<Scribble<'a>>>) -> &'a mut u32 {
+   |                          ^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/issue-45696-scribble-on-boxed-borrow.rs b/src/test/ui/issue-45696-scribble-on-boxed-borrow.rs
new file mode 100644 (file)
index 0000000..5a48742
--- /dev/null
@@ -0,0 +1,110 @@
+// 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.
+
+// rust-lang/rust#45696: This test is checking that we *cannot* return
+// mutable borrows that would be scribbled over by destructors before
+// the return occurs.
+//
+// We will explicitly test AST-borrowck, NLL, and migration modes;
+// thus we will also skip the automated compare-mode=nll.
+
+// revisions: ast nll migrate
+// ignore-compare-mode-nll
+
+// This test is going to pass in the ast and migrate revisions,
+// because the AST-borrowck accepted this code in the past (see notes
+// below). So we use `#[rustc_error]` to keep the outcome as an error
+// in all scenarios, and rely on the stderr files to show what the
+// actual behavior is. (See rust-lang/rust#49855.)
+#![feature(rustc_attrs)]
+
+#![cfg_attr(nll, feature(nll))]
+//[migrate]compile-flags: -Z borrowck=migrate -Z two-phase-borrows
+
+struct Scribble<'a>(&'a mut u32);
+
+impl<'a> Drop for Scribble<'a> { fn drop(&mut self) { *self.0 = 42; } }
+
+// this is okay, in both AST-borrowck and NLL: The `Scribble` here *has*
+// to strictly outlive `'a`
+fn borrowed_scribble<'a>(s: &'a mut Scribble) -> &'a mut u32 {
+    &mut *s.0
+}
+
+// this, by analogy to previous case, is also okay.
+fn boxed_borrowed_scribble<'a>(s: Box<&'a mut Scribble>) -> &'a mut u32 {
+    &mut *(*s).0
+}
+
+// this, by analogy to previous case, is also okay.
+fn boxed_boxed_borrowed_scribble<'a>(s: Box<Box<&'a mut Scribble>>) -> &'a mut u32 {
+    &mut *(**s).0
+}
+
+// this is not okay: in between the time that we take the mutable
+// borrow and the caller receives it as a return value, the drop of
+// `s` will scribble on it, violating our aliasing guarantees.
+//
+// * (Maybe in the future the two-phase borrows system will be
+//   extended to support this case. But for now, it is an error in
+//   NLL, even with two-phase borrows.)
+//
+// In any case, the AST-borrowck was not smart enough to know that
+// this should be an error. (Which is perhaps the essence of why
+// rust-lang/rust#45696 arose in the first place.)
+fn scribbled<'a>(s: Scribble<'a>) -> &'a mut u32 {
+    &mut *s.0 //[nll]~ ERROR `*s.0` does not live long enough [E0597]
+    //[migrate]~^ WARNING `*s.0` does not live long enough [E0597]
+    //[migrate]~| WARNING This error has been downgraded to a warning for backwards compatibility
+}
+
+// This, by analogy to previous case, is *also* not okay.
+//
+// (But again, AST-borrowck was not smart enogh to know that this
+// should be an error.)
+fn boxed_scribbled<'a>(s: Box<Scribble<'a>>) -> &'a mut u32 {
+    &mut *(*s).0 //[nll]~ ERROR `*s.0` does not live long enough [E0597]
+    //[migrate]~^ WARNING `*s.0` does not live long enough [E0597]
+    //[migrate]~| WARNING This error has been downgraded to a warning for backwards compatibility
+}
+
+// This, by analogy to previous case, is *also* not okay.
+//
+// (But again, AST-borrowck was not smart enogh to know that this
+// should be an error.)
+fn boxed_boxed_scribbled<'a>(s: Box<Box<Scribble<'a>>>) -> &'a mut u32 {
+    &mut *(**s).0 //[nll]~ ERROR `*s.0` does not live long enough [E0597]
+    //[migrate]~^ WARNING `*s.0` does not live long enough [E0597]
+    //[migrate]~| WARNING This error has been downgraded to a warning for backwards compatibility
+}
+
+#[rustc_error]
+fn main() { //[ast]~ ERROR compilation successful
+     //[migrate]~^ ERROR compilation successful
+    let mut x = 1;
+    {
+        let mut long_lived = Scribble(&mut x);
+        *borrowed_scribble(&mut long_lived) += 10;
+        // (Scribble dtor runs here, after `&mut`-borrow above ends)
+    }
+    {
+        let mut long_lived = Scribble(&mut x);
+        *boxed_borrowed_scribble(Box::new(&mut long_lived)) += 10;
+        // (Scribble dtor runs here, after `&mut`-borrow above ends)
+    }
+    {
+        let mut long_lived = Scribble(&mut x);
+        *boxed_boxed_borrowed_scribble(Box::new(Box::new(&mut long_lived))) += 10;
+        // (Scribble dtor runs here, after `&mut`-borrow above ends)
+    }
+    *scribbled(Scribble(&mut x)) += 10;
+    *boxed_scribbled(Box::new(Scribble(&mut x))) += 10;
+    *boxed_boxed_scribbled(Box::new(Box::new(Scribble(&mut x)))) += 10;
+}
diff --git a/src/test/ui/issue-49579.rs b/src/test/ui/issue-49579.rs
new file mode 100644 (file)
index 0000000..e4e97c5
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2013 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)]
+
+fn fibs(n: u32) -> impl Iterator<Item=u128> {
+    (0 .. n)
+    .scan((0, 1), |st, _| {
+        *st = (st.1, st.0 + st.1);
+        Some(*st)
+    })
+    .map(&|(f, _)| f)
+}
+
+fn main() {
+    println!("{:?}", fibs(10).collect::<Vec<_>>());
+}
diff --git a/src/test/ui/issue-49824.nll.stderr b/src/test/ui/issue-49824.nll.stderr
new file mode 100644 (file)
index 0000000..5934575
--- /dev/null
@@ -0,0 +1,20 @@
+error: unsatisfied lifetime constraints
+  --> $DIR/issue-49824.rs:22:9
+   |
+LL |         || {
+   |    _____-
+   |   |_____|
+   |  ||
+LL |  ||         || {
+   |  ||_________^
+LL | |||             let _y = &mut x;
+LL | |||         }
+   | |||_________^ requires that `'1` must outlive `'2`
+LL |  ||     };
+   |  ||     -
+   |  ||_____|
+   |  |______lifetime `'1` represents the closure body
+   |         lifetime `'2` appears in return type
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issue-49824.rs b/src/test/ui/issue-49824.rs
new file mode 100644 (file)
index 0000000..1f3e575
--- /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(rustc_attrs)]
+
+// This test checks that a failure occurs with NLL but does not fail with the
+// legacy AST output. Check issue-49824.nll.stderr for expected compilation error
+// output under NLL and #49824 for more information.
+
+#[rustc_error]
+fn main() {
+    //~^ compilation successful
+    let mut x = 0;
+    || {
+        || {
+            let _y = &mut x;
+        }
+    };
+}
diff --git a/src/test/ui/issue-49824.stderr b/src/test/ui/issue-49824.stderr
new file mode 100644 (file)
index 0000000..b6cafe5
--- /dev/null
@@ -0,0 +1,14 @@
+error: compilation successful
+  --> $DIR/issue-49824.rs:18:1
+   |
+LL | / fn main() {
+LL | |     //~^ compilation successful
+LL | |     let mut x = 0;
+LL | |     || {
+...  |
+LL | |     };
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
index 87acf106393310c5f4799e63f4b977333a6ab239..ccb2742841cc5dd107a83a53bd598451d0a721ab 100644 (file)
@@ -10,7 +10,7 @@
 
 // compile-pass
 
-#![feature(use_extern_macros, decl_macro)]
+#![feature(decl_macro)]
 
 mod type_ns {
     pub type A = u8;
index ccbb852b1457484b78f384873994876c539a1f7b..e3e389d11970a886fc365debd5d2638600e6f3e7 100644 (file)
@@ -5,7 +5,7 @@ LL |         let v: Vec<&str> = line.split_whitespace().collect();
    |                            ^^^^ borrowed value does not live long enough
 LL |         //~^ ERROR `line` does not live long enough
 LL |         println!("accumulator before add_assign {:?}", acc.map);
-   |                                                        ------- borrow later used here
+   |                                                        ------- borrow used here in later iteration of loop
 ...
 LL |     }
    |     - `line` dropped here while still borrowed
diff --git a/src/test/ui/macro-path-prelude-fail-1.rs b/src/test/ui/macro-path-prelude-fail-1.rs
new file mode 100644 (file)
index 0000000..b953805
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(use_extern_macros, extern_prelude)]
+
+mod m {
+    fn check() {
+        Vec::clone!(); //~ ERROR failed to resolve. Not a module `Vec`
+        u8::clone!(); //~ ERROR failed to resolve. Not a module `u8`
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/macro-path-prelude-fail-1.stderr b/src/test/ui/macro-path-prelude-fail-1.stderr
new file mode 100644 (file)
index 0000000..fc74937
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0433]: failed to resolve. Not a module `Vec`
+  --> $DIR/macro-path-prelude-fail-1.rs:15:9
+   |
+LL |         Vec::clone!(); //~ ERROR failed to resolve. Not a module `Vec`
+   |         ^^^ Not a module `Vec`
+
+error[E0433]: failed to resolve. Not a module `u8`
+  --> $DIR/macro-path-prelude-fail-1.rs:16:9
+   |
+LL |         u8::clone!(); //~ ERROR failed to resolve. Not a module `u8`
+   |         ^^ Not a module `u8`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/src/test/ui/macro-path-prelude-fail-2.rs b/src/test/ui/macro-path-prelude-fail-2.rs
new file mode 100644 (file)
index 0000000..ec77e27
--- /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(use_extern_macros)]
+
+mod m {
+    fn check() {
+        Result::Ok!(); //~ ERROR fail to resolve non-ident macro path
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/macro-path-prelude-fail-2.stderr b/src/test/ui/macro-path-prelude-fail-2.stderr
new file mode 100644 (file)
index 0000000..d23aed8
--- /dev/null
@@ -0,0 +1,8 @@
+error: fail to resolve non-ident macro path
+  --> $DIR/macro-path-prelude-fail-2.rs:15:9
+   |
+LL |         Result::Ok!(); //~ ERROR fail to resolve non-ident macro path
+   |         ^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/macro-path-prelude-fail-3.rs b/src/test/ui/macro-path-prelude-fail-3.rs
new file mode 100644 (file)
index 0000000..4cf9001
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(use_extern_macros)]
+
+#[derive(inline)] //~ ERROR expected a macro, found non-macro attribute
+struct S;
+
+fn main() {
+    inline!(); //~ ERROR expected a macro, found non-macro attribute
+}
diff --git a/src/test/ui/macro-path-prelude-fail-3.stderr b/src/test/ui/macro-path-prelude-fail-3.stderr
new file mode 100644 (file)
index 0000000..bd1015b
--- /dev/null
@@ -0,0 +1,14 @@
+error: expected a macro, found non-macro attribute
+  --> $DIR/macro-path-prelude-fail-3.rs:13:10
+   |
+LL | #[derive(inline)] //~ ERROR expected a macro, found non-macro attribute
+   |          ^^^^^^
+
+error: expected a macro, found non-macro attribute
+  --> $DIR/macro-path-prelude-fail-3.rs:17:5
+   |
+LL |     inline!(); //~ ERROR expected a macro, found non-macro attribute
+   |     ^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/macro-path-prelude-pass.rs b/src/test/ui/macro-path-prelude-pass.rs
new file mode 100644 (file)
index 0000000..bc58754
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-pass
+
+#![feature(use_extern_macros, extern_prelude)]
+
+mod m {
+    fn check() {
+        std::panic!(); // OK
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/macro-path-prelude-shadowing.rs b/src/test/ui/macro-path-prelude-shadowing.rs
new file mode 100644 (file)
index 0000000..1aff777
--- /dev/null
@@ -0,0 +1,41 @@
+// 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:macro-in-other-crate.rs
+
+#![feature(decl_macro, extern_prelude)]
+
+macro_rules! add_macro_expanded_things_to_macro_prelude {() => {
+    #[macro_use]
+    extern crate macro_in_other_crate;
+}}
+
+add_macro_expanded_things_to_macro_prelude!();
+
+mod m1 {
+    fn check() {
+        inline!(); //~ ERROR `inline` is ambiguous
+    }
+}
+
+mod m2 {
+    pub mod std {
+        pub macro panic() {}
+    }
+}
+
+mod m3 {
+    use m2::*; // glob-import user-defined `std`
+    fn check() {
+        std::panic!(); //~ ERROR `std` is ambiguous
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/macro-path-prelude-shadowing.stderr b/src/test/ui/macro-path-prelude-shadowing.stderr
new file mode 100644 (file)
index 0000000..0e1b9a9
--- /dev/null
@@ -0,0 +1,42 @@
+error[E0659]: `inline` is ambiguous
+  --> $DIR/macro-path-prelude-shadowing.rs:24:9
+   |
+LL |         inline!(); //~ ERROR `inline` is ambiguous
+   |         ^^^^^^
+   |
+note: `inline` could refer to the name imported here
+  --> $DIR/macro-path-prelude-shadowing.rs:16:5
+   |
+LL |     #[macro_use]
+   |     ^^^^^^^^^^^^
+...
+LL | add_macro_expanded_things_to_macro_prelude!();
+   | ---------------------------------------------- in this macro invocation
+note: `inline` could also refer to the name defined here
+  --> $DIR/macro-path-prelude-shadowing.rs:24:9
+   |
+LL |         inline!(); //~ ERROR `inline` is ambiguous
+   |         ^^^^^^
+   = note: macro-expanded macro imports do not shadow
+
+error[E0659]: `std` is ambiguous
+  --> $DIR/macro-path-prelude-shadowing.rs:37:9
+   |
+LL |         std::panic!(); //~ ERROR `std` is ambiguous
+   |         ^^^^^^^^^^
+   |
+note: `std` could refer to the name imported here
+  --> $DIR/macro-path-prelude-shadowing.rs:35:9
+   |
+LL |     use m2::*; // glob-import user-defined `std`
+   |         ^^^^^
+note: `std` could also refer to the name defined here
+  --> $DIR/macro-path-prelude-shadowing.rs:37:9
+   |
+LL |         std::panic!(); //~ ERROR `std` is ambiguous
+   |         ^^^
+   = note: consider adding an explicit import of `std` to disambiguate
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0659`.
index 2a30d9837517e2dcd42f805328e4b8683246afb7..4b716ff27446af9b000f699ff4928eb3a80f5240 100644 (file)
@@ -5,8 +5,5 @@ LL |     println!("Hello, World!");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: expanding `println! { "Hello, World!" }`
-   = note: to `{
-           # [ cfg ( not ( stage0 ) ) ] {
-           ( $crate :: io :: _print ( format_args_nl ! ( "Hello, World!" ) ) ) ; } # [
-           cfg ( stage0 ) ] { print ! ( "{}/n" , format_args ! ( "Hello, World!" ) ) } }`
+   = note: to `{ $crate :: io :: _print ( format_args_nl ! ( "Hello, World!" ) ) ; }`
 
diff --git a/src/test/ui/nll/promotable-mutable-zst-doesnt-conflict.rs b/src/test/ui/nll/promotable-mutable-zst-doesnt-conflict.rs
new file mode 100644 (file)
index 0000000..be38556
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check that mutable promoted length zero arrays don't check for conflicting
+// access
+
+// run-pass
+
+#![feature(nll)]
+
+pub fn main() {
+    let mut x: Vec<&[i32; 0]> = Vec::new();
+    for i in 0..10 {
+        x.push(&[]);
+    }
+}
index 10384e3b7ca291be7c565c19f3c138764854fd1d..606d678542269afda8d2b76830655b676543c122 100644 (file)
@@ -7,7 +7,7 @@ LL |         foo.mutate();
    |         ^^^^^^^^^^^^ mutable borrow occurs here
 LL |         //~^ ERROR cannot borrow `foo` as mutable
 LL |         println!("foo={:?}", *string);
-   |                              ------- borrow later used here
+   |                              ------- borrow used here in later iteration of loop
 
 error: aborting due to previous error
 
index f7a6b560280800892b5c2c58766f6e03539b1011..f50419434ae1ddfa518d5ef64f49bad26d7ad865 100644 (file)
@@ -12,7 +12,7 @@
 // aux-build:macro-use-warned-against2.rs
 // compile-pass
 
-#![warn(rust_2018_idioms, unused)]
+#![warn(macro_use_extern_crate, unused)]
 #![feature(use_extern_macros)]
 
 #[macro_use] //~ WARN should be replaced at use sites with a `use` statement
index bebad31510f566e5849104bef3e73fc84cc9e092..7af404fab790e432ac20cee4d7e1637fe92a9124 100644 (file)
@@ -7,9 +7,8 @@ LL | #[macro_use] //~ WARN should be replaced at use sites with a `use` statemen
 note: lint level defined here
   --> $DIR/macro-use-warned-against.rs:15:9
    |
-LL | #![warn(rust_2018_idioms, unused)]
-   |         ^^^^^^^^^^^^^^^^
-   = note: #[warn(macro_use_extern_crate)] implied by #[warn(rust_2018_idioms)]
+LL | #![warn(macro_use_extern_crate, unused)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused `#[macro_use]` import
   --> $DIR/macro-use-warned-against.rs:20:1
@@ -18,9 +17,9 @@ LL | #[macro_use] //~ WARN unused `#[macro_use]`
    | ^^^^^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/macro-use-warned-against.rs:15:27
+  --> $DIR/macro-use-warned-against.rs:15:33
    |
-LL | #![warn(rust_2018_idioms, unused)]
-   |                           ^^^^^^
+LL | #![warn(macro_use_extern_crate, unused)]
+   |                                 ^^^^^^
    = note: #[warn(unused_imports)] implied by #[warn(unused)]
 
index 225ed0f9cc832c50b66076604ea79f2190e3a316..08e4b9ec9faa2b055b1dacda481ac3232639ea48 100644 (file)
@@ -9,8 +9,6 @@ LL | }
    | |
    | `*m` dropped here while still borrowed
    | borrow later used here, when `m` is dropped
-   |
-   = note: values in a scope are dropped in the opposite order they are defined
 
 error: aborting due to previous error
 
index 08ca100c247dc16d2b083ea0f7e54ddfb1063f7c..7aaec700d8985559080944c057955878e4223f7f 100644 (file)
@@ -2,7 +2,7 @@ error[E0597]: `x` does not live long enough
   --> $DIR/regions-escape-loop-via-variable.rs:21:13
    |
 LL |         let x = 1 + *p;
-   |                     -- borrow later used here
+   |                     -- borrow used here in later iteration of loop
 LL |         p = &x;
    |             ^^ borrowed value does not live long enough
 LL |     }
index 4d81211673e6ee014631ed5bcf6b40a74d4fbd60..2dc758428ef3a48de7de92f51460fecec267afc9 100644 (file)
@@ -7,7 +7,7 @@ LL |     while x < 10 { //~ ERROR cannot use `x` because it was mutably borrowed
    |           ^ use of borrowed `x`
 LL |         let mut z = x; //~ ERROR cannot use `x` because it was mutably borrowed
 LL |         _y.push(&mut z);
-   |         -- borrow later used here
+   |         -- borrow used here in later iteration of loop
 
 error[E0503]: cannot use `x` because it was mutably borrowed
   --> $DIR/regions-escape-loop-via-vec.rs:16:21
@@ -18,7 +18,7 @@ LL |     while x < 10 { //~ ERROR cannot use `x` because it was mutably borrowed
 LL |         let mut z = x; //~ ERROR cannot use `x` because it was mutably borrowed
    |                     ^ use of borrowed `x`
 LL |         _y.push(&mut z);
-   |         -- borrow later used here
+   |         -- borrow used here in later iteration of loop
 
 error[E0597]: `z` does not live long enough
   --> $DIR/regions-escape-loop-via-vec.rs:17:17
@@ -26,7 +26,7 @@ error[E0597]: `z` does not live long enough
 LL |         _y.push(&mut z);
    |         --      ^^^^^^ borrowed value does not live long enough
    |         |
-   |         borrow later used here
+   |         borrow used here in later iteration of loop
 ...
 LL |     }
    |     - `z` dropped here while still borrowed
@@ -38,7 +38,7 @@ LL |     let mut _y = vec![&mut x];
    |                       ------ borrow of `x` occurs here
 ...
 LL |         _y.push(&mut z);
-   |         -- borrow later used here
+   |         -- borrow used here in later iteration of loop
 LL |         //~^ ERROR `z` does not live long enough
 LL |         x += 1; //~ ERROR cannot assign
    |         ^^^^^^ use of borrowed `x`
index 69208f151360b2e45ccaef5c467ed40771c93c92..c2dc927c4b52461eb9e13af807b00bb5f2ed036d 100644 (file)
@@ -12,6 +12,8 @@
 // ignore-aarch64
 // ignore-wasm
 // ignore-emscripten
+// ignore-mips
+// ignore-mips64
 // gate-test-sse4a_target_feature
 // gate-test-powerpc_target_feature
 // gate-test-avx512_target_feature
index a6f794a1a1ab2660fbefe671baf1224a7869eaac..24141d0064fb0f2c0cf92dd52a710ad22bb54785 100644 (file)
@@ -1,5 +1,5 @@
 error[E0658]: the target feature `avx512bw` is currently unstable (see issue #44839)
-  --> $DIR/target-feature-gate.rs:26:18
+  --> $DIR/target-feature-gate.rs:28:18
    |
 LL | #[target_feature(enable = "avx512bw")]
    |                  ^^^^^^^^^^^^^^^^^^^
index 8983c0ea79bd944bf239442e2460b04d8e6c154a..fe611141379c49f746cd368bc4a6af9389c51d1b 100644 (file)
@@ -13,6 +13,7 @@
 // ignore-wasm
 // ignore-emscripten
 // ignore-mips
+// ignore-mips64
 // ignore-powerpc
 // ignore-powerpc64
 // ignore-powerpc64le
index d4e1c978104b635ebd15a3d7ab5eb988a2537e7a..21c73b7ddbff0ed31faf0a6cdf786abed298332c 100644 (file)
@@ -1,35 +1,35 @@
 error: #[target_feature] attribute must be of the form #[target_feature(..)]
-  --> $DIR/target-feature-wrong.rs:25:1
+  --> $DIR/target-feature-wrong.rs:26:1
    |
 LL | #[target_feature = "+sse2"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: the feature named `foo` is not valid for this target
-  --> $DIR/target-feature-wrong.rs:27:18
+  --> $DIR/target-feature-wrong.rs:28:18
    |
 LL | #[target_feature(enable = "foo")]
    |                  ^^^^^^^^^^^^^^
 
 error: #[target_feature(..)] only accepts sub-keys of `enable` currently
-  --> $DIR/target-feature-wrong.rs:29:18
+  --> $DIR/target-feature-wrong.rs:30:18
    |
 LL | #[target_feature(bar)]
    |                  ^^^
 
 error: #[target_feature(..)] only accepts sub-keys of `enable` currently
-  --> $DIR/target-feature-wrong.rs:31:18
+  --> $DIR/target-feature-wrong.rs:32:18
    |
 LL | #[target_feature(disable = "baz")]
    |                  ^^^^^^^^^^^^^^^
 
 error: #[target_feature(..)] can only be applied to `unsafe` function
-  --> $DIR/target-feature-wrong.rs:35:1
+  --> $DIR/target-feature-wrong.rs:36:1
    |
 LL | #[target_feature(enable = "sse2")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: attribute should be applied to a function
-  --> $DIR/target-feature-wrong.rs:39:1
+  --> $DIR/target-feature-wrong.rs:40:1
    |
 LL | #[target_feature(enable = "sse2")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -38,7 +38,7 @@ LL | mod another {}
    | -------------- not a function
 
 error: cannot use #[inline(always)] with #[target_feature]
-  --> $DIR/target-feature-wrong.rs:43:1
+  --> $DIR/target-feature-wrong.rs:44:1
    |
 LL | #[inline(always)]
    | ^^^^^^^^^^^^^^^^^
diff --git a/src/test/ui/tool-attributes-disabled-1.rs b/src/test/ui/tool-attributes-disabled-1.rs
new file mode 100644 (file)
index 0000000..87d47b7
--- /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.
+
+// If macro modularization (`use_extern_macros`) is not enabled,
+// then tool attributes are treated as custom attributes.
+
+#[rustfmt::bar] //~ ERROR The attribute `rustfmt::bar` is currently unknown to the compiler
+fn main() {}
diff --git a/src/test/ui/tool-attributes-disabled-1.stderr b/src/test/ui/tool-attributes-disabled-1.stderr
new file mode 100644 (file)
index 0000000..6302c06
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0658]: The attribute `rustfmt::bar` is currently unknown to the compiler and may have meaning added to it in the future (see issue #29642)
+  --> $DIR/tool-attributes-disabled-1.rs:14:1
+   |
+LL | #[rustfmt::bar] //~ ERROR The attribute `rustfmt::bar` is currently unknown to the compiler
+   | ^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(custom_attribute)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/tool-attributes-disabled-2.rs b/src/test/ui/tool-attributes-disabled-2.rs
new file mode 100644 (file)
index 0000000..160dda0
--- /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.
+
+// If macro modularization (`use_extern_macros`) is not enabled,
+// then tool attributes are treated as custom attributes.
+
+// compile-pass
+
+#![feature(custom_attribute)]
+
+#[rustfmt::bar]
+fn main() {}
diff --git a/src/test/ui/tool-attributes-misplaced-1.rs b/src/test/ui/tool-attributes-misplaced-1.rs
new file mode 100644 (file)
index 0000000..b335535
--- /dev/null
@@ -0,0 +1,28 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(tool_attributes)]
+
+type A = rustfmt; //~ ERROR expected type, found tool module `rustfmt`
+type B = rustfmt::skip; //~ ERROR expected type, found non-macro attribute `rustfmt::skip`
+
+#[derive(rustfmt)] //~ ERROR cannot find derive macro `rustfmt` in this scope
+struct S;
+
+#[rustfmt] //~ ERROR cannot find attribute macro `rustfmt` in this scope
+fn check() {}
+
+#[rustfmt::skip] // OK
+fn main() {
+    rustfmt; //~ ERROR expected value, found tool module `rustfmt`
+    rustfmt!(); //~ ERROR cannot find macro `rustfmt!` in this scope
+
+    rustfmt::skip; //~ ERROR expected value, found non-macro attribute `rustfmt::skip`
+}
diff --git a/src/test/ui/tool-attributes-misplaced-1.stderr b/src/test/ui/tool-attributes-misplaced-1.stderr
new file mode 100644 (file)
index 0000000..b9e6112
--- /dev/null
@@ -0,0 +1,46 @@
+error: cannot find derive macro `rustfmt` in this scope
+  --> $DIR/tool-attributes-misplaced-1.rs:16:10
+   |
+LL | #[derive(rustfmt)] //~ ERROR cannot find derive macro `rustfmt` in this scope
+   |          ^^^^^^^
+
+error: cannot find attribute macro `rustfmt` in this scope
+  --> $DIR/tool-attributes-misplaced-1.rs:19:3
+   |
+LL | #[rustfmt] //~ ERROR cannot find attribute macro `rustfmt` in this scope
+   |   ^^^^^^^
+
+error: cannot find macro `rustfmt!` in this scope
+  --> $DIR/tool-attributes-misplaced-1.rs:25:5
+   |
+LL |     rustfmt!(); //~ ERROR cannot find macro `rustfmt!` in this scope
+   |     ^^^^^^^
+
+error[E0573]: expected type, found tool module `rustfmt`
+  --> $DIR/tool-attributes-misplaced-1.rs:13:10
+   |
+LL | type A = rustfmt; //~ ERROR expected type, found tool module `rustfmt`
+   |          ^^^^^^^ not a type
+
+error[E0573]: expected type, found non-macro attribute `rustfmt::skip`
+  --> $DIR/tool-attributes-misplaced-1.rs:14:10
+   |
+LL | type B = rustfmt::skip; //~ ERROR expected type, found non-macro attribute `rustfmt::skip`
+   |          ^^^^^^^^^^^^^ not a type
+
+error[E0423]: expected value, found tool module `rustfmt`
+  --> $DIR/tool-attributes-misplaced-1.rs:24:5
+   |
+LL |     rustfmt; //~ ERROR expected value, found tool module `rustfmt`
+   |     ^^^^^^^ not a value
+
+error[E0423]: expected value, found non-macro attribute `rustfmt::skip`
+  --> $DIR/tool-attributes-misplaced-1.rs:27:5
+   |
+LL |     rustfmt::skip; //~ ERROR expected value, found non-macro attribute `rustfmt::skip`
+   |     ^^^^^^^^^^^^^ not a value
+
+error: aborting due to 7 previous errors
+
+Some errors occurred: E0423, E0573.
+For more information about an error, try `rustc --explain E0423`.
diff --git a/src/test/ui/tool-attributes-misplaced-2.rs b/src/test/ui/tool-attributes-misplaced-2.rs
new file mode 100644 (file)
index 0000000..3bb0e3d
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(tool_attributes)]
+
+#[derive(rustfmt::skip)] //~ ERROR expected a macro, found non-macro attribute
+struct S;
+
+fn main() {
+    rustfmt::skip!(); //~ ERROR expected a macro, found non-macro attribute
+}
diff --git a/src/test/ui/tool-attributes-misplaced-2.stderr b/src/test/ui/tool-attributes-misplaced-2.stderr
new file mode 100644 (file)
index 0000000..6645226
--- /dev/null
@@ -0,0 +1,14 @@
+error: expected a macro, found non-macro attribute
+  --> $DIR/tool-attributes-misplaced-2.rs:13:10
+   |
+LL | #[derive(rustfmt::skip)] //~ ERROR expected a macro, found non-macro attribute
+   |          ^^^^^^^^^^^^^
+
+error: expected a macro, found non-macro attribute
+  --> $DIR/tool-attributes-misplaced-2.rs:17:5
+   |
+LL |     rustfmt::skip!(); //~ ERROR expected a macro, found non-macro attribute
+   |     ^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/tool-attributes-shadowing.rs b/src/test/ui/tool-attributes-shadowing.rs
new file mode 100644 (file)
index 0000000..7913c9f
--- /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.
+
+#![feature(tool_attributes, proc_macro_path_invoc)]
+
+mod rustfmt {}
+
+#[rustfmt::skip] //~ ERROR failed to resolve. Could not find `skip` in `rustfmt`
+fn main() {}
diff --git a/src/test/ui/tool-attributes-shadowing.stderr b/src/test/ui/tool-attributes-shadowing.stderr
new file mode 100644 (file)
index 0000000..f668d67
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0433]: failed to resolve. Could not find `skip` in `rustfmt`
+  --> $DIR/tool-attributes-shadowing.rs:15:12
+   |
+LL | #[rustfmt::skip] //~ ERROR failed to resolve. Could not find `skip` in `rustfmt`
+   |            ^^^^ Could not find `skip` in `rustfmt`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
index bbce87a7c9adf699d81c27099087c2815cccdc57..fd8fb54503a6ff85fde21499942d040608360f02 100644 (file)
@@ -89,6 +89,7 @@
     "powerpc64-unknown-linux-gnu",
     "powerpc64le-unknown-linux-gnu",
     "powerpc64le-unknown-linux-musl",
+    "riscv32imac-unknown-none-elf",
     "s390x-unknown-linux-gnu",
     "sparc-unknown-linux-gnu",
     "sparc64-unknown-linux-gnu",
index 2cd36b4ed1aef1ae39a30783e006411d1a4218ac..15433e8cc932a2b4c0d3f9638e07d08c1c7ac39d 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 2cd36b4ed1aef1ae39a30783e006411d1a4218ac
+Subproject commit 15433e8cc932a2b4c0d3f9638e07d08c1c7ac39d
index b0dabce47803c18b935ec5390de69e04ad5304c2..8ef759e0273ad97f1acbb1ea9f94322aa2a20147 160000 (submodule)
@@ -1 +1 @@
-Subproject commit b0dabce47803c18b935ec5390de69e04ad5304c2
+Subproject commit 8ef759e0273ad97f1acbb1ea9f94322aa2a20147
index 4c7cc91d5518bd29d3d59599cfb7a2e7e848d7b7..0e8d1f3e7acba9737f52dbfc4cb25e5259d4890f 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 4c7cc91d5518bd29d3d59599cfb7a2e7e848d7b7
+Subproject commit 0e8d1f3e7acba9737f52dbfc4cb25e5259d4890f
diff --git a/src/tools/rustc-workspace-hack/Cargo.toml b/src/tools/rustc-workspace-hack/Cargo.toml
new file mode 100644 (file)
index 0000000..8c947bb
--- /dev/null
@@ -0,0 +1,44 @@
+[package]
+name = "rustc-workspace-hack"
+version = "1.0.0"
+authors = ["Alex Crichton <alex@alexcrichton.com>"]
+license = 'MIT/Apache-2.0'
+description = """
+Hack for the compiler's own build system
+"""
+
+[lib]
+path = "lib.rs"
+
+# For documentation about what this is and why in the world these dependencies
+# are appearing, see `README.md`.
+
+[build-dependencies]
+# Currently Cargo/RLS depend on `failure` which depends on `synstructure` which
+# enables this feature. Clippy, however, does not depend on anything that
+# enables this feature. Enable it unconditionally.
+syn = { version = "0.14", features = ['extra-traits'] }
+
+[target.'cfg(windows)'.dependencies.winapi]
+version = "0.3"
+features = [
+  "profileapi",
+  "memoryapi",
+  "minschannel",
+  "securitybaseapi",
+  "jobapi2",
+  "schannel",
+  "sysinfoapi",
+  "jobapi",
+  "synchapi",
+  "wincrypt",
+  "winbase",
+  "minwinbase",
+  "ntsecapi",
+  "basetsd",
+  "ntstatus",
+  "psapi",
+  "timezoneapi",
+  "lmcons",
+  "wincon",
+]
diff --git a/src/tools/rustc-workspace-hack/README.md b/src/tools/rustc-workspace-hack/README.md
new file mode 100644 (file)
index 0000000..4a5286f
--- /dev/null
@@ -0,0 +1,25 @@
+# `rustc-workspace-hack`
+
+This crate is a bit of a hack to make workspaces in rustc work a bit better.
+The rationale for this existence is a bit subtle, but the general idea is that
+we want commands like `./x.py build src/tools/{rls,clippy,cargo}` to share as
+many dependencies as possible.
+
+Each invocation is a different invocation of Cargo, however. Each time Cargo
+runs a build it will re-resolve the dependency graph, notably selecting
+different features sometimes for each build.
+
+For example, let's say there's a very deep dependency like `num-traits` in each
+of these builds. For Cargo the `num-traits`'s `default` feature is turned off.
+In RLS, however, the `default` feature is turned. This means that building Cargo
+and then the RLS will actually build Cargo twice (as a transitive dependency
+changed). This is bad!
+
+The goal of this crate is to solve this problem and ensure that the resolved
+dependency graph for all of these tools is the same in the various subsets of
+each tool, notably enabling the same features of transitive dependencies.
+
+All tools vendored here depend on the `rustc-workspace-hack` crate on crates.io.
+When on crates.io this crate is an empty crate that is just a noop. We override
+it, however, in this workspace to this crate here, which means we can control
+crates in the dependency graph for each of these tools.
diff --git a/src/tools/rustc-workspace-hack/lib.rs b/src/tools/rustc-workspace-hack/lib.rs
new file mode 100644 (file)
index 0000000..ab26297
--- /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.
+
+// intentionally left blank
index 69ad879d52606ac03440744efa5b4d8ca8cc7566..d50e3618d419ec074927ea79741f0c595e7ff2d4 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 69ad879d52606ac03440744efa5b4d8ca8cc7566
+Subproject commit d50e3618d419ec074927ea79741f0c595e7ff2d4