]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #44060 - taleks:issue-43205, r=arielb1
authorbors <bors@rust-lang.org>
Sun, 27 Aug 2017 12:53:48 +0000 (12:53 +0000)
committerbors <bors@rust-lang.org>
Sun, 27 Aug 2017 12:53:48 +0000 (12:53 +0000)
Fixes issue #43205: ICE in Rvalue::Len evaluation.

- fixes evaluation of array length for zero-sized type referenced by rvalue operand.
- adds test to verify fix.

*Cause of the issue*.

Zero-sized aggregates are handled as operands, not lvalues. Therefore while visiting `Assign` statement by `LocalAnalyser`, `mark_as_lvalue()` is not called for related `Local`. This behaviour is controlled by `rvalue_creates_operand()` method.

As result it causes error later, when rvalue operand is evaluated in `trans_rvalue_operand()` while handling `Rvalue::Len` case. Array length evaluation invokes `trans_lvalue()` which expects referenced `Local` to be value, not operand.

*How it is fixed*.

In certain cases result of `Rvalue::Len` can be evaluated without calling
`trans_lvalue()`. Method `evaluate_array_len()` is introduced to handle length
evaluation for zero-sized types referenced by Locals.

*Some concerns*.

- `trans_lvalue()` has two other entry points in `rvalue.rs`: it is invoked while handling `Rvalue::Ref` and `Rvalue::Discriminant`. There is a chance those may produce the same issue, but I've failed to write a specific test that leads to this.
- `evaluate_array_len()` performs the same check (matches lvalue and `Local`), which is performed again in `trans_lvalue()`. Without changing `trans_lvalue()` signature to make it aware that caller deals with rvalue, it seems there is no cheap solution to avoid this check.

206 files changed:
README.md
appveyor.yml
src/Cargo.lock
src/Cargo.toml
src/bootstrap/sanity.rs
src/etc/htmldocck.py
src/liballoc/allocator.rs
src/liballoc/arc.rs
src/liballoc/boxed.rs
src/liballoc/lib.rs
src/liballoc/rc.rs
src/liballoc/slice.rs
src/liballoc/str.rs
src/liballoc/string.rs
src/liballoc/tests/lib.rs
src/liballoc_jemalloc/lib.rs
src/liballoc_system/lib.rs
src/libarena/lib.rs
src/libcollections/lib.rs
src/libcore/cell.rs
src/libcore/fmt/builders.rs
src/libcore/lib.rs
src/libcore/mem.rs
src/libcore/slice/mod.rs
src/libcore/tests/lib.rs
src/libfmt_macros/lib.rs
src/libgetopts/lib.rs
src/libgraphviz/lib.rs
src/libpanic_abort/lib.rs
src/libpanic_unwind/lib.rs
src/libproc_macro/lib.rs
src/libprofiler_builtins/lib.rs
src/librand/lib.rs
src/librustc/dep_graph/dep_node.rs
src/librustc/dep_graph/edges.rs
src/librustc/dep_graph/graph.rs
src/librustc/diagnostics.rs
src/librustc/hir/intravisit.rs
src/librustc/hir/lowering.rs
src/librustc/hir/map/collector.rs
src/librustc/hir/map/mod.rs
src/librustc/hir/mod.rs
src/librustc/hir/print.rs
src/librustc/ich/impls_hir.rs
src/librustc/infer/error_reporting/anon_anon_conflict.rs
src/librustc/infer/error_reporting/mod.rs
src/librustc/infer/error_reporting/named_anon_conflict.rs
src/librustc/infer/error_reporting/util.rs
src/librustc/lib.rs
src/librustc/lint/builtin.rs
src/librustc/middle/resolve_lifetime.rs
src/librustc/session/config.rs
src/librustc/session/mod.rs
src/librustc/ty/context.rs
src/librustc/ty/item_path.rs
src/librustc/ty/maps.rs
src/librustc/ty/mod.rs
src/librustc/ty/util.rs
src/librustc/ty/wf.rs
src/librustc/util/common.rs
src/librustc_apfloat/ieee.rs
src/librustc_apfloat/lib.rs
src/librustc_back/lib.rs
src/librustc_back/target/haiku_base.rs
src/librustc_back/target/l4re_base.rs
src/librustc_back/target/x86_64_unknown_l4re_uclibc.rs
src/librustc_bitflags/lib.rs
src/librustc_borrowck/Cargo.toml
src/librustc_borrowck/lib.rs
src/librustc_const_eval/lib.rs
src/librustc_const_math/lib.rs
src/librustc_data_structures/lib.rs
src/librustc_driver/driver.rs
src/librustc_driver/lib.rs
src/librustc_driver/profile/mod.rs [new file with mode: 0644]
src/librustc_driver/profile/trace.rs [new file with mode: 0644]
src/librustc_errors/diagnostic_builder.rs
src/librustc_errors/emitter.rs
src/librustc_errors/lib.rs
src/librustc_incremental/lib.rs
src/librustc_lint/lib.rs
src/librustc_lint/unused.rs
src/librustc_llvm/lib.rs
src/librustc_metadata/Cargo.toml
src/librustc_metadata/cstore_impl.rs
src/librustc_metadata/decoder.rs
src/librustc_metadata/lib.rs
src/librustc_mir/hair/cx/block.rs
src/librustc_mir/lib.rs
src/librustc_mir/transform/inline.rs
src/librustc_passes/ast_validation.rs
src/librustc_passes/lib.rs
src/librustc_platform_intrinsics/lib.rs
src/librustc_plugin/lib.rs
src/librustc_privacy/lib.rs
src/librustc_resolve/check_unused.rs
src/librustc_resolve/lib.rs
src/librustc_save_analysis/lib.rs
src/librustc_trans/lib.rs
src/librustc_trans_utils/lib.rs
src/librustc_tsan/Cargo.toml
src/librustc_tsan/lib.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/method/confirm.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check_unused.rs
src/librustc_typeck/diagnostics.rs
src/librustc_typeck/lib.rs
src/librustdoc/clean/mod.rs
src/librustdoc/html/render.rs
src/librustdoc/html/static/rustdoc.css
src/librustdoc/html/static/styles/main.css
src/librustdoc/lib.rs
src/libserialize/lib.rs
src/libstd/io/mod.rs
src/libstd/lib.rs
src/libstd/memchr.rs
src/libstd/path.rs
src/libstd/prelude/mod.rs
src/libstd/primitive_docs.rs
src/libstd/sys/redox/ext/mod.rs
src/libstd/sys/unix/ext/fs.rs
src/libstd/sys/unix/ext/mod.rs
src/libstd/sys/unix/thread.rs
src/libstd/sys/windows/c.rs
src/libstd/sys/windows/thread.rs
src/libstd/thread/mod.rs
src/libstd_unicode/lib.rs
src/libsyntax/feature_gate.rs
src/libsyntax/lib.rs
src/libsyntax/test.rs
src/libsyntax_ext/Cargo.toml
src/libsyntax_ext/lib.rs
src/libsyntax_pos/lib.rs
src/libterm/lib.rs
src/libtest/lib.rs
src/libunwind/lib.rs
src/test/compile-fail-fulldeps/plugin-as-extern-crate.rs
src/test/compile-fail/E0254.rs
src/test/compile-fail/E0259.rs
src/test/compile-fail/E0260.rs
src/test/compile-fail/associated-types-eq-expr-path.rs
src/test/compile-fail/auxiliary/lint_unused_extern_crate5.rs [new file with mode: 0644]
src/test/compile-fail/enable-unstable-lib-feature.rs
src/test/compile-fail/feature-gate-fn_must_use.rs [new file with mode: 0644]
src/test/compile-fail/feature-gate/issue-43106-gating-of-builtin-attrs.rs
src/test/compile-fail/issue-36881.rs
src/test/compile-fail/issue-43431.rs [new file with mode: 0644]
src/test/compile-fail/issue-43784-associated-type.rs [new file with mode: 0644]
src/test/compile-fail/issue-43784-supertrait.rs [new file with mode: 0644]
src/test/compile-fail/lint-stability-deprecated.rs
src/test/compile-fail/lint-unused-extern-crate.rs
src/test/compile-fail/macro-reexport-malformed-1.rs
src/test/compile-fail/macro-reexport-malformed-2.rs
src/test/compile-fail/macro-reexport-malformed-3.rs
src/test/compile-fail/macro-use-bad-args-1.rs
src/test/compile-fail/macro-use-bad-args-2.rs
src/test/compile-fail/method-call-type-binding.rs
src/test/compile-fail/no-std-inject.rs
src/test/compile-fail/placement-expr-unstable.rs
src/test/compile-fail/resolve-conflict-extern-crate-vs-extern-crate.rs
src/test/compile-fail/resolve_self_super_hint.rs
src/test/compile-fail/unboxed-closure-sugar-used-on-struct.rs
src/test/compile-fail/unused-attr.rs
src/test/mir-opt/issue-43457.rs [new file with mode: 0644]
src/test/run-make/alloc-extern-crates/Makefile
src/test/run-pass/union/union-basic.rs
src/test/run-pass/wrong-hashset-issue-42918.rs [new file with mode: 0644]
src/test/rustdoc/remove-duplicates.rs [new file with mode: 0644]
src/test/ui/issue-44023.rs [new file with mode: 0644]
src/test/ui/issue-44023.stderr [new file with mode: 0644]
src/test/ui/issue-44078.rs [new file with mode: 0644]
src/test/ui/issue-44078.stderr [new file with mode: 0644]
src/test/ui/lifetime-errors/ex2b-push-no-existing-names.stderr
src/test/ui/lifetime-errors/ex3-both-anon-regions-2.stderr
src/test/ui/lifetime-errors/ex3-both-anon-regions-3.rs
src/test/ui/lifetime-errors/ex3-both-anon-regions-3.stderr
src/test/ui/lifetime-errors/ex3-both-anon-regions-4.rs [deleted file]
src/test/ui/lifetime-errors/ex3-both-anon-regions-4.stderr [deleted file]
src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.rs [new file with mode: 0644]
src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.stderr [new file with mode: 0644]
src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.rs [new file with mode: 0644]
src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.stderr [new file with mode: 0644]
src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs.rs [new file with mode: 0644]
src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs.stderr [new file with mode: 0644]
src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.rs [new file with mode: 0644]
src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.stderr [new file with mode: 0644]
src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.rs [new file with mode: 0644]
src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.stderr [new file with mode: 0644]
src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct.rs [new file with mode: 0644]
src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct.stderr [new file with mode: 0644]
src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.rs [new file with mode: 0644]
src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr [new file with mode: 0644]
src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.rs [new file with mode: 0644]
src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr [new file with mode: 0644]
src/test/ui/lifetime-errors/ex3-both-anon-regions-using-impl-items.rs [new file with mode: 0644]
src/test/ui/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr [new file with mode: 0644]
src/test/ui/lifetime-errors/ex3-both-anon-regions.rs
src/test/ui/lifetime-errors/ex3-both-anon-regions.stderr
src/test/ui/lint/fn_must_use.rs
src/test/ui/lint/fn_must_use.stderr
src/tools/cargo
src/tools/compiletest/src/main.rs
src/tools/compiletest/src/procsrv.rs [deleted file]
src/tools/compiletest/src/runtest.rs
src/tools/rls

index b6ff6df0aec94283a4f2a0bc7eb1b2f1448ed6fb..78a9f509bbcb4c79b37608963b241f748b8aa64b 100644 (file)
--- a/README.md
+++ b/README.md
@@ -135,7 +135,7 @@ Windows build triples are:
     - `i686-pc-windows-msvc`
     - `x86_64-pc-windows-msvc`
 
-The build triple can be specified by either specifying `--build=ABI` when
+The build triple can be specified by either specifying `--build=<triple>` when
 invoking `x.py` commands, or by copying the `config.toml` file (as described
 in Building From Source), and modifying the `build` option under the `[build]`
 section.
index f81e4ba82665047be6c64d8900976239d8e9aa5b..f548d6694c80f88137e76a42b52c83ddfe27b8e2 100644 (file)
@@ -145,7 +145,8 @@ install:
   # - set PATH=%PATH%;%CD% -- this already happens above for sccache
 
   # Install InnoSetup to get `iscc` used to produce installers
-  - appveyor-retry choco install -y InnoSetup
+  - appveyor-retry appveyor DownloadFile https://s3.amazonaws.com/rust-lang-ci/rust-ci-mirror/2017-08-22-is.exe
+  - 2017-08-22-is.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP-
   - set PATH="C:\Program Files (x86)\Inno Setup 5";%PATH%
 
   # Help debug some handle issues on AppVeyor
index b5db5ce36133f33978aad38301c783b63ff8bbab..123c884585c19f276c7acc2d31968900eb55f6e4 100644 (file)
@@ -94,7 +94,7 @@ dependencies = [
  "dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -142,10 +142,10 @@ dependencies = [
  "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -161,9 +161,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 name = "build-manifest"
 version = "0.1.0"
 dependencies = [
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -176,7 +176,7 @@ dependencies = [
 [[package]]
 name = "cargo"
 version = "0.22.0"
-source = "git+https://github.com/rust-lang/cargo#88aa6423a164774d09abc78a24e74e8e665f651b"
+source = "git+https://github.com/rust-lang/cargo#bcf3997b1fa177afc5b6c632a6fbbf6cc75df427"
 replace = "cargo 0.22.0"
 
 [[package]]
@@ -187,6 +187,7 @@ dependencies = [
  "atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "cargotest 0.1.0",
+ "core-foundation 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "crates-io 0.11.0",
  "crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "curl 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -210,19 +211,20 @@ dependencies = [
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "psapi-sys 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "semver 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_ignored 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "termcolor 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -231,22 +233,16 @@ dependencies = [
 name = "cargotest"
 version = "0.1.0"
 dependencies = [
- "bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "cargo 0.22.0",
  "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)",
  "git2 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "hamcrest 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "tar 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -260,7 +256,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "clap"
-version = "2.25.1"
+version = "2.26.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -268,8 +264,8 @@ dependencies = [
  "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "textwrap 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "textwrap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "yaml-rust 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -323,14 +319,31 @@ dependencies = [
  "rand 0.0.0",
 ]
 
+[[package]]
+name = "core-foundation"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "core-foundation-sys 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "core-foundation-sys"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "crates-io"
 version = "0.11.0"
 dependencies = [
  "curl 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "error-chain 0.11.0-rc.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -348,8 +361,8 @@ dependencies = [
  "curl-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
- "socket2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "socket2 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -361,7 +374,7 @@ dependencies = [
  "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -397,8 +410,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -472,6 +485,10 @@ version = "0.1.0"
 name = "find_all_refs_no_cfg_test"
 version = "0.1.0"
 
+[[package]]
+name = "find_impls"
+version = "0.1.0"
+
 [[package]]
 name = "flate2"
 version = "0.2.19"
@@ -529,7 +546,7 @@ dependencies = [
  "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "libgit2-sys 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -588,7 +605,7 @@ dependencies = [
  "pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "quick-error 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -642,11 +659,23 @@ dependencies = [
  "walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "infer_bin"
+version = "0.1.0"
+
+[[package]]
+name = "infer_custom_bin"
+version = "0.1.0"
+
+[[package]]
+name = "infer_lib"
+version = "0.1.0"
+
 [[package]]
 name = "installer"
 version = "0.0.0"
 dependencies = [
- "clap 2.25.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "flate2 0.2.19 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -673,13 +702,13 @@ dependencies = [
 
 [[package]]
 name = "jsonrpc-core"
-version = "7.0.1"
+version = "7.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -698,8 +727,8 @@ version = "0.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -733,7 +762,7 @@ dependencies = [
  "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -745,7 +774,7 @@ dependencies = [
  "cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -771,7 +800,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "lzma-sys"
-version = "0.1.7"
+version = "0.1.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -789,16 +818,16 @@ name = "mdbook"
 version = "0.0.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "clap 2.25.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "handlebars 0.26.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "pulldown-cmark 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -832,7 +861,7 @@ version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "net2 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)",
+ "net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -843,7 +872,7 @@ version = "0.1.0"
 
 [[package]]
 name = "net2"
-version = "0.2.30"
+version = "0.2.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -859,7 +888,7 @@ version = "0.1.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "num-bigint 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
- "num-complex 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-complex 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-rational 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -879,7 +908,7 @@ dependencies = [
 
 [[package]]
 name = "num-complex"
-version = "0.1.39"
+version = "0.1.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -927,6 +956,10 @@ dependencies = [
  "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "omit_init_build"
+version = "0.1.0"
+
 [[package]]
 name = "open"
 version = "1.2.0"
@@ -934,14 +967,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "openssl"
-version = "0.9.15"
+version = "0.9.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "foreign-types 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -951,12 +984,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "openssl-sys"
-version = "0.9.15"
+version = "0.9.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1051,14 +1085,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "racer"
-version = "2.0.9"
+version = "2.0.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "clap 2.25.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntex_errors 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "syntex_syntax 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1140,20 +1172,20 @@ version = "0.1.0"
 dependencies = [
  "cargo 0.22.0 (git+https://github.com/rust-lang/cargo)",
  "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "jsonrpc-core 7.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "jsonrpc-core 7.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "languageserver-types 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "racer 2.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "racer 2.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-analysis 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-data 0.10.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.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustfmt-nightly 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustfmt-nightly 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "url_serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1177,8 +1209,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1187,8 +1219,8 @@ version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1196,7 +1228,7 @@ name = "rls-vfs"
 version = "0.4.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "racer 2.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "racer 2.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1204,7 +1236,7 @@ dependencies = [
 name = "rustbook"
 version = "0.1.0"
 dependencies = [
- "clap 2.25.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "clap 2.26.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "mdbook 0.0.22 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1231,7 +1263,7 @@ dependencies = [
 
 [[package]]
 name = "rustc-demangle"
-version = "0.1.4"
+version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -1295,7 +1327,6 @@ dependencies = [
  "graphviz 0.0.0",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
- "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
  "rustc_mir 0.0.0",
  "syntax 0.0.0",
@@ -1432,7 +1463,6 @@ dependencies = [
  "proc_macro 0.0.0",
  "rustc 0.0.0",
  "rustc_back 0.0.0",
- "rustc_const_math 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
  "serialize 0.0.0",
@@ -1544,7 +1574,7 @@ dependencies = [
  "num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
- "rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_allocator 0.0.0",
  "rustc_back 0.0.0",
  "rustc_bitflags 0.0.0",
@@ -1573,6 +1603,7 @@ dependencies = [
 name = "rustc_tsan"
 version = "0.0.0"
 dependencies = [
+ "alloc 0.0.0",
  "alloc_system 0.0.0",
  "build_helper 0.1.0",
  "cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1616,7 +1647,7 @@ dependencies = [
 
 [[package]]
 name = "rustfmt-nightly"
-version = "0.2.1"
+version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1626,13 +1657,13 @@ dependencies = [
  "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "strings 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1661,7 +1692,7 @@ version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1671,12 +1702,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "serde"
-version = "1.0.10"
+version = "1.0.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "serde_derive"
-version = "1.0.10"
+version = "1.0.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1698,7 +1729,7 @@ name = "serde_ignored"
 version = "0.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1709,7 +1740,7 @@ dependencies = [
  "dtoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1723,7 +1754,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "socket2"
-version = "0.2.1"
+version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1827,7 +1858,6 @@ name = "syntax_ext"
 version = "0.0.0"
 dependencies = [
  "fmt_macros 0.0.0",
- "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "proc_macro 0.0.0",
  "rustc_errors 0.0.0",
  "syntax 0.0.0",
@@ -1937,7 +1967,7 @@ dependencies = [
 
 [[package]]
 name = "textwrap"
-version = "0.6.0"
+version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1984,10 +2014,10 @@ dependencies = [
 
 [[package]]
 name = "toml"
-version = "0.4.2"
+version = "0.4.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2010,7 +2040,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "unicode-segmentation"
-version = "1.1.0"
+version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -2058,7 +2088,7 @@ name = "url_serde"
 version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -2147,7 +2177,7 @@ name = "xz2"
 version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "lzma-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lzma-sys 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -2170,8 +2200,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32"
 "checksum cargo 0.22.0 (git+https://github.com/rust-lang/cargo)" = "<none>"
 "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
-"checksum clap 2.25.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7f1aabf260a8f3fefa8871f16b531038c98dd9eab1cfa2c575e78c459abfa3a0"
+"checksum clap 2.26.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2267a8fdd4dce6956ba6649e130f62fb279026e5e84b92aa939ac8f85ce3f9f0"
 "checksum cmake 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b8ebbb35d3dc9cd09497168f33de1acb79b265d350ab0ac34133b98f8509af1f"
+"checksum core-foundation 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5909502e547762013619f4c4e01cc7393c20fe2d52d7fa471c1210adb2320dc7"
+"checksum core-foundation-sys 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bc9fb3d6cb663e6fd7cf1c63f9b144ee2b1e4a78595a0451dd34bff85b9a3387"
 "checksum crossbeam 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0c5ea215664ca264da8a9d9c3be80d2eaf30923c259d03e870388eb927508f97"
 "checksum curl 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7034c534a1d7d22f7971d6088aa9d281d219ef724026c3428092500f41ae9c2c"
 "checksum curl-sys 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d5481162dc4f424d088581db2f979fa7d4c238fe9794595de61d8d7522e277de"
@@ -2205,7 +2237,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum ignore 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b3fcaf2365eb14b28ec7603c98c06cc531f19de9eb283d89a3dff8417c8c99f5"
 "checksum itoa 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eb2f404fbc66fd9aac13e998248505e7ecb2ad8e44ab6388684c5fb11c6c251c"
 "checksum jobserver 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "443ae8bc0af6c106e6e8b77e04684faecc1a5ce94e058f4c2b0a037b0ea1b133"
-"checksum jsonrpc-core 7.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "da622868a84d3f4fd897f6408ba6714aabf663302802358564b384157c1a5bfa"
+"checksum jsonrpc-core 7.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "903e5eee845f3d83c1436d12848d97b1247cf850ff06a8e1db2f1ce3543af2cf"
 "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
 "checksum languageserver-types 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d52e477b23bf52cd3ca0f9fc6c5d14be954eec97e3b9cdfbd962d911bd533caf"
 "checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf"
@@ -2214,26 +2246,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum libssh2-sys 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0db4ec23611747ef772db1c4d650f8bd762f07b461727ec998f953c614024b75"
 "checksum libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "3fdd64ef8ee652185674455c1d450b83cbc8ad895625d543b5324d923f82e4d8"
 "checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b"
-"checksum lzma-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "013fa6506eb7d26040c46dab9ecb7ccb4e2896b5bf24a9d65932501ea9f67af8"
+"checksum lzma-sys 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "66b2e318eb97ab84f05725471f90c52a09c964053a5899a13fd0165acc26d00b"
 "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376"
 "checksum mdbook 0.0.22 (registry+https://github.com/rust-lang/crates.io-index)" = "22911d86cde6f80fa9f0fb2a68bbbde85d97af4fe0ce267141c83a4187d28700"
 "checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20"
 "checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4"
 "checksum miniz-sys 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "28eaee17666671fa872e567547e8428e83308ebe5808cdf6a0e28397dbe2c726"
 "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
-"checksum net2 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)" = "94101fd932816f97eb9a5116f6c1a11511a1fed7db21c5ccd823b2dc11abf566"
+"checksum net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "3a80f842784ef6c9a958b68b7516bc7e35883c614004dd94959a4dca1b716c09"
 "checksum num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "a311b77ebdc5dd4cf6449d81e4135d9f0e3b153839ac90e648a8ef538f923525"
 "checksum num-bigint 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "8fd0f8dbb4c0960998958a796281d88c16fbe68d87b1baa6f31e2979e81fd0bd"
-"checksum num-complex 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "eb24db7f1904e67a5dfe5f7f62b82f5c963e0f777b23f98cde9c5094fc4fa179"
+"checksum num-complex 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "503e668405c5492d67cf662a81e05be40efe2e6bcf10f7794a07bd9865e704e6"
 "checksum num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "d1452e8b06e448a07f0e6ebb0bb1d92b8890eea63288c0b627331d53514d0fba"
 "checksum num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "7485fcc84f85b4ecd0ea527b14189281cf27d60e583ae65ebc9c088b13dffe01"
 "checksum num-rational 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "288629c76fac4b33556f4b7ab57ba21ae202da65ba8b77466e6d598e31990790"
 "checksum num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "99843c856d68d8b4313b03a17e33c4bb42ae8f6610ea81b28abe076ac721b9b0"
 "checksum num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aec53c34f2d0247c5ca5d32cca1478762f301740468ee9ee6dcb7a0dd7a0c584"
 "checksum open 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3478ed1686bd1300c8a981a940abc92b06fac9cbef747f4c668d4e032ff7b842"
-"checksum openssl 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f776f1d8af832fd2c637ee182c801e8f7ea8895718a2be9914cca001f6e2c40a"
+"checksum openssl 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)" = "085aaedcc89a2fac1eb2bc19cd66f29d4ea99fec60f82a5f3a88a6be7dbd90b5"
 "checksum openssl-probe 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d98df0270d404ccd3c050a41d579c52d1db15375168bb3471e04ec0f5f378daf"
-"checksum openssl-sys 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)" = "ad95f8160d1c150c4f44d4c4959732e048ac046c37f597fe362f8bf57561ffb4"
+"checksum openssl-sys 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)" = "7e3a9845a4c9fdb321931868aae5549e96bb7b979bf9af7de03603d74691b5f3"
 "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
 "checksum percent-encoding 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de154f638187706bde41d9b4738748933d64e6b37bdbffc0b47a97d16a6ae356"
 "checksum pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0a6dda33d67c26f0aac90d324ab2eb7239c819fc7b2552fe9faa4fe88441edc8"
@@ -2243,7 +2275,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum quick-error 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c36987d4978eb1be2e422b1e0423a557923a5c3e7e6f31d5699e9aafaefa469"
 "checksum quote 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4c5cf478fe1006dbcc72567121d23dbdae5f1632386068c5c86ff4f645628504"
 "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
-"checksum racer 2.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9079a128fdb6f0c8850010e1478b215d4c00134654bf995bfda41824951ce9bd"
+"checksum racer 2.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "f120c7510ef7aff254aeb06067fb6fac573ec96a1660e194787cf9dced412bf0"
 "checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d"
 "checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f"
 "checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b"
@@ -2253,21 +2285,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum rls-data 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "11d339f1888e33e74d8032de0f83c40b2bdaaaf04a8cfc03b32186c3481fb534"
 "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a"
 "checksum rls-vfs 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ffd34691a510938bb67fe0444fb363103c73ffb31c121d1e16bc92d8945ea8ff"
-"checksum rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3058a43ada2c2d0b92b3ae38007a2d0fa5e9db971be260e0171408a4ff471c95"
+"checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e"
 "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
-"checksum rustfmt-nightly 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa1ffc66e1e1786355f22e8a958a57bd67fbf9564f522f87f31de9586715f8f6"
+"checksum rustfmt-nightly 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6eea0d0590ae793fc4d281df56e01dc7531575c8ed9a72fadf5fdc7305a0d32f"
 "checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7"
 "checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d"
 "checksum scopeguard 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "59a076157c1e2dc561d8de585151ee6965d910dd4dcb5dabb7ae3e83981a6c57"
 "checksum semver 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3fdd61b85a0fa777f7fb7c454b9189b2941b110d1385ce84d7f76efdf1606a85"
 "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
-"checksum serde 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "433d7d9f8530d5a939ad5e0e72a6243d2e42a24804f70bf592c679363dcacb2f"
-"checksum serde_derive 1.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "7b707cf0d4cab852084f573058def08879bb467fda89d99052485e7d00edd624"
+"checksum serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f7726f29ddf9731b17ff113c461e362c381d9d69433f79de4f3dd572488823e9"
+"checksum serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cf823e706be268e73e7747b147aa31c8f633ab4ba31f115efb57e5047c3a76dd"
 "checksum serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37aee4e0da52d801acfbc0cc219eb1eda7142112339726e427926a6f6ee65d3a"
 "checksum serde_ignored 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c10e798e4405d7dcec3658989e35ee6706f730a9ed7c1184d5ebd84317e82f46"
 "checksum serde_json 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "48b04779552e92037212c3615370f6bd57a40ebba7f20e554ff9f55e41a69a7b"
 "checksum shell-escape 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "dd5cc96481d54583947bfe88bf30c23d53f883c6cd0145368b69989d97b84ef8"
-"checksum socket2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "12cdbddbaa27bf94cc194b8e37f5811db6fe83cea96cf99cf1f8e92b65a41371"
+"checksum socket2 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4daf80fcf54186fac4fe049e0b39d36a5cfde69a11a06413e61e77f553cccf9a"
 "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b"
 "checksum strings 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "da75d8bf2c4d210d63dd09581a041b036001f9f6e03d9b151dbff810fb7ba26a"
 "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
@@ -2282,16 +2314,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum term 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fa63644f74ce96fbeb9b794f66aff2a52d601cbd5e80f4b97123e3899f4570f1"
 "checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209"
 "checksum termcolor 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9a5193a56b8d82014662c4b933dea6bec851daf018a2b01722e007daaf5f9dca"
-"checksum textwrap 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f86300c3e7416ee233abd7cda890c492007a3980f941f79185c753a701257167"
+"checksum textwrap 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f728584ea33b0ad19318e20557cb0a39097751dbb07171419673502f848c7af6"
 "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03"
 "checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5"
 "checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14"
 "checksum toml 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "736b60249cb25337bc196faa43ee12c705e426f3d55c214d73a4e7be06f92cb4"
-"checksum toml 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b0601da6c97135c8d330c7a13a013ca6cd4143221b01de2f8d4edc50a9e551c7"
+"checksum toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a7540f4ffc193e0d3c94121edb19b055670d369f77d5804db11ae053a45b6e7e"
 "checksum typed-arena 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5934776c3ac1bea4a9d56620d6bf2d483b20d394e49581db40f187e1118ff667"
 "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
 "checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f"
-"checksum unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18127285758f0e2c6cf325bb3f3d138a12fee27de4f23e146cd6a179f26c2cf3"
+"checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946"
 "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f"
 "checksum unicode-xid 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "36dff09cafb4ec7c8cf0023eb0b686cb6ce65499116a12201c9e11840ca01beb"
 "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
index 4b84272df98126b69284165fbb2b7755d248739d..ffec3eb075500fb89cf19177f7fda1d6958f1b1a 100644 (file)
@@ -32,6 +32,11 @@ members = [
   "tools/rls/test_data/multiple_bins",
   "tools/rls/test_data/bin_lib",
   "tools/rls/test_data/reformat_with_range",
+  "tools/rls/test_data/find_impls",
+  "tools/rls/test_data/infer_bin",
+  "tools/rls/test_data/infer_custom_bin",
+  "tools/rls/test_data/infer_lib",
+  "tools/rls/test_data/omit_init_build",
 ]
 
 # Curiously, compiletest will segfault if compiled with opt-level=3 on 64-bit
index a64a6130929cbb7c16792c9a844e999d751a4e56..54208d8bb57a623cfada3ec171e9ed4515fb5df0 100644 (file)
@@ -93,10 +93,27 @@ pub fn check(build: &mut Build) {
     }
 
     // Ninja is currently only used for LLVM itself.
-    // Some Linux distros rename `ninja` to `ninja-build`.
-    // CMake can work with either binary name.
-    if building_llvm && build.config.ninja && cmd_finder.maybe_have("ninja-build").is_none() {
-        cmd_finder.must_have("ninja");
+    if building_llvm {
+        if build.config.ninja {
+            // Some Linux distros rename `ninja` to `ninja-build`.
+            // CMake can work with either binary name.
+            if cmd_finder.maybe_have("ninja-build").is_none() {
+                cmd_finder.must_have("ninja");
+            }
+        }
+
+        // If ninja isn't enabled but we're building for MSVC then we try
+        // doubly hard to enable it. It was realized in #43767 that the msbuild
+        // CMake generator for MSVC doesn't respect configuration options like
+        // disabling LLVM assertions, which can often be quite important!
+        //
+        // In these cases we automatically enable Ninja if we find it in the
+        // environment.
+        if !build.config.ninja && build.config.build.contains("msvc") {
+            if cmd_finder.maybe_have("ninja").is_some() {
+                build.config.ninja = true;
+            }
+        }
     }
 
     build.config.python = build.config.python.take().map(|p| cmd_finder.must_have(p))
index a5449b748dd5e98c2434bb2d86774f21bd9a62d4..7e8fde2034640d4b033e8746590fb9d04a3ace11 100644 (file)
@@ -29,7 +29,7 @@ showing the expected renderings.
 
 In order to avoid one-off dependencies for this task, this script uses
 a reasonably working HTML parser and the existing XPath implementation
-from Python 2's standard library. Hopefully we won't render
+from Python's standard library. Hopefully we won't render
 non-well-formed HTML.
 
 # Commands
@@ -110,11 +110,17 @@ import os.path
 import re
 import shlex
 from collections import namedtuple
-from HTMLParser import HTMLParser
+try:
+    from html.parser import HTMLParser
+except ImportError:
+    from HTMLParser import HTMLParser
 from xml.etree import cElementTree as ET
 
 # &larrb;/&rarrb; are not in HTML 4 but are in HTML 5
-from htmlentitydefs import entitydefs
+try:
+    from html.entities import entitydefs
+except ImportError:
+    from htmlentitydefs import entitydefs
 entitydefs['larrb'] = u'\u21e4'
 entitydefs['rarrb'] = u'\u21e5'
 entitydefs['nbsp'] = ' '
@@ -123,6 +129,11 @@ entitydefs['nbsp'] = ' '
 VOID_ELEMENTS = set(['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen',
                      'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr'])
 
+# Python 2 -> 3 compatibility
+try:
+    unichr
+except NameError:
+    unichr = chr
 
 class CustomHTMLParser(HTMLParser):
     """simplified HTML parser.
@@ -184,12 +195,8 @@ def concat_multi_lines(f):
 
         # strip the common prefix from the current line if needed
         if lastline is not None:
-            maxprefix = 0
-            for i in xrange(min(len(line), len(lastline))):
-                if line[i] != lastline[i]:
-                    break
-                maxprefix += 1
-            line = line[maxprefix:].lstrip()
+            common_prefix = os.path.commonprefix([line, lastline])
+            line = line[len(common_prefix):].lstrip()
 
         firstlineno = firstlineno or lineno
         if line.endswith('\\'):
@@ -213,7 +220,7 @@ LINE_PATTERN = re.compile(r'''
 
 
 def get_commands(template):
-    with open(template, 'rUb') as f:
+    with open(template, 'rU') as f:
         for lineno, line in concat_multi_lines(f):
             m = LINE_PATTERN.search(line)
             if not m:
@@ -372,7 +379,7 @@ def check_command(c, cache):
                     cache.get_file(c.args[0])
                     ret = True
                 except FailedCheck as err:
-                    cerr = err.message
+                    cerr = str(err)
                     ret = False
             elif len(c.args) == 2: # @has/matches <path> <pat> = string test
                 cerr = "`PATTERN` did not match"
@@ -413,9 +420,9 @@ def check_command(c, cache):
 
     except FailedCheck as err:
         message = '@{}{} check failed'.format('!' if c.negated else '', c.cmd)
-        print_err(c.lineno, c.context, err.message, message)
+        print_err(c.lineno, c.context, str(err), message)
     except InvalidCheck as err:
-        print_err(c.lineno, c.context, err.message)
+        print_err(c.lineno, c.context, str(err))
 
 def check(target, commands):
     cache = CachedFiles(target)
index fc6585a9f951d6d58c6bb29dbe27ee5eed5eb1b4..f14f27023249e3423cbba1cdab383d6b65a7a71c 100644 (file)
@@ -110,7 +110,7 @@ pub fn from_size_align(size: usize, align: usize) -> Option<Layout> {
 
     /// Creates a layout, bypassing all checks.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function is unsafe as it does not verify that `align` is
     /// a power-of-two that is also less than or equal to 2^31, nor
@@ -485,7 +485,7 @@ pub unsafe trait Alloc {
     /// behavior, e.g. to ensure initialization to particular sets of
     /// bit patterns.)
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function is unsafe because undefined behavior can result
     /// if the caller does not ensure that `layout` has non-zero size.
@@ -513,7 +513,7 @@ pub unsafe trait Alloc {
 
     /// Deallocate the memory referenced by `ptr`.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function is unsafe because undefined behavior can result
     /// if the caller does not ensure all of the following:
@@ -617,7 +617,7 @@ fn usable_size(&self, layout: &Layout) -> (usize, usize) {
     /// behavior is well-defined (though underspecified) when this
     /// constraint is violated; further discussion below.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function is unsafe because undefined behavior can result
     /// if the caller does not ensure all of the following:
@@ -688,7 +688,7 @@ unsafe fn realloc(&mut self,
     /// Behaves like `alloc`, but also ensures that the contents
     /// are set to zero before being returned.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function is unsafe for the same reasons that `alloc` is.
     ///
@@ -714,7 +714,7 @@ unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
     /// the returned block. For some `layout` inputs, like arrays, this
     /// may include extra storage usable for additional data.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function is unsafe for the same reasons that `alloc` is.
     ///
@@ -736,7 +736,7 @@ unsafe fn alloc_excess(&mut self, layout: Layout) -> Result<Excess, AllocErr> {
     /// the returned block. For some `layout` inputs, like arrays, this
     /// may include extra storage usable for additional data.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function is unsafe for the same reasons that `realloc` is.
     ///
@@ -770,7 +770,7 @@ unsafe fn realloc_excess(&mut self,
     /// memory block referenced by `ptr` has not been transferred, and
     /// the contents of the memory block are unaltered.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function is unsafe because undefined behavior can result
     /// if the caller does not ensure all of the following:
@@ -827,7 +827,7 @@ unsafe fn grow_in_place(&mut self,
     /// the memory block has not been transferred, and the contents of
     /// the memory block are unaltered.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function is unsafe because undefined behavior can result
     /// if the caller does not ensure all of the following:
@@ -920,7 +920,7 @@ fn alloc_one<T>(&mut self) -> Result<Unique<T>, AllocErr>
     ///
     /// Captures a common usage pattern for allocators.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function is unsafe because undefined behavior can result
     /// if the caller does not ensure both:
@@ -993,7 +993,7 @@ fn alloc_array<T>(&mut self, n: usize) -> Result<Unique<T>, AllocErr>
     /// The returned block is suitable for passing to the
     /// `alloc`/`realloc` methods of this allocator.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function is unsafe because undefined behavior can result
     /// if the caller does not ensure all of the following:
@@ -1037,7 +1037,7 @@ unsafe fn realloc_array<T>(&mut self,
     ///
     /// Captures a common usage pattern for allocators.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This function is unsafe because undefined behavior can result
     /// if the caller does not ensure both:
index b967eaaaab5b1ca7b22e525f582345fb5b44d987..d734ae6a2cf61b2184bba55d315bff8024a7ea3a 100644 (file)
 //!
 //! [arc]: struct.Arc.html
 
-use boxed::Box;
-
 use core::sync::atomic;
 use core::sync::atomic::Ordering::{Acquire, Relaxed, Release, SeqCst};
 use core::borrow;
 use core::fmt;
 use core::cmp::Ordering;
 use core::intrinsics::abort;
-use core::mem;
-use core::mem::uninitialized;
+use core::mem::{self, size_of_val, uninitialized};
 use core::ops::Deref;
 use core::ops::CoerceUnsized;
 use core::ptr::{self, Shared};
 use core::{isize, usize};
 use core::convert::From;
 
-use heap::{Heap, Alloc, Layout};
+use heap::{Heap, Alloc, Layout, box_free};
+use boxed::Box;
+use string::String;
+use vec::Vec;
 
 /// A soft limit on the amount of references that may be made to an `Arc`.
 ///
@@ -532,6 +532,141 @@ pub fn ptr_eq(this: &Self, other: &Self) -> bool {
     }
 }
 
+impl<T: ?Sized> Arc<T> {
+    // Allocates an `ArcInner<T>` with sufficient space for an unsized value
+    unsafe fn allocate_for_ptr(ptr: *const T) -> *mut ArcInner<T> {
+        // Create a fake ArcInner to find allocation size and alignment
+        let fake_ptr = ptr as *mut ArcInner<T>;
+
+        let layout = Layout::for_value(&*fake_ptr);
+
+        let mem = Heap.alloc(layout)
+            .unwrap_or_else(|e| Heap.oom(e));
+
+        // Initialize the real ArcInner
+        let inner = set_data_ptr(ptr as *mut T, mem) as *mut ArcInner<T>;
+
+        ptr::write(&mut (*inner).strong, atomic::AtomicUsize::new(1));
+        ptr::write(&mut (*inner).weak, atomic::AtomicUsize::new(1));
+
+        inner
+    }
+
+    fn from_box(v: Box<T>) -> Arc<T> {
+        unsafe {
+            let bptr = Box::into_raw(v);
+
+            let value_size = size_of_val(&*bptr);
+            let ptr = Self::allocate_for_ptr(bptr);
+
+            // Copy value as bytes
+            ptr::copy_nonoverlapping(
+                bptr as *const T as *const u8,
+                &mut (*ptr).data as *mut _ as *mut u8,
+                value_size);
+
+            // Free the allocation without dropping its contents
+            box_free(bptr);
+
+            Arc { ptr: Shared::new_unchecked(ptr) }
+        }
+    }
+}
+
+// Sets the data pointer of a `?Sized` raw pointer.
+//
+// For a slice/trait object, this sets the `data` field and leaves the rest
+// unchanged. For a sized raw pointer, this simply sets the pointer.
+unsafe fn set_data_ptr<T: ?Sized, U>(mut ptr: *mut T, data: *mut U) -> *mut T {
+    ptr::write(&mut ptr as *mut _ as *mut *mut u8, data as *mut u8);
+    ptr
+}
+
+impl<T> Arc<[T]> {
+    // Copy elements from slice into newly allocated Arc<[T]>
+    //
+    // Unsafe because the caller must either take ownership or bind `T: Copy`
+    unsafe fn copy_from_slice(v: &[T]) -> Arc<[T]> {
+        let v_ptr = v as *const [T];
+        let ptr = Self::allocate_for_ptr(v_ptr);
+
+        ptr::copy_nonoverlapping(
+            v.as_ptr(),
+            &mut (*ptr).data as *mut [T] as *mut T,
+            v.len());
+
+        Arc { ptr: Shared::new_unchecked(ptr) }
+    }
+}
+
+// Specialization trait used for From<&[T]>
+trait ArcFromSlice<T> {
+    fn from_slice(slice: &[T]) -> Self;
+}
+
+impl<T: Clone> ArcFromSlice<T> for Arc<[T]> {
+    #[inline]
+    default fn from_slice(v: &[T]) -> Self {
+        // Panic guard while cloning T elements.
+        // In the event of a panic, elements that have been written
+        // into the new ArcInner will be dropped, then the memory freed.
+        struct Guard<T> {
+            mem: *mut u8,
+            elems: *mut T,
+            layout: Layout,
+            n_elems: usize,
+        }
+
+        impl<T> Drop for Guard<T> {
+            fn drop(&mut self) {
+                use core::slice::from_raw_parts_mut;
+
+                unsafe {
+                    let slice = from_raw_parts_mut(self.elems, self.n_elems);
+                    ptr::drop_in_place(slice);
+
+                    Heap.dealloc(self.mem, self.layout.clone());
+                }
+            }
+        }
+
+        unsafe {
+            let v_ptr = v as *const [T];
+            let ptr = Self::allocate_for_ptr(v_ptr);
+
+            let mem = ptr as *mut _ as *mut u8;
+            let layout = Layout::for_value(&*ptr);
+
+            // Pointer to first element
+            let elems = &mut (*ptr).data as *mut [T] as *mut T;
+
+            let mut guard = Guard{
+                mem: mem,
+                elems: elems,
+                layout: layout,
+                n_elems: 0,
+            };
+
+            for (i, item) in v.iter().enumerate() {
+                ptr::write(elems.offset(i as isize), item.clone());
+                guard.n_elems += 1;
+            }
+
+            // All clear. Forget the guard so it doesn't free the new ArcInner.
+            mem::forget(guard);
+
+            Arc { ptr: Shared::new_unchecked(ptr) }
+        }
+    }
+}
+
+impl<T: Copy> ArcFromSlice<T> for Arc<[T]> {
+    #[inline]
+    fn from_slice(v: &[T]) -> Self {
+        unsafe { Arc::copy_from_slice(v) }
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> Clone for Arc<T> {
     /// Makes a clone of the `Arc` pointer.
@@ -1216,8 +1351,56 @@ fn from(t: T) -> Self {
     }
 }
 
+#[stable(feature = "shared_from_slice", since = "1.21.0")]
+impl<'a, T: Clone> From<&'a [T]> for Arc<[T]> {
+    #[inline]
+    fn from(v: &[T]) -> Arc<[T]> {
+        <Self as ArcFromSlice<T>>::from_slice(v)
+    }
+}
+
+#[stable(feature = "shared_from_slice", since = "1.21.0")]
+impl<'a> From<&'a str> for Arc<str> {
+    #[inline]
+    fn from(v: &str) -> Arc<str> {
+        unsafe { mem::transmute(<Arc<[u8]>>::from(v.as_bytes())) }
+    }
+}
+
+#[stable(feature = "shared_from_slice", since = "1.21.0")]
+impl From<String> for Arc<str> {
+    #[inline]
+    fn from(v: String) -> Arc<str> {
+        Arc::from(&v[..])
+    }
+}
+
+#[stable(feature = "shared_from_slice", since = "1.21.0")]
+impl<T: ?Sized> From<Box<T>> for Arc<T> {
+    #[inline]
+    fn from(v: Box<T>) -> Arc<T> {
+        Arc::from_box(v)
+    }
+}
+
+#[stable(feature = "shared_from_slice", since = "1.21.0")]
+impl<T> From<Vec<T>> for Arc<[T]> {
+    #[inline]
+    fn from(mut v: Vec<T>) -> Arc<[T]> {
+        unsafe {
+            let arc = Arc::copy_from_slice(&v);
+
+            // Allow the Vec to free its memory, but not destroy its contents
+            v.set_len(0);
+
+            arc
+        }
+    }
+}
+
 #[cfg(test)]
 mod tests {
+    use std::boxed::Box;
     use std::clone::Clone;
     use std::sync::mpsc::channel;
     use std::mem::drop;
@@ -1520,6 +1703,113 @@ fn test_weak_count_locked() {
         }
         t.join().unwrap();
     }
+
+    #[test]
+    fn test_from_str() {
+        let r: Arc<str> = Arc::from("foo");
+
+        assert_eq!(&r[..], "foo");
+    }
+
+    #[test]
+    fn test_copy_from_slice() {
+        let s: &[u32] = &[1, 2, 3];
+        let r: Arc<[u32]> = Arc::from(s);
+
+        assert_eq!(&r[..], [1, 2, 3]);
+    }
+
+    #[test]
+    fn test_clone_from_slice() {
+        #[derive(Clone, Debug, Eq, PartialEq)]
+        struct X(u32);
+
+        let s: &[X] = &[X(1), X(2), X(3)];
+        let r: Arc<[X]> = Arc::from(s);
+
+        assert_eq!(&r[..], s);
+    }
+
+    #[test]
+    #[should_panic]
+    fn test_clone_from_slice_panic() {
+        use std::string::{String, ToString};
+
+        struct Fail(u32, String);
+
+        impl Clone for Fail {
+            fn clone(&self) -> Fail {
+                if self.0 == 2 {
+                    panic!();
+                }
+                Fail(self.0, self.1.clone())
+            }
+        }
+
+        let s: &[Fail] = &[
+            Fail(0, "foo".to_string()),
+            Fail(1, "bar".to_string()),
+            Fail(2, "baz".to_string()),
+        ];
+
+        // Should panic, but not cause memory corruption
+        let _r: Arc<[Fail]> = Arc::from(s);
+    }
+
+    #[test]
+    fn test_from_box() {
+        let b: Box<u32> = box 123;
+        let r: Arc<u32> = Arc::from(b);
+
+        assert_eq!(*r, 123);
+    }
+
+    #[test]
+    fn test_from_box_str() {
+        use std::string::String;
+
+        let s = String::from("foo").into_boxed_str();
+        let r: Arc<str> = Arc::from(s);
+
+        assert_eq!(&r[..], "foo");
+    }
+
+    #[test]
+    fn test_from_box_slice() {
+        let s = vec![1, 2, 3].into_boxed_slice();
+        let r: Arc<[u32]> = Arc::from(s);
+
+        assert_eq!(&r[..], [1, 2, 3]);
+    }
+
+    #[test]
+    fn test_from_box_trait() {
+        use std::fmt::Display;
+        use std::string::ToString;
+
+        let b: Box<Display> = box 123;
+        let r: Arc<Display> = Arc::from(b);
+
+        assert_eq!(r.to_string(), "123");
+    }
+
+    #[test]
+    fn test_from_box_trait_zero_sized() {
+        use std::fmt::Debug;
+
+        let b: Box<Debug> = box ();
+        let r: Arc<Debug> = Arc::from(b);
+
+        assert_eq!(format!("{:?}", r), "()");
+    }
+
+    #[test]
+    fn test_from_vec() {
+        let v = vec![1, 2, 3];
+        let r: Arc<[u32]> = Arc::from(v);
+
+        assert_eq!(&r[..], [1, 2, 3]);
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
index c0d43d9c52755d3086c480ff23dff7222d546bee..82aac4dbf63346fa2897e215df8b329faf34a7ee 100644 (file)
@@ -633,7 +633,7 @@ impl<I: FusedIterator + ?Sized> FusedIterator for Box<I> {}
 /// that `FnBox` may be deprecated in the future if `Box<FnOnce()>`
 /// closures become directly usable.)
 ///
-/// ### Example
+/// # Examples
 ///
 /// Here is a snippet of code which creates a hashmap full of boxed
 /// once closures and then removes them one by one, calling each
index 227fcfabcf11de25056fbdf7918a7ae004853dcb..2d41ed648102b2159f2341bfb2312fdc2a6fb223 100644 (file)
@@ -60,8 +60,6 @@
 //! The [`heap`](heap/index.html) module defines the low-level interface to the
 //! default global allocator. It is not compatible with the libc allocator API.
 
-#![crate_name = "alloc"]
-#![crate_type = "rlib"]
 #![allow(unused_attributes)]
 #![unstable(feature = "alloc",
             reason = "this library is unlikely to be stabilized in its current \
 #![feature(unsize)]
 #![feature(allocator_internals)]
 
-#![cfg_attr(not(test), feature(fused, fn_traits, placement_new_protocol))]
+#![cfg_attr(not(test), feature(fused, fn_traits, placement_new_protocol, swap_with_slice))]
 #![cfg_attr(test, feature(test, box_heap))]
 
 // Allow testing this library
index 9783aed895f7d689e44582ba0b2ebb65b2598dcf..47f537caf31c45bddb197416b706b5c177cdd8dc 100644 (file)
 use core::intrinsics::abort;
 use core::marker;
 use core::marker::Unsize;
-use core::mem::{self, forget, size_of, size_of_val, uninitialized};
+use core::mem::{self, forget, size_of_val, uninitialized};
 use core::ops::Deref;
 use core::ops::CoerceUnsized;
 use core::ptr::{self, Shared};
 use core::convert::From;
 
 use heap::{Heap, Alloc, Layout, box_free};
-use raw_vec::RawVec;
+use string::String;
+use vec::Vec;
 
 struct RcBox<T: ?Sized> {
     strong: Cell<usize>,
@@ -421,64 +422,6 @@ pub unsafe fn from_raw(ptr: *const T) -> Self {
     }
 }
 
-impl Rc<str> {
-    /// Constructs a new `Rc<str>` from a string slice.
-    #[doc(hidden)]
-    #[unstable(feature = "rustc_private",
-               reason = "for internal use in rustc",
-               issue = "27812")]
-    pub fn __from_str(value: &str) -> Rc<str> {
-        unsafe {
-            // Allocate enough space for `RcBox<str>`.
-            let aligned_len = 2 + (value.len() + size_of::<usize>() - 1) / size_of::<usize>();
-            let vec = RawVec::<usize>::with_capacity(aligned_len);
-            let ptr = vec.ptr();
-            forget(vec);
-            // Initialize fields of `RcBox<str>`.
-            *ptr.offset(0) = 1; // strong: Cell::new(1)
-            *ptr.offset(1) = 1; // weak: Cell::new(1)
-            ptr::copy_nonoverlapping(value.as_ptr(), ptr.offset(2) as *mut u8, value.len());
-            // Combine the allocation address and the string length into a fat pointer to `RcBox`.
-            let rcbox_ptr: *mut RcBox<str> = mem::transmute([ptr as usize, value.len()]);
-            assert!(aligned_len * size_of::<usize>() == size_of_val(&*rcbox_ptr));
-            Rc { ptr: Shared::new_unchecked(rcbox_ptr) }
-        }
-    }
-}
-
-impl<T> Rc<[T]> {
-    /// Constructs a new `Rc<[T]>` from a `Box<[T]>`.
-    #[doc(hidden)]
-    #[unstable(feature = "rustc_private",
-               reason = "for internal use in rustc",
-               issue = "27812")]
-    pub fn __from_array(value: Box<[T]>) -> Rc<[T]> {
-        unsafe {
-            let ptr: *mut RcBox<[T]> =
-                mem::transmute([mem::align_of::<RcBox<[T; 1]>>(), value.len()]);
-            // FIXME(custom-DST): creating this invalid &[T] is dubiously defined,
-            // we should have a better way of getting the size/align
-            // of a DST from its unsized part.
-            let ptr = Heap.alloc(Layout::for_value(&*ptr))
-                .unwrap_or_else(|e| Heap.oom(e));
-            let ptr: *mut RcBox<[T]> = mem::transmute([ptr as usize, value.len()]);
-
-            // Initialize the new RcBox.
-            ptr::write(&mut (*ptr).strong, Cell::new(1));
-            ptr::write(&mut (*ptr).weak, Cell::new(1));
-            ptr::copy_nonoverlapping(
-                value.as_ptr(),
-                &mut (*ptr).value as *mut [T] as *mut T,
-                value.len());
-
-            // Free the original allocation without freeing its (moved) contents.
-            box_free(Box::into_raw(value));
-
-            Rc { ptr: Shared::new_unchecked(ptr as *mut _) }
-        }
-    }
-}
-
 impl<T: ?Sized> Rc<T> {
     /// Creates a new [`Weak`][weak] pointer to this value.
     ///
@@ -665,6 +608,140 @@ pub fn make_mut(this: &mut Self) -> &mut T {
     }
 }
 
+impl<T: ?Sized> Rc<T> {
+    // Allocates an `RcBox<T>` with sufficient space for an unsized value
+    unsafe fn allocate_for_ptr(ptr: *const T) -> *mut RcBox<T> {
+        // Create a fake RcBox to find allocation size and alignment
+        let fake_ptr = ptr as *mut RcBox<T>;
+
+        let layout = Layout::for_value(&*fake_ptr);
+
+        let mem = Heap.alloc(layout)
+            .unwrap_or_else(|e| Heap.oom(e));
+
+        // Initialize the real RcBox
+        let inner = set_data_ptr(ptr as *mut T, mem) as *mut RcBox<T>;
+
+        ptr::write(&mut (*inner).strong, Cell::new(1));
+        ptr::write(&mut (*inner).weak, Cell::new(1));
+
+        inner
+    }
+
+    fn from_box(v: Box<T>) -> Rc<T> {
+        unsafe {
+            let bptr = Box::into_raw(v);
+
+            let value_size = size_of_val(&*bptr);
+            let ptr = Self::allocate_for_ptr(bptr);
+
+            // Copy value as bytes
+            ptr::copy_nonoverlapping(
+                bptr as *const T as *const u8,
+                &mut (*ptr).value as *mut _ as *mut u8,
+                value_size);
+
+            // Free the allocation without dropping its contents
+            box_free(bptr);
+
+            Rc { ptr: Shared::new_unchecked(ptr) }
+        }
+    }
+}
+
+// Sets the data pointer of a `?Sized` raw pointer.
+//
+// For a slice/trait object, this sets the `data` field and leaves the rest
+// unchanged. For a sized raw pointer, this simply sets the pointer.
+unsafe fn set_data_ptr<T: ?Sized, U>(mut ptr: *mut T, data: *mut U) -> *mut T {
+    ptr::write(&mut ptr as *mut _ as *mut *mut u8, data as *mut u8);
+    ptr
+}
+
+impl<T> Rc<[T]> {
+    // Copy elements from slice into newly allocated Rc<[T]>
+    //
+    // Unsafe because the caller must either take ownership or bind `T: Copy`
+    unsafe fn copy_from_slice(v: &[T]) -> Rc<[T]> {
+        let v_ptr = v as *const [T];
+        let ptr = Self::allocate_for_ptr(v_ptr);
+
+        ptr::copy_nonoverlapping(
+            v.as_ptr(),
+            &mut (*ptr).value as *mut [T] as *mut T,
+            v.len());
+
+        Rc { ptr: Shared::new_unchecked(ptr) }
+    }
+}
+
+trait RcFromSlice<T> {
+    fn from_slice(slice: &[T]) -> Self;
+}
+
+impl<T: Clone> RcFromSlice<T> for Rc<[T]> {
+    #[inline]
+    default fn from_slice(v: &[T]) -> Self {
+        // Panic guard while cloning T elements.
+        // In the event of a panic, elements that have been written
+        // into the new RcBox will be dropped, then the memory freed.
+        struct Guard<T> {
+            mem: *mut u8,
+            elems: *mut T,
+            layout: Layout,
+            n_elems: usize,
+        }
+
+        impl<T> Drop for Guard<T> {
+            fn drop(&mut self) {
+                use core::slice::from_raw_parts_mut;
+
+                unsafe {
+                    let slice = from_raw_parts_mut(self.elems, self.n_elems);
+                    ptr::drop_in_place(slice);
+
+                    Heap.dealloc(self.mem, self.layout.clone());
+                }
+            }
+        }
+
+        unsafe {
+            let v_ptr = v as *const [T];
+            let ptr = Self::allocate_for_ptr(v_ptr);
+
+            let mem = ptr as *mut _ as *mut u8;
+            let layout = Layout::for_value(&*ptr);
+
+            // Pointer to first element
+            let elems = &mut (*ptr).value as *mut [T] as *mut T;
+
+            let mut guard = Guard{
+                mem: mem,
+                elems: elems,
+                layout: layout,
+                n_elems: 0,
+            };
+
+            for (i, item) in v.iter().enumerate() {
+                ptr::write(elems.offset(i as isize), item.clone());
+                guard.n_elems += 1;
+            }
+
+            // All clear. Forget the guard so it doesn't free the new RcBox.
+            forget(guard);
+
+            Rc { ptr: Shared::new_unchecked(ptr) }
+        }
+    }
+}
+
+impl<T: Copy> RcFromSlice<T> for Rc<[T]> {
+    #[inline]
+    fn from_slice(v: &[T]) -> Self {
+        unsafe { Rc::copy_from_slice(v) }
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> Deref for Rc<T> {
     type Target = T;
@@ -959,6 +1036,53 @@ fn from(t: T) -> Self {
     }
 }
 
+#[stable(feature = "shared_from_slice", since = "1.21.0")]
+impl<'a, T: Clone> From<&'a [T]> for Rc<[T]> {
+    #[inline]
+    fn from(v: &[T]) -> Rc<[T]> {
+        <Self as RcFromSlice<T>>::from_slice(v)
+    }
+}
+
+#[stable(feature = "shared_from_slice", since = "1.21.0")]
+impl<'a> From<&'a str> for Rc<str> {
+    #[inline]
+    fn from(v: &str) -> Rc<str> {
+        unsafe { mem::transmute(<Rc<[u8]>>::from(v.as_bytes())) }
+    }
+}
+
+#[stable(feature = "shared_from_slice", since = "1.21.0")]
+impl From<String> for Rc<str> {
+    #[inline]
+    fn from(v: String) -> Rc<str> {
+        Rc::from(&v[..])
+    }
+}
+
+#[stable(feature = "shared_from_slice", since = "1.21.0")]
+impl<T: ?Sized> From<Box<T>> for Rc<T> {
+    #[inline]
+    fn from(v: Box<T>) -> Rc<T> {
+        Rc::from_box(v)
+    }
+}
+
+#[stable(feature = "shared_from_slice", since = "1.21.0")]
+impl<T> From<Vec<T>> for Rc<[T]> {
+    #[inline]
+    fn from(mut v: Vec<T>) -> Rc<[T]> {
+        unsafe {
+            let rc = Rc::copy_from_slice(&v);
+
+            // Allow the Vec to free its memory, but not destroy its contents
+            v.set_len(0);
+
+            rc
+        }
+    }
+}
+
 /// `Weak` is a version of [`Rc`] that holds a non-owning reference to the
 /// managed value. The value is accessed by calling [`upgrade`] on the `Weak`
 /// pointer, which returns an [`Option`]`<`[`Rc`]`<T>>`.
@@ -1465,6 +1589,113 @@ fn test_ptr_eq() {
         assert!(Rc::ptr_eq(&five, &same_five));
         assert!(!Rc::ptr_eq(&five, &other_five));
     }
+
+    #[test]
+    fn test_from_str() {
+        let r: Rc<str> = Rc::from("foo");
+
+        assert_eq!(&r[..], "foo");
+    }
+
+    #[test]
+    fn test_copy_from_slice() {
+        let s: &[u32] = &[1, 2, 3];
+        let r: Rc<[u32]> = Rc::from(s);
+
+        assert_eq!(&r[..], [1, 2, 3]);
+    }
+
+    #[test]
+    fn test_clone_from_slice() {
+        #[derive(Clone, Debug, Eq, PartialEq)]
+        struct X(u32);
+
+        let s: &[X] = &[X(1), X(2), X(3)];
+        let r: Rc<[X]> = Rc::from(s);
+
+        assert_eq!(&r[..], s);
+    }
+
+    #[test]
+    #[should_panic]
+    fn test_clone_from_slice_panic() {
+        use std::string::{String, ToString};
+
+        struct Fail(u32, String);
+
+        impl Clone for Fail {
+            fn clone(&self) -> Fail {
+                if self.0 == 2 {
+                    panic!();
+                }
+                Fail(self.0, self.1.clone())
+            }
+        }
+
+        let s: &[Fail] = &[
+            Fail(0, "foo".to_string()),
+            Fail(1, "bar".to_string()),
+            Fail(2, "baz".to_string()),
+        ];
+
+        // Should panic, but not cause memory corruption
+        let _r: Rc<[Fail]> = Rc::from(s);
+    }
+
+    #[test]
+    fn test_from_box() {
+        let b: Box<u32> = box 123;
+        let r: Rc<u32> = Rc::from(b);
+
+        assert_eq!(*r, 123);
+    }
+
+    #[test]
+    fn test_from_box_str() {
+        use std::string::String;
+
+        let s = String::from("foo").into_boxed_str();
+        let r: Rc<str> = Rc::from(s);
+
+        assert_eq!(&r[..], "foo");
+    }
+
+    #[test]
+    fn test_from_box_slice() {
+        let s = vec![1, 2, 3].into_boxed_slice();
+        let r: Rc<[u32]> = Rc::from(s);
+
+        assert_eq!(&r[..], [1, 2, 3]);
+    }
+
+    #[test]
+    fn test_from_box_trait() {
+        use std::fmt::Display;
+        use std::string::ToString;
+
+        let b: Box<Display> = box 123;
+        let r: Rc<Display> = Rc::from(b);
+
+        assert_eq!(r.to_string(), "123");
+    }
+
+    #[test]
+    fn test_from_box_trait_zero_sized() {
+        use std::fmt::Debug;
+
+        let b: Box<Debug> = box ();
+        let r: Rc<Debug> = Rc::from(b);
+
+        assert_eq!(format!("{:?}", r), "()");
+    }
+
+    #[test]
+    fn test_from_vec() {
+        let v = vec![1, 2, 3];
+        let r: Rc<[u32]> = Rc::from(v);
+
+        assert_eq!(&r[..], [1, 2, 3]);
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
index 356ca7a5f5e0cee6adf9372629a330b886cc3774..7787ace944119861181c671b805688ae763174be 100644 (file)
@@ -171,7 +171,7 @@ pub fn to_vec<T>(s: &[T]) -> Vec<T>
 impl<T> [T] {
     /// Returns the number of elements in the slice.
     ///
-    /// # Example
+    /// # Examples
     ///
     /// ```
     /// let a = [1, 2, 3];
@@ -185,7 +185,7 @@ pub fn len(&self) -> usize {
 
     /// Returns `true` if the slice has a length of 0.
     ///
-    /// # Example
+    /// # Examples
     ///
     /// ```
     /// let a = [1, 2, 3];
@@ -523,7 +523,7 @@ pub fn swap(&mut self, a: usize, b: usize) {
 
     /// Reverses the order of elements in the slice, in place.
     ///
-    /// # Example
+    /// # Examples
     ///
     /// ```
     /// let mut v = [1, 2, 3];
@@ -580,7 +580,7 @@ pub fn iter_mut(&mut self) -> IterMut<T> {
     ///
     /// Panics if `size` is 0.
     ///
-    /// # Example
+    /// # Examples
     ///
     /// ```
     /// let slice = ['r', 'u', 's', 't'];
@@ -613,7 +613,7 @@ pub fn windows(&self, size: usize) -> Windows<T> {
     ///
     /// Panics if `size` is 0.
     ///
-    /// # Example
+    /// # Examples
     ///
     /// ```
     /// let slice = ['l', 'o', 'r', 'e', 'm'];
@@ -1040,7 +1040,7 @@ pub fn ends_with(&self, needle: &[T]) -> bool
     /// `Err` is returned, containing the index where a matching
     /// element could be inserted while maintaining sorted order.
     ///
-    /// # Example
+    /// # Examples
     ///
     /// Looks up a series of four elements. The first is found, with a
     /// uniquely determined position; the second and third are not
@@ -1074,7 +1074,7 @@ pub fn binary_search(&self, x: &T) -> Result<usize, usize>
     /// `Err` is returned, containing the index where a matching
     /// element could be inserted while maintaining sorted order.
     ///
-    /// # Example
+    /// # Examples
     ///
     /// Looks up a series of four elements. The first is found, with a
     /// uniquely determined position; the second and third are not
@@ -1419,7 +1419,7 @@ pub fn rotate(&mut self, mid: usize) {
     ///
     /// This function will panic if the two slices have different lengths.
     ///
-    /// # Example
+    /// # Examples
     ///
     /// ```
     /// let mut dst = [0, 0, 0];
@@ -1445,7 +1445,7 @@ pub fn clone_from_slice(&mut self, src: &[T]) where T: Clone {
     ///
     /// This function will panic if the two slices have different lengths.
     ///
-    /// # Example
+    /// # Examples
     ///
     /// ```
     /// let mut dst = [0, 0, 0];
@@ -1461,6 +1461,31 @@ pub fn copy_from_slice(&mut self, src: &[T]) where T: Copy {
         core_slice::SliceExt::copy_from_slice(self, src)
     }
 
+    /// Swaps all elements in `self` with those in `src`.
+    ///
+    /// The length of `src` must be the same as `self`.
+    ///
+    /// # Panics
+    ///
+    /// This function will panic if the two slices have different lengths.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// #![feature(swap_with_slice)]
+    ///
+    /// let mut src = [1, 2, 3];
+    /// let mut dst = [7, 8, 9];
+    ///
+    /// src.swap_with_slice(&mut dst);
+    /// assert_eq!(src, [7, 8, 9]);
+    /// assert_eq!(dst, [1, 2, 3]);
+    /// ```
+    #[unstable(feature = "swap_with_slice", issue = "44030")]
+    pub fn swap_with_slice(&mut self, src: &mut [T]) {
+        core_slice::SliceExt::swap_with_slice(self, src)
+    }
+
     /// Copies `self` into a new `Vec`.
     ///
     /// # Examples
index 80317cd763b5c8680e6b5d5dc6d51fce0ea87e98..79b2bbce2af7cf13e59ad095572ce3a4e6b2d54a 100644 (file)
@@ -1714,7 +1714,7 @@ pub fn trim_right_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str
     ///
     /// [`Err`]: str/trait.FromStr.html#associatedtype.Err
     ///
-    /// # Example
+    /// # Examples
     ///
     /// Basic usage
     ///
index 96bd6273c9484b15a20b3b2a2b354e3806eff6b5..b1919c7c968c9bdda239c74ce22a2c64fd69aebe 100644 (file)
@@ -82,7 +82,7 @@
 ///
 /// # Examples
 ///
-/// You can create a `String` from a literal string with `String::from`:
+/// You can create a `String` from a literal string with [`String::from`]:
 ///
 /// ```
 /// let hello = String::from("Hello, world!");
@@ -98,6 +98,7 @@
 /// hello.push_str("orld!");
 /// ```
 ///
+/// [`String::from`]: #method.from
 /// [`char`]: ../../std/primitive.char.html
 /// [`push`]: #method.push
 /// [`push_str`]: #method.push_str
index 86309dd87de9bc690456221956e6885927e37188..8f3e71ef794465fb8a5b3e1c23d28faf5ffaf32c 100644 (file)
@@ -10,7 +10,6 @@
 
 #![deny(warnings)]
 
-#![feature(alloc)]
 #![feature(attr_literals)]
 #![feature(box_syntax)]
 #![feature(inclusive_range_syntax)]
 #![feature(splice)]
 #![feature(str_escape)]
 #![feature(string_retain)]
-#![feature(test)]
 #![feature(unboxed_closures)]
 #![feature(unicode)]
 
-extern crate alloc;
-extern crate test;
 extern crate std_unicode;
-extern crate core;
 
 use std::hash::{Hash, Hasher};
 use std::collections::hash_map::DefaultHasher;
index 3a9cc1dd5a6b88417d388ccd6467c65f4e108c1c..efefabc974c7fb0c068a422e487de10318daf86d 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![crate_name = "alloc_jemalloc"]
-#![crate_type = "rlib"]
 #![no_std]
 #![unstable(feature = "alloc_jemalloc",
             reason = "this library is unlikely to be stabilized in its current \
@@ -21,7 +19,7 @@
 #![feature(libc)]
 #![feature(linkage)]
 #![feature(staged_api)]
-#![cfg_attr(dummy_jemalloc, allow(dead_code))]
+#![cfg_attr(dummy_jemalloc, allow(dead_code, unused_extern_crates))]
 #![cfg_attr(not(dummy_jemalloc), feature(allocator_api))]
 
 extern crate alloc;
index 9a7cba21e3c78a8a192cc6ffe5f45493e766aae6..1defe308713a7772f64aa159f7c2d12b375155e7 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![crate_name = "alloc_system"]
-#![crate_type = "rlib"]
 #![no_std]
 #![deny(warnings)]
 #![unstable(feature = "alloc_system",
index 8e3b3f2074da953386ddfa2f7b789189c9942856..96fcc81e8e6edfaabaa78e99e73ec23bbebd00a1 100644 (file)
@@ -18,9 +18,6 @@
 //! This crate implements `TypedArena`, a simple arena that can only hold
 //! objects of a single type.
 
-#![crate_name = "arena"]
-#![crate_type = "rlib"]
-#![crate_type = "dylib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/",
index 38143593eb12bd3d3147e23b23abfa3420de3475..55316db3d5a4358f6582328f9951fa489e227113 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![crate_name = "collections"]
-#![crate_type = "rlib"]
 #![allow(unused_attributes)]
 #![unstable(feature = "collections",
             reason = "this library is unlikely to be stabilized in its current \
index dc0905e297251f86c5c6161ef69501ff6248aa23..e0a3b8d52f40efb5df9180a1b741928196675fed 100644 (file)
@@ -998,7 +998,7 @@ pub fn clone(orig: &Ref<'b, T>) -> Ref<'b, T> {
     /// A method would interfere with methods of the same name on the contents
     /// of a `RefCell` used through `Deref`.
     ///
-    /// # Example
+    /// # Examples
     ///
     /// ```
     /// use std::cell::{RefCell, Ref};
@@ -1040,7 +1040,7 @@ impl<'b, T: ?Sized> RefMut<'b, T> {
     /// `RefMut::map(...)`.  A method would interfere with methods of the same
     /// name on the contents of a `RefCell` used through `Deref`.
     ///
-    /// # Example
+    /// # Examples
     ///
     /// ```
     /// use std::cell::{RefCell, RefMut};
index 8125097d7d1056573e82d36c7297e36af77a2053..b594c886b64f5d35a80a9ccd79b3836954d0f63e 100644 (file)
@@ -58,7 +58,7 @@ fn write_str(&mut self, mut s: &str) -> fmt::Result {
 /// [`Formatter::debug_struct`](struct.Formatter.html#method.debug_struct)
 /// method.
 ///
-/// # Example
+/// # Examples
 ///
 /// ```
 /// use std::fmt;
@@ -153,7 +153,7 @@ fn is_pretty(&self) -> bool {
 /// [`Formatter::debug_tuple`](struct.Formatter.html#method.debug_tuple)
 /// method.
 ///
-/// # Example
+/// # Examples
 ///
 /// ```
 /// use std::fmt;
@@ -290,7 +290,7 @@ fn is_pretty(&self) -> bool {
 /// [`Formatter::debug_set`](struct.Formatter.html#method.debug_set)
 /// method.
 ///
-/// # Example
+/// # Examples
 ///
 /// ```
 /// use std::fmt;
@@ -361,7 +361,7 @@ pub fn finish(&mut self) -> fmt::Result {
 /// [`Formatter::debug_list`](struct.Formatter.html#method.debug_list)
 /// method.
 ///
-/// # Example
+/// # Examples
 ///
 /// ```
 /// use std::fmt;
@@ -432,7 +432,7 @@ pub fn finish(&mut self) -> fmt::Result {
 /// [`Formatter::debug_map`](struct.Formatter.html#method.debug_map)
 /// method.
 ///
-/// # Example
+/// # Examples
 ///
 /// ```
 /// use std::fmt;
index 546d2a21939ff3ea36c0e20a4b52a45889238929..c270c6ae0dbad23944db36f3d19ff8ecc2b885e2 100644 (file)
@@ -51,9 +51,7 @@
 // Since libcore defines many fundamental lang items, all tests live in a
 // separate crate, libcoretest, to avoid bizarre issues.
 
-#![crate_name = "core"]
 #![stable(feature = "core", since = "1.6.0")]
-#![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/",
index 6f7adbe1e7a0e9e67754ae9731582c4e209b4668..4b866cab1eae2f00b97e5d0af34240ec4fb21904 100644 (file)
@@ -901,7 +901,7 @@ pub fn into_inner(slot: ManuallyDrop<T>) -> T {
 
     /// Manually drops the contained value.
     ///
-    /// # Unsafety
+    /// # 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
index 0509936153c39c5d244ca0be69c8991eb1d2ceb9..31d8266510a1ea652cb400e407829307f90938b5 100644 (file)
@@ -212,6 +212,9 @@ unsafe fn get_unchecked_mut<I>(&mut self, index: I) -> &mut I::Output
     #[stable(feature = "copy_from_slice", since = "1.9.0")]
     fn copy_from_slice(&mut self, src: &[Self::Item]) where Self::Item: Copy;
 
+    #[unstable(feature = "swap_with_slice", issue = "44030")]
+    fn swap_with_slice(&mut self, src: &mut [Self::Item]);
+
     #[stable(feature = "sort_unstable", since = "1.20.0")]
     fn sort_unstable(&mut self)
         where Self::Item: Ord;
@@ -673,6 +676,16 @@ fn copy_from_slice(&mut self, src: &[T]) where T: Copy {
         }
     }
 
+    #[inline]
+    fn swap_with_slice(&mut self, src: &mut [T]) {
+        assert!(self.len() == src.len(),
+                "destination and source slices have different lengths");
+        unsafe {
+            ptr::swap_nonoverlapping(
+                self.as_mut_ptr(), src.as_mut_ptr(), self.len());
+        }
+    }
+
     #[inline]
     fn binary_search_by_key<'a, B, F, Q: ?Sized>(&'a self, b: &Q, mut f: F) -> Result<usize, usize>
         where F: FnMut(&'a Self::Item) -> B,
index 84a3be99c275f5ca2a01956c55172edddcb2579f..ab2022b1824ca3a2e5f5b682731d53c52abb5a14 100644 (file)
@@ -26,7 +26,6 @@
 #![feature(inclusive_range)]
 #![feature(inclusive_range_syntax)]
 #![feature(iter_rfind)]
-#![feature(libc)]
 #![feature(nonzero)]
 #![feature(ord_max_min)]
 #![feature(rand)]
 #![feature(test)]
 #![feature(trusted_len)]
 #![feature(try_from)]
-#![feature(unicode)]
 #![feature(unique)]
 
 extern crate core;
 extern crate test;
-extern crate libc;
-extern crate std_unicode;
 extern crate rand;
 
 mod any;
index 43345c6d0977b3e2d07675418fdb94bba4d4f295..24430b2e377f599529c02afdc1371349a73abf2d 100644 (file)
@@ -14,9 +14,6 @@
 //! Parsing does not happen at runtime: structures of `std::fmt::rt` are
 //! generated instead.
 
-#![crate_name = "fmt_macros"]
-#![crate_type = "rlib"]
-#![crate_type = "dylib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/",
index 83f2de54023158d9a954df22aba65103e413e988..a0eacc817ca817b516f578dd98bc69d2ce6668ac 100644 (file)
@@ -77,9 +77,6 @@
 //! }
 //! ```
 
-#![crate_name = "getopts"]
-#![crate_type = "rlib"]
-#![crate_type = "dylib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/",
index 4ee0c3d92bd2cc51eb0d7ac808c4864286d6271f..5b1cf2dee9a83db9abfe1ccabc6679754d9472e6 100644 (file)
 //!
 //! * [DOT language](http://www.graphviz.org/doc/info/lang.html)
 
-#![crate_name = "graphviz"]
-#![crate_type = "rlib"]
-#![crate_type = "dylib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/",
index 348180a48dc38323e6c33913f004922fa84fac2e..8be6f6470231dcb8e30f0cd68ea7d8923efb7cbb 100644 (file)
@@ -14,8 +14,6 @@
 //! simpler! That being said, it's not quite as versatile, but here goes!
 
 #![no_std]
-#![crate_name = "panic_abort"]
-#![crate_type = "rlib"]
 #![unstable(feature = "panic_abort", issue = "32837")]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
index 90f4b364482e6390f6cb552e6dfe00575339df1a..558286f4ec0707c1fb740cf499f65222afe6243c 100644 (file)
@@ -23,8 +23,6 @@
 //! module.
 
 #![no_std]
-#![crate_name = "panic_unwind"]
-#![crate_type = "rlib"]
 #![unstable(feature = "panic_unwind", issue = "32837")]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
@@ -36,7 +34,9 @@
 #![feature(core_intrinsics)]
 #![feature(lang_items)]
 #![feature(libc)]
-#![feature(panic_unwind)]
+#![cfg_attr(not(any(target_env = "msvc",
+                    all(windows, target_arch = "x86_64", target_env = "gnu"))),
+            feature(panic_unwind))]
 #![feature(raw)]
 #![feature(staged_api)]
 #![feature(unwind_attributes)]
@@ -47,6 +47,7 @@
 
 extern crate alloc;
 extern crate libc;
+#[cfg(not(any(target_env = "msvc", all(windows, target_arch = "x86_64", target_env = "gnu"))))]
 extern crate unwind;
 
 use core::intrinsics;
index 92386d6d060248a989dd51eee2d9c80a2ce607bc..3f425c24a9143479b72c3ed62ec4adb80f917a75 100644 (file)
 //!
 //! See [the book](../book/first-edition/procedural-macros.html) for more.
 
-#![crate_name = "proc_macro"]
 #![stable(feature = "proc_macro_lib", since = "1.15.0")]
-#![crate_type = "rlib"]
-#![crate_type = "dylib"]
 #![deny(warnings)]
 #![deny(missing_docs)]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
@@ -246,9 +243,9 @@ pub enum TokenNode {
 pub enum Delimiter {
     /// `( ... )`
     Parenthesis,
-    /// `[ ... ]`
-    Brace,
     /// `{ ... }`
+    Brace,
+    /// `[ ... ]`
     Bracket,
     /// An implicit delimiter, e.g. `$var`, where $var is  `...`.
     None,
index 1fb2c6b7dbb5d1919bd27da5a68edb04ad36a92e..6d0d6d115b7163528e3e0a54737ce114124ffe32 100644 (file)
@@ -14,7 +14,5 @@
 #![unstable(feature = "profiler_runtime_lib",
             reason = "internal implementation detail of rustc right now",
             issue = "0")]
-#![crate_name = "profiler_builtins"]
-#![crate_type = "rlib"]
 #![allow(unused_features)]
 #![feature(staged_api)]
index a3c4f6a4b1db11ed4f822463ee6ec1b2b0a4386f..90b3020fff9d1ebfa6a9bb2c1baef5220fd2db45 100644 (file)
@@ -16,8 +16,6 @@
 //! is not recommended to use this library directly, but rather the official
 //! interface through `std::rand`.
 
-#![crate_name = "rand"]
-#![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/",
index 9e5d40812311d992a35a47fec8087ecfdb5fd61d..01fff60528394366345e212528a0c04b4b43ed33 100644 (file)
@@ -522,6 +522,8 @@ pub fn to_dep_node(self, tcx: TyCtxt, kind: DepKind) -> DepNode {
     [] DylibDepFormats(DefId),
     [] IsAllocator(DefId),
     [] IsPanicRuntime(DefId),
+    [] IsCompilerBuiltins(DefId),
+    [] HasGlobalAllocator(DefId),
     [] ExternCrate(DefId),
     [] LintLevels,
 );
index 9aa634770df933ea8ae16f13cfd8644fb0f123a3..809d1dfcf60a2ff479798bc722197e958a312b99 100644 (file)
@@ -244,8 +244,8 @@ pub fn add_edge(&mut self, source: DepNode, target: DepNode) {
         self.edges.insert((source, target));
     }
 
-    pub fn add_node(&mut self, node: DepNode) {
-        self.get_or_create_node(node);
+    pub fn add_node(&mut self, node: DepNode) -> DepNodeIndex {
+        self.get_or_create_node(node)
     }
 
     #[inline]
index 4ca59132e0ad917d80e40723b45ec3e2ff086351..c487fc963ca14a46ae9f0b01eb8e2ded237247b2 100644 (file)
@@ -12,6 +12,7 @@
 use session::config::OutputType;
 use std::cell::{Ref, RefCell};
 use std::rc::Rc;
+use util::common::{ProfileQueriesMsg, profq_msg};
 
 use super::dep_node::{DepNode, DepKind, WorkProductId};
 use super::query::DepGraphQuery;
@@ -118,7 +119,13 @@ pub fn with_task<C, A, R>(&self,
     {
         if let Some(ref data) = self.data {
             data.edges.borrow_mut().push_task(key);
+            if cfg!(debug_assertions) {
+                profq_msg(ProfileQueriesMsg::TaskBegin(key.clone()))
+            };
             let result = task(cx, arg);
+            if cfg!(debug_assertions) {
+                profq_msg(ProfileQueriesMsg::TaskEnd)
+            };
             let dep_node_index = data.edges.borrow_mut().pop_task(key);
             (result, dep_node_index)
         } else {
@@ -166,6 +173,14 @@ pub fn add_node_directly(&self, node: DepNode) {
         self.data.as_ref().unwrap().edges.borrow_mut().add_node(node);
     }
 
+    pub fn alloc_input_node(&self, node: DepNode) -> DepNodeIndex {
+        if let Some(ref data) = self.data {
+            data.edges.borrow_mut().add_node(node)
+        } else {
+            DepNodeIndex::INVALID
+        }
+    }
+
     /// Indicates that a previous work product exists for `v`. This is
     /// invoked during initial start-up based on what nodes are clean
     /// (and what files exist in the incr. directory).
index 34d31028385cfa9b27b60ba95506e0ba815ab672..412759e11423e94ed22176988b06ba484b1833e7 100644 (file)
@@ -687,6 +687,21 @@ fn foo<T: MyTransmutableType>(x: Vec<T>) {
 See also https://doc.rust-lang.org/book/first-edition/no-stdlib.html
 "##,
 
+E0214: r##"
+A generic type was described using parentheses rather than angle brackets. For
+example:
+
+```compile_fail,E0214
+fn main() {
+    let v: Vec(&str) = vec!["foo"];
+}
+```
+
+This is not currently supported: `v` should be defined as `Vec<&str>`.
+Parentheses are currently only used with generic types when defining parameters
+for `Fn`-family traits.
+"##,
+
 E0261: r##"
 When using a lifetime like `'a` in a type, it must be declared before being
 used.
index 2a0c76d99bfbd9dc142a69f6d784ed603ae94018..d52cc26eaebc666afcc248d19048cde449e5cd40 100644 (file)
@@ -617,17 +617,9 @@ pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V,
 pub fn walk_path_parameters<'v, V: Visitor<'v>>(visitor: &mut V,
                                                 _path_span: Span,
                                                 path_parameters: &'v PathParameters) {
-    match *path_parameters {
-        AngleBracketedParameters(ref data) => {
-            walk_list!(visitor, visit_ty, &data.types);
-            walk_list!(visitor, visit_lifetime, &data.lifetimes);
-            walk_list!(visitor, visit_assoc_type_binding, &data.bindings);
-        }
-        ParenthesizedParameters(ref data) => {
-            walk_list!(visitor, visit_ty, &data.inputs);
-            walk_list!(visitor, visit_ty, &data.output);
-        }
-    }
+    walk_list!(visitor, visit_lifetime, &path_parameters.lifetimes);
+    walk_list!(visitor, visit_ty, &path_parameters.types);
+    walk_list!(visitor, visit_assoc_type_binding, &path_parameters.bindings);
 }
 
 pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(visitor: &mut V,
@@ -835,7 +827,16 @@ pub fn walk_trait_item_ref<'v, V: Visitor<'v>>(visitor: &mut V, trait_item_ref:
 
 pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplItem) {
     // NB: Deliberately force a compilation error if/when new fields are added.
-    let ImplItem { id: _, name, ref vis, ref defaultness, ref attrs, ref node, span } = *impl_item;
+    let ImplItem {
+        id: _,
+        hir_id: _,
+        name,
+        ref vis,
+        ref defaultness,
+        ref attrs,
+        ref node,
+        span
+    } = *impl_item;
 
     visitor.visit_name(span, name);
     visitor.visit_vis(vis);
index 58bb5b9580f51f2897a7c3bdc70c156a1438a016..ac26cbc833dea0b073028f493dec2fea43cc8195 100644 (file)
 use hir::map::definitions::DefPathData;
 use hir::def_id::{DefIndex, DefId, CRATE_DEF_INDEX};
 use hir::def::{Def, PathResolution};
+use lint::builtin::PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES;
 use rustc_data_structures::indexed_vec::IndexVec;
 use session::Session;
+use util::common::FN_OUTPUT_NAME;
 use util::nodemap::{DefIdMap, FxHashMap, NodeMap};
 
 use std::collections::BTreeMap;
 use std::fmt::Debug;
 use std::iter;
 use std::mem;
-
 use syntax::attr;
 use syntax::ast::*;
 use syntax::errors;
@@ -160,6 +161,12 @@ struct LoweredNodeId {
     hir_id: hir::HirId,
 }
 
+enum ParenthesizedGenericArgs {
+    Ok,
+    Warn,
+    Err,
+}
+
 impl<'a> LoweringContext<'a> {
     fn lower_crate(mut self, c: &Crate) -> hir::Crate {
         /// Full-crate AST visitor that inserts into a fresh
@@ -749,6 +756,21 @@ fn lower_qpath(&mut self,
                     Def::Trait(def_id) if i + 1 == proj_start => Some(def_id),
                     _ => None
                 };
+                let parenthesized_generic_args = match resolution.base_def() {
+                    // `a::b::Trait(Args)`
+                    Def::Trait(..) if i + 1 == proj_start => ParenthesizedGenericArgs::Ok,
+                    // `a::b::Trait(Args)::TraitItem`
+                    Def::Method(..) |
+                    Def::AssociatedConst(..) |
+                    Def::AssociatedTy(..) if i + 2 == proj_start => ParenthesizedGenericArgs::Ok,
+                    // Avoid duplicated errors
+                    Def::Err => ParenthesizedGenericArgs::Ok,
+                    // An error
+                    Def::Struct(..) | Def::Enum(..) | Def::Union(..) | Def::TyAlias(..) |
+                    Def::Variant(..) if i + 1 == proj_start => ParenthesizedGenericArgs::Err,
+                    // A warning for now, for compatibility reasons
+                    _ => ParenthesizedGenericArgs::Warn,
+                };
 
                 let num_lifetimes = type_def_id.map_or(0, |def_id| {
                     if let Some(&n) = self.type_def_lifetime_params.get(&def_id) {
@@ -759,7 +781,8 @@ fn lower_qpath(&mut self,
                     self.type_def_lifetime_params.insert(def_id, n);
                     n
                 });
-                self.lower_path_segment(p.span, segment, param_mode, num_lifetimes)
+                self.lower_path_segment(p.span, segment, param_mode, num_lifetimes,
+                                        parenthesized_generic_args)
             }).collect(),
             span: p.span,
         });
@@ -794,7 +817,8 @@ fn lower_qpath(&mut self,
         //   3. `<<std::vec::Vec<T>>::IntoIter>::Item`
         // * final path is `<<<std::vec::Vec<T>>::IntoIter>::Item>::clone`
         for (i, segment) in p.segments.iter().enumerate().skip(proj_start) {
-            let segment = P(self.lower_path_segment(p.span, segment, param_mode, 0));
+            let segment = P(self.lower_path_segment(p.span, segment, param_mode, 0,
+                                                    ParenthesizedGenericArgs::Warn));
             let qpath = hir::QPath::TypeRelative(ty, segment);
 
             // It's finished, return the extension of the right node type.
@@ -827,7 +851,8 @@ fn lower_path_extra(&mut self,
         hir::Path {
             def: self.expect_full_def(id),
             segments: segments.map(|segment| {
-                self.lower_path_segment(p.span, segment, param_mode, 0)
+                self.lower_path_segment(p.span, segment, param_mode, 0,
+                                        ParenthesizedGenericArgs::Err)
             }).chain(name.map(|name| {
                 hir::PathSegment {
                     name,
@@ -851,29 +876,37 @@ fn lower_path_segment(&mut self,
                           path_span: Span,
                           segment: &PathSegment,
                           param_mode: ParamMode,
-                          expected_lifetimes: usize)
+                          expected_lifetimes: usize,
+                          parenthesized_generic_args: ParenthesizedGenericArgs)
                           -> hir::PathSegment {
         let mut parameters = if let Some(ref parameters) = segment.parameters {
+            let msg = "parenthesized parameters may only be used with a trait";
             match **parameters {
                 PathParameters::AngleBracketed(ref data) => {
-                    let data = self.lower_angle_bracketed_parameter_data(data, param_mode);
-                    hir::AngleBracketedParameters(data)
+                    self.lower_angle_bracketed_parameter_data(data, param_mode)
                 }
-                PathParameters::Parenthesized(ref data) => {
-                    hir::ParenthesizedParameters(self.lower_parenthesized_parameter_data(data))
+                PathParameters::Parenthesized(ref data) => match parenthesized_generic_args {
+                    ParenthesizedGenericArgs::Ok => self.lower_parenthesized_parameter_data(data),
+                    ParenthesizedGenericArgs::Warn => {
+                        self.sess.buffer_lint(PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
+                                              CRATE_NODE_ID, data.span, msg.into());
+                        hir::PathParameters::none()
+                    }
+                    ParenthesizedGenericArgs::Err => {
+                        struct_span_err!(self.sess, data.span, E0214, "{}", msg)
+                            .span_label(data.span, "only traits may use parentheses").emit();
+                        hir::PathParameters::none()
+                    }
                 }
             }
         } else {
-            let data = self.lower_angle_bracketed_parameter_data(&Default::default(), param_mode);
-            hir::AngleBracketedParameters(data)
+            self.lower_angle_bracketed_parameter_data(&Default::default(), param_mode)
         };
 
-        if let hir::AngleBracketedParameters(ref mut data) = parameters {
-            if data.lifetimes.is_empty() {
-                data.lifetimes = (0..expected_lifetimes).map(|_| {
-                    self.elided_lifetime(path_span)
-                }).collect();
-            }
+        if !parameters.parenthesized && parameters.lifetimes.is_empty() {
+            parameters.lifetimes = (0..expected_lifetimes).map(|_| {
+                self.elided_lifetime(path_span)
+            }).collect();
         }
 
         hir::PathSegment {
@@ -885,24 +918,38 @@ fn lower_path_segment(&mut self,
     fn lower_angle_bracketed_parameter_data(&mut self,
                                             data: &AngleBracketedParameterData,
                                             param_mode: ParamMode)
-                                            -> hir::AngleBracketedParameterData {
+                                            -> hir::PathParameters {
         let &AngleBracketedParameterData { ref lifetimes, ref types, ref bindings, .. } = data;
-        hir::AngleBracketedParameterData {
+        hir::PathParameters {
             lifetimes: self.lower_lifetimes(lifetimes),
             types: types.iter().map(|ty| self.lower_ty(ty)).collect(),
             infer_types: types.is_empty() && param_mode == ParamMode::Optional,
             bindings: bindings.iter().map(|b| self.lower_ty_binding(b)).collect(),
+            parenthesized: false,
         }
     }
 
     fn lower_parenthesized_parameter_data(&mut self,
                                           data: &ParenthesizedParameterData)
-                                          -> hir::ParenthesizedParameterData {
+                                          -> hir::PathParameters {
         let &ParenthesizedParameterData { ref inputs, ref output, span } = data;
-        hir::ParenthesizedParameterData {
-            inputs: inputs.iter().map(|ty| self.lower_ty(ty)).collect(),
-            output: output.as_ref().map(|ty| self.lower_ty(ty)),
-            span,
+        let inputs = inputs.iter().map(|ty| self.lower_ty(ty)).collect();
+        let mk_tup = |this: &mut Self, tys, span| {
+            P(hir::Ty { node: hir::TyTup(tys), id: this.next_id().node_id, span })
+        };
+
+        hir::PathParameters {
+            lifetimes: hir::HirVec::new(),
+            types: hir_vec![mk_tup(self, inputs, span)],
+            infer_types: false,
+            bindings: hir_vec![hir::TypeBinding {
+                id: self.next_id().node_id,
+                name: Symbol::intern(FN_OUTPUT_NAME),
+                ty: output.as_ref().map(|ty| self.lower_ty(&ty))
+                                   .unwrap_or_else(|| mk_tup(self, hir::HirVec::new(), span)),
+                span: output.as_ref().map_or(span, |ty| ty.span),
+            }],
+            parenthesized: true,
         }
     }
 
@@ -1268,7 +1315,12 @@ fn lower_item_kind(&mut self,
                             path.span = span;
 
                             self.allocate_hir_id_counter(import.id, import);
-                            self.with_hir_id_owner(import.id, |this| {
+                            let LoweredNodeId {
+                                node_id: import_node_id,
+                                hir_id: import_hir_id,
+                            } = self.lower_node_id(import.id);
+
+                            self.with_hir_id_owner(import_node_id, |this| {
                                 let vis = match *vis {
                                     hir::Visibility::Public => hir::Visibility::Public,
                                     hir::Visibility::Crate => hir::Visibility::Crate,
@@ -1282,8 +1334,9 @@ fn lower_item_kind(&mut self,
                                     }
                                 };
 
-                                this.items.insert(import.id, hir::Item {
-                                    id: import.id,
+                                this.items.insert(import_node_id, hir::Item {
+                                    id: import_node_id,
+                                    hir_id: import_hir_id,
                                     name: import.rename.unwrap_or(ident).name,
                                     attrs: attrs.clone(),
                                     node: hir::ItemUse(P(path), hir::UseKind::Single),
@@ -1414,8 +1467,11 @@ fn lower_item_kind(&mut self,
 
     fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem {
         self.with_parent_def(i.id, |this| {
+            let LoweredNodeId { node_id, hir_id } = this.lower_node_id(i.id);
+
             hir::TraitItem {
-                id: this.lower_node_id(i.id).node_id,
+                id: node_id,
+                hir_id,
                 name: this.lower_ident(i.ident),
                 attrs: this.lower_attrs(&i.attrs),
                 node: match i.node {
@@ -1475,8 +1531,11 @@ fn lower_trait_item_ref(&mut self, i: &TraitItem) -> hir::TraitItemRef {
 
     fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem {
         self.with_parent_def(i.id, |this| {
+            let LoweredNodeId { node_id, hir_id } = this.lower_node_id(i.id);
+
             hir::ImplItem {
-                id: this.lower_node_id(i.id).node_id,
+                id: node_id,
+                hir_id,
                 name: this.lower_ident(i.ident),
                 attrs: this.lower_attrs(&i.attrs),
                 vis: this.lower_visibility(&i.vis, None),
@@ -1567,8 +1626,11 @@ pub fn lower_item(&mut self, i: &Item) -> Option<hir::Item> {
             this.lower_item_kind(i.id, &mut name, &attrs, &mut vis, &i.node)
         });
 
+        let LoweredNodeId { node_id, hir_id } = self.lower_node_id(i.id);
+
         Some(hir::Item {
-            id: self.lower_node_id(i.id).node_id,
+            id: node_id,
+            hir_id,
             name,
             attrs,
             node,
@@ -1877,7 +1939,8 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                 hir::ExprCall(f, args.iter().map(|x| self.lower_expr(x)).collect())
             }
             ExprKind::MethodCall(ref seg, ref args) => {
-                let hir_seg = self.lower_path_segment(e.span, seg, ParamMode::Optional, 0);
+                let hir_seg = self.lower_path_segment(e.span, seg, ParamMode::Optional, 0,
+                                                      ParenthesizedGenericArgs::Err);
                 let args = args.iter().map(|x| self.lower_expr(x)).collect();
                 hir::ExprMethodCall(hir_seg, seg.span, args)
             }
index 0928081decda0aefcb1b6f4d196690bdf9b365ce..a54068c648310ffbda503d9ba5f8c1925a0e6a7c 100644 (file)
 
 use super::*;
 
+use dep_graph::{DepGraph, DepKind, DepNodeIndex};
 use hir::intravisit::{Visitor, NestedVisitorMap};
 use std::iter::repeat;
 use syntax::ast::{NodeId, CRATE_NODE_ID};
 use syntax_pos::Span;
 
 /// A Visitor that walks over the HIR and collects Nodes into a HIR map
-pub struct NodeCollector<'hir> {
+pub(super) struct NodeCollector<'a, 'hir> {
     /// The crate
-    pub krate: &'hir Crate,
+    krate: &'hir Crate,
     /// The node map
-    pub(super) map: Vec<MapEntry<'hir>>,
+    map: Vec<MapEntry<'hir>>,
     /// The parent of this node
-    pub parent_node: NodeId,
+    parent_node: NodeId,
+
+    current_dep_node_owner: DefIndex,
+    current_dep_node_index: DepNodeIndex,
+
+    dep_graph: &'a DepGraph,
+    definitions: &'a definitions::Definitions,
 }
 
-impl<'hir> NodeCollector<'hir> {
-    pub fn root(krate: &'hir Crate) -> NodeCollector<'hir> {
+impl<'a, 'hir> NodeCollector<'a, 'hir> {
+    pub(super) fn root(krate: &'hir Crate,
+                dep_graph: &'a DepGraph,
+                definitions: &'a definitions::Definitions)
+                -> NodeCollector<'a, 'hir> {
+        let root_mod_def_path_hash = definitions.def_path_hash(CRATE_DEF_INDEX);
+        let root_mod_dep_node = root_mod_def_path_hash.to_dep_node(DepKind::Hir);
+        let root_mod_dep_node_index = dep_graph.alloc_input_node(root_mod_dep_node);
+
         let mut collector = NodeCollector {
             krate,
             map: vec![],
             parent_node: CRATE_NODE_ID,
+            current_dep_node_index: root_mod_dep_node_index,
+            current_dep_node_owner: CRATE_DEF_INDEX,
+            dep_graph,
+            definitions,
         };
-        collector.insert_entry(CRATE_NODE_ID, RootCrate);
+        collector.insert_entry(CRATE_NODE_ID, RootCrate(root_mod_dep_node_index));
 
         collector
     }
 
+    pub(super) fn into_map(self) -> Vec<MapEntry<'hir>> {
+        self.map
+    }
+
     fn insert_entry(&mut self, id: NodeId, entry: MapEntry<'hir>) {
         debug!("hir_map: {:?} => {:?}", id, entry);
         let len = self.map.len();
@@ -47,8 +69,55 @@ fn insert_entry(&mut self, id: NodeId, entry: MapEntry<'hir>) {
     }
 
     fn insert(&mut self, id: NodeId, node: Node<'hir>) {
-        let entry = MapEntry::from_node(self.parent_node, node);
+        let parent = self.parent_node;
+        let dep_node_index = self.current_dep_node_index;
+
+        let entry = match node {
+            NodeItem(n) => EntryItem(parent, dep_node_index, n),
+            NodeForeignItem(n) => EntryForeignItem(parent, dep_node_index, n),
+            NodeTraitItem(n) => EntryTraitItem(parent, dep_node_index, n),
+            NodeImplItem(n) => EntryImplItem(parent, dep_node_index, n),
+            NodeVariant(n) => EntryVariant(parent, dep_node_index, n),
+            NodeField(n) => EntryField(parent, dep_node_index, n),
+            NodeExpr(n) => EntryExpr(parent, dep_node_index, n),
+            NodeStmt(n) => EntryStmt(parent, dep_node_index, n),
+            NodeTy(n) => EntryTy(parent, dep_node_index, n),
+            NodeTraitRef(n) => EntryTraitRef(parent, dep_node_index, n),
+            NodeBinding(n) => EntryBinding(parent, dep_node_index, n),
+            NodePat(n) => EntryPat(parent, dep_node_index, n),
+            NodeBlock(n) => EntryBlock(parent, dep_node_index, n),
+            NodeStructCtor(n) => EntryStructCtor(parent, dep_node_index, n),
+            NodeLifetime(n) => EntryLifetime(parent, dep_node_index, n),
+            NodeTyParam(n) => EntryTyParam(parent, dep_node_index, n),
+            NodeVisibility(n) => EntryVisibility(parent, dep_node_index, n),
+            NodeLocal(n) => EntryLocal(parent, dep_node_index, n),
+        };
+
+        // Make sure that the DepNode of some node coincides with the HirId
+        // owner of that node.
+        if cfg!(debug_assertions) {
+            let hir_id_owner = self.definitions.node_to_hir_id(id).owner;
+
+            if hir_id_owner != self.current_dep_node_owner {
+                let node_str = match self.definitions.opt_def_index(id) {
+                    Some(def_index) => {
+                        self.definitions.def_path(def_index).to_string_no_crate()
+                    }
+                    None => format!("{:?}", node)
+                };
+
+                bug!("inconsistent DepNode for `{}`: \
+                      current_dep_node_owner={}, hir_id.owner={}",
+                    node_str,
+                    self.definitions
+                        .def_path(self.current_dep_node_owner)
+                        .to_string_no_crate(),
+                    self.definitions.def_path(hir_id_owner).to_string_no_crate())
+            }
+        }
+
         self.insert_entry(id, entry);
+
     }
 
     fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_id: NodeId, f: F) {
@@ -57,9 +126,27 @@ fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_id: NodeId, f: F) {
         f(self);
         self.parent_node = parent_node;
     }
+
+    fn with_dep_node_owner<F: FnOnce(&mut Self)>(&mut self,
+                                                 dep_node_owner: DefIndex,
+                                                 f: F) {
+        let prev_owner = self.current_dep_node_owner;
+        let prev_index = self.current_dep_node_index;
+
+        // When we enter a new owner (item, impl item, or trait item), we always
+        // start out again with DepKind::Hir.
+        let new_dep_node = self.definitions
+                               .def_path_hash(dep_node_owner)
+                               .to_dep_node(DepKind::Hir);
+        self.current_dep_node_index = self.dep_graph.alloc_input_node(new_dep_node);
+        self.current_dep_node_owner = dep_node_owner;
+        f(self);
+        self.current_dep_node_index = prev_index;
+        self.current_dep_node_owner = prev_owner;
+    }
 }
 
-impl<'hir> Visitor<'hir> for NodeCollector<'hir> {
+impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
     /// Because we want to track parent items and so forth, enable
     /// deep walking so that we walk nested items in the context of
     /// their outer items.
@@ -82,25 +169,37 @@ fn visit_nested_impl_item(&mut self, item_id: ImplItemId) {
     }
 
     fn visit_nested_body(&mut self, id: BodyId) {
+        // When we enter a body, we switch to DepKind::HirBody.
+        // Note that current_dep_node_index might already be DepKind::HirBody,
+        // e.g. when entering the body of a closure that is already part of a
+        // surrounding body. That's expected and not a problem.
+        let prev_index = self.current_dep_node_index;
+        let new_dep_node = self.definitions
+                               .def_path_hash(self.current_dep_node_owner)
+                               .to_dep_node(DepKind::HirBody);
+        self.current_dep_node_index = self.dep_graph.alloc_input_node(new_dep_node);
         self.visit_body(self.krate.body(id));
+        self.current_dep_node_index = prev_index;
     }
 
     fn visit_item(&mut self, i: &'hir Item) {
         debug!("visit_item: {:?}", i);
-
-        self.insert(i.id, NodeItem(i));
-
-        self.with_parent(i.id, |this| {
-            match i.node {
-                ItemStruct(ref struct_def, _) => {
-                    // If this is a tuple-like struct, register the constructor.
-                    if !struct_def.is_struct() {
-                        this.insert(struct_def.id(), NodeStructCtor(struct_def));
+        debug_assert_eq!(i.hir_id.owner,
+                         self.definitions.opt_def_index(i.id).unwrap());
+        self.with_dep_node_owner(i.hir_id.owner, |this| {
+            this.insert(i.id, NodeItem(i));
+            this.with_parent(i.id, |this| {
+                match i.node {
+                    ItemStruct(ref struct_def, _) => {
+                        // If this is a tuple-like struct, register the constructor.
+                        if !struct_def.is_struct() {
+                            this.insert(struct_def.id(), NodeStructCtor(struct_def));
+                        }
                     }
+                    _ => {}
                 }
-                _ => {}
-            }
-            intravisit::walk_item(this, i);
+                intravisit::walk_item(this, i);
+            });
         });
     }
 
@@ -121,18 +220,26 @@ fn visit_generics(&mut self, generics: &'hir Generics) {
     }
 
     fn visit_trait_item(&mut self, ti: &'hir TraitItem) {
-        self.insert(ti.id, NodeTraitItem(ti));
-
-        self.with_parent(ti.id, |this| {
-            intravisit::walk_trait_item(this, ti);
+        debug_assert_eq!(ti.hir_id.owner,
+                         self.definitions.opt_def_index(ti.id).unwrap());
+        self.with_dep_node_owner(ti.hir_id.owner, |this| {
+            this.insert(ti.id, NodeTraitItem(ti));
+
+            this.with_parent(ti.id, |this| {
+                intravisit::walk_trait_item(this, ti);
+            });
         });
     }
 
     fn visit_impl_item(&mut self, ii: &'hir ImplItem) {
-        self.insert(ii.id, NodeImplItem(ii));
-
-        self.with_parent(ii.id, |this| {
-            intravisit::walk_impl_item(this, ii);
+        debug_assert_eq!(ii.hir_id.owner,
+                         self.definitions.opt_def_index(ii.id).unwrap());
+        self.with_dep_node_owner(ii.hir_id.owner, |this| {
+            this.insert(ii.id, NodeImplItem(ii));
+
+            this.with_parent(ii.id, |this| {
+                intravisit::walk_impl_item(this, ii);
+            });
         });
     }
 
@@ -238,4 +345,33 @@ fn visit_struct_field(&mut self, field: &'hir StructField) {
             intravisit::walk_struct_field(this, field);
         });
     }
+
+    fn visit_trait_item_ref(&mut self, ii: &'hir TraitItemRef) {
+        // Do not visit the duplicate information in TraitItemRef. We want to
+        // map the actual nodes, not the duplicate ones in the *Ref.
+        let TraitItemRef {
+            id,
+            name: _,
+            kind: _,
+            span: _,
+            defaultness: _,
+        } = *ii;
+
+        self.visit_nested_trait_item(id);
+    }
+
+    fn visit_impl_item_ref(&mut self, ii: &'hir ImplItemRef) {
+        // Do not visit the duplicate information in ImplItemRef. We want to
+        // map the actual nodes, not the duplicate ones in the *Ref.
+        let ImplItemRef {
+            id,
+            name: _,
+            kind: _,
+            span: _,
+            vis: _,
+            defaultness: _,
+        } = *ii;
+
+        self.visit_nested_impl_item(id);
+    }
 }
index 1ff3166110aa0a31a079b224c5797f15c66567e9..63a5b70cb81a9f2ba60ad756d7987f00df16717d 100644 (file)
@@ -15,7 +15,7 @@
 pub use self::definitions::{Definitions, DefKey, DefPath, DefPathData,
                             DisambiguatedDefPathData, DefPathHash};
 
-use dep_graph::{DepGraph, DepNode, DepKind};
+use dep_graph::{DepGraph, DepNode, DepKind, DepNodeIndex};
 
 use hir::def_id::{CRATE_DEF_INDEX, DefId, DefIndexAddressSpace};
 
@@ -74,27 +74,28 @@ enum MapEntry<'hir> {
     NotPresent,
 
     /// All the node types, with a parent ID.
-    EntryItem(NodeId, &'hir Item),
-    EntryForeignItem(NodeId, &'hir ForeignItem),
-    EntryTraitItem(NodeId, &'hir TraitItem),
-    EntryImplItem(NodeId, &'hir ImplItem),
-    EntryVariant(NodeId, &'hir Variant),
-    EntryField(NodeId, &'hir StructField),
-    EntryExpr(NodeId, &'hir Expr),
-    EntryStmt(NodeId, &'hir Stmt),
-    EntryTy(NodeId, &'hir Ty),
-    EntryTraitRef(NodeId, &'hir TraitRef),
-    EntryBinding(NodeId, &'hir Pat),
-    EntryPat(NodeId, &'hir Pat),
-    EntryBlock(NodeId, &'hir Block),
-    EntryStructCtor(NodeId, &'hir VariantData),
-    EntryLifetime(NodeId, &'hir Lifetime),
-    EntryTyParam(NodeId, &'hir TyParam),
-    EntryVisibility(NodeId, &'hir Visibility),
-    EntryLocal(NodeId, &'hir Local),
-
-    /// Roots for node trees.
-    RootCrate,
+    EntryItem(NodeId, DepNodeIndex, &'hir Item),
+    EntryForeignItem(NodeId, DepNodeIndex, &'hir ForeignItem),
+    EntryTraitItem(NodeId, DepNodeIndex, &'hir TraitItem),
+    EntryImplItem(NodeId, DepNodeIndex, &'hir ImplItem),
+    EntryVariant(NodeId, DepNodeIndex, &'hir Variant),
+    EntryField(NodeId, DepNodeIndex, &'hir StructField),
+    EntryExpr(NodeId, DepNodeIndex, &'hir Expr),
+    EntryStmt(NodeId, DepNodeIndex, &'hir Stmt),
+    EntryTy(NodeId, DepNodeIndex, &'hir Ty),
+    EntryTraitRef(NodeId, DepNodeIndex, &'hir TraitRef),
+    EntryBinding(NodeId, DepNodeIndex, &'hir Pat),
+    EntryPat(NodeId, DepNodeIndex, &'hir Pat),
+    EntryBlock(NodeId, DepNodeIndex, &'hir Block),
+    EntryStructCtor(NodeId, DepNodeIndex, &'hir VariantData),
+    EntryLifetime(NodeId, DepNodeIndex, &'hir Lifetime),
+    EntryTyParam(NodeId, DepNodeIndex, &'hir TyParam),
+    EntryVisibility(NodeId, DepNodeIndex, &'hir Visibility),
+    EntryLocal(NodeId, DepNodeIndex, &'hir Local),
+
+    /// Roots for node trees. The DepNodeIndex is the dependency node of the
+    /// crate's root module.
+    RootCrate(DepNodeIndex),
 }
 
 impl<'hir> Clone for MapEntry<'hir> {
@@ -104,82 +105,59 @@ fn clone(&self) -> MapEntry<'hir> {
 }
 
 impl<'hir> MapEntry<'hir> {
-    fn from_node(p: NodeId, node: Node<'hir>) -> MapEntry<'hir> {
-        match node {
-            NodeItem(n) => EntryItem(p, n),
-            NodeForeignItem(n) => EntryForeignItem(p, n),
-            NodeTraitItem(n) => EntryTraitItem(p, n),
-            NodeImplItem(n) => EntryImplItem(p, n),
-            NodeVariant(n) => EntryVariant(p, n),
-            NodeField(n) => EntryField(p, n),
-            NodeExpr(n) => EntryExpr(p, n),
-            NodeStmt(n) => EntryStmt(p, n),
-            NodeTy(n) => EntryTy(p, n),
-            NodeTraitRef(n) => EntryTraitRef(p, n),
-            NodeBinding(n) => EntryBinding(p, n),
-            NodePat(n) => EntryPat(p, n),
-            NodeBlock(n) => EntryBlock(p, n),
-            NodeStructCtor(n) => EntryStructCtor(p, n),
-            NodeLifetime(n) => EntryLifetime(p, n),
-            NodeTyParam(n) => EntryTyParam(p, n),
-            NodeVisibility(n) => EntryVisibility(p, n),
-            NodeLocal(n) => EntryLocal(p, n),
-        }
-    }
-
     fn parent_node(self) -> Option<NodeId> {
         Some(match self {
-            EntryItem(id, _) => id,
-            EntryForeignItem(id, _) => id,
-            EntryTraitItem(id, _) => id,
-            EntryImplItem(id, _) => id,
-            EntryVariant(id, _) => id,
-            EntryField(id, _) => id,
-            EntryExpr(id, _) => id,
-            EntryStmt(id, _) => id,
-            EntryTy(id, _) => id,
-            EntryTraitRef(id, _) => id,
-            EntryBinding(id, _) => id,
-            EntryPat(id, _) => id,
-            EntryBlock(id, _) => id,
-            EntryStructCtor(id, _) => id,
-            EntryLifetime(id, _) => id,
-            EntryTyParam(id, _) => id,
-            EntryVisibility(id, _) => id,
-            EntryLocal(id, _) => id,
+            EntryItem(id, _, _) => id,
+            EntryForeignItem(id, _, _) => id,
+            EntryTraitItem(id, _, _) => id,
+            EntryImplItem(id, _, _) => id,
+            EntryVariant(id, _, _) => id,
+            EntryField(id, _, _) => id,
+            EntryExpr(id, _, _) => id,
+            EntryStmt(id, _, _) => id,
+            EntryTy(id, _, _) => id,
+            EntryTraitRef(id, _, _) => id,
+            EntryBinding(id, _, _) => id,
+            EntryPat(id, _, _) => id,
+            EntryBlock(id, _, _) => id,
+            EntryStructCtor(id, _, _) => id,
+            EntryLifetime(id, _, _) => id,
+            EntryTyParam(id, _, _) => id,
+            EntryVisibility(id, _, _) => id,
+            EntryLocal(id, _, _) => id,
 
             NotPresent |
-            RootCrate => return None,
+            RootCrate(_) => return None,
         })
     }
 
     fn to_node(self) -> Option<Node<'hir>> {
         Some(match self {
-            EntryItem(_, n) => NodeItem(n),
-            EntryForeignItem(_, n) => NodeForeignItem(n),
-            EntryTraitItem(_, n) => NodeTraitItem(n),
-            EntryImplItem(_, n) => NodeImplItem(n),
-            EntryVariant(_, n) => NodeVariant(n),
-            EntryField(_, n) => NodeField(n),
-            EntryExpr(_, n) => NodeExpr(n),
-            EntryStmt(_, n) => NodeStmt(n),
-            EntryTy(_, n) => NodeTy(n),
-            EntryTraitRef(_, n) => NodeTraitRef(n),
-            EntryBinding(_, n) => NodeBinding(n),
-            EntryPat(_, n) => NodePat(n),
-            EntryBlock(_, n) => NodeBlock(n),
-            EntryStructCtor(_, n) => NodeStructCtor(n),
-            EntryLifetime(_, n) => NodeLifetime(n),
-            EntryTyParam(_, n) => NodeTyParam(n),
-            EntryVisibility(_, n) => NodeVisibility(n),
-            EntryLocal(_, n) => NodeLocal(n),
+            EntryItem(_, _, n) => NodeItem(n),
+            EntryForeignItem(_, _, n) => NodeForeignItem(n),
+            EntryTraitItem(_, _, n) => NodeTraitItem(n),
+            EntryImplItem(_, _, n) => NodeImplItem(n),
+            EntryVariant(_, _, n) => NodeVariant(n),
+            EntryField(_, _, n) => NodeField(n),
+            EntryExpr(_, _, n) => NodeExpr(n),
+            EntryStmt(_, _, n) => NodeStmt(n),
+            EntryTy(_, _, n) => NodeTy(n),
+            EntryTraitRef(_, _, n) => NodeTraitRef(n),
+            EntryBinding(_, _, n) => NodeBinding(n),
+            EntryPat(_, _, n) => NodePat(n),
+            EntryBlock(_, _, n) => NodeBlock(n),
+            EntryStructCtor(_, _, n) => NodeStructCtor(n),
+            EntryLifetime(_, _, n) => NodeLifetime(n),
+            EntryTyParam(_, _, n) => NodeTyParam(n),
+            EntryVisibility(_, _, n) => NodeVisibility(n),
+            EntryLocal(_, _, n) => NodeLocal(n),
             _ => return None
         })
     }
 
     fn associated_body(self) -> Option<BodyId> {
         match self {
-            EntryItem(_, item) => {
+            EntryItem(_, _, item) => {
                 match item.node {
                     ItemConst(_, body) |
                     ItemStatic(.., body) |
@@ -188,7 +166,7 @@ fn associated_body(self) -> Option<BodyId> {
                 }
             }
 
-            EntryTraitItem(_, item) => {
+            EntryTraitItem(_, _, item) => {
                 match item.node {
                     TraitItemKind::Const(_, Some(body)) |
                     TraitItemKind::Method(_, TraitMethod::Provided(body)) => Some(body),
@@ -196,7 +174,7 @@ fn associated_body(self) -> Option<BodyId> {
                 }
             }
 
-            EntryImplItem(_, item) => {
+            EntryImplItem(_, _, item) => {
                 match item.node {
                     ImplItemKind::Const(_, body) |
                     ImplItemKind::Method(_, body) => Some(body),
@@ -204,7 +182,7 @@ fn associated_body(self) -> Option<BodyId> {
                 }
             }
 
-            EntryExpr(_, expr) => {
+            EntryExpr(_, _, expr) => {
                 match expr.node {
                     ExprClosure(.., body, _) => Some(body),
                     _ => None,
@@ -282,83 +260,40 @@ impl<'hir> Map<'hir> {
     /// read recorded). If the function just returns a DefId or
     /// NodeId, no actual content was returned, so no read is needed.
     pub fn read(&self, id: NodeId) {
-        self.dep_graph.read(self.dep_node(id));
-    }
-
-    fn dep_node(&self, id0: NodeId) -> DepNode {
-        let mut id = id0;
-        let mut last_expr = None;
-        loop {
-            let entry = self.map[id.as_usize()];
-            match entry {
-                EntryItem(..) |
-                EntryTraitItem(..) |
-                EntryImplItem(..) => {
-                    let def_index = self.definitions.opt_def_index(id).unwrap();
+        let entry = self.map[id.as_usize()];
+        match entry {
+            EntryItem(_, dep_node_index, _) |
+            EntryTraitItem(_, dep_node_index, _) |
+            EntryImplItem(_, dep_node_index, _) |
+            EntryVariant(_, dep_node_index, _) |
+            EntryForeignItem(_, dep_node_index, _) |
+            EntryField(_, dep_node_index, _) |
+            EntryStmt(_, dep_node_index, _) |
+            EntryTy(_, dep_node_index, _) |
+            EntryTraitRef(_, dep_node_index, _) |
+            EntryBinding(_, dep_node_index, _) |
+            EntryPat(_, dep_node_index, _) |
+            EntryBlock(_, dep_node_index, _) |
+            EntryStructCtor(_, dep_node_index, _) |
+            EntryLifetime(_, dep_node_index, _) |
+            EntryTyParam(_, dep_node_index, _) |
+            EntryVisibility(_, dep_node_index, _) |
+            EntryExpr(_, dep_node_index, _) |
+            EntryLocal(_, dep_node_index, _) |
+            RootCrate(dep_node_index) => {
+                self.dep_graph.read_index(dep_node_index);
+            }
+            NotPresent => {
+                // Some nodes, notably macro definitions, are not
+                // present in the map for whatever reason, but
+                // they *do* have def-ids. So if we encounter an
+                // empty hole, check for that case.
+                if let Some(def_index) = self.definitions.opt_def_index(id) {
                     let def_path_hash = self.definitions.def_path_hash(def_index);
-
-                    if let Some(last_id) = last_expr {
-                        // The body may have a separate dep node
-                        if entry.is_body_owner(last_id) {
-                            return def_path_hash.to_dep_node(DepKind::HirBody);
-                        }
-                    }
-                    return def_path_hash.to_dep_node(DepKind::Hir);
-                }
-
-                EntryVariant(p, v) => {
-                    id = p;
-
-                    if last_expr.is_some() {
-                        if v.node.disr_expr.map(|e| e.node_id) == last_expr {
-                            // The enum parent holds both Hir and HirBody nodes.
-                            let def_index = self.definitions.opt_def_index(id).unwrap();
-                            let def_path_hash = self.definitions.def_path_hash(def_index);
-                            return def_path_hash.to_dep_node(DepKind::HirBody);
-                        }
-                    }
-                }
-
-                EntryForeignItem(p, _) |
-                EntryField(p, _) |
-                EntryStmt(p, _) |
-                EntryTy(p, _) |
-                EntryTraitRef(p, _) |
-                EntryBinding(p, _) |
-                EntryPat(p, _) |
-                EntryBlock(p, _) |
-                EntryStructCtor(p, _) |
-                EntryLifetime(p, _) |
-                EntryTyParam(p, _) |
-                EntryVisibility(p, _) |
-                EntryLocal(p, _) =>
-                    id = p,
-
-                EntryExpr(p, _) => {
-                    last_expr = Some(id);
-                    id = p;
-                }
-
-                RootCrate => {
-                    let def_path_hash = self.definitions.def_path_hash(CRATE_DEF_INDEX);
-                    return def_path_hash.to_dep_node(DepKind::Hir);
+                    self.dep_graph.read(def_path_hash.to_dep_node(DepKind::Hir));
+                } else {
+                    bug!("called HirMap::read() with invalid NodeId")
                 }
-
-                NotPresent =>
-                    // Some nodes, notably macro definitions, are not
-                    // present in the map for whatever reason, but
-                    // they *do* have def-ids. So if we encounter an
-                    // empty hole, check for that case.
-                    return self.definitions.opt_def_index(id)
-                               .map(|def_index| {
-                                    let def_path_hash = self.definitions.def_path_hash(def_index);
-                                    def_path_hash.to_dep_node(DepKind::Hir)
-                                })
-                               .unwrap_or_else(|| {
-                                   bug!("Walking parents from `{}` \
-                                         led to `NotPresent` at `{}`",
-                                        id0, id)
-                               }),
             }
         }
     }
@@ -481,7 +416,7 @@ pub fn maybe_body_owned_by(&self, id: NodeId) -> Option<BodyId> {
                 Some(body_id)
             } else {
                 // For some expressions, the expression is its own body.
-                if let EntryExpr(_, expr) = entry {
+                if let EntryExpr(_, _, expr) = entry {
                     Some(BodyId { node_id: expr.id })
                 } else {
                     None
@@ -760,7 +695,7 @@ pub fn get_parent_did(&self, id: NodeId) -> DefId {
     pub fn get_foreign_abi(&self, id: NodeId) -> Abi {
         let parent = self.get_parent(id);
         let abi = match self.find_entry(parent) {
-            Some(EntryItem(_, i)) => {
+            Some(EntryItem(_, _, i)) => {
                 match i.node {
                     ItemForeignMod(ref nm) => Some(nm.abi),
                     _ => None
@@ -911,27 +846,27 @@ pub fn nodes_matching_suffix<'a>(&'a self, parts: &'a [String])
     pub fn span(&self, id: NodeId) -> Span {
         self.read(id); // reveals span from node
         match self.find_entry(id) {
-            Some(EntryItem(_, item)) => item.span,
-            Some(EntryForeignItem(_, foreign_item)) => foreign_item.span,
-            Some(EntryTraitItem(_, trait_method)) => trait_method.span,
-            Some(EntryImplItem(_, impl_item)) => impl_item.span,
-            Some(EntryVariant(_, variant)) => variant.span,
-            Some(EntryField(_, field)) => field.span,
-            Some(EntryExpr(_, expr)) => expr.span,
-            Some(EntryStmt(_, stmt)) => stmt.span,
-            Some(EntryTy(_, ty)) => ty.span,
-            Some(EntryTraitRef(_, tr)) => tr.path.span,
-            Some(EntryBinding(_, pat)) => pat.span,
-            Some(EntryPat(_, pat)) => pat.span,
-            Some(EntryBlock(_, block)) => block.span,
-            Some(EntryStructCtor(_, _)) => self.expect_item(self.get_parent(id)).span,
-            Some(EntryLifetime(_, lifetime)) => lifetime.span,
-            Some(EntryTyParam(_, ty_param)) => ty_param.span,
-            Some(EntryVisibility(_, &Visibility::Restricted { ref path, .. })) => path.span,
-            Some(EntryVisibility(_, v)) => bug!("unexpected Visibility {:?}", v),
-            Some(EntryLocal(_, local)) => local.span,
-
-            Some(RootCrate) => self.forest.krate.span,
+            Some(EntryItem(_, _, item)) => item.span,
+            Some(EntryForeignItem(_, _, foreign_item)) => foreign_item.span,
+            Some(EntryTraitItem(_, _, trait_method)) => trait_method.span,
+            Some(EntryImplItem(_, _, impl_item)) => impl_item.span,
+            Some(EntryVariant(_, _, variant)) => variant.span,
+            Some(EntryField(_, _, field)) => field.span,
+            Some(EntryExpr(_, _, expr)) => expr.span,
+            Some(EntryStmt(_, _, stmt)) => stmt.span,
+            Some(EntryTy(_, _, ty)) => ty.span,
+            Some(EntryTraitRef(_, _, tr)) => tr.path.span,
+            Some(EntryBinding(_, _, pat)) => pat.span,
+            Some(EntryPat(_, _, pat)) => pat.span,
+            Some(EntryBlock(_, _, block)) => block.span,
+            Some(EntryStructCtor(_, _, _)) => self.expect_item(self.get_parent(id)).span,
+            Some(EntryLifetime(_, _, lifetime)) => lifetime.span,
+            Some(EntryTyParam(_, _, ty_param)) => ty_param.span,
+            Some(EntryVisibility(_, _, &Visibility::Restricted { ref path, .. })) => path.span,
+            Some(EntryVisibility(_, _, v)) => bug!("unexpected Visibility {:?}", v),
+            Some(EntryLocal(_, _, local)) => local.span,
+
+            Some(RootCrate(_)) => self.forest.krate.span,
             Some(NotPresent) | None => {
                 bug!("hir::map::Map::span: id not in map: {:?}", id)
             }
@@ -1029,12 +964,12 @@ fn next(&mut self) -> Option<NodeId> {
             }
             self.idx = NodeId::from_u32(self.idx.as_u32() + 1);
             let name = match self.map.find_entry(idx) {
-                Some(EntryItem(_, n))       => n.name(),
-                Some(EntryForeignItem(_, n))=> n.name(),
-                Some(EntryTraitItem(_, n))  => n.name(),
-                Some(EntryImplItem(_, n))   => n.name(),
-                Some(EntryVariant(_, n))    => n.name(),
-                Some(EntryField(_, n))      => n.name(),
+                Some(EntryItem(_, _, n))       => n.name(),
+                Some(EntryForeignItem(_, _, n))=> n.name(),
+                Some(EntryTraitItem(_, _, n))  => n.name(),
+                Some(EntryImplItem(_, _, n))   => n.name(),
+                Some(EntryVariant(_, _, n))    => n.name(),
+                Some(EntryField(_, _, n))      => n.name(),
                 _ => continue,
             };
             if self.matches_names(self.map.get_parent(idx), name) {
@@ -1060,9 +995,13 @@ impl Named for ImplItem { fn name(&self) -> Name { self.name } }
 pub fn map_crate<'hir>(forest: &'hir mut Forest,
                        definitions: Definitions)
                        -> Map<'hir> {
-    let mut collector = NodeCollector::root(&forest.krate);
-    intravisit::walk_crate(&mut collector, &forest.krate);
-    let map = collector.map;
+    let map = {
+        let mut collector = NodeCollector::root(&forest.krate,
+                                                &forest.dep_graph,
+                                                &definitions);
+        intravisit::walk_crate(&mut collector, &forest.krate);
+        collector.into_map()
+    };
 
     if log_enabled!(::log::LogLevel::Debug) {
         // This only makes sense for ordered stores; note the
index 400f46d66f8681d0e8169e046c2f98564022d8b6..df67f8416212c413deb77a94c14d7a25805cb6e9 100644 (file)
@@ -26,7 +26,6 @@
 pub use self::UnOp::*;
 pub use self::UnsafeSource::*;
 pub use self::Visibility::{Public, Inherited};
-pub use self::PathParameters::*;
 
 use hir::def::Def;
 use hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX};
@@ -227,65 +226,7 @@ pub fn from_name(name: Name) -> PathSegment {
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub enum PathParameters {
-    /// The `<'a, A,B,C>` in `foo::bar::baz::<'a, A,B,C>`
-    AngleBracketedParameters(AngleBracketedParameterData),
-    /// The `(A,B)` and `C` in `Foo(A,B) -> C`
-    ParenthesizedParameters(ParenthesizedParameterData),
-}
-
-impl PathParameters {
-    pub fn none() -> PathParameters {
-        AngleBracketedParameters(AngleBracketedParameterData {
-            lifetimes: HirVec::new(),
-            types: HirVec::new(),
-            infer_types: true,
-            bindings: HirVec::new(),
-        })
-    }
-
-    /// Returns the types that the user wrote. Note that these do not necessarily map to the type
-    /// parameters in the parenthesized case.
-    pub fn types(&self) -> HirVec<&P<Ty>> {
-        match *self {
-            AngleBracketedParameters(ref data) => {
-                data.types.iter().collect()
-            }
-            ParenthesizedParameters(ref data) => {
-                data.inputs
-                    .iter()
-                    .chain(data.output.iter())
-                    .collect()
-            }
-        }
-    }
-
-    pub fn lifetimes(&self) -> HirVec<&Lifetime> {
-        match *self {
-            AngleBracketedParameters(ref data) => {
-                data.lifetimes.iter().collect()
-            }
-            ParenthesizedParameters(_) => {
-                HirVec::new()
-            }
-        }
-    }
-
-    pub fn bindings(&self) -> HirVec<&TypeBinding> {
-        match *self {
-            AngleBracketedParameters(ref data) => {
-                data.bindings.iter().collect()
-            }
-            ParenthesizedParameters(_) => {
-                HirVec::new()
-            }
-        }
-    }
-}
-
-/// A path like `Foo<'a, T>`
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub struct AngleBracketedParameterData {
+pub struct PathParameters {
     /// The lifetime parameters for this path segment.
     pub lifetimes: HirVec<Lifetime>,
     /// The type parameters for this path segment, if present.
@@ -298,19 +239,33 @@ pub struct AngleBracketedParameterData {
     /// Bindings (equality constraints) on associated types, if present.
     /// E.g., `Foo<A=Bar>`.
     pub bindings: HirVec<TypeBinding>,
+    /// Were parameters written in parenthesized form `Fn(T) -> U`?
+    /// This is required mostly for pretty-printing and diagnostics,
+    /// but also for changing lifetime elision rules to be "function-like".
+    pub parenthesized: bool,
 }
 
-/// A path like `Foo(A,B) -> C`
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub struct ParenthesizedParameterData {
-    /// Overall span
-    pub span: Span,
-
-    /// `(A,B)`
-    pub inputs: HirVec<P<Ty>>,
+impl PathParameters {
+    pub fn none() -> Self {
+        Self {
+            lifetimes: HirVec::new(),
+            types: HirVec::new(),
+            infer_types: true,
+            bindings: HirVec::new(),
+            parenthesized: false,
+        }
+    }
 
-    /// `C`
-    pub output: Option<P<Ty>>,
+    pub fn inputs(&self) -> &[P<Ty>] {
+        if self.parenthesized {
+            if let Some(ref ty) = self.types.get(0) {
+                if let TyTup(ref tys) = ty.node {
+                    return tys;
+                }
+            }
+        }
+        bug!("PathParameters::inputs: not a `Fn(T) -> U`");
+    }
 }
 
 /// The AST represents all type param bounds as types.
@@ -1265,6 +1220,7 @@ pub struct TraitItemId {
 pub struct TraitItem {
     pub id: NodeId,
     pub name: Name,
+    pub hir_id: HirId,
     pub attrs: HirVec<Attribute>,
     pub node: TraitItemKind,
     pub span: Span,
@@ -1306,6 +1262,7 @@ pub struct ImplItemId {
 pub struct ImplItem {
     pub id: NodeId,
     pub name: Name,
+    pub hir_id: HirId,
     pub vis: Visibility,
     pub defaultness: Defaultness,
     pub attrs: HirVec<Attribute>,
@@ -1712,8 +1669,9 @@ pub struct ItemId {
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct Item {
     pub name: Name,
-    pub attrs: HirVec<Attribute>,
     pub id: NodeId,
+    pub hir_id: HirId,
+    pub attrs: HirVec<Attribute>,
     pub node: Item_,
     pub vis: Visibility,
     pub span: Span,
index abfb00a24a115364b7f825a1ae5d1f7c1117ac1b..876875bce4a5e54cc550dfb35507482020f7b537 100644 (file)
@@ -1194,9 +1194,9 @@ fn print_expr_method_call(&mut self,
         self.print_expr(&args[0])?;
         self.s.word(".")?;
         self.print_name(segment.name)?;
-        if !segment.parameters.lifetimes().is_empty() ||
-                !segment.parameters.types().is_empty() ||
-                !segment.parameters.bindings().is_empty() {
+        if !segment.parameters.lifetimes.is_empty() ||
+                !segment.parameters.types.is_empty() ||
+                !segment.parameters.bindings.is_empty() {
             self.print_path_parameters(&segment.parameters, true)?;
         }
         self.print_call_post(base_args)
@@ -1581,61 +1581,55 @@ fn print_path_parameters(&mut self,
                              parameters: &hir::PathParameters,
                              colons_before_params: bool)
                              -> io::Result<()> {
-        match *parameters {
-            hir::AngleBracketedParameters(ref data) => {
-                let start = if colons_before_params { "::<" } else { "<" };
-                let empty = Cell::new(true);
-                let start_or_comma = |this: &mut Self| {
-                    if empty.get() {
-                        empty.set(false);
-                        this.s.word(start)
-                    } else {
-                        this.word_space(",")
-                    }
-                };
+        if parameters.parenthesized {
+            self.s.word("(")?;
+            self.commasep(Inconsistent, parameters.inputs(), |s, ty| s.print_type(&ty))?;
+            self.s.word(")")?;
 
-                if !data.lifetimes.iter().all(|lt| lt.is_elided()) {
-                    for lifetime in &data.lifetimes {
-                        start_or_comma(self)?;
-                        self.print_lifetime(lifetime)?;
-                    }
-                }
-
-                if !data.types.is_empty() {
-                    start_or_comma(self)?;
-                    self.commasep(Inconsistent, &data.types, |s, ty| s.print_type(&ty))?;
+            self.space_if_not_bol()?;
+            self.word_space("->")?;
+            self.print_type(&parameters.bindings[0].ty)?;
+        } else {
+            let start = if colons_before_params { "::<" } else { "<" };
+            let empty = Cell::new(true);
+            let start_or_comma = |this: &mut Self| {
+                if empty.get() {
+                    empty.set(false);
+                    this.s.word(start)
+                } else {
+                    this.word_space(",")
                 }
+            };
 
-                // FIXME(eddyb) This would leak into error messages, e.g.:
-                // "non-exhaustive patterns: `Some::<..>(_)` not covered".
-                if data.infer_types && false {
+            if !parameters.lifetimes.iter().all(|lt| lt.is_elided()) {
+                for lifetime in &parameters.lifetimes {
                     start_or_comma(self)?;
-                    self.s.word("..")?;
+                    self.print_lifetime(lifetime)?;
                 }
+            }
 
-                for binding in data.bindings.iter() {
-                    start_or_comma(self)?;
-                    self.print_name(binding.name)?;
-                    self.s.space()?;
-                    self.word_space("=")?;
-                    self.print_type(&binding.ty)?;
-                }
+            if !parameters.types.is_empty() {
+                start_or_comma(self)?;
+                self.commasep(Inconsistent, &parameters.types, |s, ty| s.print_type(&ty))?;
+            }
 
-                if !empty.get() {
-                    self.s.word(">")?
-                }
+            // FIXME(eddyb) This would leak into error messages, e.g.:
+            // "non-exhaustive patterns: `Some::<..>(_)` not covered".
+            if parameters.infer_types && false {
+                start_or_comma(self)?;
+                self.s.word("..")?;
             }
 
-            hir::ParenthesizedParameters(ref data) => {
-                self.s.word("(")?;
-                self.commasep(Inconsistent, &data.inputs, |s, ty| s.print_type(&ty))?;
-                self.s.word(")")?;
+            for binding in parameters.bindings.iter() {
+                start_or_comma(self)?;
+                self.print_name(binding.name)?;
+                self.s.space()?;
+                self.word_space("=")?;
+                self.print_type(&binding.ty)?;
+            }
 
-                if let Some(ref ty) = data.output {
-                    self.space_if_not_bol()?;
-                    self.word_space("->")?;
-                    self.print_type(&ty)?;
-                }
+            if !empty.get() {
+                self.s.word(">")?
             }
         }
 
index 4c70816c0b83300e1337cc23c95f3fc437261dcf..a79133187895a861736d587050b91b86071302f6 100644 (file)
@@ -133,22 +133,12 @@ fn hash_stable<W: StableHasherResult>(&self,
     parameters
 });
 
-impl_stable_hash_for!(enum hir::PathParameters {
-    AngleBracketedParameters(data),
-    ParenthesizedParameters(data)
-});
-
-impl_stable_hash_for!(struct hir::AngleBracketedParameterData {
+impl_stable_hash_for!(struct hir::PathParameters {
     lifetimes,
     types,
     infer_types,
-    bindings
-});
-
-impl_stable_hash_for!(struct hir::ParenthesizedParameterData {
-    span,
-    inputs,
-    output
+    bindings,
+    parenthesized
 });
 
 impl_stable_hash_for!(enum hir::TyParamBound {
@@ -741,6 +731,7 @@ fn hash_stable<W: StableHasherResult>(&self,
                                           hasher: &mut StableHasher<W>) {
         let hir::TraitItem {
             id,
+            hir_id: _,
             name,
             ref attrs,
             ref node,
@@ -774,6 +765,7 @@ fn hash_stable<W: StableHasherResult>(&self,
                                           hasher: &mut StableHasher<W>) {
         let hir::ImplItem {
             id,
+            hir_id: _,
             name,
             ref vis,
             defaultness,
@@ -930,6 +922,7 @@ fn hash_stable<W: StableHasherResult>(&self,
             name,
             ref attrs,
             id,
+            hir_id: _,
             ref node,
             ref vis,
             span
index 2e9109688181527e9c5aef75aac26ec6a9833011..c80ce3c96f1a98a3d44870719fd5edffcd028f4e 100644 (file)
@@ -27,65 +27,84 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     //    { x.push(y); }.
     // The example gives
     // fn foo(x: &mut Vec<&u8>, y: &u8) {
-    //                    ---      --- these references must have the same lifetime
+    //                    ---      --- these references are declared with different lifetimes...
     //            x.push(y);
-    //            ^ data from `y` flows into `x` here
-    // It will later be extended to trait objects and structs.
+    //            ^ ...but data from `y` flows into `x` here
+    // It has been extended for the case of structs too.
+    // Consider the example
+    // struct Ref<'a> { x: &'a u32 }
+    // fn foo(mut x: Vec<Ref>, y: Ref) {
+    //                   ---      --- these structs are declared with different lifetimes...
+    //               x.push(y);
+    //               ^ ...but data from `y` flows into `x` here
+    // }
+    // It will later be extended to trait objects.
     pub fn try_report_anon_anon_conflict(&self, error: &RegionResolutionError<'tcx>) -> bool {
-
         let (span, sub, sup) = match *error {
             ConcreteFailure(ref origin, sub, sup) => (origin.span(), sub, sup),
             _ => return false, // inapplicable
         };
 
         // Determine whether the sub and sup consist of both anonymous (elided) regions.
-        let (ty1, ty2) = if self.is_suitable_anonymous_region(sup).is_some() &&
-                            self.is_suitable_anonymous_region(sub).is_some() {
-            if let (Some(anon_reg1), Some(anon_reg2)) =
-                (self.is_suitable_anonymous_region(sup), self.is_suitable_anonymous_region(sub)) {
-                let ((_, br1), (_, br2)) = (anon_reg1, anon_reg2);
-                if self.find_anon_type(sup, &br1).is_some() &&
-                   self.find_anon_type(sub, &br2).is_some() {
-                    (self.find_anon_type(sup, &br1).unwrap(),
-                     self.find_anon_type(sub, &br2).unwrap())
-                } else {
-                    return false;
-                }
-            } else {
-                return false;
-            }
-        } else {
-            return false; // inapplicable
-        };
+        let anon_reg_sup = or_false!(self.is_suitable_anonymous_region(sup));
 
-        if let (Some(sup_arg), Some(sub_arg)) =
+        let anon_reg_sub = or_false!(self.is_suitable_anonymous_region(sub));
+        let scope_def_id_sup = anon_reg_sup.def_id;
+        let bregion_sup = anon_reg_sup.boundregion;
+        let scope_def_id_sub = anon_reg_sub.def_id;
+        let bregion_sub = anon_reg_sub.boundregion;
+
+        let ty_sup = or_false!(self.find_anon_type(sup, &bregion_sup));
+
+        let ty_sub = or_false!(self.find_anon_type(sub, &bregion_sub));
+
+        let (main_label, label1, label2) = if let (Some(sup_arg), Some(sub_arg)) =
             (self.find_arg_with_anonymous_region(sup, sup),
              self.find_arg_with_anonymous_region(sub, sub)) {
-            let ((anon_arg1, _, _, _), (anon_arg2, _, _, _)) = (sup_arg, sub_arg);
 
-            let span_label_var1 = if let Some(simple_name) = anon_arg1.pat.simple_name() {
-                format!(" from `{}` ", simple_name)
-            } else {
-                format!(" ")
-            };
+            let (anon_arg_sup, is_first_sup, anon_arg_sub, is_first_sub) =
+                (sup_arg.arg, sup_arg.is_first, sub_arg.arg, sub_arg.is_first);
+            if self.is_self_anon(is_first_sup, scope_def_id_sup) ||
+               self.is_self_anon(is_first_sub, scope_def_id_sub) {
+                return false;
+            }
 
-            let span_label_var2 = if let Some(simple_name) = anon_arg2.pat.simple_name() {
-                format!(" into `{}` ", simple_name)
+            if self.is_return_type_anon(scope_def_id_sup, bregion_sup) ||
+               self.is_return_type_anon(scope_def_id_sub, bregion_sub) {
+                return false;
+            }
+
+            if anon_arg_sup == anon_arg_sub {
+                (format!("this type was declared with multiple lifetimes..."),
+                 format!(" with one lifetime"),
+                 format!(" into the other"))
             } else {
-                format!(" ")
-            };
-
-            struct_span_err!(self.tcx.sess, span, E0623, "lifetime mismatch")
-                .span_label(ty1.span,
-                            format!("these references are not declared with the same lifetime..."))
-                .span_label(ty2.span, format!(""))
-                .span_label(span,
-                            format!("...but data{}flows{}here", span_label_var1, span_label_var2))
-                .emit();
+                let span_label_var1 = if let Some(simple_name) = anon_arg_sup.pat.simple_name() {
+                    format!(" from `{}`", simple_name)
+                } else {
+                    format!("")
+                };
+
+                let span_label_var2 = if let Some(simple_name) = anon_arg_sub.pat.simple_name() {
+                    format!(" into `{}`", simple_name)
+                } else {
+                    format!("")
+                };
+
+                let span_label =
+                    format!("these two types are declared with different lifetimes...",);
+
+                (span_label, span_label_var1, span_label_var2)
+            }
         } else {
             return false;
-        }
+        };
 
+        struct_span_err!(self.tcx.sess, span, E0623, "lifetime mismatch")
+            .span_label(ty_sup.span, main_label)
+            .span_label(ty_sub.span, format!(""))
+            .span_label(span, format!("...but data{} flows{} here", label1, label2))
+            .emit();
         return true;
     }
 
@@ -94,7 +113,6 @@ pub fn try_report_anon_anon_conflict(&self, error: &RegionResolutionError<'tcx>)
     /// contains the anonymous type.
     ///
     /// # Arguments
-    ///
     /// region - the anonymous region corresponding to the anon_anon conflict
     /// br - the bound region corresponding to the above region which is of type `BrAnon(_)`
     ///
@@ -105,39 +123,56 @@ pub fn try_report_anon_anon_conflict(&self, error: &RegionResolutionError<'tcx>)
     /// ```
     /// The function returns the nested type corresponding to the anonymous region
     /// for e.g. `&u8` and Vec<`&u8`.
-    fn find_anon_type(&self, region: Region<'tcx>, br: &ty::BoundRegion) -> Option<&hir::Ty> {
+    pub fn find_anon_type(&self, region: Region<'tcx>, br: &ty::BoundRegion) -> Option<&hir::Ty> {
         if let Some(anon_reg) = self.is_suitable_anonymous_region(region) {
-            let (def_id, _) = anon_reg;
+            let def_id = anon_reg.def_id;
             if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) {
                 let ret_ty = self.tcx.type_of(def_id);
                 if let ty::TyFnDef(_, _) = ret_ty.sty {
-                    if let hir_map::NodeItem(it) = self.tcx.hir.get(node_id) {
-                        if let hir::ItemFn(ref fndecl, _, _, _, _, _) = it.node {
-                            return fndecl
-                                       .inputs
-                                       .iter()
-                                       .filter_map(|arg| {
-                                let mut nested_visitor = FindNestedTypeVisitor {
-                                    infcx: &self,
-                                    hir_map: &self.tcx.hir,
-                                    bound_region: *br,
-                                    found_type: None,
-                                };
-                                nested_visitor.visit_ty(&**arg);
-                                if nested_visitor.found_type.is_some() {
-                                    nested_visitor.found_type
-                                } else {
-                                    None
-                                }
-                            })
-                                       .next();
-                        }
-                    }
+                    let inputs: &[_] =
+                        match self.tcx.hir.get(node_id) {
+                            hir_map::NodeItem(&hir::Item {
+                                                  node: hir::ItemFn(ref fndecl, ..), ..
+                                              }) => &fndecl.inputs,
+                            hir_map::NodeTraitItem(&hir::TraitItem {
+                                                   node: hir::TraitItemKind::Method(ref fndecl, ..),
+                                                   ..
+                                               }) => &fndecl.decl.inputs,
+                            hir_map::NodeImplItem(&hir::ImplItem {
+                                                  node: hir::ImplItemKind::Method(ref fndecl, ..),
+                                                  ..
+                                              }) => &fndecl.decl.inputs,
+
+                            _ => &[],
+                        };
+
+                    return inputs
+                               .iter()
+                               .filter_map(|arg| {
+                                               self.find_component_for_bound_region(&**arg, br)
+                                           })
+                               .next();
                 }
             }
         }
         None
     }
+
+    // This method creates a FindNestedTypeVisitor which returns the type corresponding
+    // to the anonymous region.
+    fn find_component_for_bound_region(&self,
+                                       arg: &'gcx hir::Ty,
+                                       br: &ty::BoundRegion)
+                                       -> Option<(&'gcx hir::Ty)> {
+        let mut nested_visitor = FindNestedTypeVisitor {
+            infcx: &self,
+            hir_map: &self.tcx.hir,
+            bound_region: *br,
+            found_type: None,
+        };
+        nested_visitor.visit_ty(arg);
+        nested_visitor.found_type
+    }
 }
 
 // The FindNestedTypeVisitor captures the corresponding `hir::Ty` of the
@@ -176,8 +211,8 @@ fn visit_ty(&mut self, arg: &'gcx hir::Ty) {
             hir::TyRptr(ref lifetime, _) => {
                 match self.infcx.tcx.named_region_map.defs.get(&lifetime.id) {
                     // the lifetime of the TyRptr
-                    Some(&rl::Region::LateBoundAnon(debuijn_index, anon_index)) => {
-                        if debuijn_index.depth == 1 && anon_index == br_index {
+                    Some(&rl::Region::LateBoundAnon(debruijn_index, anon_index)) => {
+                        if debruijn_index.depth == 1 && anon_index == br_index {
                             self.found_type = Some(arg);
                             return; // we can stop visiting now
                         }
@@ -191,6 +226,20 @@ fn visit_ty(&mut self, arg: &'gcx hir::Ty) {
                     }
                 }
             }
+            // Checks if it is of type `hir::TyPath` which corresponds to a struct.
+            hir::TyPath(_) => {
+                let subvisitor = &mut TyPathVisitor {
+                                          infcx: self.infcx,
+                                          found_it: false,
+                                          bound_region: self.bound_region,
+                                          hir_map: self.hir_map,
+                                      };
+                intravisit::walk_ty(subvisitor, arg); // call walk_ty; as visit_ty is empty,
+                // this will visit only outermost type
+                if subvisitor.found_it {
+                    self.found_type = Some(arg);
+                }
+            }
             _ => {}
         }
         // walk the embedded contents: e.g., if we are visiting `Vec<&Foo>`,
@@ -198,3 +247,56 @@ fn visit_ty(&mut self, arg: &'gcx hir::Ty) {
         intravisit::walk_ty(self, arg);
     }
 }
+
+// The visitor captures the corresponding `hir::Ty` of the anonymous region
+// in the case of structs ie. `hir::TyPath`.
+// This visitor would be invoked for each lifetime corresponding to a struct,
+// and would walk the types like Vec<Ref> in the above example and Ref looking for the HIR
+// where that lifetime appears. This allows us to highlight the
+// specific part of the type in the error message.
+struct TyPathVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
+    infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
+    hir_map: &'a hir::map::Map<'gcx>,
+    found_it: bool,
+    bound_region: ty::BoundRegion,
+}
+
+impl<'a, 'gcx, 'tcx> Visitor<'gcx> for TyPathVisitor<'a, 'gcx, 'tcx> {
+    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
+        NestedVisitorMap::OnlyBodies(&self.hir_map)
+    }
+
+    fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) {
+        let br_index = match self.bound_region {
+            ty::BrAnon(index) => index,
+            _ => return,
+        };
+
+        match self.infcx.tcx.named_region_map.defs.get(&lifetime.id) {
+            // the lifetime of the TyPath!
+            Some(&rl::Region::LateBoundAnon(debruijn_index, anon_index)) => {
+                if debruijn_index.depth == 1 && anon_index == br_index {
+                    self.found_it = true;
+                }
+            }
+            Some(&rl::Region::Static) |
+            Some(&rl::Region::EarlyBound(_, _)) |
+            Some(&rl::Region::LateBound(_, _)) |
+            Some(&rl::Region::Free(_, _)) |
+            None => {
+                debug!("no arg found");
+            }
+        }
+    }
+
+    fn visit_ty(&mut self, arg: &'gcx hir::Ty) {
+        // ignore nested types
+        //
+        // If you have a type like `Foo<'a, &Ty>` we
+        // are only interested in the immediate lifetimes ('a).
+        //
+        // Making `visit_ty` empty will ignore the `&Ty` embedded
+        // inside, it will get reached by the outer visitor.
+        debug!("`Ty` corresponding to a struct is {:?}", arg);
+    }
+}
index 8281d4716c4cec7d2c49f6cbb92ed44c22634cb9..edf9ca89b3394e7bc11ffd2d1758d5c8ab69ee08 100644 (file)
 mod note;
 
 mod need_type_info;
-mod util;
+
 mod named_anon_conflict;
+#[macro_use]
+mod util;
 mod anon_anon_conflict;
 
 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
index 491079a1f9259ad33b9f13932a57cf99df1cad99..0aae008396a00615b09cd7386ac0baec47506c90 100644 (file)
@@ -11,7 +11,6 @@
 //! Error Reporting for Anonymous Region Lifetime Errors
 //! where one region is named and the other is anonymous.
 use infer::InferCtxt;
-use ty;
 use infer::region_inference::RegionResolutionError::*;
 use infer::region_inference::RegionResolutionError;
 
@@ -30,8 +29,8 @@ pub fn try_report_named_anon_conflict(&self, error: &RegionResolutionError<'tcx>
         // where the anonymous region appears (there must always be one; we
         // only introduced anonymous regions in parameters) as well as a
         // version new_ty of its type where the anonymous region is replaced
-        // with the named one.
-        let (named, (arg, new_ty, br, is_first), (scope_def_id, _)) =
+        // with the named one.//scope_def_id
+        let (named, anon_arg_info, region_info) =
             if sub.is_named_region() && self.is_suitable_anonymous_region(sup).is_some() {
                 (sub,
                  self.find_arg_with_anonymous_region(sup, sub).unwrap(),
@@ -44,50 +43,38 @@ pub fn try_report_named_anon_conflict(&self, error: &RegionResolutionError<'tcx>
                 return false; // inapplicable
             };
 
-        // Here, we check for the case where the anonymous region
-        // is in the return type.
-        // FIXME(#42703) - Need to handle certain cases here.
-        let ret_ty = self.tcx.type_of(scope_def_id);
-        match ret_ty.sty {
-            ty::TyFnDef(_, _) => {
-                let sig = ret_ty.fn_sig(self.tcx);
-                let late_bound_regions = self.tcx
-                    .collect_referenced_late_bound_regions(&sig.output());
-                if late_bound_regions.iter().any(|r| *r == br) {
-                    return false;
-                }
-            }
-            _ => {}
-        }
-
-        // Here we check for the case where anonymous region
-        // corresponds to self and if yes, we display E0312.
-        // FIXME(#42700) - Need to format self properly to
-        // enable E0621 for it.
-        if is_first &&
-           self.tcx
-               .opt_associated_item(scope_def_id)
-               .map(|i| i.method_has_self_argument)
-               .unwrap_or(false) {
+        let (arg, new_ty, br, is_first, scope_def_id, is_impl_item) = (anon_arg_info.arg,
+                                                                       anon_arg_info.arg_ty,
+                                                                       anon_arg_info.bound_region,
+                                                                       anon_arg_info.is_first,
+                                                                       region_info.def_id,
+                                                                       region_info.is_impl_item);
+        if is_impl_item {
             return false;
         }
 
-        let (error_var, span_label_var) = if let Some(simple_name) = arg.pat.simple_name() {
-            (format!("the type of `{}`", simple_name), format!("the type of `{}`", simple_name))
+        if self.is_return_type_anon(scope_def_id, br) || self.is_self_anon(is_first, scope_def_id) {
+            return false;
         } else {
-            ("parameter type".to_owned(), "type".to_owned())
-        };
 
-        struct_span_err!(self.tcx.sess,
-                         span,
-                         E0621,
-                         "explicit lifetime required in {}",
-                         error_var)
-                .span_label(arg.pat.span,
-                            format!("consider changing {} to `{}`", span_label_var, new_ty))
-                .span_label(span, format!("lifetime `{}` required", named))
-                .emit();
+            let (error_var, span_label_var) = if let Some(simple_name) = arg.pat.simple_name() {
+                (format!("the type of `{}`", simple_name), format!("the type of `{}`", simple_name))
+            } else {
+                ("parameter type".to_owned(), "type".to_owned())
+            };
+
+            struct_span_err!(self.tcx.sess,
+                             span,
+                             E0621,
+                             "explicit lifetime required in {}",
+                             error_var)
+                    .span_label(arg.pat.span,
+                                format!("consider changing {} to `{}`", span_label_var, new_ty))
+                    .span_label(span, format!("lifetime `{}` required", named))
+                    .emit();
 
+
+        }
         return true;
     }
 }
index c8f78367420e64e0c00a52c98cb80bdb6999bbb1..04153038da89faaede49e3cfdc849454a4337f67 100644 (file)
 use hir::def_id::DefId;
 use hir::map as hir_map;
 
+macro_rules! or_false {
+     ($v:expr) => {
+          match $v {
+               Some(v) => v,
+               None => return false,
+          }
+     }
+}
+
+// The struct contains the information about the anonymous region
+// we are searching for.
+pub struct AnonymousArgInfo<'tcx> {
+    // the argument corresponding to the anonymous region
+    pub arg: &'tcx hir::Arg,
+    // the type corresponding to the anonymopus region argument
+    pub arg_ty: ty::Ty<'tcx>,
+    // the ty::BoundRegion corresponding to the anonymous region
+    pub bound_region: ty::BoundRegion,
+    // corresponds to id the argument is the first parameter
+    // in the declaration
+    pub is_first: bool,
+}
+
+// This struct contains information regarding the
+// Refree((FreeRegion) corresponding to lifetime conflict
+pub struct FreeRegionInfo {
+    // def id corresponding to FreeRegion
+    pub def_id: DefId,
+    // the bound region corresponding to FreeRegion
+    pub boundregion: ty::BoundRegion,
+    // checks if bound region is in Impl Item
+    pub is_impl_item: bool,
+}
+
 impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     // This method walks the Type of the function body arguments using
     // `fold_regions()` function and returns the
@@ -28,14 +62,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     // i32, which is the type of y but with the anonymous region replaced
     // with 'a, the corresponding bound region and is_first which is true if
     // the hir::Arg is the first argument in the function declaration.
-    pub fn find_arg_with_anonymous_region
-        (&self,
-         anon_region: Region<'tcx>,
-         replace_region: Region<'tcx>)
-         -> Option<(&hir::Arg, ty::Ty<'tcx>, ty::BoundRegion, bool)> {
+    pub fn find_arg_with_anonymous_region(&self,
+                                          anon_region: Region<'tcx>,
+                                          replace_region: Region<'tcx>)
+                                          -> Option<AnonymousArgInfo> {
 
         if let ty::ReFree(ref free_region) = *anon_region {
-
             let id = free_region.scope;
             let hir = &self.tcx.hir;
             if let Some(node_id) = hir.as_local_node_id(id) {
@@ -57,7 +89,12 @@ pub fn find_arg_with_anonymous_region
                                     });
                                 if found_anon_region {
                                     let is_first = index == 0;
-                                    Some((arg, new_arg_ty, free_region.bound_region, is_first))
+                                    Some(AnonymousArgInfo {
+                                             arg: arg,
+                                             arg_ty: new_arg_ty,
+                                             bound_region: free_region.bound_region,
+                                             is_first: is_first,
+                                         })
                                 } else {
                                     None
                                 }
@@ -79,42 +116,81 @@ pub fn find_arg_with_anonymous_region
 
     // This method returns whether the given Region is Anonymous
     // and returns the DefId and the BoundRegion corresponding to the given region.
-    pub fn is_suitable_anonymous_region(&self,
-                                        region: Region<'tcx>)
-                                        -> Option<(DefId, ty::BoundRegion)> {
+    pub fn is_suitable_anonymous_region(&self, region: Region<'tcx>) -> Option<FreeRegionInfo> {
         if let ty::ReFree(ref free_region) = *region {
-            if let ty::BrAnon(..) = free_region.bound_region{
-                    let anonymous_region_binding_scope = free_region.scope;
-                    let node_id = self.tcx
-                        .hir
-                        .as_local_node_id(anonymous_region_binding_scope)
-                        .unwrap();
-                    match self.tcx.hir.find(node_id) {
-                        Some(hir_map::NodeItem(..)) |
-                        Some(hir_map::NodeTraitItem(..)) => {
-                            // Success -- proceed to return Some below
-                        }
-                        Some(hir_map::NodeImplItem(..)) => {
-                            let container_id = self.tcx
-                                .associated_item(anonymous_region_binding_scope)
-                                .container
-                                .id();
-                            if self.tcx.impl_trait_ref(container_id).is_some() {
-                                // For now, we do not try to target impls of traits. This is
-                                // because this message is going to suggest that the user
-                                // change the fn signature, but they may not be free to do so,
-                                // since the signature must match the trait.
-                                //
-                                // FIXME(#42706) -- in some cases, we could do better here.
-                                return None;
-                            }
-                        }
-                        _ => return None, // inapplicable
-                        // we target only top-level functions
+            if let ty::BrAnon(..) = free_region.bound_region {
+                let anonymous_region_binding_scope = free_region.scope;
+                let node_id = self.tcx
+                    .hir
+                    .as_local_node_id(anonymous_region_binding_scope)
+                    .unwrap();
+                let mut is_impl_item = false;
+                match self.tcx.hir.find(node_id) {
+
+                    Some(hir_map::NodeItem(..)) |
+                    Some(hir_map::NodeTraitItem(..)) => {
+                        // Success -- proceed to return Some below
                     }
-                    return Some((anonymous_region_binding_scope, free_region.bound_region));
+                    Some(hir_map::NodeImplItem(..)) => {
+                        is_impl_item =
+                            self.is_bound_region_in_impl_item(anonymous_region_binding_scope);
+                    }
+                    _ => return None,
                 }
+                return Some(FreeRegionInfo {
+                                def_id: anonymous_region_binding_scope,
+                                boundregion: free_region.bound_region,
+                                is_impl_item: is_impl_item,
+                            });
             }
-            None
         }
+        None
+    }
+
+    // Here, we check for the case where the anonymous region
+    // is in the return type.
+    // FIXME(#42703) - Need to handle certain cases here.
+    pub fn is_return_type_anon(&self, scope_def_id: DefId, br: ty::BoundRegion) -> bool {
+        let ret_ty = self.tcx.type_of(scope_def_id);
+        match ret_ty.sty {
+            ty::TyFnDef(_, _) => {
+                let sig = ret_ty.fn_sig(self.tcx);
+                let late_bound_regions = self.tcx
+                    .collect_referenced_late_bound_regions(&sig.output());
+                if late_bound_regions.iter().any(|r| *r == br) {
+                    return true;
+                }
+            }
+            _ => {}
+        }
+        false
+    }
+    // Here we check for the case where anonymous region
+    // corresponds to self and if yes, we display E0312.
+    // FIXME(#42700) - Need to format self properly to
+    // enable E0621 for it.
+    pub fn is_self_anon(&self, is_first: bool, scope_def_id: DefId) -> bool {
+        is_first &&
+        self.tcx
+            .opt_associated_item(scope_def_id)
+            .map(|i| i.method_has_self_argument) == Some(true)
+    }
+
+    // Here we check if the bound region is in Impl Item.
+    pub fn is_bound_region_in_impl_item(&self, anonymous_region_binding_scope: DefId) -> bool {
+        let container_id = self.tcx
+            .associated_item(anonymous_region_binding_scope)
+            .container
+            .id();
+        if self.tcx.impl_trait_ref(container_id).is_some() {
+            // For now, we do not try to target impls of traits. This is
+            // because this message is going to suggest that the user
+            // change the fn signature, but they may not be free to do so,
+            // since the signature must match the trait.
+            //
+            // FIXME(#42706) -- in some cases, we could do better here.
+            return true;
+        }
+        false
+    }
 }
index 5b0760e561e3f68d4c14e7ed1ee832ec6b6242ec..152b2e2aa5ebc104d80936b458b66de4db488cb8 100644 (file)
@@ -14,9 +14,6 @@
 //!
 //! This API is completely unstable and subject to change.
 
-#![crate_name = "rustc"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/")]
@@ -29,7 +26,7 @@
 #![feature(core_intrinsics)]
 #![feature(discriminant_value)]
 #![feature(i128_type)]
-#![feature(libc)]
+#![cfg_attr(windows, feature(libc))]
 #![feature(never_type)]
 #![feature(nonzero)]
 #![feature(quote)]
@@ -48,6 +45,7 @@
 extern crate fmt_macros;
 extern crate getopts;
 extern crate graphviz;
+#[cfg(windows)]
 extern crate libc;
 extern crate owning_ref;
 extern crate rustc_back;
@@ -65,7 +63,9 @@
 
 // Note that librustc doesn't actually depend on these crates, see the note in
 // `Cargo.toml` for this crate about why these are here.
+#[allow(unused_extern_crates)]
 extern crate flate2;
+#[allow(unused_extern_crates)]
 extern crate test;
 
 #[macro_use]
index cbe642a9a76a65b3afca29288f97de502778745e..811bf9776101d4d5e0fd453d5e68c97a5e6e98b7 100644 (file)
@@ -30,7 +30,7 @@
 
 declare_lint! {
     pub UNUSED_EXTERN_CRATES,
-    Allow,
+    Warn,
     "extern crates that are never used"
 }
 
index 12362c8d3bf5232813f5cff1ba59ca197699c62c..a8e98e53db394960de8abd5537dfdae7fafb763d 100644 (file)
@@ -915,18 +915,15 @@ fn visit_segment_parameters(&mut self,
                                 def: Def,
                                 depth: usize,
                                 params: &'tcx hir::PathParameters) {
-        let data = match *params {
-            hir::ParenthesizedParameters(ref data) => {
-                self.visit_fn_like_elision(&data.inputs, data.output.as_ref());
-                return;
-            }
-            hir::AngleBracketedParameters(ref data) => data
-        };
+        if params.parenthesized {
+            self.visit_fn_like_elision(params.inputs(), Some(&params.bindings[0].ty));
+            return;
+        }
 
-        if data.lifetimes.iter().all(|l| l.is_elided()) {
-            self.resolve_elided_lifetimes(&data.lifetimes);
+        if params.lifetimes.iter().all(|l| l.is_elided()) {
+            self.resolve_elided_lifetimes(&params.lifetimes);
         } else {
-            for l in &data.lifetimes { self.visit_lifetime(l); }
+            for l in &params.lifetimes { self.visit_lifetime(l); }
         }
 
         // Figure out if this is a type/trait segment,
@@ -995,13 +992,13 @@ fn visit_segment_parameters(&mut self,
                             Some(Region::Static)
                         }
                     }
-                    Set1::One(r) => r.subst(&data.lifetimes, map),
+                    Set1::One(r) => r.subst(&params.lifetimes, map),
                     Set1::Many => None
                 }
             }).collect()
         });
 
-        for (i, ty) in data.types.iter().enumerate() {
+        for (i, ty) in params.types.iter().enumerate() {
             if let Some(&lt) = object_lifetime_defaults.get(i) {
                 let scope = Scope::ObjectLifetimeDefault {
                     lifetime: lt,
@@ -1013,7 +1010,7 @@ fn visit_segment_parameters(&mut self,
             }
         }
 
-        for b in &data.bindings { self.visit_assoc_type_binding(b); }
+        for b in &params.bindings { self.visit_assoc_type_binding(b); }
     }
 
     fn visit_fn_like_elision(&mut self, inputs: &'tcx [P<hir::Ty>],
index 5985dcb97c739b170ccceed2c727824dceb10691..99fe8e60ae52b139d049d47e6fc9ef21296b8d19 100644 (file)
@@ -995,6 +995,10 @@ fn parse_optimization_fuel(slot: &mut Option<(String, u64)>, v: Option<&str>) ->
           "dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv)"),
     query_dep_graph: bool = (false, parse_bool, [UNTRACKED],
           "enable queries of the dependency graph for regression testing"),
+    profile_queries: bool = (false, parse_bool, [UNTRACKED],
+          "trace and profile the queries of the incremental compilation framework"),
+    profile_queries_and_keys: bool = (false, parse_bool, [UNTRACKED],
+          "trace and profile the queries and keys of the incremental compilation framework"),
     no_analysis: bool = (false, parse_bool, [UNTRACKED],
           "parse and expand the source, but run no analysis"),
     extra_plugins: Vec<String> = (Vec::new(), parse_list, [TRACKED],
index 23dcaf27c2c704502a3d4609bf2e8bf491813b30..823a637c7e0d4272c70876efd577a26c0664efdd 100644 (file)
@@ -389,6 +389,13 @@ pub fn codemap<'a>(&'a self) -> &'a codemap::CodeMap {
     }
     pub fn verbose(&self) -> bool { self.opts.debugging_opts.verbose }
     pub fn time_passes(&self) -> bool { self.opts.debugging_opts.time_passes }
+    pub fn profile_queries(&self) -> bool {
+        self.opts.debugging_opts.profile_queries ||
+            self.opts.debugging_opts.profile_queries_and_keys
+    }
+    pub fn profile_queries_and_keys(&self) -> bool {
+        self.opts.debugging_opts.profile_queries_and_keys
+    }
     pub fn count_llvm_insns(&self) -> bool {
         self.opts.debugging_opts.count_llvm_insns
     }
index da1039c5de1768088a0bf4805f86c4f42c36d1de..6ce2232eb3e5d38ad36c2ae8af266990584d15df 100644 (file)
@@ -797,6 +797,8 @@ pub struct GlobalCtxt<'tcx> {
 
     pub maybe_unused_trait_imports: NodeSet,
 
+    pub maybe_unused_extern_crates: Vec<(NodeId, Span)>,
+
     // Internal cache for metadata decoding. No need to track deps on this.
     pub rcache: RefCell<FxHashMap<ty::CReaderCacheKey, Ty<'tcx>>>,
 
@@ -1038,6 +1040,7 @@ pub fn create_and_enter<F, R>(s: &'tcx Session,
             mir_passes,
             freevars: RefCell::new(resolutions.freevars),
             maybe_unused_trait_imports: resolutions.maybe_unused_trait_imports,
+            maybe_unused_extern_crates: resolutions.maybe_unused_extern_crates,
             rcache: RefCell::new(FxHashMap()),
             normalized_cache: RefCell::new(FxHashMap()),
             inhabitedness_cache: RefCell::new(FxHashMap()),
index 76a20ed8f30233e201d5668c7f436efe6a635cd7..5caf5139812802f2abf2429bc88d4cd5e43b0bfe 100644 (file)
@@ -13,7 +13,6 @@
 use ty::{self, Ty, TyCtxt};
 use syntax::ast;
 use syntax::symbol::Symbol;
-use syntax_pos::DUMMY_SP;
 
 use std::cell::Cell;
 
@@ -222,11 +221,7 @@ fn push_impl_path<T>(self,
         let use_types = !self.is_default_impl(impl_def_id) && (!impl_def_id.is_local() || {
             // Otherwise, use filename/line-number if forced.
             let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get());
-            !force_no_types && {
-                // Otherwise, use types if we can query them without inducing a cycle.
-                ty::queries::impl_trait_ref::try_get(self, DUMMY_SP, impl_def_id).is_ok() &&
-                    ty::queries::type_of::try_get(self, DUMMY_SP, impl_def_id).is_ok()
-            }
+            !force_no_types
         });
 
         if !use_types {
index 26b51630d93e0d1da168020e87fdf2ac56476864..a73202ced61e627ef2dfc2cb24fae0ebb873b218 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 use dep_graph::{DepConstructor, DepNode, DepNodeIndex};
+use errors::{Diagnostic, DiagnosticBuilder};
 use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use hir::def::Def;
 use hir;
 use ty::subst::Substs;
 use ty::fast_reject::SimplifiedType;
 use util::nodemap::{DefIdSet, NodeSet};
+use util::common::{profq_msg, ProfileQueriesMsg};
 
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_data_structures::fx::FxHashMap;
-use std::cell::{RefCell, RefMut};
+use std::cell::{RefCell, RefMut, Cell};
 use std::fmt::Debug;
 use std::hash::Hash;
 use std::marker::PhantomData;
@@ -187,7 +189,18 @@ fn from_cycle_error<'a>(_: TyCtxt<'a, 'tcx, 'tcx>) -> Self {
 
 struct QueryMap<D: QueryDescription> {
     phantom: PhantomData<D>,
-    map: FxHashMap<D::Key, (D::Value, DepNodeIndex)>,
+    map: FxHashMap<D::Key, QueryValue<D::Value>>,
+}
+
+struct QueryValue<T> {
+    value: T,
+    index: DepNodeIndex,
+    diagnostics: Option<Box<QueryDiagnostics>>,
+}
+
+struct QueryDiagnostics {
+    diagnostics: Vec<Diagnostic>,
+    emitted_diagnostics: Cell<bool>,
 }
 
 impl<M: QueryDescription> QueryMap<M> {
@@ -199,13 +212,15 @@ fn new() -> QueryMap<M> {
     }
 }
 
-pub struct CycleError<'a, 'tcx: 'a> {
+struct CycleError<'a, 'tcx: 'a> {
     span: Span,
     cycle: RefMut<'a, [(Span, Query<'tcx>)]>,
 }
 
 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
-    pub fn report_cycle(self, CycleError { span, cycle }: CycleError) {
+    fn report_cycle(self, CycleError { span, cycle }: CycleError)
+        -> DiagnosticBuilder<'a>
+    {
         // Subtle: release the refcell lock before invoking `describe()`
         // below by dropping `cycle`.
         let stack = cycle.to_vec();
@@ -234,8 +249,8 @@ pub fn report_cycle(self, CycleError { span, cycle }: CycleError) {
             err.note(&format!("...which then again requires {}, completing the cycle.",
                               stack[0].1.describe(self)));
 
-            err.emit();
-        });
+            return err
+        })
     }
 
     fn cycle_check<F, R>(self, span: Span, query: Query<'gcx>, compute: F)
@@ -501,6 +516,18 @@ fn describe(_: TyCtxt, _: DefId) -> String {
     }
 }
 
+impl<'tcx> QueryDescription for queries::is_compiler_builtins<'tcx> {
+    fn describe(_: TyCtxt, _: DefId) -> String {
+        "checking if the crate is_compiler_builtins".to_string()
+    }
+}
+
+impl<'tcx> QueryDescription for queries::has_global_allocator<'tcx> {
+    fn describe(_: TyCtxt, _: DefId) -> String {
+        "checking if the crate has_global_allocator".to_string()
+    }
+}
+
 impl<'tcx> QueryDescription for queries::extern_crate<'tcx> {
     fn describe(_: TyCtxt, _: DefId) -> String {
         "getting crate's ExternCrateData".to_string()
@@ -513,6 +540,29 @@ fn describe(_tcx: TyCtxt, _: CrateNum) -> String {
     }
 }
 
+// If enabled, send a message to the profile-queries thread
+macro_rules! profq_msg {
+    ($tcx:expr, $msg:expr) => {
+        if cfg!(debug_assertions) {
+            if  $tcx.sess.profile_queries() {
+                profq_msg($msg)
+            }
+        }
+    }
+}
+
+// If enabled, format a key using its debug string, which can be
+// expensive to compute (in terms of time).
+macro_rules! profq_key {
+    ($tcx:expr, $key:expr) => {
+        if cfg!(debug_assertions) {
+            if $tcx.sess.profile_queries_and_keys() {
+                Some(format!("{:?}", $key))
+            } else { None }
+        } else { None }
+    }
+}
+
 macro_rules! define_maps {
     (<$tcx:tt>
      $($(#[$attr:meta])*
@@ -539,6 +589,12 @@ pub enum Query<$tcx> {
             $($(#[$attr])* $name($K)),*
         }
 
+        #[allow(bad_style)]
+        #[derive(Clone, Debug, PartialEq, Eq)]
+        pub enum QueryMsg {
+            $($name(Option<String>)),*
+        }
+
         impl<$tcx> Query<$tcx> {
             pub fn describe(&self, tcx: TyCtxt) -> String {
                 match *self {
@@ -581,10 +637,30 @@ fn try_get_with<F, R>(tcx: TyCtxt<'a, $tcx, 'lcx>,
                        key,
                        span);
 
-                if let Some(&(ref result, dep_node_index)) = tcx.maps.$name.borrow().map.get(&key) {
-                    tcx.dep_graph.read_index(dep_node_index);
-                    return Ok(f(result));
+                profq_msg!(tcx,
+                    ProfileQueriesMsg::QueryBegin(
+                        span.clone(),
+                        QueryMsg::$name(profq_key!(tcx, key))
+                    )
+                );
+
+                if let Some(value) = tcx.maps.$name.borrow().map.get(&key) {
+                    if let Some(ref d) = value.diagnostics {
+                        if !d.emitted_diagnostics.get() {
+                            d.emitted_diagnostics.set(true);
+                            let handle = tcx.sess.diagnostic();
+                            for diagnostic in d.diagnostics.iter() {
+                                DiagnosticBuilder::new_diagnostic(handle, diagnostic.clone())
+                                    .emit();
+                            }
+                        }
+                    }
+                    profq_msg!(tcx, ProfileQueriesMsg::CacheHit);
+                    tcx.dep_graph.read_index(value.index);
+                    return Ok(f(&value.value));
                 }
+                // else, we are going to run the provider:
+                profq_msg!(tcx, ProfileQueriesMsg::ProviderBegin);
 
                 // FIXME(eddyb) Get more valid Span's on queries.
                 // def_span guard is necessary to prevent a recursive loop,
@@ -593,40 +669,60 @@ fn try_get_with<F, R>(tcx: TyCtxt<'a, $tcx, 'lcx>,
                     span = key.default_span(tcx)
                 }
 
-                let (result, dep_node_index) = tcx.cycle_check(span, Query::$name(key), || {
+                let res = tcx.cycle_check(span, Query::$name(key), || {
                     let dep_node = Self::to_dep_node(tcx, &key);
 
-                    if dep_node.kind.is_anon() {
-                        tcx.dep_graph.with_anon_task(dep_node.kind, || {
-                            let provider = tcx.maps.providers[key.map_crate()].$name;
-                            provider(tcx.global_tcx(), key)
-                        })
-                    } else {
-                        fn run_provider<'a, 'tcx, 'lcx>(tcx: TyCtxt<'a, 'tcx, 'lcx>,
-                                                        key: $K)
-                                                        -> $V {
-                            let provider = tcx.maps.providers[key.map_crate()].$name;
-                            provider(tcx.global_tcx(), key)
+                    tcx.sess.diagnostic().track_diagnostics(|| {
+                        if dep_node.kind.is_anon() {
+                            tcx.dep_graph.with_anon_task(dep_node.kind, || {
+                                let provider = tcx.maps.providers[key.map_crate()].$name;
+                                provider(tcx.global_tcx(), key)
+                            })
+                        } else {
+                            fn run_provider<'a, 'tcx, 'lcx>(tcx: TyCtxt<'a, 'tcx, 'lcx>,
+                                                            key: $K)
+                                                            -> $V {
+                                let provider = tcx.maps.providers[key.map_crate()].$name;
+                                provider(tcx.global_tcx(), key)
+                            }
+
+                            tcx.dep_graph.with_task(dep_node, tcx, key, run_provider)
                         }
-
-                        tcx.dep_graph.with_task(dep_node, tcx, key, run_provider)
-                    }
+                    })
                 })?;
+                profq_msg!(tcx, ProfileQueriesMsg::ProviderEnd);
+                let ((result, dep_node_index), diagnostics) = res;
 
                 tcx.dep_graph.read_index(dep_node_index);
 
+                let value = QueryValue {
+                    value: result,
+                    index: dep_node_index,
+                    diagnostics: if diagnostics.len() == 0 {
+                        None
+                    } else {
+                        Some(Box::new(QueryDiagnostics {
+                            diagnostics,
+                            emitted_diagnostics: Cell::new(true),
+                        }))
+                    },
+                };
+
                 Ok(f(&tcx.maps
                          .$name
                          .borrow_mut()
                          .map
                          .entry(key)
-                         .or_insert((result, dep_node_index))
-                         .0))
+                         .or_insert(value)
+                         .value))
             }
 
             pub fn try_get(tcx: TyCtxt<'a, $tcx, 'lcx>, span: Span, key: $K)
-                           -> Result<$V, CycleError<'a, $tcx>> {
-                Self::try_get_with(tcx, span, key, Clone::clone)
+                           -> Result<$V, DiagnosticBuilder<'a>> {
+                match Self::try_get_with(tcx, span, key, Clone::clone) {
+                    Ok(e) => Ok(e),
+                    Err(e) => Err(tcx.report_cycle(e)),
+                }
             }
 
             pub fn force(tcx: TyCtxt<'a, $tcx, 'lcx>, span: Span, key: $K) {
@@ -635,7 +731,7 @@ pub fn force(tcx: TyCtxt<'a, $tcx, 'lcx>, span: Span, key: $K) {
 
                 match Self::try_get_with(tcx, span, key, |_| ()) {
                     Ok(()) => {}
-                    Err(e) => tcx.report_cycle(e)
+                    Err(e) => tcx.report_cycle(e).emit(),
                 }
             }
         })*
@@ -672,8 +768,8 @@ pub fn $name(self, key: $K) -> $V {
         impl<'a, $tcx, 'lcx> TyCtxtAt<'a, $tcx, 'lcx> {
             $($(#[$attr])*
             pub fn $name(self, key: $K) -> $V {
-                queries::$name::try_get(self.tcx, self.span, key).unwrap_or_else(|e| {
-                    self.report_cycle(e);
+                queries::$name::try_get(self.tcx, self.span, key).unwrap_or_else(|mut e| {
+                    e.emit();
                     Value::from_cycle_error(self.global_tcx())
                 })
             })*
@@ -995,6 +1091,8 @@ fn default() -> Self {
 
     [] is_allocator: IsAllocator(DefId) -> bool,
     [] is_panic_runtime: IsPanicRuntime(DefId) -> bool,
+    [] is_compiler_builtins: IsCompilerBuiltins(DefId) -> bool,
+    [] has_global_allocator: HasGlobalAllocator(DefId) -> bool,
 
     [] extern_crate: ExternCrate(DefId) -> Rc<Option<ExternCrate>>,
 
index f9bbcc1bbe086cb1a22dae090e12ec224dd858de..6597dccf25816d55da840a68d16034a11047d740 100644 (file)
@@ -131,6 +131,7 @@ pub struct Resolutions {
     pub freevars: FreevarMap,
     pub trait_map: TraitMap,
     pub maybe_unused_trait_imports: NodeSet,
+    pub maybe_unused_extern_crates: Vec<(NodeId, Span)>,
     pub export_map: ExportMap,
 }
 
@@ -1684,12 +1685,15 @@ pub fn destructor(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Destructor> {
     pub fn sized_constraint(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> &'tcx [Ty<'tcx>] {
         match queries::adt_sized_constraint::try_get(tcx, DUMMY_SP, self.did) {
             Ok(tys) => tys,
-            Err(_) => {
+            Err(mut bug) => {
                 debug!("adt_sized_constraint: {:?} is recursive", self);
                 // This should be reported as an error by `check_representable`.
                 //
                 // Consider the type as Sized in the meanwhile to avoid
-                // further errors.
+                // further errors. Delay our `bug` diagnostic here to get
+                // emitted later as well in case we accidentally otherwise don't
+                // emit an error.
+                bug.delay_as_bug();
                 tcx.intern_type_list(&[tcx.types.err])
             }
         }
index 9cd6aa2111873a69f9becbb6b011e205b25f2978..bbbb8611f98a5f104b11b96b2d93954d3826bda3 100644 (file)
@@ -1069,11 +1069,15 @@ fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let needs_drop = |ty: Ty<'tcx>| -> bool {
         match ty::queries::needs_drop_raw::try_get(tcx, DUMMY_SP, param_env.and(ty)) {
             Ok(v) => v,
-            Err(_) => {
+            Err(mut bug) => {
                 // Cycles should be reported as an error by `check_representable`.
                 //
-                // Consider the type as not needing drop in the meanwhile to avoid
-                // further errors.
+                // Consider the type as not needing drop in the meanwhile to
+                // avoid further errors.
+                //
+                // In case we forgot to emit a bug elsewhere, delay our
+                // diagnostic to get emitted as a compiler bug.
+                bug.delay_as_bug();
                 false
             }
         }
index c24c583ad1e19a384056197b4f1fe579040562c8..6d9e648452fd345fb8732a4660892e70fc06c705 100644 (file)
@@ -58,7 +58,7 @@ pub fn trait_obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
                                          -> Vec<traits::PredicateObligation<'tcx>>
 {
     let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![] };
-    wf.compute_trait_ref(trait_ref);
+    wf.compute_trait_ref(trait_ref, Elaborate::All);
     wf.normalize()
 }
 
@@ -74,7 +74,7 @@ pub fn predicate_obligations<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
     // (*) ok to skip binders, because wf code is prepared for it
     match *predicate {
         ty::Predicate::Trait(ref t) => {
-            wf.compute_trait_ref(&t.skip_binder().trait_ref); // (*)
+            wf.compute_trait_ref(&t.skip_binder().trait_ref, Elaborate::None); // (*)
         }
         ty::Predicate::Equate(ref t) => {
             wf.compute(t.skip_binder().0);
@@ -114,6 +114,35 @@ struct WfPredicates<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     out: Vec<traits::PredicateObligation<'tcx>>,
 }
 
+/// Controls whether we "elaborate" supertraits and so forth on the WF
+/// predicates. This is a kind of hack to address #43784. The
+/// underlying problem in that issue was a trait structure like:
+///
+/// ```
+/// trait Foo: Copy { }
+/// trait Bar: Foo { }
+/// impl<T: Bar> Foo for T { }
+/// impl<T> Bar for T { }
+/// ```
+///
+/// Here, in the `Foo` impl, we will check that `T: Copy` holds -- but
+/// we decide that this is true because `T: Bar` is in the
+/// where-clauses (and we can elaborate that to include `T:
+/// Copy`). This wouldn't be a problem, except that when we check the
+/// `Bar` impl, we decide that `T: Foo` must hold because of the `Foo`
+/// impl. And so nowhere did we check that `T: Copy` holds!
+///
+/// To resolve this, we elaborate the WF requirements that must be
+/// proven when checking impls. This means that (e.g.) the `impl Bar
+/// for T` will be forced to prove not only that `T: Foo` but also `T:
+/// Copy` (which it won't be able to do, because there is no `Copy`
+/// impl for `T`).
+#[derive(Debug, PartialEq, Eq, Copy, Clone)]
+enum Elaborate {
+    All,
+    None,
+}
+
 impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
     fn cause(&mut self, code: traits::ObligationCauseCode<'tcx>) -> traits::ObligationCause<'tcx> {
         traits::ObligationCause::new(self.span, self.body_id, code)
@@ -135,12 +164,25 @@ fn normalize(&mut self) -> Vec<traits::PredicateObligation<'tcx>> {
 
     /// Pushes the obligations required for `trait_ref` to be WF into
     /// `self.out`.
-    fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>) {
+    fn compute_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>, elaborate: Elaborate) {
         let obligations = self.nominal_obligations(trait_ref.def_id, trait_ref.substs);
-        self.out.extend(obligations);
 
         let cause = self.cause(traits::MiscObligation);
         let param_env = self.param_env;
+
+        if let Elaborate::All = elaborate {
+            let predicates = obligations.iter()
+                                        .map(|obligation| obligation.predicate.clone())
+                                        .collect();
+            let implied_obligations = traits::elaborate_predicates(self.infcx.tcx, predicates);
+            let implied_obligations = implied_obligations.map(|pred| {
+                traits::Obligation::new(cause.clone(), param_env, pred)
+            });
+            self.out.extend(implied_obligations);
+        }
+
+        self.out.extend(obligations);
+
         self.out.extend(
             trait_ref.substs.types()
                             .filter(|ty| !ty.has_escaping_regions())
@@ -156,7 +198,7 @@ fn compute_projection(&mut self, data: ty::ProjectionTy<'tcx>) {
         // WF and (b) the trait-ref holds.  (It may also be
         // normalizable and be WF that way.)
         let trait_ref = data.trait_ref(self.infcx.tcx);
-        self.compute_trait_ref(&trait_ref);
+        self.compute_trait_ref(&trait_ref, Elaborate::None);
 
         if !data.has_escaping_regions() {
             let predicate = trait_ref.to_predicate();
index 885be8464eb304ece548de0d6a6c0114845c8c73..618a4ed331e766056cf1a207a86cd5dca747902e 100644 (file)
 use std::path::Path;
 use std::time::{Duration, Instant};
 
+use std::sync::mpsc::{Sender};
+use syntax_pos::{Span};
+use ty::maps::{QueryMsg};
+use dep_graph::{DepNode};
+
 // The name of the associated type for `Fn` return types
 pub const FN_OUTPUT_NAME: &'static str = "Output";
 
 
 thread_local!(static TIME_DEPTH: Cell<usize> = Cell::new(0));
 
+/// Initialized for -Z profile-queries
+thread_local!(static PROFQ_CHAN: RefCell<Option<Sender<ProfileQueriesMsg>>> = RefCell::new(None));
+
+/// Parameters to the `Dump` variant of type `ProfileQueriesMsg`.
+#[derive(Clone,Debug)]
+pub struct ProfQDumpParams {
+    /// A base path for the files we will dump
+    pub path:String,
+    /// To ensure that the compiler waits for us to finish our dumps
+    pub ack:Sender<()>,
+    /// toggle dumping a log file with every `ProfileQueriesMsg`
+    pub dump_profq_msg_log:bool,
+}
+
+/// A sequence of these messages induce a trace of query-based incremental compilation.
+/// FIXME(matthewhammer): Determine whether we should include cycle detection here or not.
+#[derive(Clone,Debug)]
+pub enum ProfileQueriesMsg {
+    /// begin a timed pass
+    TimeBegin(String),
+    /// end a timed pass
+    TimeEnd,
+    /// begin a task (see dep_graph::graph::with_task)
+    TaskBegin(DepNode),
+    /// end a task
+    TaskEnd,
+    /// begin a new query
+    QueryBegin(Span, QueryMsg),
+    /// query is satisfied by using an already-known value for the given key
+    CacheHit,
+    /// query requires running a provider; providers may nest, permitting queries to nest.
+    ProviderBegin,
+    /// query is satisfied by a provider terminating with a value
+    ProviderEnd,
+    /// dump a record of the queries to the given path
+    Dump(ProfQDumpParams),
+    /// halt the profiling/monitoring background thread
+    Halt
+}
+
+/// If enabled, send a message to the profile-queries thread
+pub fn profq_msg(msg: ProfileQueriesMsg) {
+    PROFQ_CHAN.with(|sender|{
+        if let Some(s) = sender.borrow().as_ref() {
+            s.send(msg).unwrap()
+        } else {
+            // Do nothing.
+            //
+            // FIXME(matthewhammer): Multi-threaded translation phase triggers the panic below.
+            // From backtrace: rustc_trans::back::write::spawn_work::{{closure}}.
+            //
+            // panic!("no channel on which to send profq_msg: {:?}", msg)
+        }
+    })
+}
+
+/// Set channel for profile queries channel
+pub fn profq_set_chan(s: Sender<ProfileQueriesMsg>) -> bool {
+    PROFQ_CHAN.with(|chan|{
+        if chan.borrow().is_none() {
+            *chan.borrow_mut() = Some(s);
+            true
+        } else { false }
+    })
+}
+
 /// Read the current depth of `time()` calls. This is used to
 /// encourage indentation across threads.
 pub fn time_depth() -> usize {
@@ -53,9 +124,15 @@ pub fn time<T, F>(do_it: bool, what: &str, f: F) -> T where
         r
     });
 
+    if cfg!(debug_assertions) {
+        profq_msg(ProfileQueriesMsg::TimeBegin(what.to_string()))
+    };
     let start = Instant::now();
     let rv = f();
     let dur = start.elapsed();
+    if cfg!(debug_assertions) {
+        profq_msg(ProfileQueriesMsg::TimeEnd)
+    };
 
     print_time_passes_entry_internal(what, dur);
 
index 3545a77c75de64cde2e5573409b254c6b0bf9734..124c840cc56d63cbf311a8676598e8bb7e8586e6 100644 (file)
@@ -460,18 +460,15 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             // rem <- sig % 10
             // sig <- sig / 10
             let mut rem = 0;
-            for limb in sig.iter_mut().rev() {
-                // We don't have an integer doubly wide than Limb,
-                // so we have to split the divrem on two halves.
-                const HALF_BITS: usize = LIMB_BITS / 2;
-                let mut halves = [*limb & ((1 << HALF_BITS) - 1), *limb >> HALF_BITS];
-                for half in halves.iter_mut().rev() {
-                    *half |= rem << HALF_BITS;
-                    rem = *half % 10;
-                    *half /= 10;
-                }
-                *limb = halves[0] | (halves[1] << HALF_BITS);
-            }
+
+            // Use 64-bit division and remainder, with 32-bit chunks from sig.
+            sig::each_chunk(&mut sig, 32, |chunk| {
+                let chunk = chunk as u32;
+                let combined = ((rem as u64) << 32) | (chunk as u64);
+                rem = (combined % 10) as u8;
+                (combined / 10) as u32 as Limb
+            });
+
             // Reduce the sigificand to avoid wasting time dividing 0's.
             while sig.last() == Some(&0) {
                 sig.pop();
@@ -491,7 +488,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                 exp += 1;
             } else {
                 in_trail = false;
-                buffer.push(b'0' + digit as u8);
+                buffer.push(b'0' + digit);
             }
         }
 
@@ -2065,7 +2062,7 @@ fn from_decimal_string(s: &str, round: Round) -> Result<StatusAnd<Self>, ParseEr
         };
 
         // Attempt dec_sig * 10^dec_exp with increasing precision.
-        let mut attempt = 1;
+        let mut attempt = 0;
         loop {
             let calc_precision = (LIMB_BITS << attempt) - 1;
             attempt += 1;
@@ -2310,6 +2307,17 @@ pub(super) fn is_all_zeros(limbs: &[Limb]) -> bool {
         limbs.iter().all(|&l| l == 0)
     }
 
+    /// One, not zero, based LSB. That is, returns 0 for a zeroed significand.
+    pub(super) fn olsb(limbs: &[Limb]) -> usize {
+        for i in 0..limbs.len() {
+            if limbs[i] != 0 {
+                return i * LIMB_BITS + limbs[i].trailing_zeros() as usize + 1;
+            }
+        }
+
+        0
+    }
+
     /// One, not zero, based MSB. That is, returns 0 for a zeroed significand.
     pub(super) fn omsb(limbs: &[Limb]) -> usize {
         for i in (0..limbs.len()).rev() {
@@ -2468,6 +2476,20 @@ pub(super) fn from_limbs(dst: &mut [Limb], src: &[Limb], precision: usize) -> (L
         }
     }
 
+    /// For every consecutive chunk of `bits` bits from `limbs`,
+    /// going from most significant to the least significant bits,
+    /// call `f` to transform those bits and store the result back.
+    pub(super) fn each_chunk<F: FnMut(Limb) -> Limb>(limbs: &mut [Limb], bits: usize, mut f: F) {
+        assert_eq!(LIMB_BITS % bits, 0);
+        for limb in limbs.iter_mut().rev() {
+            let mut r = 0;
+            for i in (0..LIMB_BITS / bits).rev() {
+                r |= f((*limb >> (i * bits)) & ((1 << bits) - 1)) << (i * bits);
+            }
+            *limb = r;
+        }
+    }
+
     /// Increment in-place, return the carry flag.
     pub(super) fn increment(dst: &mut [Limb]) -> Limb {
         for x in dst {
@@ -2686,10 +2708,6 @@ pub(super) fn div(
         divisor: &mut [Limb],
         precision: usize,
     ) -> Loss {
-        // Zero the quotient before setting bits in it.
-        for x in &mut quotient[..limbs_for_bits(precision)] {
-            *x = 0;
-        }
 
         // Normalize the divisor.
         let bits = precision - omsb(divisor);
@@ -2700,6 +2718,13 @@ pub(super) fn div(
         let bits = precision - omsb(dividend);
         shift_left(dividend, exp, bits);
 
+        // Division by 1.
+        let olsb_divisor = olsb(divisor);
+        if olsb_divisor == precision {
+            quotient.copy_from_slice(dividend);
+            return Loss::ExactlyZero;
+        }
+
         // Ensure the dividend >= divisor initially for the loop below.
         // Incidentally, this means that the division loop below is
         // guaranteed to set the integer bit to one.
@@ -2708,6 +2733,58 @@ pub(super) fn div(
             assert_ne!(cmp(dividend, divisor), Ordering::Less)
         }
 
+        // Helper for figuring out the lost fraction.
+        let lost_fraction = |dividend: &[Limb], divisor: &[Limb]| {
+            match cmp(dividend, divisor) {
+                Ordering::Greater => Loss::MoreThanHalf,
+                Ordering::Equal => Loss::ExactlyHalf,
+                Ordering::Less => {
+                    if is_all_zeros(dividend) {
+                        Loss::ExactlyZero
+                    } else {
+                        Loss::LessThanHalf
+                    }
+                }
+            }
+        };
+
+        // Try to perform a (much faster) short division for small divisors.
+        let divisor_bits = precision - (olsb_divisor - 1);
+        macro_rules! try_short_div {
+            ($W:ty, $H:ty, $half:expr) => {
+                if divisor_bits * 2 <= $half {
+                    // Extract the small divisor.
+                    let _: Loss = shift_right(divisor, &mut 0, olsb_divisor - 1);
+                    let divisor = divisor[0] as $H as $W;
+
+                    // Shift the dividend to produce a quotient with the unit bit set.
+                    let top_limb = *dividend.last().unwrap();
+                    let mut rem = (top_limb >> (LIMB_BITS - (divisor_bits - 1))) as $H;
+                    shift_left(dividend, &mut 0, divisor_bits - 1);
+
+                    // Apply short division in place on $H (of $half bits) chunks.
+                    each_chunk(dividend, $half, |chunk| {
+                        let chunk = chunk as $H;
+                        let combined = ((rem as $W) << $half) | (chunk as $W);
+                        rem = (combined % divisor) as $H;
+                        (combined / divisor) as $H as Limb
+                    });
+                    quotient.copy_from_slice(dividend);
+
+                    return lost_fraction(&[(rem as Limb) << 1], &[divisor as Limb]);
+                }
+            }
+        }
+
+        try_short_div!(u32, u16, 16);
+        try_short_div!(u64, u32, 32);
+        try_short_div!(u128, u64, 64);
+
+        // Zero the quotient before setting bits in it.
+        for x in &mut quotient[..limbs_for_bits(precision)] {
+            *x = 0;
+        }
+
         // Long division.
         for bit in (0..precision).rev() {
             if cmp(dividend, divisor) != Ordering::Less {
@@ -2717,17 +2794,6 @@ pub(super) fn div(
             shift_left(dividend, &mut 0, 1);
         }
 
-        // Figure out the lost fraction.
-        match cmp(dividend, divisor) {
-            Ordering::Greater => Loss::MoreThanHalf,
-            Ordering::Equal => Loss::ExactlyHalf,
-            Ordering::Less => {
-                if is_all_zeros(dividend) {
-                    Loss::ExactlyZero
-                } else {
-                    Loss::LessThanHalf
-                }
-            }
-        }
+        lost_fraction(dividend, divisor)
     }
 }
index d9dbf787856520f2d508c1fa870898f6f2093325..d4a020657616a05c93cd023cc9a2708e3a0811f8 100644 (file)
@@ -39,7 +39,6 @@
 //!
 //! This API is completely unstable and subject to change.
 
-#![crate_name = "rustc_apfloat"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
index 55b39f226701fb450f5120b32b8021c26240022b..6a9833d3784a487c637661e9f98312b179aec187 100644 (file)
@@ -21,9 +21,6 @@
 //! one that doesn't; the one that doesn't might get decent parallel
 //! build speedups.
 
-#![crate_name = "rustc_back"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
index 21410dcd4126448967a4aa3e40434ce3aad81d46..112f424f7a8bb46b64f56984bc2f9d108fae44f4 100644 (file)
@@ -20,7 +20,6 @@ pub fn opts() -> TargetOptions {
         target_family: Some("unix".to_string()),
         relro_level: RelroLevel::Full,
         linker_is_gnu: true,
-        no_integrated_as: true,
         .. Default::default()
     }
 }
index d95f6fa97cf422ce26e0bcb502f8c0065fb07074..31d428d2668395e4830ae934ec12495617abd241 100644 (file)
 use LinkerFlavor;
 use target::{LinkArgs, TargetOptions};
 use std::default::Default;
+use std::env;
+use std::process::Command;
 
-pub fn opts() -> TargetOptions {
+// Use GCC to locate code for crt* libraries from the host, not from L4Re. Note
+// that a few files also come from L4Re, for these, the function shouldn't be
+// used. This uses GCC for the location of the file, but GCC is required for L4Re anyway.
+fn get_path_or(filename: &str) -> String {
+    let child = Command::new("gcc")
+        .arg(format!("-print-file-name={}", filename)).output()
+        .expect("Failed to execute GCC");
+    String::from_utf8(child.stdout)
+        .expect("Couldn't read path from GCC").trim().into()
+}
+
+pub fn opts() -> Result<TargetOptions, String> {
+    let l4re_lib_path = env::var_os("L4RE_LIBDIR").ok_or("Unable to find L4Re \
+        library directory: L4RE_LIBDIR not set.")?.into_string().unwrap();
     let mut pre_link_args = LinkArgs::new();
     pre_link_args.insert(LinkerFlavor::Ld, vec![
-            "-nostdlib".to_string(),
+        format!("-T{}/main_stat.ld", l4re_lib_path),
+        "--defsym=__executable_start=0x01000000".to_string(),
+        "--defsym=__L4_KIP_ADDR__=0x6ffff000".to_string(),
+        format!("{}/crt1.o", l4re_lib_path),
+        format!("{}/crti.o", l4re_lib_path),
+        get_path_or("crtbeginT.o"),
+    ]);
+    let mut post_link_args = LinkArgs::new();
+    post_link_args.insert(LinkerFlavor::Ld, vec![
+        format!("{}/l4f/libpthread.a", l4re_lib_path),
+        format!("{}/l4f/libc_be_sig.a", l4re_lib_path),
+        format!("{}/l4f/libc_be_sig_noop.a", l4re_lib_path),
+        format!("{}/l4f/libc_be_socket_noop.a", l4re_lib_path),
+        format!("{}/l4f/libc_be_fs_noop.a", l4re_lib_path),
+        format!("{}/l4f/libc_be_sem_noop.a", l4re_lib_path),
+        format!("{}/l4f/libl4re-vfs.o.a", l4re_lib_path),
+        format!("{}/l4f/lib4re.a", l4re_lib_path),
+        format!("{}/l4f/lib4re-util.a", l4re_lib_path),
+        format!("{}/l4f/libc_support_misc.a", l4re_lib_path),
+        format!("{}/l4f/libsupc++.a", l4re_lib_path),
+        format!("{}/l4f/lib4shmc.a", l4re_lib_path),
+        format!("{}/l4f/lib4re-c.a", l4re_lib_path),
+        format!("{}/l4f/lib4re-c-util.a", l4re_lib_path),
+        get_path_or("libgcc_eh.a"),
+        format!("{}/l4f/libdl.a", l4re_lib_path),
+        "--start-group".to_string(),
+        format!("{}/l4f/libl4util.a", l4re_lib_path),
+        format!("{}/l4f/libc_be_l4re.a", l4re_lib_path),
+        format!("{}/l4f/libuc_c.a", l4re_lib_path),
+        format!("{}/l4f/libc_be_l4refile.a", l4re_lib_path),
+        "--end-group".to_string(),
+        format!("{}/l4f/libl4sys.a", l4re_lib_path),
+        "-gc-sections".to_string(),
+        get_path_or("crtend.o"),
+        format!("{}/crtn.o", l4re_lib_path),
     ]);
 
-    TargetOptions {
+    Ok(TargetOptions {
         executables: true,
         has_elf_tls: false,
-        exe_allocation_crate: Some("alloc_system".to_string()),
+        exe_allocation_crate: None,
         panic_strategy: PanicStrategy::Abort,
         linker: "ld".to_string(),
         pre_link_args,
+        post_link_args,
         target_family: Some("unix".to_string()),
         .. Default::default()
-    }
+    })
 }
index b447f8a989db64839287cf83fb20147f1ff45769..99d3171e1c0e0f9dc1eef6f7d616dc9e5c28f77c 100644 (file)
@@ -12,7 +12,7 @@
 use target::{Target, TargetResult};
 
 pub fn target() -> TargetResult {
-    let mut base = super::l4re_base::opts();
+    let mut base = super::l4re_base::opts()?;
     base.cpu = "x86-64".to_string();
     base.max_atomic_width = Some(64);
 
index 731256557929d20d12fb57179220f44a70469c1b..eb47144d1f995f5431ad9d366776afdcd4767175 100644 (file)
@@ -9,8 +9,6 @@
 // except according to those terms.
 
 
-#![crate_name = "rustc_bitflags"]
-#![crate_type = "rlib"]
 #![no_std]
 #![deny(warnings)]
 
index af99c0e938724d95023ff8c3831fdbb6e3d44670..25f02537490fa8d694a52ff0a366692622c54d45 100644 (file)
@@ -15,6 +15,5 @@ syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
 graphviz = { path = "../libgraphviz" }
 rustc = { path = "../librustc" }
-rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_mir = { path = "../librustc_mir" }
 rustc_errors = { path = "../librustc_errors" }
index 7a77939faa3e7a4b430b4205a7f22dba88fc8181..9bedbfed5db6d3039b3e3a61dfe926042cb28521 100644 (file)
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![crate_name = "rustc_borrowck"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
@@ -31,9 +28,7 @@
 extern crate graphviz as dot;
 #[macro_use]
 extern crate rustc;
-extern crate rustc_data_structures;
 extern crate rustc_mir;
-extern crate core; // for NonZero
 
 pub use borrowck::check_crate;
 pub use borrowck::build_borrowck_dataflow_data_for_fn;
index 3483752d4ff01854731ae29423e3867f429595db..9fedee80d46a8e748804199cc2b621075ed8b787 100644 (file)
@@ -14,9 +14,6 @@
 //!
 //! This API is completely unstable and subject to change.
 
-#![crate_name = "rustc_const_eval"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
index 3947edecb5aff20215fe82888e3e4534b5660ce4..93b70ef8e4a5856a1e13a3f1529bd003373bae56 100644 (file)
@@ -14,9 +14,6 @@
 //!
 //! This API is completely unstable and subject to change.
 
-#![crate_name = "rustc_const_math"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
index 54eed6dc92a77442c388fc1651aa812076311020..da00ebc4b9ee90a21b4dd3050a2907ceef226cfd 100644 (file)
@@ -16,9 +16,6 @@
 //!
 //! This API is completely unstable and subject to change.
 
-#![crate_name = "rustc_data_structures"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://www.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
index 246fc7fc5241b9c3a8d31b03abd48162800e128e..96688c6ac9cdb07afd45f6f0bf0c514e7128028f 100644 (file)
@@ -64,6 +64,8 @@
 
 use derive_registrar;
 
+use profile;
+
 pub fn compile_input(sess: &Session,
                      cstore: &CStore,
                      input: &Input,
@@ -105,6 +107,10 @@ macro_rules! controller_entry_point {
         sess.abort_if_errors();
     }
 
+    if sess.profile_queries() {
+        profile::begin();
+    }
+
     // We need nested scopes here, because the intermediate results can keep
     // large chunks of memory alive and we want to free them as soon as
     // possible to keep the peak memory usage low
@@ -537,6 +543,10 @@ pub fn phase_1_parse_input<'a>(control: &CompileController,
                                -> PResult<'a, ast::Crate> {
     sess.diagnostic().set_continue_after_error(control.continue_parse_after_error);
 
+    if sess.profile_queries() {
+        profile::begin();
+    }
+
     let krate = time(sess.time_passes(), "parsing", || {
         match *input {
             Input::File(ref file) => {
@@ -833,10 +843,6 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
         })
     })?;
 
-    time(time_passes,
-         "early lint checks",
-         || lint::check_ast_crate(sess, &krate));
-
     // Lower ast -> hir.
     let hir_forest = time(time_passes, "lowering ast -> hir", || {
         let hir_crate = lower_crate(sess, &krate, &mut resolver);
@@ -848,6 +854,10 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
         hir_map::Forest::new(hir_crate, &sess.dep_graph)
     });
 
+    time(time_passes,
+         "early lint checks",
+         || lint::check_ast_crate(sess, &krate));
+
     // Discard hygiene data, which isn't required after lowering to HIR.
     if !keep_hygiene_data(sess) {
         syntax::ext::hygiene::clear_markings();
@@ -867,6 +877,7 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
             export_map: resolver.export_map,
             trait_map: resolver.trait_map,
             maybe_unused_trait_imports: resolver.maybe_unused_trait_imports,
+            maybe_unused_extern_crates: resolver.maybe_unused_extern_crates,
         },
         hir_forest,
     })
@@ -1120,6 +1131,10 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
              "translation",
              move || trans::trans_crate(tcx, analysis, incremental_hashes_map, output_filenames));
 
+    if tcx.sess.profile_queries() {
+        profile::dump("profile_queries".to_string())
+    }
+
     translation
 }
 
index 64f61b65323c05b4f325a14d1e9eeaf502fd0ecc..1915a1c86484a6148239c3714882c42fe49a9ce8 100644 (file)
 //!
 //! This API is completely unstable and subject to change.
 
-#![crate_name = "rustc_driver"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![deny(warnings)]
 
 #![feature(box_syntax)]
-#![feature(libc)]
+#![cfg_attr(unix, feature(libc))]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(set_stdio)]
@@ -32,6 +29,7 @@
 extern crate getopts;
 extern crate graphviz;
 extern crate env_logger;
+#[cfg(unix)]
 extern crate libc;
 extern crate rustc;
 extern crate rustc_allocator;
 #[cfg(test)]
 mod test;
 
+pub mod profile;
 pub mod driver;
 pub mod pretty;
 pub mod target_features;
diff --git a/src/librustc_driver/profile/mod.rs b/src/librustc_driver/profile/mod.rs
new file mode 100644 (file)
index 0000000..061077d
--- /dev/null
@@ -0,0 +1,316 @@
+// Copyright 2012-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.
+
+use rustc::util::common::{ProfQDumpParams, ProfileQueriesMsg, profq_msg, profq_set_chan};
+use std::sync::mpsc::{Receiver};
+use std::io::{Write};
+use rustc::dep_graph::{DepNode};
+use std::time::{Duration, Instant};
+
+pub mod trace;
+
+/// begin a profile thread, if not already running
+pub fn begin() {
+    use std::thread;
+    use std::sync::mpsc::{channel};
+    let (tx, rx) = channel();
+    if profq_set_chan(tx) {
+        thread::spawn(move||profile_queries_thread(rx));
+    }
+}
+
+/// dump files with profiling information to the given base path, and
+/// wait for this dump to complete.
+///
+/// wraps the RPC (send/recv channel logic) of requesting a dump.
+pub fn dump(path:String) {
+    use std::sync::mpsc::{channel};
+    let (tx, rx) = channel();
+    let params = ProfQDumpParams{
+        path, ack:tx,
+        // FIXME: Add another compiler flag to toggle whether this log
+        // is written; false for now
+        dump_profq_msg_log:true,
+    };
+    profq_msg(ProfileQueriesMsg::Dump(params));
+    let _ = rx.recv().unwrap();
+}
+
+// State for parsing recursive trace structure in separate thread, via messages
+#[derive(Clone, Eq, PartialEq)]
+enum ParseState {
+    // No (local) parse state; may be parsing a tree, focused on a
+    // sub-tree that could be anything.
+    Clear,
+    // Have Query information from the last message
+    HaveQuery(trace::Query, Instant),
+    // Have "time-begin" information from the last message (doit flag, and message)
+    HaveTimeBegin(String, Instant),
+    // Have "task-begin" information from the last message
+    HaveTaskBegin(DepNode, Instant),
+}
+struct StackFrame {
+    pub parse_st: ParseState,
+    pub traces:   Vec<trace::Rec>,
+}
+
+fn total_duration(traces: &Vec<trace::Rec>) -> Duration {
+    let mut sum : Duration = Duration::new(0,0);
+    for t in traces.iter() { sum += t.dur_total; }
+    return sum
+}
+
+// profiling thread; retains state (in local variables) and dump traces, upon request.
+fn profile_queries_thread(r:Receiver<ProfileQueriesMsg>) {
+    use self::trace::*;
+    use std::fs::File;
+    use std::time::{Instant};
+
+    let mut profq_msgs : Vec<ProfileQueriesMsg> = vec![];
+    let mut frame : StackFrame = StackFrame{ parse_st:ParseState::Clear, traces:vec![] };
+    let mut stack : Vec<StackFrame> = vec![];
+    loop {
+        let msg = r.recv();
+        if let Err(_recv_err) = msg {
+            // FIXME: Perhaps do something smarter than simply quitting?
+            break
+        };
+        let msg = msg.unwrap();
+        debug!("profile_queries_thread: {:?}", msg);
+
+        // Meta-level versus _actual_ queries messages
+        match msg {
+            ProfileQueriesMsg::Halt => return,
+            ProfileQueriesMsg::Dump(params) => {
+                assert!(stack.len() == 0);
+                assert!(frame.parse_st == ParseState::Clear);
+                {
+                    // write log of all messages
+                    if params.dump_profq_msg_log {
+                        let mut log_file =
+                            File::create(format!("{}.log.txt", params.path)).unwrap();
+                        for m in profq_msgs.iter() {
+                            writeln!(&mut log_file, "{:?}", m).unwrap()
+                        };
+                    }
+
+                    // write HTML file, and counts file
+                    let html_path = format!("{}.html", params.path);
+                    let mut html_file = File::create(&html_path).unwrap();
+
+                    let counts_path = format!("{}.counts.txt", params.path);
+                    let mut counts_file = File::create(&counts_path).unwrap();
+
+                    write!(html_file, "<html>\n").unwrap();
+                    write!(html_file,
+                           "<head>\n<link rel=\"stylesheet\" type=\"text/css\" href=\"{}\">\n",
+                           "profile_queries.css").unwrap();
+                    write!(html_file, "<style>\n").unwrap();
+                    trace::write_style(&mut html_file);
+                    write!(html_file, "</style>\n").unwrap();
+                    write!(html_file, "</head>\n").unwrap();
+                    write!(html_file, "<body>\n").unwrap();
+                    trace::write_traces(&mut html_file, &mut counts_file, &frame.traces);
+                    write!(html_file, "</body>\n</html>\n").unwrap();
+
+                    let ack_path = format!("{}.ack", params.path);
+                    let ack_file = File::create(&ack_path).unwrap();
+                    drop(ack_file);
+
+                    // Tell main thread that we are done, e.g., so it can exit
+                    params.ack.send(()).unwrap();
+                }
+                continue
+            }
+            // Actual query message:
+            msg => {
+                // Record msg in our log
+                profq_msgs.push(msg.clone());
+                // Respond to the message, knowing that we've already handled Halt and Dump, above.
+                match (frame.parse_st.clone(), msg) {
+                    (_,ProfileQueriesMsg::Halt) => unreachable!(),
+                    (_,ProfileQueriesMsg::Dump(_)) => unreachable!(),
+
+                    // Parse State: Clear
+                    (ParseState::Clear,
+                     ProfileQueriesMsg::QueryBegin(span,querymsg)) => {
+                        let start = Instant::now();
+                        frame.parse_st = ParseState::HaveQuery
+                            (Query{span:span, msg:querymsg}, start)
+                    },
+                    (ParseState::Clear,
+                     ProfileQueriesMsg::CacheHit) => {
+                        panic!("parse error: unexpected CacheHit; expected QueryBegin")
+                    },
+                    (ParseState::Clear,
+                     ProfileQueriesMsg::ProviderBegin) => {
+                        panic!("parse error: expected QueryBegin before beginning a provider")
+                    },
+                    (ParseState::Clear,
+                     ProfileQueriesMsg::ProviderEnd) => {
+                        let provider_extent = frame.traces;
+                        match stack.pop() {
+                            None =>
+                                panic!("parse error: expected a stack frame; found an empty stack"),
+                            Some(old_frame) => {
+                                match old_frame.parse_st {
+                                    ParseState::HaveQuery(q, start) => {
+                                        let duration = start.elapsed();
+                                        frame = StackFrame{
+                                            parse_st:ParseState::Clear,
+                                            traces:old_frame.traces
+                                        };
+                                        let dur_extent = total_duration(&provider_extent);
+                                        let trace = Rec {
+                                            effect: Effect::QueryBegin(q, CacheCase::Miss),
+                                            extent: Box::new(provider_extent),
+                                            start: start,
+                                            dur_self: duration - dur_extent,
+                                            dur_total: duration,
+                                        };
+                                        frame.traces.push( trace );
+                                    },
+                                    _ => panic!("internal parse error: malformed parse stack")
+                                }
+                            }
+                        }
+                    },
+
+
+                    (ParseState::Clear,
+                     ProfileQueriesMsg::TimeBegin(msg)) => {
+                        let start = Instant::now();
+                        frame.parse_st = ParseState::HaveTimeBegin(msg, start);
+                        stack.push(frame);
+                        frame = StackFrame{parse_st:ParseState::Clear, traces:vec![]};
+                    },
+                    (_, ProfileQueriesMsg::TimeBegin(_)) =>
+                        panic!("parse error; did not expect time begin here"),
+
+                    (ParseState::Clear,
+                     ProfileQueriesMsg::TimeEnd) => {
+                        let provider_extent = frame.traces;
+                        match stack.pop() {
+                            None =>
+                                panic!("parse error: expected a stack frame; found an empty stack"),
+                            Some(old_frame) => {
+                                match old_frame.parse_st {
+                                    ParseState::HaveTimeBegin(msg, start) => {
+                                        let duration = start.elapsed();
+                                        frame = StackFrame{
+                                            parse_st:ParseState::Clear,
+                                            traces:old_frame.traces
+                                        };
+                                        let dur_extent = total_duration(&provider_extent);
+                                        let trace = Rec {
+                                            effect: Effect::TimeBegin(msg),
+                                            extent: Box::new(provider_extent),
+                                            start: start,
+                                            dur_total: duration,
+                                            dur_self: duration - dur_extent,
+                                        };
+                                        frame.traces.push( trace );
+                                    },
+                                    _ => panic!("internal parse error: malformed parse stack")
+                                }
+                            }
+                        }
+                    },
+                    (_, ProfileQueriesMsg::TimeEnd) => { panic!("parse error") }
+
+                    (ParseState::Clear,
+                     ProfileQueriesMsg::TaskBegin(key)) => {
+                        let start = Instant::now();
+                        frame.parse_st = ParseState::HaveTaskBegin(key, start);
+                        stack.push(frame);
+                        frame = StackFrame{parse_st:ParseState::Clear, traces:vec![]};
+                    },
+                    (_, ProfileQueriesMsg::TaskBegin(_)) =>
+                        panic!("parse error; did not expect time begin here"),
+
+                    (ParseState::Clear,
+                     ProfileQueriesMsg::TaskEnd) => {
+                        let provider_extent = frame.traces;
+                        match stack.pop() {
+                            None =>
+                                panic!("parse error: expected a stack frame; found an empty stack"),
+                            Some(old_frame) => {
+                                match old_frame.parse_st {
+                                    ParseState::HaveTaskBegin(key, start) => {
+                                        let duration = start.elapsed();
+                                        frame = StackFrame{
+                                            parse_st:ParseState::Clear,
+                                            traces:old_frame.traces
+                                        };
+                                        let dur_extent = total_duration(&provider_extent);
+                                        let trace = Rec {
+                                            effect: Effect::TaskBegin(key),
+                                            extent: Box::new(provider_extent),
+                                            start: start,
+                                            dur_total: duration,
+                                            dur_self: duration - dur_extent,
+                                        };
+                                        frame.traces.push( trace );
+                                    },
+                                    _ => panic!("internal parse error: malformed parse stack")
+                                }
+                            }
+                        }
+                    },
+                    (_, ProfileQueriesMsg::TaskEnd) => { panic!("parse error") }
+
+                    // Parse State: HaveQuery
+                    (ParseState::HaveQuery(q,start),
+                     ProfileQueriesMsg::CacheHit) => {
+                        let duration = start.elapsed();
+                        let trace : Rec = Rec{
+                            effect: Effect::QueryBegin(q, CacheCase::Hit),
+                            extent: Box::new(vec![]),
+                            start: start,
+                            dur_self: duration,
+                            dur_total: duration,
+                        };
+                        frame.traces.push( trace );
+                        frame.parse_st = ParseState::Clear;
+                    },
+                    (ParseState::HaveQuery(_,_),
+                     ProfileQueriesMsg::ProviderBegin) => {
+                        stack.push(frame);
+                        frame = StackFrame{parse_st:ParseState::Clear, traces:vec![]};
+                    },
+
+                    //
+                    //
+                    // Parse errors:
+
+                    (ParseState::HaveQuery(q,_),
+                     ProfileQueriesMsg::ProviderEnd) => {
+                        panic!("parse error: unexpected ProviderEnd; \
+                                expected something else to follow BeginQuery for {:?}", q)
+                    },
+                    (ParseState::HaveQuery(q1,_),
+                     ProfileQueriesMsg::QueryBegin(span2,querymsg2)) => {
+                        panic!("parse error: unexpected QueryBegin; \
+                                earlier query is unfinished: {:?} and now {:?}",
+                               q1, Query{span:span2, msg:querymsg2})
+                    },
+
+                    (ParseState::HaveTimeBegin(_, _), _) => {
+                        unreachable!()
+                    },
+                    (ParseState::HaveTaskBegin(_, _), _) => {
+                        unreachable!()
+                    },
+                }
+
+            }
+        }
+    }
+}
diff --git a/src/librustc_driver/profile/trace.rs b/src/librustc_driver/profile/trace.rs
new file mode 100644 (file)
index 0000000..f507983
--- /dev/null
@@ -0,0 +1,315 @@
+// Copyright 2012-2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use super::*;
+use syntax_pos::Span;
+use rustc::ty::maps::QueryMsg;
+use std::fs::File;
+use std::time::{Duration, Instant};
+use std::collections::hash_map::HashMap;
+use rustc::dep_graph::{DepNode};
+
+#[derive(Debug, Clone, Eq, PartialEq)]
+pub struct Query {
+    pub span: Span,
+    pub msg: QueryMsg,
+}
+pub enum Effect {
+    QueryBegin(Query, CacheCase),
+    TimeBegin(String),
+    TaskBegin(DepNode),
+}
+pub enum CacheCase {
+    Hit, Miss
+}
+/// Recursive trace structure
+pub struct Rec {
+    pub effect: Effect,
+    pub start: Instant,
+    pub dur_self: Duration,
+    pub dur_total: Duration,
+    pub extent: Box<Vec<Rec>>,
+}
+pub struct QueryMetric {
+    pub count: usize,
+    pub dur_self: Duration,
+    pub dur_total: Duration,
+}
+
+pub fn cons_of_query_msg(q: &trace::Query) -> String {
+    let s = format!("{:?}", q.msg);
+    let cons: Vec<&str> = s.split(|d| d == '(' || d == '{').collect();
+    assert!(cons.len() > 0 && cons[0] != "");
+    cons[0].to_string()
+}
+
+pub fn cons_of_key(k: &DepNode) -> String {
+    let s = format!("{:?}", k);
+    let cons: Vec<&str> = s.split(|d| d == '(' || d == '{').collect();
+    assert!(cons.len() > 0 && cons[0] != "");
+    cons[0].to_string()
+}
+
+// First return value is text; second return value is a CSS class
+pub fn html_of_effect(eff: &Effect) -> (String, String) {
+    match *eff {
+        Effect::TimeBegin(ref msg) => {
+            (msg.clone(),
+             format!("time-begin"))
+        },
+        Effect::TaskBegin(ref key) => {
+            let cons = cons_of_key(key);
+            (cons.clone(), format!("{} task-begin", cons))
+        },
+        Effect::QueryBegin(ref qmsg, ref cc) => {
+            let cons = cons_of_query_msg(qmsg);
+            (cons.clone(),
+             format!("{} {}",
+                     cons,
+                     match *cc {
+                         CacheCase::Hit => "hit",
+                         CacheCase::Miss => "miss",
+                     }))
+        }
+    }
+}
+
+// First return value is text; second return value is a CSS class
+fn html_of_duration(_start: &Instant, dur: &Duration) -> (String, String) {
+    use rustc::util::common::duration_to_secs_str;
+    (duration_to_secs_str(dur.clone()),
+     "".to_string()
+    )
+}
+
+fn html_of_fraction(frac: f64) -> (String, String) {
+    let css = {
+        if       frac > 0.50  { format!("frac-50") }
+        else if  frac > 0.40  { format!("frac-40") }
+        else if  frac > 0.30  { format!("frac-30") }
+        else if  frac > 0.20  { format!("frac-20") }
+        else if  frac > 0.10  { format!("frac-10") }
+        else if  frac > 0.05  { format!("frac-05") }
+        else if  frac > 0.02  { format!("frac-02") }
+        else if  frac > 0.01  { format!("frac-01") }
+        else if  frac > 0.001 { format!("frac-001") }
+        else                  { format!("frac-0") }
+    };
+    let percent = frac * 100.0;
+    if percent > 0.1 { (format!("{:.1}%", percent), css) }
+    else { (format!("< 0.1%", ), css) }
+}
+
+fn total_duration(traces: &Vec<Rec>) -> Duration {
+    let mut sum : Duration = Duration::new(0,0);
+    for t in traces.iter() {
+        sum += t.dur_total;
+    }
+    return sum
+}
+
+fn duration_div(nom: Duration, den: Duration) -> f64 {
+    fn to_nanos(d: Duration) -> u64 {
+        d.as_secs() * 1_000_000_000 + d.subsec_nanos() as u64
+    }
+
+    to_nanos(nom) as f64 / to_nanos(den) as f64
+}
+
+fn write_traces_rec(file: &mut File, traces: &Vec<Rec>, total: Duration, depth: usize) {
+    for t in traces {
+        let (eff_text, eff_css_classes) = html_of_effect(&t.effect);
+        let (dur_text, dur_css_classes) = html_of_duration(&t.start, &t.dur_total);
+        let fraction = duration_div(t.dur_total, total);
+        let percent = fraction * 100.0;
+        let (frc_text, frc_css_classes) = html_of_fraction(fraction);
+        write!(file, "<div class=\"trace depth-{} extent-{}{} {} {} {}\">\n",
+               depth,
+               t.extent.len(),
+               /* Heuristic for 'important' CSS class: */
+               if t.extent.len() > 5 || percent >= 1.0 {
+                   " important" }
+               else { "" },
+               eff_css_classes,
+               dur_css_classes,
+               frc_css_classes,
+        ).unwrap();
+        write!(file, "<div class=\"eff\">{}</div>\n", eff_text).unwrap();
+        write!(file, "<div class=\"dur\">{}</div>\n", dur_text).unwrap();
+        write!(file, "<div class=\"frc\">{}</div>\n", frc_text).unwrap();
+        write_traces_rec(file, &t.extent, total, depth + 1);
+        write!(file, "</div>\n").unwrap();
+    }
+}
+
+fn compute_counts_rec(counts: &mut HashMap<String,QueryMetric>, traces: &Vec<Rec>) {
+    for t in traces.iter() {
+        match t.effect {
+            Effect::TimeBegin(ref msg) => {
+                let qm = match counts.get(msg) {
+                    Some(_qm) => { panic!("TimeBegin with non-unique, repeat message") }
+                    None => QueryMetric{
+                        count: 1,
+                        dur_self: t.dur_self,
+                        dur_total: t.dur_total,
+                    }};
+                counts.insert(msg.clone(), qm);
+            },
+            Effect::TaskBegin(ref key) => {
+                let cons = cons_of_key(key);
+                let qm = match counts.get(&cons) {
+                    Some(qm) =>
+                        QueryMetric{
+                            count: qm.count + 1,
+                            dur_self: qm.dur_self + t.dur_self,
+                            dur_total: qm.dur_total + t.dur_total,
+                        },
+                    None => QueryMetric{
+                        count: 1,
+                        dur_self: t.dur_self,
+                        dur_total: t.dur_total,
+                    }};
+                counts.insert(cons, qm);
+            },
+            Effect::QueryBegin(ref qmsg, ref _cc) => {
+                let qcons = cons_of_query_msg(qmsg);
+                let qm = match counts.get(&qcons) {
+                    Some(qm) =>
+                        QueryMetric{
+                            count: qm.count + 1,
+                            dur_total: qm.dur_total + t.dur_total,
+                            dur_self: qm.dur_self + t.dur_self
+                        },
+                    None => QueryMetric{
+                        count: 1,
+                        dur_total: t.dur_total,
+                        dur_self: t.dur_self,
+                    }
+                };
+                counts.insert(qcons, qm);
+            }
+        }
+        compute_counts_rec(counts, &t.extent)
+    }
+}
+
+pub fn write_counts(count_file: &mut File, counts: &mut HashMap<String,QueryMetric>) {
+    use rustc::util::common::duration_to_secs_str;
+    use std::cmp::Ordering;
+
+    let mut data = vec![];
+    for (ref cons, ref qm) in counts.iter() {
+        data.push((cons.clone(), qm.count.clone(), qm.dur_total.clone(), qm.dur_self.clone()));
+    };
+    data.sort_by(|&(_,_,_,self1),&(_,_,_,self2)|
+                 if self1 > self2 { Ordering::Less } else { Ordering::Greater } );
+    for (cons, count, dur_total, dur_self) in data {
+        write!(count_file, "{}, {}, {}, {}\n",
+               cons, count,
+               duration_to_secs_str(dur_total),
+               duration_to_secs_str(dur_self)
+        ).unwrap();
+    }
+}
+
+pub fn write_traces(html_file: &mut File, counts_file: &mut File, traces: &Vec<Rec>) {
+    let mut counts : HashMap<String,QueryMetric> = HashMap::new();
+    compute_counts_rec(&mut counts, traces);
+    write_counts(counts_file, &mut counts);
+
+    let total : Duration = total_duration(traces);
+    write_traces_rec(html_file, traces, total, 0)
+}
+
+pub fn write_style(html_file: &mut File) {
+    write!(html_file,"{}", "
+body {
+    font-family: sans-serif;
+    background: black;
+}
+.trace {
+    color: black;
+    display: inline-block;
+    border-style: solid;
+    border-color: red;
+    border-width: 1px;
+    border-radius: 5px;
+    padding: 0px;
+    margin: 1px;
+    font-size: 0px;
+}
+.task-begin {
+    border-width: 1px;
+    color: white;
+    border-color: #ff8;
+    font-size: 0px;
+}
+.miss {
+    border-color: red;
+    border-width: 1px;
+}
+.extent-0 {
+    padding: 2px;
+}
+.time-begin {
+    border-width: 4px;
+    font-size: 12px;
+    color: white;
+    border-color: #afa;
+}
+.important {
+    border-width: 3px;
+    font-size: 12px;
+    color: white;
+    border-color: #f77;
+}
+.hit {
+    padding: 0px;
+    border-color: blue;
+    border-width: 3px;
+}
+.eff {
+  color: #fff;
+  display: inline-block;
+}
+.frc {
+  color: #7f7;
+  display: inline-block;
+}
+.dur {
+  display: none
+}
+.frac-50 {
+  padding: 10px;
+  border-width: 10px;
+  font-size: 32px;
+}
+.frac-40 {
+  padding: 8px;
+  border-width: 8px;
+  font-size: 24px;
+}
+.frac-30 {
+  padding: 6px;
+  border-width: 6px;
+  font-size: 18px;
+}
+.frac-20 {
+  padding: 4px;
+  border-width: 6px;
+  font-size: 16px;
+}
+.frac-10 {
+  padding: 2px;
+  border-width: 6px;
+  font-size: 14px;
+}
+").unwrap();
+}
index 8d7ce4eb4f6d31edc81f9124a2efc39e75ce3da8..2c8d8b4691f0a10356be35771859713d382eb267 100644 (file)
@@ -98,7 +98,7 @@ pub fn emit(&mut self) {
             }
         };
 
-        self.handler.emitter.borrow_mut().emit(&self);
+        self.handler.emit_db(&self);
         self.cancel();
 
         if is_error {
@@ -110,6 +110,22 @@ pub fn emit(&mut self) {
         // }
     }
 
+    /// Delay emission of this diagnostic as a bug.
+    ///
+    /// This can be useful in contexts where an error indicates a bug but
+    /// typically this only happens when other compilation errors have already
+    /// happened. In those cases this can be used to defer emission of this
+    /// diagnostic as a bug in the compiler only if no other errors have been
+    /// emitted.
+    ///
+    /// In the meantime, though, callsites are required to deal with the "bug"
+    /// locally in whichever way makes the most sense.
+    pub fn delay_as_bug(&mut self) {
+        self.level = Level::Bug;
+        *self.handler.delayed_span_bug.borrow_mut() = Some(self.diagnostic.clone());
+        self.cancel();
+    }
+
     /// Add a span/label to be included in the resulting snippet.
     /// This is pushed onto the `MultiSpan` that was created when the
     /// diagnostic was first built. If you don't call this function at
@@ -178,10 +194,15 @@ pub fn new_with_code(handler: &'a Handler,
                          code: Option<String>,
                          message: &str)
                          -> DiagnosticBuilder<'a> {
-        DiagnosticBuilder {
-            handler,
-            diagnostic: Diagnostic::new_with_code(level, code, message)
-        }
+        let diagnostic = Diagnostic::new_with_code(level, code, message);
+        DiagnosticBuilder::new_diagnostic(handler, diagnostic)
+    }
+
+    /// Creates a new `DiagnosticBuilder` with an already constructed
+    /// diagnostic.
+    pub fn new_diagnostic(handler: &'a Handler, diagnostic: Diagnostic)
+                         -> DiagnosticBuilder<'a> {
+        DiagnosticBuilder { handler, diagnostic }
     }
 }
 
index 3b1414ef83a6998ecf285a6e362f9e0e928ae8f2..53d90531cc946a4c043d7c7983200f0f6ffc1228 100644 (file)
@@ -311,7 +311,9 @@ fn render_source_line(&self,
         if line.annotations.len() == 1 {
             if let Some(ref ann) = line.annotations.get(0) {
                 if let AnnotationType::MultilineStart(depth) = ann.annotation_type {
-                    if source_string[0..ann.start_col].trim() == "" {
+                    if source_string.chars()
+                                    .take(ann.start_col)
+                                    .all(|c| c.is_whitespace()) {
                         let style = if ann.is_primary {
                             Style::UnderlinePrimary
                         } else {
index 12b5ccf483762d6e1f9b76c5ec96d59243b365b5..870bb01bb9ffb7963ff6a6b6057721a690e28c31 100644 (file)
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![crate_name = "rustc_errors"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![feature(custom_attribute)]
 #![allow(unused_attributes)]
 #![feature(range_contains)]
-#![feature(libc)]
+#![cfg_attr(unix, feature(libc))]
 #![feature(conservative_impl_trait)]
 
 extern crate term;
+#[cfg(unix)]
 extern crate libc;
 extern crate serialize as rustc_serialize;
 extern crate syntax_pos;
@@ -35,8 +33,9 @@
 
 use std::borrow::Cow;
 use std::cell::{RefCell, Cell};
-use std::{error, fmt};
+use std::mem;
 use std::rc::Rc;
+use std::{error, fmt};
 
 mod diagnostic;
 mod diagnostic_builder;
@@ -274,7 +273,8 @@ pub struct Handler {
     pub can_emit_warnings: bool,
     treat_err_as_bug: bool,
     continue_after_error: Cell<bool>,
-    delayed_span_bug: RefCell<Option<(MultiSpan, String)>>,
+    delayed_span_bug: RefCell<Option<Diagnostic>>,
+    tracked_diagnostics: RefCell<Option<Vec<Diagnostic>>>,
 }
 
 impl Handler {
@@ -298,6 +298,7 @@ pub fn with_emitter(can_emit_warnings: bool,
             treat_err_as_bug,
             continue_after_error: Cell::new(true),
             delayed_span_bug: RefCell::new(None),
+            tracked_diagnostics: RefCell::new(None),
         }
     }
 
@@ -439,8 +440,9 @@ pub fn delay_span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
         if self.treat_err_as_bug {
             self.span_bug(sp, msg);
         }
-        let mut delayed = self.delayed_span_bug.borrow_mut();
-        *delayed = Some((sp.into(), msg.to_string()));
+        let mut diagnostic = Diagnostic::new(Level::Bug, msg);
+        diagnostic.set_span(sp.into());
+        *self.delayed_span_bug.borrow_mut() = Some(diagnostic);
     }
     pub fn span_bug_no_panic<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
         self.emit(&sp.into(), msg, Bug);
@@ -507,14 +509,9 @@ pub fn abort_if_errors(&self) {
         let s;
         match self.err_count.get() {
             0 => {
-                let delayed_bug = self.delayed_span_bug.borrow();
-                match *delayed_bug {
-                    Some((ref span, ref errmsg)) => {
-                        self.span_bug(span.clone(), errmsg);
-                    }
-                    _ => {}
+                if let Some(bug) = self.delayed_span_bug.borrow_mut().take() {
+                    DiagnosticBuilder::new_diagnostic(self, bug).emit();
                 }
-
                 return;
             }
             1 => s = "aborting due to previous error".to_string(),
@@ -547,6 +544,24 @@ pub fn emit_with_code(&self, msp: &MultiSpan, msg: &str, code: &str, lvl: Level)
             self.abort_if_errors();
         }
     }
+
+    pub fn track_diagnostics<F, R>(&self, f: F) -> (R, Vec<Diagnostic>)
+        where F: FnOnce() -> R
+    {
+        let prev = mem::replace(&mut *self.tracked_diagnostics.borrow_mut(),
+                                Some(Vec::new()));
+        let ret = f();
+        let diagnostics = mem::replace(&mut *self.tracked_diagnostics.borrow_mut(), prev)
+            .unwrap();
+        (ret, diagnostics)
+    }
+
+    fn emit_db(&self, db: &DiagnosticBuilder) {
+        if let Some(ref mut list) = *self.tracked_diagnostics.borrow_mut() {
+            list.push((**db).clone());
+        }
+        self.emitter.borrow_mut().emit(db);
+    }
 }
 
 
index c68153140d97ce171a5404a75b857c8bc599422d..8870033095c9c2a1106ddd91d3d88ca049367cb3 100644 (file)
@@ -10,9 +10,6 @@
 
 //! Support for serializing the dep-graph and reloading it.
 
-#![crate_name = "rustc_incremental"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
index 755370b64659dfee03f2c4d1b3915211a9a5f189..5ef277f02ace6b6cb59f4ec0855720c4b0e8aac2 100644 (file)
@@ -19,9 +19,6 @@
 //!
 //! This API is completely unstable and subject to change.
 
-#![crate_name = "rustc_lint"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
index 195bd2acce0fe3ed1ee2ad7837f5eb2a5d23e836..cbc4ebe90fd091070c9ec648f8b049d8905254df 100644 (file)
@@ -160,21 +160,25 @@ fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) {
         };
 
         let mut fn_warned = false;
-        let maybe_def = match expr.node {
-            hir::ExprCall(ref callee, _) => {
-                match callee.node {
-                    hir::ExprPath(ref qpath) => Some(cx.tables.qpath_def(qpath, callee.hir_id)),
-                    _ => None
-                }
-            },
-            hir::ExprMethodCall(..) => {
-                cx.tables.type_dependent_defs().get(expr.hir_id).cloned()
-            },
-            _ => { None }
-        };
-        if let Some(def) = maybe_def {
-            let def_id = def.def_id();
-            fn_warned = check_must_use(cx, def_id, s.span, "return value of ");
+        if cx.tcx.sess.features.borrow().fn_must_use {
+            let maybe_def = match expr.node {
+                hir::ExprCall(ref callee, _) => {
+                    match callee.node {
+                        hir::ExprPath(ref qpath) => {
+                            Some(cx.tables.qpath_def(qpath, callee.hir_id))
+                        },
+                        _ => None
+                    }
+                },
+                hir::ExprMethodCall(..) => {
+                    cx.tables.type_dependent_defs().get(expr.hir_id).cloned()
+                },
+                _ => None
+            };
+            if let Some(def) = maybe_def {
+                let def_id = def.def_id();
+                fn_warned = check_must_use(cx, def_id, s.span, "return value of ");
+            }
         }
 
         if !(ty_warned || fn_warned) {
index 5f12f561faf45086eeb2572ae03b174252952e6a..3c3e627ee4b36e71e5912ab5d1d1388bc699de6a 100644 (file)
@@ -13,9 +13,6 @@
 #![allow(non_snake_case)]
 #![allow(dead_code)]
 
-#![crate_name = "rustc_llvm"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/")]
index 67b459ea18f4af0ed646bfebff099b7e9dfa8b35..40b75be36fefb061c7fcabb5a71f02853b0d2874 100644 (file)
@@ -15,7 +15,6 @@ owning_ref = "0.3.3"
 proc_macro = { path = "../libproc_macro" }
 rustc = { path = "../librustc" }
 rustc_back = { path = "../librustc_back" }
-rustc_const_math = { path = "../librustc_const_math" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_errors = { path = "../librustc_errors" }
 serialize = { path = "../libserialize" }
index cfba11b5151a2ea28fadd6c6baf1d22b7232ae75..ad320a7ff3d1e659f8ee6a52e96bb6b337e3ff62 100644 (file)
@@ -137,6 +137,8 @@ pub fn provide<$lt>(providers: &mut Providers<$lt>) {
 
     dylib_dependency_formats => { Rc::new(cdata.get_dylib_dependency_formats(&tcx.dep_graph)) }
     is_panic_runtime => { cdata.is_panic_runtime(&tcx.dep_graph) }
+    is_compiler_builtins => { cdata.is_compiler_builtins(&tcx.dep_graph) }
+    has_global_allocator => { cdata.has_global_allocator(&tcx.dep_graph) }
     extern_crate => { Rc::new(cdata.extern_crate.get()) }
 }
 
index 5c37333fc7e82d5903ecc58af49540bec498060f..73b2e972b93ca81a803b18e9a695705f16f9ff32 100644 (file)
@@ -892,7 +892,7 @@ pub fn get_item_attrs(&self,
         if def_key.disambiguated_data.data == DefPathData::StructCtor {
             item = self.entry(def_key.parent.unwrap());
         }
-        let result = Rc::__from_array(self.get_attributes(&item).into_boxed_slice());
+        let result: Rc<[ast::Attribute]> = Rc::from(self.get_attributes(&item));
         let vec_ = &mut self.attribute_cache.borrow_mut()[node_as];
         if vec_.len() < node_index + 1 {
             vec_.resize(node_index + 1, None);
index 8fd87ae88a88450c7f0bc915a61ba85685f930b4..f79abecf9da4b3ea2154783762dd7e7cdbeaa0a2 100644 (file)
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![crate_name = "rustc_metadata"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/")]
@@ -42,7 +39,6 @@
 #[macro_use]
 extern crate rustc;
 extern crate rustc_back;
-extern crate rustc_const_math;
 extern crate rustc_data_structures;
 
 mod diagnostics;
index 0324552cd56fd34bef71d04e0d05282f6473d90e..61d128fc847827d2a3adcb7c6dd38d86d46aa614 100644 (file)
@@ -22,10 +22,7 @@ fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Block<'tcx> {
         // We have to eagerly translate the "spine" of the statements
         // in order to get the lexical scoping correctly.
         let stmts = mirror_stmts(cx, self.id, &*self.stmts);
-        let opt_def_id = cx.tcx.hir.opt_local_def_id(self.id);
-        let opt_destruction_extent = opt_def_id.and_then(|def_id| {
-            cx.tcx.region_maps(def_id).opt_destruction_extent(self.id)
-        });
+        let opt_destruction_extent = cx.region_maps.opt_destruction_extent(self.id);
         Block {
             targeted_by_break: self.targeted_by_break,
             extent: CodeExtent::Misc(self.id),
@@ -42,11 +39,8 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                                 stmts: &'tcx [hir::Stmt])
                                 -> Vec<StmtRef<'tcx>> {
     let mut result = vec![];
-    let opt_def_id = cx.tcx.hir.opt_local_def_id(block_id);
     for (index, stmt) in stmts.iter().enumerate() {
-        let opt_dxn_ext = opt_def_id.and_then(|def_id| {
-            cx.tcx.region_maps(def_id).opt_destruction_extent(stmt.node.id())
-        });
+        let opt_dxn_ext = cx.region_maps.opt_destruction_extent(stmt.node.id());
         match stmt.node {
             hir::StmtExpr(ref expr, id) |
             hir::StmtSemi(ref expr, id) => {
index 7aa4679992471fa436bd11324728b22f8ebc25ed..dba625e98fd81db81c4512ea54244cce621b3e29 100644 (file)
@@ -14,9 +14,6 @@
 
 */
 
-#![crate_name = "rustc_mir"]
-#![crate_type = "rlib"]
-#![crate_type = "dylib"]
 #![deny(warnings)]
 
 #![feature(box_patterns)]
index 28aedc8d6749752c12de5a742fd4466c708f123f..53b46dd2683fc512967781990770c188dec83b24 100644 (file)
@@ -115,8 +115,13 @@ fn run_pass(&self, caller_mir: &mut Mir<'tcx>) {
                     Ok(ref callee_mir) if self.should_inline(callsite, callee_mir) => {
                         callee_mir.subst(self.tcx, callsite.substs)
                     }
+                    Ok(_) => continue,
 
-                    _ => continue,
+                    Err(mut bug) => {
+                        // FIXME(#43542) shouldn't have to cancel an error
+                        bug.cancel();
+                        continue
+                    }
                 };
 
                 let start = caller_mir.basic_blocks().len();
index b22f8112d7a38e889a85b8f85c9fb7c8e6f788e5..ffe444933a3b1c04db6599b07ec38b17258b2f1b 100644 (file)
@@ -140,14 +140,6 @@ fn visit_expr(&mut self, expr: &'a Expr) {
             ExprKind::Continue(Some(ident)) => {
                 self.check_label(ident.node, ident.span);
             }
-            ExprKind::MethodCall(ref segment, ..) => {
-                if let Some(ref params) = segment.parameters {
-                    if let PathParameters::Parenthesized(..) = **params {
-                        self.err_handler().span_err(expr.span,
-                            "parenthesized parameters cannot be used on method calls");
-                    }
-                }
-            }
             _ => {}
         }
 
index 6c41aad98d54d64d36fbb26ff856c4aa238a439a..28b99e1185bd2d3738191b98cd317aa188370d64 100644 (file)
@@ -14,9 +14,6 @@
 //!
 //! This API is completely unstable and subject to change.
 
-#![crate_name = "rustc_passes"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/")]
index ef1d9093df20e7bfcb6bf821eafb2d7e125c9985..4cc65ee28e89f703d3ebd261907471b7e0e1fe00 100644 (file)
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![crate_name = "rustc_platform_intrinsics"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![deny(warnings)]
 #![allow(bad_style)]
 
index 602b71dca05aba92af522e92c4a7fd160531b79b..a2a6d183e9ccc3d795980792c8bdc872ded6f31c 100644 (file)
@@ -60,9 +60,6 @@
 //! See the [`plugin` feature](../../unstable-book/language-features/plugin.html) of
 //! the Unstable Book for more examples.
 
-#![crate_name = "rustc_plugin"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/")]
index eb82dddaf56fb6a4bd0f0a468017a8547f40c9c8..772b16bbecfbaa72a17f7e40674aa13e9bbf0d84 100644 (file)
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![crate_name = "rustc_privacy"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/")]
index 05c227340d8685d7e89772f112628eb3fadcdc5d..a66d1ce0859b7efe179eda60087d3c5c7ddf4a7e 100644 (file)
@@ -121,9 +121,7 @@ pub fn check_crate(resolver: &mut Resolver, krate: &ast::Crate) {
                  directive.vis.get() == ty::Visibility::Public ||
                  directive.span.source_equal(&DUMMY_SP) => {}
             ImportDirectiveSubclass::ExternCrate => {
-                let lint = lint::builtin::UNUSED_EXTERN_CRATES;
-                let msg = "unused extern crate";
-             ;   resolver.session.buffer_lint(lint, directive.id, directive.span, msg)
+                resolver.maybe_unused_extern_crates.push((directive.id, directive.span));
             }
             ImportDirectiveSubclass::MacroUse => {
                 let lint = lint::builtin::UNUSED_IMPORTS;
index bfc76ee2f74f67204495d8b0decc56d368496019..a83ac9bb6336958e4d5e6d644f73c30b8fc72743 100644 (file)
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![crate_name = "rustc_resolve"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
@@ -1253,6 +1250,7 @@ pub struct Resolver<'a> {
 
     used_imports: FxHashSet<(NodeId, Namespace)>,
     pub maybe_unused_trait_imports: NodeSet,
+    pub maybe_unused_extern_crates: Vec<(NodeId, Span)>,
 
     /// privacy errors are delayed until the end in order to deduplicate them
     privacy_errors: Vec<PrivacyError<'a>>,
@@ -1460,6 +1458,7 @@ pub fn new(session: &'a Session,
 
             used_imports: FxHashSet(),
             maybe_unused_trait_imports: NodeSet(),
+            maybe_unused_extern_crates: Vec::new(),
 
             privacy_errors: Vec::new(),
             ambiguity_errors: Vec::new(),
index bc9d760d148952c07872be7c172683f8c7bfe350..9b74df865d74756059db8a89d272f6a17a2675d9 100644 (file)
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![crate_name = "rustc_save_analysis"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
index 6da42caf75bef1480a2543da48ef29f02275fe45..1758e331129d52a54d4fc3fb75f9467193e7e6e2 100644 (file)
@@ -14,9 +14,6 @@
 //!
 //! This API is completely unstable and subject to change.
 
-#![crate_name = "rustc_trans"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
index 81e83076f8c0c9812f0059455aa36e08648811d5..90e17906328fbabaa80b047598e614bfef825cca 100644 (file)
@@ -12,9 +12,6 @@
 //!
 //! This API is completely unstable and subject to change.
 
-#![crate_name = "rustc_trans_utils"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
index 97c1181e3a220209e87e11964a668b14a9cb04c5..7b83985ba673167370da3e40d6fb8dd6d9ba5e2f 100644 (file)
@@ -14,5 +14,6 @@ build_helper = { path = "../build_helper" }
 cmake = "0.1.18"
 
 [dependencies]
+alloc = { path = "../liballoc" }
 alloc_system = { path = "../liballoc_system" }
 core = { path = "../libcore" }
index 54941362e845091861e06dba9cabea1e9310cdc2..3429e3bda0f6770bfcb49f84be94a35bc0e23312 100644 (file)
@@ -9,8 +9,10 @@
 // except according to those terms.
 
 #![sanitizer_runtime]
-#![feature(sanitizer_runtime)]
 #![feature(alloc_system)]
+#![feature(allocator_api)]
+#![feature(global_allocator)]
+#![feature(sanitizer_runtime)]
 #![feature(staged_api)]
 #![no_std]
 #![unstable(feature = "sanitizer_runtime_lib",
@@ -18,3 +20,8 @@
             issue = "0")]
 
 extern crate alloc_system;
+
+use alloc_system::System;
+
+#[global_allocator]
+static ALLOC: System = System;
index 32fa0534db618abf994697e9a6f3ea68f906c116..ee1e6bd950fa17e8c8385511d9284b1e7743d73e 100644 (file)
 use rustc::traits;
 use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable};
 use rustc::ty::wf::object_region_bounds;
-use rustc::lint::builtin::PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES;
 use rustc_back::slice;
 use require_c_abi_if_variadic;
-use util::common::{ErrorReported, FN_OUTPUT_NAME};
+use util::common::ErrorReported;
 use util::nodemap::FxHashSet;
 
 use std::iter;
 use syntax::{abi, ast};
 use syntax::feature_gate::{GateIssue, emit_feature_err};
-use syntax::symbol::Symbol;
 use syntax_pos::Span;
 
 pub trait AstConv<'gcx, 'tcx> {
@@ -152,21 +150,6 @@ pub fn ast_path_substs_for_ty(&self,
         item_segment: &hir::PathSegment)
         -> &'tcx Substs<'tcx>
     {
-        let tcx = self.tcx();
-
-        match item_segment.parameters {
-            hir::AngleBracketedParameters(_) => {}
-            hir::ParenthesizedParameters(..) => {
-                self.prohibit_parenthesized_params(item_segment, true);
-
-                return Substs::for_item(tcx, def_id, |_, _| {
-                    tcx.types.re_static
-                }, |_, _| {
-                    tcx.types.err
-                });
-            }
-        }
-
         let (substs, assoc_bindings) =
             self.create_substs_for_ast_path(span,
                                             def_id,
@@ -196,19 +179,13 @@ fn create_substs_for_ast_path(&self,
                parameters={:?})",
                def_id, self_ty, parameters);
 
-        let (lifetimes, num_types_provided, infer_types) = match *parameters {
-            hir::AngleBracketedParameters(ref data) => {
-                (&data.lifetimes[..], data.types.len(), data.infer_types)
-            }
-            hir::ParenthesizedParameters(_) => (&[][..], 1, false)
-        };
-
         // If the type is parameterized by this region, then replace this
         // region with the current anon region binding (in other words,
         // whatever & would get replaced with).
         let decl_generics = tcx.generics_of(def_id);
+        let num_types_provided = parameters.types.len();
         let expected_num_region_params = decl_generics.regions.len();
-        let supplied_num_region_params = lifetimes.len();
+        let supplied_num_region_params = parameters.lifetimes.len();
         if expected_num_region_params != supplied_num_region_params {
             report_lifetime_number_error(tcx, span,
                                          supplied_num_region_params,
@@ -220,7 +197,7 @@ fn create_substs_for_ast_path(&self,
 
         // Check the number of type parameters supplied by the user.
         let ty_param_defs = &decl_generics.types[self_ty.is_some() as usize..];
-        if !infer_types || num_types_provided > ty_param_defs.len() {
+        if !parameters.infer_types || num_types_provided > ty_param_defs.len() {
             check_type_argument_count(tcx, span, num_types_provided, ty_param_defs);
         }
 
@@ -237,10 +214,9 @@ fn create_substs_for_ast_path(&self,
             false
         };
 
-        let mut output_assoc_binding = None;
         let substs = Substs::for_item(tcx, def_id, |def, _| {
             let i = def.index as usize - self_ty.is_some() as usize;
-            if let Some(lifetime) = lifetimes.get(i) {
+            if let Some(lifetime) = parameters.lifetimes.get(i) {
                 self.ast_region_to_region(lifetime, Some(def))
             } else {
                 tcx.types.re_static
@@ -256,18 +232,8 @@ fn create_substs_for_ast_path(&self,
             let i = i - self_ty.is_some() as usize - decl_generics.regions.len();
             if i < num_types_provided {
                 // A provided type parameter.
-                match *parameters {
-                    hir::AngleBracketedParameters(ref data) => {
-                        self.ast_ty_to_ty(&data.types[i])
-                    }
-                    hir::ParenthesizedParameters(ref data) => {
-                        assert_eq!(i, 0);
-                        let (ty, assoc) = self.convert_parenthesized_parameters(data);
-                        output_assoc_binding = Some(assoc);
-                        ty
-                    }
-                }
-            } else if infer_types {
+                self.ast_ty_to_ty(&parameters.types[i])
+            } else if parameters.infer_types {
                 // No type parameters were provided, we can infer all.
                 let ty_var = if !default_needs_object_self(def) {
                     self.ty_infer_for_def(def, substs, span)
@@ -306,24 +272,13 @@ fn create_substs_for_ast_path(&self,
             }
         });
 
-        let assoc_bindings = match *parameters {
-            hir::AngleBracketedParameters(ref data) => {
-                data.bindings.iter().map(|b| {
-                    ConvertedBinding {
-                        item_name: b.name,
-                        ty: self.ast_ty_to_ty(&b.ty),
-                        span: b.span
-                    }
-                }).collect()
-            }
-            hir::ParenthesizedParameters(ref data) => {
-                vec![output_assoc_binding.unwrap_or_else(|| {
-                    // This is an error condition, but we should
-                    // get the associated type binding anyway.
-                    self.convert_parenthesized_parameters(data).1
-                })]
+        let assoc_bindings = parameters.bindings.iter().map(|binding| {
+            ConvertedBinding {
+                item_name: binding.name,
+                ty: self.ast_ty_to_ty(&binding.ty),
+                span: binding.span,
             }
-        };
+        }).collect();
 
         debug!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}) -> {:?}",
                decl_generics, self_ty, substs);
@@ -331,32 +286,6 @@ fn create_substs_for_ast_path(&self,
         (substs, assoc_bindings)
     }
 
-    fn convert_parenthesized_parameters(&self,
-                                        data: &hir::ParenthesizedParameterData)
-                                        -> (Ty<'tcx>, ConvertedBinding<'tcx>)
-    {
-        let inputs = self.tcx().mk_type_list(data.inputs.iter().map(|a_t| {
-            self.ast_ty_to_ty(a_t)
-        }));
-
-        let (output, output_span) = match data.output {
-            Some(ref output_ty) => {
-                (self.ast_ty_to_ty(output_ty), output_ty.span)
-            }
-            None => {
-                (self.tcx().mk_nil(), data.span)
-            }
-        };
-
-        let output_binding = ConvertedBinding {
-            item_name: Symbol::intern(FN_OUTPUT_NAME),
-            ty: output,
-            span: output_span
-        };
-
-        (self.tcx().mk_ty(ty::TyTuple(inputs, false)), output_binding)
-    }
-
     /// Instantiates the path for the given trait reference, assuming that it's
     /// bound to a valid trait type. Returns the def_id for the defining trait.
     /// Fails if the type is a type other than a trait type.
@@ -453,29 +382,17 @@ fn create_substs_for_ast_trait_ref(&self,
 
         let trait_def = self.tcx().trait_def(trait_def_id);
 
-        match trait_segment.parameters {
-            hir::AngleBracketedParameters(_) => {
-                // For now, require that parenthetical notation be used
-                // only with `Fn()` etc.
-                if !self.tcx().sess.features.borrow().unboxed_closures && trait_def.paren_sugar {
-                    emit_feature_err(&self.tcx().sess.parse_sess,
-                                     "unboxed_closures", span, GateIssue::Language,
-                                     "\
-                        the precise format of `Fn`-family traits' \
-                        type parameters is subject to change. \
-                        Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead");
-                }
-            }
-            hir::ParenthesizedParameters(_) => {
-                // For now, require that parenthetical notation be used
-                // only with `Fn()` etc.
-                if !self.tcx().sess.features.borrow().unboxed_closures && !trait_def.paren_sugar {
-                    emit_feature_err(&self.tcx().sess.parse_sess,
-                                     "unboxed_closures", span, GateIssue::Language,
-                                     "\
-                        parenthetical notation is only stable when used with `Fn`-family traits");
-                }
-            }
+        if !self.tcx().sess.features.borrow().unboxed_closures &&
+           trait_segment.parameters.parenthesized != trait_def.paren_sugar {
+            // For now, require that parenthetical notation be used only with `Fn()` etc.
+            let msg = if trait_def.paren_sugar {
+                "the precise format of `Fn`-family traits' type parameters is subject to change. \
+                 Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead"
+            } else {
+                "parenthetical notation is only stable when used with `Fn`-family traits"
+            };
+            emit_feature_err(&self.tcx().sess.parse_sess, "unboxed_closures",
+                             span, GateIssue::Language, msg);
         }
 
         self.create_substs_for_ast_path(span,
@@ -951,18 +868,14 @@ fn qpath_to_ty(&self,
 
     pub fn prohibit_type_params(&self, segments: &[hir::PathSegment]) {
         for segment in segments {
-            if let hir::ParenthesizedParameters(_) = segment.parameters {
-                self.prohibit_parenthesized_params(segment, false);
-                break;
-            }
-            for typ in segment.parameters.types() {
+            for typ in &segment.parameters.types {
                 struct_span_err!(self.tcx().sess, typ.span, E0109,
                                  "type parameters are not allowed on this type")
                     .span_label(typ.span, "type parameter not allowed")
                     .emit();
                 break;
             }
-            for lifetime in segment.parameters.lifetimes() {
+            for lifetime in &segment.parameters.lifetimes {
                 struct_span_err!(self.tcx().sess, lifetime.span, E0110,
                                  "lifetime parameters are not allowed on this type")
                     .span_label(lifetime.span,
@@ -970,28 +883,13 @@ pub fn prohibit_type_params(&self, segments: &[hir::PathSegment]) {
                     .emit();
                 break;
             }
-            for binding in segment.parameters.bindings() {
+            for binding in &segment.parameters.bindings {
                 self.prohibit_projection(binding.span);
                 break;
             }
         }
     }
 
-    pub fn prohibit_parenthesized_params(&self, segment: &hir::PathSegment, emit_error: bool) {
-        if let hir::ParenthesizedParameters(ref data) = segment.parameters {
-            if emit_error {
-                struct_span_err!(self.tcx().sess, data.span, E0214,
-                          "parenthesized parameters may only be used with a trait")
-                    .span_label(data.span, "only traits may use parentheses")
-                    .emit();
-            } else {
-                let msg = "parenthesized parameters may only be used with a trait";
-                self.tcx().lint_node(PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
-                                     ast::CRATE_NODE_ID, data.span, msg);
-            }
-        }
-    }
-
     pub fn prohibit_projection(&self, span: Span) {
         let mut err = struct_span_err!(self.tcx().sess, span, E0229,
                                        "associated type bindings are not allowed here");
@@ -1392,13 +1290,13 @@ fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                     Some(trait_did) == tcx.lang_items.sync_trait() {
                     let segments = &bound.trait_ref.path.segments;
                     let parameters = &segments[segments.len() - 1].parameters;
-                    if !parameters.types().is_empty() {
+                    if !parameters.types.is_empty() {
                         check_type_argument_count(tcx, bound.trait_ref.path.span,
-                                                  parameters.types().len(), &[]);
+                                                  parameters.types.len(), &[]);
                     }
-                    if !parameters.lifetimes().is_empty() {
+                    if !parameters.lifetimes.is_empty() {
                         report_lifetime_number_error(tcx, bound.trait_ref.path.span,
-                                                     parameters.lifetimes().len(), 0);
+                                                     parameters.lifetimes.len(), 0);
                     }
                     true
                 } else {
index cd2adfb7ab0c19d34d18e03913d56ccf15ed29cf..db383b6305b4a424fd60490907442f62c2e92363 100644 (file)
@@ -311,17 +311,14 @@ fn instantiate_method_substs(&mut self,
 
         // Create subst for early-bound lifetime parameters, combining
         // parameters from the type and those from the method.
-        let (supplied_types, supplied_lifetimes) = match segment.parameters {
-            hir::AngleBracketedParameters(ref data) => (&data.types, &data.lifetimes),
-            _ => bug!("unexpected generic arguments: {:?}", segment.parameters),
-        };
         assert_eq!(method_generics.parent_count(), parent_substs.len());
+        let provided = &segment.parameters;
         Substs::for_item(self.tcx, pick.item.def_id, |def, _| {
             let i = def.index as usize;
             if i < parent_substs.len() {
                 parent_substs.region_at(i)
-            } else if let Some(lifetime) =
-                    supplied_lifetimes.get(i - parent_substs.len()) {
+            } else if let Some(lifetime)
+                    = provided.lifetimes.get(i - parent_substs.len()) {
                 AstConv::ast_region_to_region(self.fcx, lifetime, Some(def))
             } else {
                 self.region_var_for_def(self.span, def)
@@ -330,8 +327,8 @@ fn instantiate_method_substs(&mut self,
             let i = def.index as usize;
             if i < parent_substs.len() {
                 parent_substs.type_at(i)
-            } else if let Some(ast_ty) =
-                    supplied_types.get(i - parent_substs.len() - method_generics.regions.len()) {
+            } else if let Some(ast_ty)
+                    = provided.types.get(i - parent_substs.len() - method_generics.regions.len()) {
                 self.to_ty(ast_ty)
             } else {
                 self.type_var_for_def(self.span, def, cur_substs)
index dbdaabfee8ab56b4fe4f2cc80addea63921e0da1..955171203e13a34e343bcc9e46ae82c1875a6f9c 100644 (file)
@@ -4620,11 +4620,7 @@ pub fn instantiate_value_path(&self,
                 i -= fn_start;
                 fn_segment
             };
-            let lifetimes = match segment.map(|(s, _)| &s.parameters) {
-                Some(&hir::AngleBracketedParameters(ref data)) => &data.lifetimes[..],
-                Some(&hir::ParenthesizedParameters(_)) => bug!(),
-                None => &[]
-            };
+            let lifetimes = segment.map_or(&[][..], |(s, _)| &s.parameters.lifetimes[..]);
 
             if let Some(lifetime) = lifetimes.get(i) {
                 AstConv::ast_region_to_region(self, lifetime, Some(def))
@@ -4647,13 +4643,9 @@ pub fn instantiate_value_path(&self,
                 i -= fn_start;
                 fn_segment
             };
-            let (types, infer_types) = match segment.map(|(s, _)| &s.parameters) {
-                Some(&hir::AngleBracketedParameters(ref data)) => {
-                    (&data.types[..], data.infer_types)
-                }
-                Some(&hir::ParenthesizedParameters(_)) => bug!(),
-                None => (&[][..], true)
-            };
+            let (types, infer_types) = segment.map_or((&[][..], true), |(s, _)| {
+                (&s.parameters.types[..], s.parameters.infer_types)
+            });
 
             // Skip over the lifetimes in the same segment.
             if let Some((_, generics)) = segment {
@@ -4727,19 +4719,10 @@ fn check_path_parameter_count(&self,
                                   span: Span,
                                   segment: &mut Option<(&hir::PathSegment, &ty::Generics)>,
                                   is_method_call: bool) {
-        let (lifetimes, types, infer_types, bindings) = {
-            match segment.map(|(s, _)| &s.parameters) {
-                Some(&hir::AngleBracketedParameters(ref data)) => {
-                    (&data.lifetimes[..], &data.types[..], data.infer_types, &data.bindings[..])
-                }
-                Some(&hir::ParenthesizedParameters(_)) => {
-                    AstConv::prohibit_parenthesized_params(self, &segment.as_ref().unwrap().0,
-                                                           false);
-                    (&[][..], &[][..], true, &[][..])
-                }
-                None => (&[][..], &[][..], true, &[][..])
-            }
-        };
+        let (lifetimes, types, infer_types, bindings) = segment.map_or(
+            (&[][..], &[][..], true, &[][..]),
+            |(s, _)| (&s.parameters.lifetimes[..], &s.parameters.types[..],
+                      s.parameters.infer_types, &s.parameters.bindings[..]));
         let infer_lifetimes = lifetimes.len() == 0;
 
         let count_lifetime_params = |n| {
@@ -4785,9 +4768,7 @@ fn check_path_parameter_count(&self,
         }
 
         if !bindings.is_empty() {
-            span_err!(self.tcx.sess, bindings[0].span, E0182,
-                      "unexpected binding of associated item in expression path \
-                       (only allowed in type paths)");
+            AstConv::prohibit_projection(self, bindings[0].span);
         }
 
         // Check provided lifetime parameters.
index e95d49f00bf76614741c1f0a349c7fc40067155a..3da154e0689addb8a26ed863906e0fe3f4576646 100644 (file)
@@ -72,4 +72,15 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
 
     let mut visitor = CheckVisitor { tcx, used_trait_imports };
     tcx.hir.krate().visit_all_item_likes(&mut visitor);
+
+    for &(id, span) in &tcx.maybe_unused_extern_crates {
+        let cnum = tcx.sess.cstore.extern_mod_stmt_cnum(id).unwrap().as_def_id();
+        if !tcx.is_compiler_builtins(cnum)
+            && !tcx.is_panic_runtime(cnum)
+            && !tcx.has_global_allocator(cnum) {
+                let lint = lint::builtin::UNUSED_EXTERN_CRATES;
+                let msg = "unused extern crate";
+                tcx.lint_node(lint, id, span, msg);
+            }
+    }
 }
index c74dc24ddc3406583bbaa96eb2406787508ffff8..cb430efd9508fc9433a98b801213b82d47ad43f4 100644 (file)
@@ -1636,45 +1636,6 @@ fn bar(foo: Foo) -> u32 {
 ```
 "##,
 
-E0182: r##"
-You bound an associated type in an expression path which is not
-allowed.
-
-Erroneous code example:
-
-```compile_fail,E0182
-trait Foo {
-    type A;
-    fn bar() -> isize;
-}
-
-impl Foo for isize {
-    type A = usize;
-    fn bar() -> isize { 42 }
-}
-
-// error: unexpected binding of associated item in expression path
-let x: isize = Foo::<A=usize>::bar();
-```
-
-To give a concrete type when using the Universal Function Call Syntax,
-use "Type as Trait". Example:
-
-```
-trait Foo {
-    type A;
-    fn bar() -> isize;
-}
-
-impl Foo for isize {
-    type A = usize;
-    fn bar() -> isize { 42 }
-}
-
-let x: isize = <isize as Foo>::bar(); // ok!
-```
-"##,
-
 E0184: r##"
 Explicitly implementing both Drop and Copy for a type is currently disallowed.
 This feature can make some sense in theory, but the current implementation is
@@ -2359,21 +2320,6 @@ fn x(self: Box<Foo>) {} // ok!
 "##,
      */
 
-E0214: r##"
-A generic type was described using parentheses rather than angle brackets. For
-example:
-
-```compile_fail,E0214
-fn main() {
-    let v: Vec(&str) = vec!["foo"];
-}
-```
-
-This is not currently supported: `v` should be defined as `Vec<&str>`.
-Parentheses are currently only used with generic types when defining parameters
-for `Fn`-family traits.
-"##,
-
 E0220: r##"
 You used an associated type which isn't defined in the trait.
 Erroneous code example:
@@ -4721,6 +4667,7 @@ pub fn method(&self) {} // It's now public.
 //  E0172, // non-trait found in a type sum, moved to resolve
 //  E0173, // manual implementations of unboxed closure traits are experimental
 //  E0174,
+//  E0182, // merged into E0229
     E0183,
 //  E0187, // can't infer the kind of the closure
 //  E0188, // can not cast an immutable reference to a mutable pointer
index 294429b5b3671de74b66c86128edc4dd53a740c5..86feea13b17232cee655239370670b3d93e1dcde 100644 (file)
@@ -63,9 +63,6 @@
 
 */
 
-#![crate_name = "rustc_typeck"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
index f4aef8ab377c01f53d2421b4e61769386d730368..7d6ad5286d1114b410964cea64cc19583f926829 100644 (file)
@@ -323,6 +323,10 @@ pub fn is_primitive(&self) -> bool {
     pub fn is_union(&self) -> bool {
         self.type_() == ItemType::Union
     }
+    pub fn is_import(&self) -> bool {
+        self.type_() == ItemType::Import
+    }
+
     pub fn is_stripped(&self) -> bool {
         match self.inner { StrippedItem(..) => true, _ => false }
     }
@@ -1794,16 +1798,14 @@ fn clean(&self, cx: &DocContext) -> Type {
                     let mut lt_substs = FxHashMap();
                     for (i, ty_param) in generics.ty_params.iter().enumerate() {
                         let ty_param_def = Def::TyParam(cx.tcx.hir.local_def_id(ty_param.id));
-                        if let Some(ty) = provided_params.types().get(i).cloned()
-                                                                        .cloned() {
+                        if let Some(ty) = provided_params.types.get(i).cloned() {
                             ty_substs.insert(ty_param_def, ty.unwrap().clean(cx));
                         } else if let Some(default) = ty_param.default.clone() {
                             ty_substs.insert(ty_param_def, default.unwrap().clean(cx));
                         }
                     }
                     for (i, lt_param) in generics.lifetimes.iter().enumerate() {
-                        if let Some(lt) = provided_params.lifetimes().get(i).cloned()
-                                                                            .cloned() {
+                        if let Some(lt) = provided_params.lifetimes.get(i).cloned() {
                             if !lt.is_elided() {
                                 lt_substs.insert(lt_param.lifetime.id, lt.clean(cx));
                             }
@@ -2314,24 +2316,21 @@ pub enum PathParameters {
 
 impl Clean<PathParameters> for hir::PathParameters {
     fn clean(&self, cx: &DocContext) -> PathParameters {
-        match *self {
-            hir::AngleBracketedParameters(ref data) => {
-                PathParameters::AngleBracketed {
-                    lifetimes: if data.lifetimes.iter().all(|lt| lt.is_elided()) {
-                        vec![]
-                    } else {
-                        data.lifetimes.clean(cx)
-                    },
-                    types: data.types.clean(cx),
-                    bindings: data.bindings.clean(cx),
-                }
+        if self.parenthesized {
+            let output = self.bindings[0].ty.clean(cx);
+            PathParameters::Parenthesized {
+                inputs: self.inputs().clean(cx),
+                output: if output != Type::Tuple(Vec::new()) { Some(output) } else { None }
             }
-
-            hir::ParenthesizedParameters(ref data) => {
-                PathParameters::Parenthesized {
-                    inputs: data.inputs.clean(cx),
-                    output: data.output.clean(cx),
-                }
+        } else {
+            PathParameters::AngleBracketed {
+                lifetimes: if self.lifetimes.iter().all(|lt| lt.is_elided()) {
+                    vec![]
+                } else {
+                    self.lifetimes.clean(cx)
+                },
+                types: self.types.clean(cx),
+                bindings: self.bindings.clean(cx),
             }
         }
     }
index 6593d6dfd6cff7ff105ff7cf425b5bd0b9bc725a..5457f69cb6dab02bf9c3d420a83f94533909e4c7 100644 (file)
@@ -1764,6 +1764,37 @@ fn cmp(i1: &clean::Item, i2: &clean::Item, idx1: usize, idx2: usize) -> Ordering
     }
 
     indices.sort_by(|&i1, &i2| cmp(&items[i1], &items[i2], i1, i2));
+    // This call is to remove reexport duplicates in cases such as:
+    //
+    // ```
+    // pub mod foo {
+    //     pub mod bar {
+    //         pub trait Double { fn foo(); }
+    //     }
+    // }
+    //
+    // pub use foo::bar::*;
+    // pub use foo::*;
+    // ```
+    //
+    // `Double` will appear twice in the generated docs.
+    //
+    // FIXME: This code is quite ugly and could be improved. Small issue: DefId
+    // can be identical even if the elements are different (mostly in imports).
+    // So in case this is an import, we keep everything by adding a "unique id"
+    // (which is the position in the vector).
+    indices.dedup_by_key(|i| (items[*i].def_id,
+                              if items[*i].name.as_ref().is_some() {
+                                  Some(full_path(cx, &items[*i]).clone())
+                              } else {
+                                  None
+                              },
+                              items[*i].type_(),
+                              if items[*i].is_import() {
+                                  *i
+                              } else {
+                                  0
+                              }));
 
     debug!("{:?}", indices);
     let mut curty = None;
@@ -2925,7 +2956,13 @@ fn render_deref_methods(w: &mut fmt::Formatter, cx: &Context, impl_: &Impl,
 fn render_impl(w: &mut fmt::Formatter, cx: &Context, i: &Impl, link: AssocItemLink,
                render_mode: RenderMode, outer_version: Option<&str>) -> fmt::Result {
     if render_mode == RenderMode::Normal {
-        write!(w, "<h3 class='impl'><span class='in-band'><code>{}</code>", i.inner_impl())?;
+        let id = derive_id(match i.inner_impl().trait_ {
+            Some(ref t) => format!("impl-{}", Escape(&format!("{:#}", t))),
+            None => "impl".to_string(),
+        });
+        write!(w, "<h3 id='{}' class='impl'><span class='in-band'><code>{}</code>",
+               id, i.inner_impl())?;
+        write!(w, "<a href='#{}' class='anchor'></a>", id)?;
         write!(w, "</span><span class='out-of-band'>")?;
         let since = i.impl_item.stability.as_ref().map(|s| &s.since[..]);
         if let Some(l) = (Item { item: &i.impl_item, cx: cx }).src_href() {
index ee94f0baeb9a39bdf9cf590adc1b4c88878ab00b..4a3286b421ae9e40f87be7297b217da86639ee2c 100644 (file)
@@ -126,6 +126,10 @@ p {
        margin: 0 0 .6em 0;
 }
 
+summary {
+       outline: none;
+}
+
 code, pre {
        font-family: "Source Code Pro", Menlo, Monaco, Consolas, "DejaVu Sans Mono", Inconsolata, monospace;
        white-space: pre-wrap;
@@ -441,6 +445,10 @@ a {
 .small-section-header:hover > .anchor {
        display: initial;
 }
+
+.in-band:hover > .anchor {
+       display: initial;
+}
 .anchor {
        display: none;
 }
index 08bf5a10fe9d981280810ff6bbd4ff9dac1e1301..c5f4272b932fca74a3cd985a710aa09c7f3fd2f6 100644 (file)
@@ -26,6 +26,7 @@ h1.fqn {
 h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.type):not(.tymethod) {
        border-bottom-color: #DDDDDD;
 }
+
 .in-band {
        background-color: white;
 }
@@ -83,6 +84,11 @@ pre {
 }
 
 :target { background: #FDFFD3; }
+
+:target > .in-band {
+       background: #FDFFD3;
+}
+
 .content .highlighted {
        color: #000 !important;
        background-color: #ccc;
index 1c3f296bed96cbde9251c72a4c6c4ef3b0fe165e..61a8165d26af16283b3cc49f85f538d47b71f791 100644 (file)
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![crate_name = "rustdoc"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/",
index c3107d1f190c2b3afbc7d249bd358a791f8fa7a8..2e354252c1573813770a50ccf0c7af29d85c1362 100644 (file)
@@ -14,9 +14,6 @@
 Core encoding and decoding interfaces.
 */
 
-#![crate_name = "serialize"]
-#![crate_type = "rlib"]
-#![crate_type = "dylib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/",
index 0fff833e7d83e2a9bc93f1fd07150a1a3cfe4278..074ab3ebd8fdca9b045f86672f04f093abf2704b 100644 (file)
@@ -522,7 +522,7 @@ pub trait Read {
     /// `Read`er - the method only takes `&self` so that it can be used through
     /// trait objects.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This method is unsafe because a `Read`er could otherwise return a
     /// non-zeroing `Initializer` from another `Read` type without an `unsafe`
@@ -903,7 +903,7 @@ pub fn zeroing() -> Initializer {
 
     /// Returns a new `Initializer` which will not zero out buffers.
     ///
-    /// # Unsafety
+    /// # Safety
     ///
     /// This may only be called by `Read`ers which guarantee that they will not
     /// read from buffers passed to `Read` methods, and that the return value of
index 880caa2ade5d82a39a7418b6e80a4a09d86b76d2..b57067e35e9d95db0180cd983a5881eaeabb4cde 100644 (file)
@@ -81,7 +81,7 @@
 //! Note the documentation for the primitives [`str`] and [`[T]`][slice] (also
 //! called 'slice'). Many method calls on [`String`] and [`Vec<T>`] are actually
 //! calls to methods on [`str`] and [`[T]`][slice] respectively, via [deref
-//! coercions].
+//! coercions][deref-coercions].
 //!
 //! Third, the standard library defines [The Rust Prelude], a small collection
 //! of items - mostly traits - that are imported into every module of every
 //! [`use`]: ../book/first-edition/crates-and-modules.html#importing-modules-with-use
 //! [crate root]: ../book/first-edition/crates-and-modules.html#basic-terminology-crates-and-modules
 //! [crates.io]: https://crates.io
-//! [deref coercions]: ../book/first-edition/deref-coercions.html
+//! [deref-coercions]: ../book/second-edition/ch15-02-deref.html#implicit-deref-coercions-with-functions-and-methods
 //! [files]: fs/struct.File.html
 //! [multithreading]: thread/index.html
 //! [other]: #what-is-in-the-standard-library-documentation
 //! [primitive types]: ../book/first-edition/primitive-types.html
 
-#![crate_name = "std"]
 #![stable(feature = "rust1", since = "1.0.0")]
-#![crate_type = "rlib"]
-#![crate_type = "dylib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/",
 extern crate libc;
 
 // We always need an unwinder currently for backtraces
+#[allow(unused_extern_crates)]
 extern crate unwind;
 
 // compiler-rt intrinsics
index 98642f86f4dc22fc900d1addf902a4256880d7f0..240e82069ff4d64fbb0c72a33eb7a2fdd49d7672 100644 (file)
@@ -20,7 +20,7 @@
 /// magnitude faster than `haystack.iter().position(|&b| b == needle)`.
 /// (See benchmarks.)
 ///
-/// # Example
+/// # Examples
 ///
 /// This shows how to find the first position of a byte in a byte string.
 ///
@@ -40,7 +40,7 @@ pub fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
 /// Returns the index corresponding to the last occurrence of `needle` in
 /// `haystack`, or `None` if one is not found.
 ///
-/// # Example
+/// # Examples
 ///
 /// This shows how to find the last position of a byte in a byte string.
 ///
index 680bb057858bef263117175886da02bfc5f8d08e..830b9dc475d6daf534bd0e4e803aa379f9bc389a 100644 (file)
@@ -323,6 +323,11 @@ unsafe fn u8_slice_as_os_str(s: &[u8]) -> &OsStr {
     mem::transmute(s)
 }
 
+// Detect scheme on Redox
+fn has_redox_scheme(s: &[u8]) -> bool {
+    cfg!(target_os = "redox") && s.split(|b| *b == b'/').next().unwrap_or(b"").contains(&b':')
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Cross-platform, iterator-independent parsing
 ////////////////////////////////////////////////////////////////////////////////
@@ -1685,8 +1690,12 @@ pub fn to_path_buf(&self) -> PathBuf {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[allow(deprecated)]
     pub fn is_absolute(&self) -> bool {
-        // FIXME: Remove target_os = "redox" and allow Redox prefixes
-        self.has_root() && (cfg!(unix) || cfg!(target_os = "redox") || self.prefix().is_some())
+        if !cfg!(target_os = "redox") {
+            self.has_root() && (cfg!(unix) || self.prefix().is_some())
+        } else {
+            // FIXME: Allow Redox prefixes
+            has_redox_scheme(self.as_u8_slice())
+        }
     }
 
     /// Returns `true` if the `Path` is relative, i.e. not absolute.
@@ -2050,7 +2059,8 @@ pub fn components(&self) -> Components {
         Components {
             path: self.as_u8_slice(),
             prefix,
-            has_physical_root: has_physical_root(self.as_u8_slice(), prefix),
+            has_physical_root: has_physical_root(self.as_u8_slice(), prefix) ||
+                               has_redox_scheme(self.as_u8_slice()),
             front: State::Prefix,
             back: State::Body,
         }
index 49cdba21a1d37241831bc6b326b87aa9177d7012..538753d86923eebcbd2e2e9871f696cb5e1d7394 100644 (file)
@@ -23,6 +23,7 @@
 //! On a technical level, Rust inserts
 //!
 //! ```
+//! # #[allow(unused_extern_crates)]
 //! extern crate std;
 //! ```
 //!
index 6746754ebc3449fa8d26b97cc57692cb3bd0c110..76ef36cc9a733737663fdba36ed588c48fe31ede 100644 (file)
@@ -188,9 +188,10 @@ mod prim_unit { }
 /// Working with raw pointers in Rust is uncommon,
 /// typically limited to a few patterns.
 ///
-/// Use the [`null`] function to create null pointers, and the [`is_null`] method
-/// of the `*const T` type  to check for null. The `*const T` type also defines
-/// the [`offset`] method, for pointer math.
+/// Use the [`null`] and [`null_mut`] functions to create null pointers, and the
+/// [`is_null`] method of the `*const T` and `*mut T` types to check for null.
+/// The `*const T` and `*mut T` types also define the [`offset`] method, for
+/// pointer math.
 ///
 /// # Common ways to create raw pointers
 ///
@@ -261,6 +262,7 @@ mod prim_unit { }
 /// *[See also the `std::ptr` module](ptr/index.html).*
 ///
 /// [`null`]: ../std/ptr/fn.null.html
+/// [`null_mut`]: ../std/ptr/fn.null_mut.html
 /// [`is_null`]: ../std/primitive.pointer.html#method.is_null
 /// [`offset`]: ../std/primitive.pointer.html#method.offset
 /// [`into_raw`]: ../std/boxed/struct.Box.html#method.into_raw
index 259cda5bcb3ebe485d07f2cd5f8090e2ebf1b18a..9fd8d6c91869c07422eedf0c7f10deb008ed985c 100644 (file)
@@ -13,7 +13,7 @@
 //! For now, this module is limited to extracting file descriptors,
 //! but its functionality will grow over time.
 //!
-//! # Example
+//! # Examples
 //!
 //! ```no_run
 //! use std::fs::File;
index a94585723a1eee12ad03f0ce8eb62c7933d9a17f..f44b9aa9615683f7e3b87c6e7e92efacdbbd9cff 100644 (file)
@@ -154,8 +154,6 @@ pub trait OpenOptionsExt {
     /// # Examples
     ///
     /// ```no_run
-    /// # #![feature(libc)]
-    /// extern crate libc;
     /// use std::fs::OpenOptions;
     /// use std::os::unix::fs::OpenOptionsExt;
     ///
index 67fe46cc9c7a20326b6c8b4dec7726f8356128b6..98bc90dd4e13246694c14531affe2fd53cd47012 100644 (file)
@@ -13,7 +13,7 @@
 //! For now, this module is limited to extracting file descriptors,
 //! but its functionality will grow over time.
 //!
-//! # Example
+//! # Examples
 //!
 //! ```no_run
 //! use std::fs::File;
index 15747746611c9dd72efac438e8b52fe5c96869b5..40f1d6a6db15be67ed1664978fa0df604a46591a 100644 (file)
@@ -168,7 +168,8 @@ pub fn join(self) {
         unsafe {
             let ret = libc::pthread_join(self.id, ptr::null_mut());
             mem::forget(self);
-            debug_assert_eq!(ret, 0);
+            assert!(ret == 0,
+                    "failed to join thread: {}", io::Error::from_raw_os_error(ret));
         }
     }
 
index ba54ca6ea18281a893d698d8d49104e02d012976..7dfcc996e18e2e8202b7f6c061800ea005356204 100644 (file)
@@ -273,6 +273,7 @@ pub struct ipv6_mreq {
 
 pub const WAIT_OBJECT_0: DWORD = 0x00000000;
 pub const WAIT_TIMEOUT: DWORD = 258;
+pub const WAIT_FAILED: DWORD = 0xFFFFFFFF;
 
 #[cfg(target_env = "msvc")]
 pub const MAX_SYM_NAME: usize = 2000;
index 5a376a867ee6448288bac2cd1c534a7bb56e77a9..2cdd86e88b0a074eb87125792b9f888aeb9eaaa3 100644 (file)
@@ -61,7 +61,11 @@ pub fn set_name(_name: &CStr) {
     }
 
     pub fn join(self) {
-        unsafe { c::WaitForSingleObject(self.handle.raw(), c::INFINITE); }
+        let rc = unsafe { c::WaitForSingleObject(self.handle.raw(), c::INFINITE) };
+        if rc == c::WAIT_FAILED {
+            panic!("failed to join on thread: {}",
+                   io::Error::last_os_error());
+        }
     }
 
     pub fn yield_now() {
index 83feb595bce51ed42c2a2afba13c28f7ee9122ba..4912ff93abdb389c19fc458398234220fd0c4b35 100644 (file)
@@ -374,7 +374,7 @@ pub fn spawn<F, T>(self, f: F) -> io::Result<JoinHandle<T>> where
     {
         let Builder { name, stack_size } = self;
 
-        let stack_size = stack_size.unwrap_or(util::min_stack());
+        let stack_size = stack_size.unwrap_or_else(util::min_stack);
 
         let my_thread = Thread::new(name);
         let their_thread = my_thread.clone();
@@ -807,7 +807,7 @@ pub fn park_timeout_ms(ms: u32) {
 /// Platforms which do not support nanosecond precision for sleeping will have
 /// `dur` rounded up to the nearest granularity of time they can sleep for.
 ///
-/// # Example
+/// # Examples
 ///
 /// Waiting for the complete expiration of the timeout:
 ///
@@ -1230,6 +1230,11 @@ pub fn thread(&self) -> &Thread {
     /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
     /// [`panic`]: ../../std/macro.panic.html
     ///
+    /// # Panics
+    ///
+    /// This function may panic on some platforms if a thread attempts to join
+    /// itself or otherwise may create a deadlock with joining threads.
+    ///
     /// # Examples
     ///
     /// ```
index d568baa2cd7706c2da8619c1f28139b60721f67f..e5a114caed0f4e90378751d7e736f1667cd62fb9 100644 (file)
@@ -20,9 +20,7 @@
 //! provide for basic string-related manipulations. This crate does not
 //! (yet) aim to provide a full set of Unicode tables.
 
-#![crate_name = "std_unicode"]
 #![unstable(feature = "unicode", issue = "27783")]
-#![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/",
index 801343689b728f37f93700d16d979a45fd14ea7e..09574d5ba129e80282dea9f6ff850371507d1166 100644 (file)
@@ -112,8 +112,8 @@ pub fn new() -> Features {
 // was set. This is most important for knowing when a particular feature became
 // stable (active).
 //
-// NB: The featureck.py script parses this information directly out of the source
-// so take care when modifying it.
+// NB: tools/tidy/src/features.rs parses this information directly out of the
+// source, so take care when modifying it.
 
 declare_features! (
     (active, asm, "1.0.0", Some(29722)),
@@ -372,6 +372,9 @@ pub fn new() -> Features {
 
     // #[doc(cfg(...))]
     (active, doc_cfg, "1.21.0", Some(43781)),
+
+    // allow `#[must_use]` on functions (RFC 1940)
+    (active, fn_must_use, "1.21.0", Some(43302)),
 );
 
 declare_features! (
@@ -915,20 +918,27 @@ struct Context<'a> {
 }
 
 macro_rules! gate_feature_fn {
-    ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{
-        let (cx, has_feature, span, name, explain) = ($cx, $has_feature, $span, $name, $explain);
+    ($cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $level: expr) => {{
+        let (cx, has_feature, span,
+             name, explain, level) = ($cx, $has_feature, $span, $name, $explain, $level);
         let has_feature: bool = has_feature(&$cx.features);
         debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
         if !has_feature && !span.allows_unstable() {
-            emit_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain);
+            leveled_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain, level)
+                .emit();
         }
     }}
 }
 
 macro_rules! gate_feature {
     ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {
-        gate_feature_fn!($cx, |x:&Features| x.$feature, $span, stringify!($feature), $explain)
-    }
+        gate_feature_fn!($cx, |x:&Features| x.$feature, $span,
+                         stringify!($feature), $explain, GateStrength::Hard)
+    };
+    ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {
+        gate_feature_fn!($cx, |x:&Features| x.$feature, $span,
+                         stringify!($feature), $explain, $level)
+    };
 }
 
 impl<'a> Context<'a> {
@@ -938,7 +948,7 @@ fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) {
         for &(n, ty, ref gateage) in BUILTIN_ATTRIBUTES {
             if name == n {
                 if let Gated(_, name, desc, ref has_feature) = *gateage {
-                    gate_feature_fn!(self, has_feature, attr.span, name, desc);
+                    gate_feature_fn!(self, has_feature, attr.span, name, desc, GateStrength::Hard);
                 }
                 debug!("check_attribute: {:?} is builtin, {:?}, {:?}", attr.path, ty, gateage);
                 return;
@@ -1008,13 +1018,26 @@ pub enum GateIssue {
     Library(Option<u32>)
 }
 
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+pub enum GateStrength {
+    /// A hard error. (Most feature gates should use this.)
+    Hard,
+    /// Only a warning. (Use this only as backwards-compatibility demands.)
+    Soft,
+}
+
 pub fn emit_feature_err(sess: &ParseSess, feature: &str, span: Span, issue: GateIssue,
                         explain: &str) {
     feature_err(sess, feature, span, issue, explain).emit();
 }
 
 pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue,
-                   explain: &str) -> DiagnosticBuilder<'a> {
+                       explain: &str) -> DiagnosticBuilder<'a> {
+    leveled_feature_err(sess, feature, span, issue, explain, GateStrength::Hard)
+}
+
+fn leveled_feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: GateIssue,
+                           explain: &str, level: GateStrength) -> DiagnosticBuilder<'a> {
     let diag = &sess.span_diagnostic;
 
     let issue = match issue {
@@ -1022,10 +1045,15 @@ pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: Ga
         GateIssue::Library(lib) => lib,
     };
 
-    let mut err = if let Some(n) = issue {
-        diag.struct_span_err(span, &format!("{} (see issue #{})", explain, n))
+    let explanation = if let Some(n) = issue {
+        format!("{} (see issue #{})", explain, n)
     } else {
-        diag.struct_span_err(span, explain)
+        explain.to_owned()
+    };
+
+    let mut err = match level {
+        GateStrength::Hard => diag.struct_span_err(span, &explanation),
+        GateStrength::Soft => diag.struct_span_warn(span, &explanation),
     };
 
     // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
@@ -1035,7 +1063,15 @@ pub fn feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue: Ga
                           feature));
     }
 
+    // If we're on stable and only emitting a "soft" warning, add a note to
+    // clarify that the feature isn't "on" (rather than being on but
+    // warning-worthy).
+    if !sess.unstable_features.is_nightly_build() && level == GateStrength::Soft {
+        err.help("a nightly build of the compiler is required to enable this feature");
+    }
+
     err
+
 }
 
 const EXPLAIN_BOX_SYNTAX: &'static str =
@@ -1092,6 +1128,12 @@ macro_rules! gate_feature_post {
         if !span.allows_unstable() {
             gate_feature!(cx.context, $feature, span, $explain)
         }
+    }};
+    ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {{
+        let (cx, span) = ($cx, $span);
+        if !span.allows_unstable() {
+            gate_feature!(cx.context, $feature, span, $explain, $level)
+        }
     }}
 }
 
@@ -1234,6 +1276,11 @@ fn visit_item(&mut self, i: &'a ast::Item) {
                                         function may change over time, for now \
                                         a top-level `fn main()` is required");
                 }
+                if attr::contains_name(&i.attrs[..], "must_use") {
+                    gate_feature_post!(&self, fn_must_use, i.span,
+                                       "`#[must_use]` on functions is experimental",
+                                       GateStrength::Soft);
+                }
             }
 
             ast::ItemKind::Struct(..) => {
@@ -1271,7 +1318,7 @@ fn visit_item(&mut self, i: &'a ast::Item) {
                                     and possibly buggy");
             }
 
-            ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, _) => {
+            ast::ItemKind::Impl(_, polarity, defaultness, _, _, _, ref impl_items) => {
                 if polarity == ast::ImplPolarity::Negative {
                     gate_feature_post!(&self, optin_builtin_traits,
                                        i.span,
@@ -1284,6 +1331,16 @@ fn visit_item(&mut self, i: &'a ast::Item) {
                                        i.span,
                                        "specialization is unstable");
                 }
+
+                for impl_item in impl_items {
+                    if let ast::ImplItemKind::Method(..) = impl_item.node {
+                        if attr::contains_name(&impl_item.attrs[..], "must_use") {
+                            gate_feature_post!(&self, fn_must_use, impl_item.span,
+                                               "`#[must_use]` on methods is experimental",
+                                               GateStrength::Soft);
+                        }
+                    }
+                }
             }
 
             ast::ItemKind::MacroDef(ast::MacroDef { legacy: false, .. }) => {
index 43345b02bf614e65029c888192c048037afed96e..e3c9f0a9345eacbe4c122c5e56137a1ab880fa38 100644 (file)
@@ -14,9 +14,6 @@
 //!
 //! This API is completely unstable and subject to change.
 
-#![crate_name = "syntax"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/",
index eeb8bf7214467874957163134ec74703525066a3..35dc98195290800cb1a9ab6f1fa6b738653b990d 100644 (file)
@@ -56,13 +56,12 @@ struct Test {
 }
 
 struct TestCtxt<'a> {
-    sess: &'a ParseSess,
     span_diagnostic: &'a errors::Handler,
     path: Vec<Ident>,
     ext_cx: ExtCtxt<'a>,
     testfns: Vec<Test>,
     reexport_test_harness_main: Option<Symbol>,
-    is_test_crate: bool,
+    is_libtest: bool,
     ctxt: SyntaxContext,
 
     // top-level re-export submodule, filled out after folding is finished
@@ -272,14 +271,15 @@ fn generate_test_harness(sess: &ParseSess,
     let krate = cleaner.fold_crate(krate);
 
     let mark = Mark::fresh(Mark::root());
+
     let mut cx: TestCtxt = TestCtxt {
-        sess,
         span_diagnostic: sd,
         ext_cx: ExtCtxt::new(sess, ExpansionConfig::default("test".to_string()), resolver),
         path: Vec::new(),
         testfns: Vec::new(),
         reexport_test_harness_main,
-        is_test_crate: is_test_crate(&krate),
+        // NB: doesn't consider the value of `--crate-name` passed on the command line.
+        is_libtest: attr::find_crate_name(&krate.attrs).map(|s| s == "test").unwrap_or(false),
         toplevel_reexport: None,
         ctxt: SyntaxContext::empty().apply_mark(mark),
     };
@@ -454,7 +454,7 @@ fn main() {
 fn mk_std(cx: &TestCtxt) -> P<ast::Item> {
     let id_test = Ident::from_str("test");
     let sp = ignored_span(cx, DUMMY_SP);
-    let (vi, vis, ident) = if cx.is_test_crate {
+    let (vi, vis, ident) = if cx.is_libtest {
         (ast::ItemKind::Use(
             P(nospan(ast::ViewPathSimple(id_test,
                                          path_node(vec![id_test]))))),
@@ -608,13 +608,6 @@ fn mk_tests(cx: &TestCtxt) -> P<ast::Item> {
                    test_descs)
 }
 
-fn is_test_crate(krate: &ast::Crate) -> bool {
-    match attr::find_crate_name(&krate.attrs) {
-        Some(s) if "test" == s.as_str() => true,
-        _ => false
-    }
-}
-
 fn mk_test_descs(cx: &TestCtxt) -> P<ast::Expr> {
     debug!("building test vector from {} tests", cx.testfns.len());
 
index bdcec26cb838b211ba5980542da2ca62bb386b99..1c4702402886d59b9553ebdf3beba6c0839e429f 100644 (file)
@@ -10,7 +10,6 @@ crate-type = ["dylib"]
 
 [dependencies]
 fmt_macros = { path = "../libfmt_macros" }
-log = "0.3"
 proc_macro = { path = "../libproc_macro" }
 rustc_errors = { path = "../librustc_errors" }
 syntax = { path = "../libsyntax" }
index 439538a8b5ee311305babf8a9b5fb569df77bbb8..42bbb4ae0cbee35a18aaa513d4655ea9e7751db5 100644 (file)
@@ -10,9 +10,6 @@
 
 //! Syntax extensions in the Rust compiler.
 
-#![crate_name = "syntax_ext"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/")]
@@ -21,7 +18,6 @@
 #![feature(proc_macro_internals)]
 
 extern crate fmt_macros;
-extern crate log;
 #[macro_use]
 extern crate syntax;
 extern crate syntax_pos;
index 2385e3509ad1c14ff6928476784880b73aaa8a6a..d34dcfa3ed3246d363d87ee2791648093949c4bc 100644 (file)
@@ -14,9 +14,6 @@
 //!
 //! This API is completely unstable and subject to change.
 
-#![crate_name = "syntax_pos"]
-#![crate_type = "dylib"]
-#![crate_type = "rlib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/")]
index 4864e4581faab87c033a023409d8958f6c015ff1..ad0e582b1c324e4ef38ab460476c2b19e7696037 100644 (file)
@@ -40,9 +40,6 @@
 //! [win]: http://msdn.microsoft.com/en-us/library/windows/desktop/ms682010%28v=vs.85%29.aspx
 //! [ti]: https://en.wikipedia.org/wiki/Terminfo
 
-#![crate_name = "term"]
-#![crate_type = "rlib"]
-#![crate_type = "dylib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/",
index 5e34688f8cb8f0e7ffc6997cee5aa353bf728843..642eb28556408339c78e39f4b9ca107eaa04f13d 100644 (file)
 // running tests while providing a base that other test frameworks may
 // build off of.
 
+// NB: this is also specified in this crate's Cargo.toml, but libsyntax contains logic specific to
+// this crate, which relies on this attribute (rather than the value of `--crate-name` passed by
+// cargo) to detect this crate.
 #![crate_name = "test"]
 #![unstable(feature = "test", issue = "27812")]
-#![crate_type = "rlib"]
-#![crate_type = "dylib"]
 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
        html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
        html_root_url = "https://doc.rust-lang.org/nightly/",
 #![deny(warnings)]
 
 #![feature(asm)]
-#![feature(libc)]
+#![cfg_attr(unix, feature(libc))]
 #![feature(set_stdio)]
 #![feature(panic_unwind)]
 #![feature(staged_api)]
 
 extern crate getopts;
 extern crate term;
+#[cfg(unix)]
 extern crate libc;
 extern crate panic_unwind;
 
index 1ff0a1e19d7b312e6a3f12bfd3bdd60d577fab47..461b49aa363b4406716d1f2af76bb3e2a98abf4a 100644 (file)
@@ -9,8 +9,6 @@
 // except according to those terms.
 
 #![no_std]
-#![crate_name = "unwind"]
-#![crate_type = "rlib"]
 #![unstable(feature = "panic_unwind", issue = "32837")]
 #![deny(warnings)]
 
@@ -30,7 +28,7 @@
 #[cfg(not(target_env = "msvc"))]
 pub use libunwind::*;
 
-#[cfg(target_env = "musl")]
-#[link(name = "unwind", kind = "static-nobundle", cfg(target_feature = "crt-static"))]
+#[cfg(all(target_env = "musl", not(target_arch = "mips")))]
+#[link(name = "unwind", kind = "static", cfg(target_feature = "crt-static"))]
 #[link(name = "gcc_s", cfg(not(target_feature = "crt-static")))]
 extern {}
index edbb77fe39063bb3e4defb5f08f9e0250b4d7faf..bb292e2e52a95418cf89881184473170d62aa8f1 100644 (file)
@@ -15,6 +15,7 @@
 // libsyntax is not compiled for it.
 
 #![deny(plugin_as_library)]
+#![allow(unused_extern_crates)]
 
 extern crate macro_crate_test; //~ ERROR compiler plugin used as an ordinary library
 
index 89227f6b0100c806144f0d4ba235f45075b5315d..996a6b97cd9989c9a25cb654fe59fc3571d6225e 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![feature(alloc)]
+#![allow(unused_extern_crates)]
 
 extern crate alloc;
 //~^ NOTE previous import of the extern crate `alloc` here
index 60bcd2ae07649178489dec08000b35bb5ada526f..c285c4d9e00c1b342d806e03a107cab1e9f5e5ea 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![feature(alloc, libc)]
+#![allow(unused_extern_crates)]
 
 extern crate alloc;
 //~^ NOTE previous import of the extern crate `alloc` here
index 5e802bbbe3dda7dbdfb428068d399ef4749c45e3..ad8888e58f79ad4176b537850c836d2933d77b77 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![feature(alloc)]
+#![allow(unused_extern_crates)]
 
 extern crate alloc;
 //~^ NOTE previous import of the extern crate `alloc` here
index 1f9dfdb18470b3718b97289e62345b762f748e65..847393ba2b89f4168069b2ad97c1d09fd0cf9cac 100644 (file)
@@ -22,5 +22,5 @@ fn bar() -> isize { 42 }
 
 pub fn main() {
     let x: isize = Foo::<A=usize>::bar();
-    //~^ ERROR unexpected binding of associated item in expression path
+    //~^ ERROR associated type bindings are not allowed here
 }
diff --git a/src/test/compile-fail/auxiliary/lint_unused_extern_crate5.rs b/src/test/compile-fail/auxiliary/lint_unused_extern_crate5.rs
new file mode 100644 (file)
index 0000000..fc4bca8
--- /dev/null
@@ -0,0 +1,9 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
index c65b2366bf10f7360f69e167aa453f57e18bb4d9..bc9e2345f0ebb57a098ea525585f98da4d8ecd1b 100644 (file)
@@ -16,6 +16,7 @@
 #![deny(non_snake_case)] // To trigger a hard error
 
 // Shouldn't generate a warning about unstable features
+#[allow(unused_extern_crates)]
 extern crate stability_cfg2;
 
 pub fn BOGUS() { } //~ ERROR
diff --git a/src/test/compile-fail/feature-gate-fn_must_use.rs b/src/test/compile-fail/feature-gate-fn_must_use.rs
new file mode 100644 (file)
index 0000000..2dd6b90
--- /dev/null
@@ -0,0 +1,31 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(rustc_attrs)]
+
+struct MyStruct;
+
+impl MyStruct {
+    #[must_use]
+    fn need_to_use_method() -> bool { true } //~ WARN `#[must_use]` on methods is experimental
+}
+
+#[must_use]
+fn need_to_use_it() -> bool { true } //~ WARN `#[must_use]` on functions is experimental
+
+
+// Feature gates are tidy-required to have a specially named (or
+// comment-annotated) compile-fail test (which MUST fail), but for
+// backwards-compatibility reasons, we want `#[must_use]` on functions to be
+// compilable even if the `fn_must_use` feature is absent, thus necessitating
+// the usage of `#[rustc_error]` here, pragmatically if awkwardly solving this
+// dilemma until a superior solution can be devised.
+#[rustc_error]
+fn main() {} //~ ERROR compilation successful
index 29a2b0609fcd2dd368cede7d473fcf592448c9c5..204190d64acc1f61a33a02b7e02a510c52ce464d 100644 (file)
@@ -680,6 +680,7 @@ mod must_use {
     mod inner { #![must_use="1400"] }
 
     #[must_use = "1400"] fn f() { }
+    //~^ WARN `#[must_use]` on functions is experimental
 
     #[must_use = "1400"] struct S;
 
index e05dc06619969015e26a4da65a8906d9dc695eed..0f5aa24926beb9d3d24026f5a68ab9904458f85d 100644 (file)
@@ -11,6 +11,7 @@
 // aux-build:issue-36881-aux.rs
 
 fn main() {
+    #[allow(unused_extern_crates)]
     extern crate issue_36881_aux;
     use issue_36881_aux::Foo; //~ ERROR unresolved import
 }
diff --git a/src/test/compile-fail/issue-43431.rs b/src/test/compile-fail/issue-43431.rs
new file mode 100644 (file)
index 0000000..e9f6215
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(fn_traits)]
+
+trait CallSingle<A, B> {
+    fn call(&self, a: A) -> B where Self: Fn(A) -> B;
+}
+
+impl<A, B, F: Fn(A) -> B> CallSingle<A, B> for F {
+    fn call(&self, a: A) -> B {
+        <Self as Fn(A) -> B>::call(self, (a,))
+        //~^ ERROR associated type bindings are not allowed here
+    }
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-43784-associated-type.rs b/src/test/compile-fail/issue-43784-associated-type.rs
new file mode 100644 (file)
index 0000000..94b5c00
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub trait Partial<X: ?Sized>: Copy {
+}
+
+pub trait Complete {
+    type Assoc: Partial<Self>;
+}
+
+impl<T> Partial<T> for T::Assoc where
+    T: Complete
+{
+}
+
+impl<T> Complete for T { //~ ERROR the trait bound `T: std::marker::Copy` is not satisfied
+    type Assoc = T;
+}
diff --git a/src/test/compile-fail/issue-43784-supertrait.rs b/src/test/compile-fail/issue-43784-supertrait.rs
new file mode 100644 (file)
index 0000000..e70df11
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub trait Partial: Copy {
+}
+
+pub trait Complete: Partial {
+}
+
+impl<T> Partial for T where T: Complete {}
+impl<T> Complete for T {} //~ ERROR the trait bound `T: std::marker::Copy` is not satisfied
index 8443518b3f5681c682c188f1e98905768b50bb2b..9bc2c021904aad24dee2886f8a9cf2b8db797e5a 100644 (file)
@@ -14,7 +14,7 @@
 // aux-build:stability_cfg2.rs
 
 #![warn(deprecated)]
-#![allow(dead_code)]
+#![allow(dead_code, unused_extern_crates)]
 #![feature(staged_api, test_feature, rustc_attrs)]
 
 #![stable(feature = "rust1", since = "1.0.0")]
index b12ef6277bb4b5135f896661834efe9d8abadeee..a3cfa1349831d6f477967879059369bd8556b44a 100644 (file)
 // aux-build:lint_unused_extern_crate2.rs
 // aux-build:lint_unused_extern_crate3.rs
 // aux-build:lint_unused_extern_crate4.rs
+// aux-build:lint_unused_extern_crate5.rs
 
 #![deny(unused_extern_crates)]
 #![allow(unused_variables)]
 #![allow(deprecated)]
 
-extern crate lint_unused_extern_crate4; //~ ERROR: unused extern crate
+extern crate lint_unused_extern_crate5; //~ ERROR: unused extern crate
+
+pub extern crate lint_unused_extern_crate4; // no error, it is reexported
 
 extern crate lint_unused_extern_crate3; // no error, it is used
 
index ea2dfca0714fc5f35468f8b9293301a1f54a24b9..a2778a831306bbb7a5ec6c54c588788f0a7ee391 100644 (file)
@@ -11,5 +11,6 @@
 #![no_std]
 #![feature(macro_reexport)]
 
+#[allow(unused_extern_crates)]
 #[macro_reexport]  //~ ERROR bad macro reexport
 extern crate std;
index 844955fb7e6647a760cb7548f9562c0ac8f370a5..c5af9e3799de77bc3d1e0b379dd85e344d394dc8 100644 (file)
@@ -11,5 +11,6 @@
 #![no_std]
 #![feature(macro_reexport)]
 
+#[allow(unused_extern_crates)]
 #[macro_reexport="foo"]  //~ ERROR bad macro reexport
 extern crate std;
index 381c22854e6545eac2d476d33496dfbc8ac546ea..d72d1ee004ef77ce09923c960fa8fc0f1c0713d8 100644 (file)
@@ -11,5 +11,6 @@
 #![no_std]
 #![feature(macro_reexport)]
 
+#[allow(unused_extern_crates)]
 #[macro_reexport(foo="bar")]  //~ ERROR bad macro reexport
 extern crate std;
index 39c09c6977963350b5903fb4d9728659c2f27233..a07cc834411732da96fd7dc9e87df1bc72ce64e2 100644 (file)
@@ -10,5 +10,6 @@
 
 #![no_std]
 
+#[allow(unused_extern_crates)]
 #[macro_use(foo(bar))]  //~ ERROR bad macro import
 extern crate std;
index 11a0108b99b89a30e8fa1a2cae690cb42b08291f..89004f16897742944693a75edb034c449fab82bb 100644 (file)
@@ -10,5 +10,6 @@
 
 #![no_std]
 
+#[allow(unused_extern_crates)]
 #[macro_use(foo="bar")]  //~ ERROR bad macro import
 extern crate std;
index 3ae878ed1cbc0659929d47885f8daaa90ce154ab..6c0793ee78f19c5adaed14a58312e894162f2050 100644 (file)
@@ -9,5 +9,5 @@
 // except according to those terms.
 
 fn main() {
-    0.clone::<T = u8>(); //~ ERROR unexpected binding of associated item
+    0.clone::<T = u8>(); //~ ERROR associated type bindings are not allowed here
 }
index f384eafa34bdf44922f0210a3852472380691bfb..49064853d21d6830190f7a46d4ffd8f000e31118 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![no_std]
+#![allow(unused_extern_crates)]
 
 extern crate core; //~ ERROR: the name `core` is defined multiple times
 extern crate std;
index cc73cbe15fe5f9f16dfe8aa62b98fc895ac3b2e8..35695efe1a9b2293fd3d1e3aeed16a8edad06801 100644 (file)
@@ -12,8 +12,6 @@
 
 #![feature(placement_in_syntax)]
 
-extern crate core;
-
 fn main() {
     use std::boxed::HEAP; //~ ERROR use of unstable library feature
 
index 87a17c0f19a6de64480064e5d0f9efe96941df04..6a04a2c370430c47fdbf2f7c1ff3cca906a45da7 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#[allow(unused_extern_crates)]
 extern crate std;
 //~^ ERROR the name `std` is defined multiple times
 
index 099513484480bacb86d884462b41290c28126999..a89fd802baf0c11f936c9672da05c4be557ad6b3 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![feature(alloc)]
+#![allow(unused_extern_crates)]
 
 mod a {
     extern crate alloc;
index fd6c8ad08d65eb6258e50b57ad05defcce9886d8..5fcde4facbe8d5ecb1d05dcd4e4ad846e796b7c8 100644 (file)
@@ -16,6 +16,7 @@ struct Bar<A> {
 
 fn foo(b: Box<Bar()>) {
     //~^ ERROR parenthesized parameters may only be used with a trait
+    //~| ERROR the type placeholder `_` is not allowed within types on item signatures
 }
 
 fn main() { }
index 6416e1cacdc0cb94d09b56684e8c21d9d43389dd..e20d03478ec188ed66208e08ea95b4f69f17f9d0 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 #![deny(unused_attributes)]
-#![allow(dead_code, unused_imports)]
+#![allow(dead_code, unused_imports, unused_extern_crates)]
 #![feature(custom_attribute)]
 
 #![foo] //~ ERROR unused attribute
diff --git a/src/test/mir-opt/issue-43457.rs b/src/test/mir-opt/issue-43457.rs
new file mode 100644 (file)
index 0000000..708784d
--- /dev/null
@@ -0,0 +1,55 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -Z identify_regions -Z span_free_formats
+// ignore-tidy-linelength
+
+// Regression test for #43457: an `EndRegion` was missing from output
+// because compiler was using a faulty means for region map lookup.
+
+use std::cell::RefCell;
+
+fn rc_refcell_test(r: RefCell<i32>) {
+    r.borrow_mut();
+}
+
+fn main() { }
+
+// END RUST SOURCE
+// START rustc.node5.SimplifyCfg-qualify-consts.after.mir
+//
+// fn rc_refcell_test(_1: std::cell::RefCell<i32>) -> () {
+//     let mut _0: ();
+//     scope 1 {
+//         let _2: std::cell::RefCell<i32>;
+//     }
+//     let mut _3: std::cell::RefMut<'17dce, i32>;
+//     let mut _4: &'17dce std::cell::RefCell<i32>;
+//
+//     bb0: {
+//         StorageLive(_2);
+//         _2 = _1;
+//         StorageLive(_4);
+//         _4 = &'17dce _2;
+//         _3 = const <std::cell::RefCell<T>>::borrow_mut(_4) -> bb1;
+//     }
+//
+//     bb1: {
+//         drop(_3) -> bb2;
+//     }
+//
+//     bb2: {
+//         StorageDead(_4);
+//         EndRegion('17dce);
+//         _0 = ();
+//         StorageDead(_2);
+//         return;
+//     }
+// }
index b8c52378554bacef36952bf19fc48cdc511e477e..7197f4e17e3cc89750dc5aa9f125150533c48049 100644 (file)
@@ -2,4 +2,4 @@
 
 all:
        $(RUSTC) fakealloc.rs
-       $(RUSTC) ../../../liballoc/lib.rs --cfg feature=\"external_crate\" --extern external=$(TMPDIR)/$(shell $(RUSTC) --print file-names fakealloc.rs)
+       $(RUSTC) --crate-type=rlib ../../../liballoc/lib.rs --cfg feature=\"external_crate\" --extern external=$(TMPDIR)/$(shell $(RUSTC) --print file-names fakealloc.rs)
index de744520cc6beff198ccccb8c7009ea7903c657a..079f6a6b641e9178dd2aae3402e6537bdf256b4b 100644 (file)
 
 // aux-build:union.rs
 
-// FIXME: This test case makes little-endian assumptions.
-// ignore-s390x
-// ignore-sparc
-
 extern crate union;
 use std::mem::{size_of, align_of, zeroed};
 
@@ -39,7 +35,7 @@ fn local() {
         assert_eq!(w.b, 0);
         w.a = 1;
         assert_eq!(w.a, 1);
-        assert_eq!(w.b, 1);
+        assert_eq!(w.b.to_le(), 1);
     }
 }
 
@@ -60,7 +56,7 @@ fn xcrate() {
         assert_eq!(w.b, 0);
         w.a = 1;
         assert_eq!(w.a, 1);
-        assert_eq!(w.b, 1);
+        assert_eq!(w.b.to_le(), 1);
     }
 }
 
diff --git a/src/test/run-pass/wrong-hashset-issue-42918.rs b/src/test/run-pass/wrong-hashset-issue-42918.rs
new file mode 100644 (file)
index 0000000..5a23ade
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+//
+// compile-flags: -O
+
+use std::collections::HashSet;
+
+#[derive(PartialEq, Debug, Hash, Eq, Clone, PartialOrd, Ord)]
+enum MyEnum {
+    E0,
+
+    E1,
+
+    E2,
+    E3,
+    E4,
+
+    E5,
+    E6,
+    E7,
+}
+
+
+fn main() {
+    use MyEnum::*;
+    let s: HashSet<_> = [E4, E1].iter().cloned().collect();
+    let mut v: Vec<_> = s.into_iter().collect();
+    v.sort();
+
+    assert_eq!([E1, E4], &v[..]);
+}
diff --git a/src/test/rustdoc/remove-duplicates.rs b/src/test/rustdoc/remove-duplicates.rs
new file mode 100644 (file)
index 0000000..6c4f6d0
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_name = "foo"]
+
+mod foo {
+    pub use bar::*;
+    pub mod bar {
+        pub trait Foo {
+            fn foo();
+        }
+    }
+}
+
+// @count foo/index.html '//*[@class="trait"]' 1
+pub use foo::bar::*;
+pub use foo::*;
diff --git a/src/test/ui/issue-44023.rs b/src/test/ui/issue-44023.rs
new file mode 100644 (file)
index 0000000..295d480
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(non_ascii_idents)]
+
+pub fn main () {}
+
+fn საჭმელად_გემრიელი_სადილი ( ) -> isize {
+}
diff --git a/src/test/ui/issue-44023.stderr b/src/test/ui/issue-44023.stderr
new file mode 100644 (file)
index 0000000..a17512b
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-44023.rs:15:42
+   |
+15 |   fn საჭმელად_გემრიელი_სადილი ( ) -> isize {
+   |  __________________________________________^
+16 | | }
+   | |_^ expected isize, found ()
+   |
+   = note: expected type `isize`
+              found type `()`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issue-44078.rs b/src/test/ui/issue-44078.rs
new file mode 100644 (file)
index 0000000..ef47214
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    "😊"";
+}
diff --git a/src/test/ui/issue-44078.stderr b/src/test/ui/issue-44078.stderr
new file mode 100644 (file)
index 0000000..389f3b2
--- /dev/null
@@ -0,0 +1,10 @@
+error: unterminated double quote string
+  --> $DIR/issue-44078.rs:12:8
+   |
+12 |       "😊"";
+   |  ________^
+13 | | }
+   | |__^
+
+error: aborting due to previous error
+
index 6764c58f4bb59aeb1b9b345eab5f840ba0032c48..1ee0099799760d392a7bc037b3cd74c447678d36 100644 (file)
@@ -1,25 +1,10 @@
-error[E0308]: mismatched types
+error[E0623]: lifetime mismatch
   --> $DIR/ex2b-push-no-existing-names.rs:16:12
    |
+15 | fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
+   |                    --------      -------- these two types are declared with different lifetimes...
 16 |     x.push(y);
-   |            ^ lifetime mismatch
-   |
-   = note: expected type `Ref<'_, _>`
-              found type `Ref<'_, _>`
-note: the anonymous lifetime #3 defined on the function body at 15:1...
-  --> $DIR/ex2b-push-no-existing-names.rs:15:1
-   |
-15 | / fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
-16 | |     x.push(y);
-17 | | }
-   | |_^
-note: ...does not necessarily outlive the anonymous lifetime #2 defined on the function body at 15:1
-  --> $DIR/ex2b-push-no-existing-names.rs:15:1
-   |
-15 | / fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
-16 | |     x.push(y);
-17 | | }
-   | |_^
+   |            ^ ...but data from `y` flows into `x` here
 
 error: aborting due to previous error
 
index 4c878f3c0dc03f40013e02a81d05c66e17bb6b91..74a40c87c2fb1841b7a64acaa36cf7cb2c95b746 100644 (file)
@@ -2,7 +2,7 @@ error[E0623]: lifetime mismatch
   --> $DIR/ex3-both-anon-regions-2.rs:12:9
    |
 11 | fn foo((v, w): (&u8, &u8), x: &u8) {
-   |                 ---           --- these references are not declared with the same lifetime...
+   |                 ---           --- these two types are declared with different lifetimes...
 12 |     v = x;
    |         ^ ...but data from `x` flows here
 
index 7bd5ebf805f1e8a85d01e880eb136df3480270b6..51271243bdfdcc2399ca1d0f6b251cb7c0f1e540 100644 (file)
@@ -8,8 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn foo((v, w): (&u8, &u8), (x, y): (&u8, &u8)) {
-    v = x;
+fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
+    z.push((x,y));
 }
 
 fn main() { }
+
index 08506b8befa03ac387c9d674d7b4fe58e59d0f6d..898866c75f2140fccba2edc7a040a13816eec910 100644 (file)
@@ -1,10 +1,18 @@
 error[E0623]: lifetime mismatch
-  --> $DIR/ex3-both-anon-regions-3.rs:12:9
+  --> $DIR/ex3-both-anon-regions-3.rs:12:13
    |
-11 | fn foo((v, w): (&u8, &u8), (x, y): (&u8, &u8)) {
-   |                 ---                 --- these references are not declared with the same lifetime...
-12 |     v = x;
-   |         ^ ...but data flows here
+11 | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
+   |                     ---                 --- these two types are declared with different lifetimes...
+12 |     z.push((x,y));
+   |             ^ ...but data flows into `z` here
 
-error: aborting due to previous error
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-3.rs:12:15
+   |
+11 | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
+   |                         ---                  --- these two types are declared with different lifetimes...
+12 |     z.push((x,y));
+   |               ^ ...but data flows into `z` here
+
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-4.rs b/src/test/ui/lifetime-errors/ex3-both-anon-regions-4.rs
deleted file mode 100644 (file)
index fdb010a..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
-    z.push((x,y));
-}
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-4.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-4.stderr
deleted file mode 100644 (file)
index 9c2630f..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-error[E0601]: main function not found
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ex3-both-anon-regions-4.rs:12:13
-   |
-11 | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
-   |                     ---                 --- these references are not declared with the same lifetime...
-12 |     z.push((x,y));
-   |             ^ ...but data flows into `z` here
-
-error[E0623]: lifetime mismatch
-  --> $DIR/ex3-both-anon-regions-4.rs:12:15
-   |
-11 | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
-   |                         ---                  --- these references are not declared with the same lifetime...
-12 |     z.push((x,y));
-   |               ^ ...but data flows into `z` here
-
-error: aborting due to 3 previous errors
-
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.rs b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.rs
new file mode 100644 (file)
index 0000000..2fbf31a
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+struct Ref<'a, 'b> {
+    a: &'a u32,
+    b: &'b u32,
+}
+
+fn foo(mut x: Ref, y: Ref) {
+    x.b = y.b;
+}
+
+fn main() {}
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-2.stderr
new file mode 100644 (file)
index 0000000..26f31de
--- /dev/null
@@ -0,0 +1,10 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-both-are-structs-2.rs:16:11
+   |
+15 | fn foo(mut x: Ref, y: Ref) {
+   |               ---     --- these two types are declared with different lifetimes...
+16 |     x.b = y.b;
+   |           ^^^ ...but data from `y` flows into `x` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.rs b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.rs
new file mode 100644 (file)
index 0000000..120a7ca
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+struct Ref<'a, 'b> {
+    a: &'a u32,
+    b: &'b u32,
+}
+
+fn foo(mut x: Ref) {
+    x.a = x.b;
+}
+
+fn main() {}
\ No newline at end of file
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs-3.stderr
new file mode 100644 (file)
index 0000000..1b5ac7c
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-both-are-structs-3.rs:16:11
+   |
+15 | fn foo(mut x: Ref) {
+   |               ---
+   |               |
+   |               this type was declared with multiple lifetimes...
+16 |     x.a = x.b;
+   |           ^^^ ...but data with one lifetime flows into the other here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs.rs b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs.rs
new file mode 100644 (file)
index 0000000..67ba8ee
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// 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.
+struct Ref<'a> {
+    x: &'a u32,
+}
+
+fn foo(mut x: Vec<Ref>, y: Ref) {
+    x.push(y);
+}
+
+fn main() {}
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-both-are-structs.stderr
new file mode 100644 (file)
index 0000000..6ad7954
--- /dev/null
@@ -0,0 +1,10 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-both-are-structs.rs:15:12
+   |
+14 | fn foo(mut x: Vec<Ref>, y: Ref) {
+   |                   ---      --- these two types are declared with different lifetimes...
+15 |     x.push(y);
+   |            ^ ...but data from `y` flows into `x` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.rs b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.rs
new file mode 100644 (file)
index 0000000..a8b1f53
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Ref<'a, 'b> { a: &'a u32, b: &'b u32 }
+
+fn foo(mut x: Ref, y: &u32) {
+    y = x.b;
+}
+
+fn main() { }
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-2.stderr
new file mode 100644 (file)
index 0000000..31c7ebf
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-one-is-struct-2.rs:14:9
+   |
+13 | fn foo(mut x: Ref, y: &u32) {
+   |               ---     ----
+   |               |
+   |               these two types are declared with different lifetimes...
+14 |     y = x.b;
+   |         ^^^ ...but data from `x` flows into `y` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.rs b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.rs
new file mode 100644 (file)
index 0000000..4933dbb
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Ref<'a, 'b> { a: &'a u32, b: &'b u32 }
+
+fn foo(mut y: Ref, x: &u32) {
+    y.b = x;
+}
+
+fn main() { }
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct-3.stderr
new file mode 100644 (file)
index 0000000..d54b526
--- /dev/null
@@ -0,0 +1,10 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-one-is-struct-3.rs:14:11
+   |
+13 | fn foo(mut y: Ref, x: &u32) {
+   |               ---     ---- these two types are declared with different lifetimes...
+14 |     y.b = x;
+   |           ^ ...but data from `x` flows into `y` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct.rs b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct.rs
new file mode 100644 (file)
index 0000000..e1594b1
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Ref<'a, 'b> {
+    a: &'a u32,
+    b: &'b u32,
+}
+
+fn foo(mut x: Ref, y: &u32) {
+    x.b = y;
+}
+
+fn main() {}
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-one-is-struct.stderr
new file mode 100644 (file)
index 0000000..bb7b9ea
--- /dev/null
@@ -0,0 +1,10 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-one-is-struct.rs:17:11
+   |
+16 | fn foo(mut x: Ref, y: &u32) {
+   |               ---     ---- these two types are declared with different lifetimes...
+17 |     x.b = y;
+   |           ^ ...but data from `y` flows into `x` here
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.rs b/src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.rs
new file mode 100644 (file)
index 0000000..0dc257a
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Foo {
+  field: i32
+}
+
+impl Foo {
+  fn foo<'a>(&self, x: &i32) -> &i32 {
+    x
+  }
+}
+
+fn main() { }
+
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.stderr
new file mode 100644 (file)
index 0000000..890f9b3
--- /dev/null
@@ -0,0 +1,23 @@
+error[E0312]: lifetime of reference outlives lifetime of borrowed content...
+  --> $DIR/ex3-both-anon-regions-return-type-is-anon.rs:17:5
+   |
+17 |     x
+   |     ^
+   |
+note: ...the reference is valid for the anonymous lifetime #1 defined on the method body at 16:3...
+  --> $DIR/ex3-both-anon-regions-return-type-is-anon.rs:16:3
+   |
+16 | /   fn foo<'a>(&self, x: &i32) -> &i32 {
+17 | |     x
+18 | |   }
+   | |___^
+note: ...but the borrowed content is only valid for the anonymous lifetime #2 defined on the method body at 16:3
+  --> $DIR/ex3-both-anon-regions-return-type-is-anon.rs:16:3
+   |
+16 | /   fn foo<'a>(&self, x: &i32) -> &i32 {
+17 | |     x
+18 | |   }
+   | |___^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.rs b/src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.rs
new file mode 100644 (file)
index 0000000..0940ce1
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Foo {
+    field: i32,
+}
+
+impl Foo {
+    fn foo<'a>(&self, x: &Foo) -> &Foo {
+        if true { x } else { self }
+    }
+}
+
+fn main() {}
+
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-self-is-anon.stderr
new file mode 100644 (file)
index 0000000..43f00c3
--- /dev/null
@@ -0,0 +1,23 @@
+error[E0312]: lifetime of reference outlives lifetime of borrowed content...
+  --> $DIR/ex3-both-anon-regions-self-is-anon.rs:17:19
+   |
+17 |         if true { x } else { self }
+   |                   ^
+   |
+note: ...the reference is valid for the anonymous lifetime #1 defined on the method body at 16:5...
+  --> $DIR/ex3-both-anon-regions-self-is-anon.rs:16:5
+   |
+16 | /     fn foo<'a>(&self, x: &Foo) -> &Foo {
+17 | |         if true { x } else { self }
+18 | |     }
+   | |_____^
+note: ...but the borrowed content is only valid for the anonymous lifetime #2 defined on the method body at 16:5
+  --> $DIR/ex3-both-anon-regions-self-is-anon.rs:16:5
+   |
+16 | /     fn foo<'a>(&self, x: &Foo) -> &Foo {
+17 | |         if true { x } else { self }
+18 | |     }
+   | |_____^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-impl-items.rs b/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-impl-items.rs
new file mode 100644 (file)
index 0000000..3a7ba41
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+trait Foo {
+    fn foo<'a>(x: &mut Vec<&u8>, y: &u8);
+}
+impl Foo for () {
+    fn foo(x: &mut Vec<&u8>, y: &u8) {
+        x.push(y);
+    }
+}
+fn main() {}
diff --git a/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr b/src/test/ui/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr
new file mode 100644 (file)
index 0000000..9591df8
--- /dev/null
@@ -0,0 +1,10 @@
+error[E0623]: lifetime mismatch
+  --> $DIR/ex3-both-anon-regions-using-impl-items.rs:15:16
+   |
+14 |     fn foo(x: &mut Vec<&u8>, y: &u8) {
+   |                        ---      --- these two types are declared with different lifetimes...
+15 |         x.push(y);
+   |                ^ ...but data from `y` flows into `x` here
+
+error: aborting due to previous error
+
index 9ebff5118768d0a19b4a99440b568e377ff4e81d..be48d07b94e06098e811eb97395cef030c37f159 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
index a183d1fffc0b68ea13c05db03b0aa7a80ba43390..d3291063859cac81ee35beaa3f6048d878864ac7 100644 (file)
@@ -2,7 +2,7 @@ error[E0623]: lifetime mismatch
   --> $DIR/ex3-both-anon-regions.rs:12:12
    |
 11 | fn foo(x: &mut Vec<&u8>, y: &u8) {
-   |                    ---      --- these references are not declared with the same lifetime...
+   |                    ---      --- these two types are declared with different lifetimes...
 12 |     x.push(y);
    |            ^ ...but data from `y` flows into `x` here
 
index 5aea5f2ca06423823f51bbee89a1b0f0a66de551..c549ded4db2188ea4d06d4cd42e16c9812a95f22 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(fn_must_use)]
 #![warn(unused_must_use)]
 
 struct MyStruct {
index 20eb7452aea7163b200f252f09482f150b44ffff..242837793a0bf2f4acd1d92d6248189eeee9b443 100644 (file)
@@ -1,18 +1,18 @@
 warning: unused return value of `need_to_use_this_value` which must be used: it's important
-  --> $DIR/fn_must_use.rs:30:5
+  --> $DIR/fn_must_use.rs:31:5
    |
-30 |     need_to_use_this_value();
+31 |     need_to_use_this_value();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: lint level defined here
-  --> $DIR/fn_must_use.rs:11:9
+  --> $DIR/fn_must_use.rs:12:9
    |
-11 | #![warn(unused_must_use)]
+12 | #![warn(unused_must_use)]
    |         ^^^^^^^^^^^^^^^
 
 warning: unused return value of `MyStruct::need_to_use_this_method_value` which must be used
-  --> $DIR/fn_must_use.rs:33:5
+  --> $DIR/fn_must_use.rs:34:5
    |
-33 |     m.need_to_use_this_method_value();
+34 |     m.need_to_use_this_method_value();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
index 7704f7b1fd52607104cc7fdc435d636c9de1fe90..3d3f2c05d742e5f907e951aa8849b03f0bc1a895 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 7704f7b1fd52607104cc7fdc435d636c9de1fe90
+Subproject commit 3d3f2c05d742e5f907e951aa8849b03f0bc1a895
index 384ae3f45f60cced4636e9b85191662e48206e22..15216f52d91fd1bdfda89a9691472f6298454cac 100644 (file)
@@ -14,6 +14,7 @@
 
 #![deny(warnings)]
 
+#[cfg(any(target_os = "macos", target_os = "ios"))]
 extern crate libc;
 extern crate test;
 extern crate getopts;
@@ -39,7 +40,6 @@
 
 use self::header::EarlyProps;
 
-pub mod procsrv;
 pub mod util;
 mod json;
 pub mod header;
diff --git a/src/tools/compiletest/src/procsrv.rs b/src/tools/compiletest/src/procsrv.rs
deleted file mode 100644 (file)
index ffcc60e..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use std::env;
-use std::ffi::OsString;
-use std::io::prelude::*;
-use std::io;
-use std::path::PathBuf;
-use std::process::{Child, Command, ExitStatus, Output, Stdio};
-
-/// Get the name of the environment variable that holds dynamic library
-/// locations
-pub fn dylib_env_var() -> &'static str {
-    if cfg!(windows) {
-        "PATH"
-    } else if cfg!(target_os = "macos") {
-        "DYLD_LIBRARY_PATH"
-    } else if cfg!(target_os = "haiku") {
-        "LIBRARY_PATH"
-    } else {
-        "LD_LIBRARY_PATH"
-    }
-}
-
-/// Add `lib_path` and `aux_path` (if it is `Some`) to the dynamic library
-/// env var
-fn add_target_env(cmd: &mut Command, lib_path: &str, aux_path: Option<&str>) {
-    // Need to be sure to put both the lib_path and the aux path in the dylib
-    // search path for the child.
-    let var = dylib_env_var();
-    let mut path = env::split_paths(&env::var_os(var).unwrap_or(OsString::new()))
-        .collect::<Vec<_>>();
-    if let Some(p) = aux_path {
-        path.insert(0, PathBuf::from(p))
-    }
-    path.insert(0, PathBuf::from(lib_path));
-
-    // Add the new dylib search path var
-    let newpath = env::join_paths(&path).unwrap();
-    cmd.env(var, newpath);
-}
-
-/// Represents exit status, stdout and stderr of a completed process
-pub struct Result {
-    pub status: ExitStatus,
-    pub out: String,
-    pub err: String,
-}
-
-/// Runs a test program
-///
-/// # Params
-///  - `lib_path` Path to search for required library
-///  - `prog` command to run
-///  - `aux_path` Optional extra path to search for required
-///    auxiliary libraries
-///  - `args` List of arguments to pass to `prog`
-///  - `env` List of environment variables to set, `.0` is variable name,
-///    `.1` is value
-///  - `input` String to be fed as stdin
-///  - `current_dir` Optional working dir to run command in
-///
-pub fn run(lib_path: &str,
-           prog: &str,
-           aux_path: Option<&str>,
-           args: &[String],
-           env: Vec<(String, String)>,
-           input: Option<String>,
-           current_dir: Option<String>)
-           -> io::Result<Result> {
-
-    let mut cmd = Command::new(prog);
-    cmd.args(args)
-        .stdout(Stdio::piped())
-        .stderr(Stdio::piped())
-        .stdin(Stdio::piped());
-
-    add_target_env(&mut cmd, lib_path, aux_path);
-    for (key, val) in env {
-        cmd.env(&key, &val);
-    }
-    if let Some(cwd) = current_dir {
-        cmd.current_dir(cwd);
-    }
-
-    let mut process = cmd.spawn()?;
-    if let Some(input) = input {
-        process.stdin.as_mut().unwrap().write_all(input.as_bytes()).unwrap();
-    }
-    let Output { status, stdout, stderr } = process.wait_with_output().unwrap();
-
-    Ok(Result {
-        status,
-        out: String::from_utf8(stdout).unwrap(),
-        err: String::from_utf8(stderr).unwrap(),
-    })
-}
-
-/// Same as `run`, but return process rather than waiting on completion
-pub fn run_background(lib_path: &str,
-                      prog: &str,
-                      aux_path: Option<&str>,
-                      args: &[String],
-                      env: Vec<(String, String)>,
-                      input: Option<String>,
-                      current_dir: Option<String>)
-                      -> io::Result<Child> {
-
-    let mut cmd = Command::new(prog);
-    cmd.args(args)
-       .stdin(Stdio::piped())
-       .stdout(Stdio::piped());
-    add_target_env(&mut cmd, lib_path, aux_path);
-    for (key, val) in env {
-        cmd.env(&key, &val);
-    }
-    if let Some(cwd) = current_dir {
-        cmd.current_dir(cwd);
-    }
-
-    let mut process = cmd.spawn()?;
-    if let Some(input) = input {
-        process.stdin.as_mut().unwrap().write_all(input.as_bytes()).unwrap();
-    }
-
-    Ok(process)
-}
index 02511ac6d98bc6d01e2398b7c3eb8158ed2b160d..d2a0c776b33e683f4c830b62bd458d2de45cce6a 100644 (file)
 use filetime::FileTime;
 use json;
 use header::TestProps;
-use procsrv;
 use test::TestPaths;
 use util::logv;
 
+use std::collections::HashMap;
 use std::collections::HashSet;
 use std::env;
+use std::ffi::OsString;
 use std::fs::{self, File, create_dir_all};
 use std::io::prelude::*;
 use std::io::{self, BufReader};
 use std::path::{Path, PathBuf};
-use std::process::{Command, Output, ExitStatus};
+use std::process::{Command, Output, ExitStatus, Stdio};
 use std::str;
-use std::collections::HashMap;
 
 use extract_gdb_version;
 
+/// The name of the environment variable that holds dynamic library locations.
+pub fn dylib_env_var() -> &'static str {
+    if cfg!(windows) {
+        "PATH"
+    } else if cfg!(target_os = "macos") {
+        "DYLD_LIBRARY_PATH"
+    } else if cfg!(target_os = "haiku") {
+        "LIBRARY_PATH"
+    } else {
+        "LD_LIBRARY_PATH"
+    }
+}
+
 pub fn run(config: Config, testpaths: &TestPaths) {
     match &*config.target {
 
@@ -325,37 +338,23 @@ fn run_pretty_test(&self) {
         }
     }
 
-    fn print_source(&self,
-                    src: String,
-                    pretty_type: &str)
-                    -> ProcRes {
+    fn print_source(&self, src: String, pretty_type: &str) -> ProcRes {
         let aux_dir = self.aux_output_dir_name();
-        self.compose_and_run(self.make_pp_args(pretty_type.to_owned()),
-                             self.props.exec_env.clone(),
+
+        let mut rustc = Command::new(&self.config.rustc_path);
+        rustc.arg("-")
+            .arg("-Zunstable-options")
+            .args(&["--unpretty", &pretty_type])
+            .args(&["--target", &self.config.target])
+            .arg("-L").arg(&aux_dir)
+            .args(self.split_maybe_args(&self.config.target_rustcflags))
+            .args(&self.props.compile_flags)
+            .envs(self.props.exec_env.clone());
+
+        self.compose_and_run(rustc,
                              self.config.compile_lib_path.to_str().unwrap(),
                              Some(aux_dir.to_str().unwrap()),
-                             Some(src),
-                             None)
-    }
-
-    fn make_pp_args(&self,
-                    pretty_type: String)
-                    -> ProcArgs {
-        let aux_dir = self.aux_output_dir_name();
-        // FIXME (#9639): This needs to handle non-utf8 paths
-        let mut args = vec!["-".to_owned(),
-                            "-Zunstable-options".to_owned(),
-                            "--unpretty".to_owned(),
-                            pretty_type,
-                            format!("--target={}", self.config.target),
-                            "-L".to_owned(),
-                            aux_dir.to_str().unwrap().to_owned()];
-        args.extend(self.split_maybe_args(&self.config.target_rustcflags));
-        args.extend(self.props.compile_flags.iter().cloned());
-        ProcArgs {
-            prog: self.config.rustc_path.to_str().unwrap().to_owned(),
-            args,
-        }
+                             Some(src))
     }
 
     fn compare_source(&self,
@@ -379,45 +378,35 @@ fn compare_source(&self,
     }
 
     fn typecheck_source(&self, src: String) -> ProcRes {
-        let args = self.make_typecheck_args();
-        self.compose_and_run_compiler(args, Some(src))
-    }
+        let mut rustc = Command::new(&self.config.rustc_path);
+
+        let out_dir = self.output_base_name().with_extension("pretty-out");
+        let _ = fs::remove_dir_all(&out_dir);
+        create_dir_all(&out_dir).unwrap();
 
-    fn make_typecheck_args(&self) -> ProcArgs {
-        let aux_dir = self.aux_output_dir_name();
         let target = if self.props.force_host {
             &*self.config.host
         } else {
             &*self.config.target
         };
 
-        let out_dir = self.output_base_name().with_extension("pretty-out");
-        let _ = fs::remove_dir_all(&out_dir);
-        create_dir_all(&out_dir).unwrap();
+        let aux_dir = self.aux_output_dir_name();
+
+        rustc.arg("-")
+            .arg("-Zno-trans")
+            .arg("--out-dir").arg(&out_dir)
+            .arg(&format!("--target={}", target))
+            .arg("-L").arg(&self.config.build_base)
+            .arg("-L").arg(aux_dir);
 
-        // FIXME (#9639): This needs to handle non-utf8 paths
-        let mut args = vec!["-".to_owned(),
-                            "-Zno-trans".to_owned(),
-                            "--out-dir".to_owned(),
-                            out_dir.to_str().unwrap().to_owned(),
-                            format!("--target={}", target),
-                            "-L".to_owned(),
-                            self.config.build_base.to_str().unwrap().to_owned(),
-                            "-L".to_owned(),
-                            aux_dir.to_str().unwrap().to_owned()];
         if let Some(revision) = self.revision {
-            args.extend(vec![
-                "--cfg".to_string(),
-                revision.to_string(),
-            ]);
-        }
-        args.extend(self.split_maybe_args(&self.config.target_rustcflags));
-        args.extend(self.props.compile_flags.iter().cloned());
-        // FIXME (#9639): This needs to handle non-utf8 paths
-        ProcArgs {
-            prog: self.config.rustc_path.to_str().unwrap().to_owned(),
-            args,
+            rustc.args(&["--cfg", revision]);
         }
+
+        rustc.args(self.split_maybe_args(&self.config.target_rustcflags));
+        rustc.args(&self.props.compile_flags);
+
+        self.compose_and_run_compiler(rustc, Some(src))
     }
 
     fn run_debuginfo_gdb_test(&self) {
@@ -500,32 +489,19 @@ fn run_debuginfo_gdb_test_no_opt(&self) {
                 debug!("script_str = {}", script_str);
                 self.dump_output_file(&script_str, "debugger.script");
 
+                let adb_path = &self.config.adb_path;
 
-                procsrv::run("",
-                             &self.config.adb_path,
-                             None,
-                             &[
-                                 "push".to_owned(),
-                                 exe_file.to_str().unwrap().to_owned(),
-                                 self.config.adb_test_dir.clone()
-                             ],
-                             Vec::new(),
-                             None,
-                             None)
-                    .expect(&format!("failed to exec `{:?}`", self.config.adb_path));
-
-                procsrv::run("",
-                             &self.config.adb_path,
-                             None,
-                             &[
-                                 "forward".to_owned(),
-                                 "tcp:5039".to_owned(),
-                                 "tcp:5039".to_owned()
-                             ],
-                             Vec::new(),
-                             None,
-                             None)
-                    .expect(&format!("failed to exec `{:?}`", self.config.adb_path));
+                Command::new(adb_path)
+                    .arg("push")
+                    .arg(&exe_file)
+                    .arg(&self.config.adb_test_dir)
+                    .status()
+                    .expect(&format!("failed to exec `{:?}`", adb_path));
+
+                Command::new(adb_path)
+                    .args(&["forward", "tcp:5039", "tcp:5039"])
+                    .status()
+                    .expect(&format!("failed to exec `{:?}`", adb_path));
 
                 let adb_arg = format!("export LD_LIBRARY_PATH={}; \
                                        gdbserver{} :5039 {}/{}",
@@ -537,23 +513,17 @@ fn run_debuginfo_gdb_test_no_opt(&self) {
                                       .unwrap());
 
                 debug!("adb arg: {}", adb_arg);
-                let mut process = procsrv::run_background("",
-                                                          &self.config.adb_path
-                                                          ,
-                                                          None,
-                                                          &[
-                                                              "shell".to_owned(),
-                                                              adb_arg.clone()
-                                                          ],
-                                                          Vec::new(),
-                                                          None,
-                                                          None)
-                    .expect(&format!("failed to exec `{:?}`", self.config.adb_path));
+                let mut adb = Command::new(adb_path)
+                    .args(&["shell", &adb_arg])
+                    .stdout(Stdio::piped())
+                    .stderr(Stdio::inherit())
+                    .spawn()
+                    .expect(&format!("failed to exec `{:?}`", adb_path));
 
                 // Wait for the gdbserver to print out "Listening on port ..."
                 // at which point we know that it's started and then we can
                 // execute the debugger below.
-                let mut stdout = BufReader::new(process.stdout.take().unwrap());
+                let mut stdout = BufReader::new(adb.stdout.take().unwrap());
                 let mut line = String::new();
                 loop {
                     line.truncate(0);
@@ -574,33 +544,29 @@ fn run_debuginfo_gdb_test_no_opt(&self) {
 
                 let mut gdb_path = tool_path;
                 gdb_path.push_str("/bin/gdb");
-                let procsrv::Result {
-                    out,
-                    err,
-                    status
-                } = procsrv::run("",
-                                 &gdb_path,
-                                 None,
-                                 &debugger_opts,
-                                 Vec::new(),
-                                 None,
-                                 None)
+                let Output {
+                    status,
+                    stdout,
+                    stderr
+                } = Command::new(&gdb_path)
+                    .args(&debugger_opts)
+                    .output()
                     .expect(&format!("failed to exec `{:?}`", gdb_path));
                 let cmdline = {
-                    let cmdline = self.make_cmdline("",
-                                                    &format!("{}-gdb", self.config.target),
-                                                    &debugger_opts);
+                    let mut gdb = Command::new(&format!("{}-gdb", self.config.target));
+                    gdb.args(&debugger_opts);
+                    let cmdline = self.make_cmdline(&gdb, "");
                     logv(self.config, format!("executing {}", cmdline));
                     cmdline
                 };
 
                 debugger_run_result = ProcRes {
                     status,
-                    stdout: out,
-                    stderr: err,
+                    stdout: String::from_utf8(stdout).unwrap(),
+                    stderr: String::from_utf8(stderr).unwrap(),
                     cmdline,
                 };
-                if process.kill().is_err() {
+                if adb.kill().is_err() {
                     println!("Adb process is already finished.");
                 }
             }
@@ -679,19 +645,14 @@ fn run_debuginfo_gdb_test_no_opt(&self) {
                          "-nx".to_owned(),
                          format!("-command={}", debugger_script.to_str().unwrap())];
 
-                let proc_args = ProcArgs {
-                    prog: self.config.gdb.as_ref().unwrap().to_owned(),
-                    args: debugger_opts,
-                };
-
-                let environment = vec![("PYTHONPATH".to_owned(), rust_pp_module_abs_path)];
+                let mut gdb = Command::new(self.config.gdb.as_ref().unwrap());
+                gdb.args(&debugger_opts)
+                    .env("PYTHONPATH", rust_pp_module_abs_path);
 
                 debugger_run_result =
-                    self.compose_and_run(proc_args,
-                                         environment,
+                    self.compose_and_run(gdb,
                                          self.config.run_lib_path.to_str().unwrap(),
                                          None,
-                                         None,
                                          None);
             }
         }
@@ -1154,10 +1115,11 @@ fn is_unexpected_compiler_message(&self,
     }
 
     fn compile_test(&self) -> ProcRes {
-        let aux_dir = self.aux_output_dir_name();
-        // FIXME (#9639): This needs to handle non-utf8 paths
-        let mut extra_args = vec!["-L".to_owned(),
-                                  aux_dir.to_str().unwrap().to_owned()];
+        let mut rustc = self.make_compile_args(
+            &self.testpaths.file, TargetLocation::ThisFile(self.make_exe_name()));
+
+        rustc.arg("-L").arg(&self.aux_output_dir_name());
+
         match self.config.mode {
             CompileFail | Ui => {
                 // compile-fail and ui tests tend to have tons of unused code as
@@ -1165,15 +1127,12 @@ fn compile_test(&self) -> ProcRes {
                 // want to actually assert warnings about all this code. Instead
                 // let's just ignore unused code warnings by defaults and tests
                 // can turn it back on if needed.
-                extra_args.push("-A".to_owned());
-                extra_args.push("unused".to_owned());
+                rustc.args(&["-A", "unused"]);
             }
             _ => {}
         }
-        let args = self.make_compile_args(extra_args,
-                                          &self.testpaths.file,
-                                          TargetLocation::ThisFile(self.make_exe_name()));
-        self.compose_and_run_compiler(args, None)
+
+        self.compose_and_run_compiler(rustc, None)
     }
 
     fn document(&self, out_dir: &Path) -> ProcRes {
@@ -1197,22 +1156,20 @@ fn document(&self, out_dir: &Path) -> ProcRes {
         }
 
         let aux_dir = self.aux_output_dir_name();
-        let mut args = vec!["-L".to_owned(),
-                            aux_dir.to_str().unwrap().to_owned(),
-                            "-o".to_owned(),
-                            out_dir.to_str().unwrap().to_owned(),
-                            self.testpaths.file.to_str().unwrap().to_owned()];
-        args.extend(self.props.compile_flags.iter().cloned());
-        let args = ProcArgs {
-            prog: self.config.rustdoc_path
-                .as_ref().expect("--rustdoc-path passed").to_str().unwrap().to_owned(),
-            args,
-        };
-        self.compose_and_run_compiler(args, None)
+
+        let rustdoc_path = self.config.rustdoc_path.as_ref().expect("--rustdoc-path passed");
+        let mut rustdoc = Command::new(rustdoc_path);
+
+        rustdoc.arg("-L").arg(aux_dir)
+            .arg("-o").arg(out_dir)
+            .arg(&self.testpaths.file)
+            .args(&self.props.compile_flags);
+
+        self.compose_and_run_compiler(rustdoc, None)
     }
 
     fn exec_compiled_test(&self) -> ProcRes {
-        let env = self.props.exec_env.clone();
+        let env = &self.props.exec_env;
 
         match &*self.config.target {
             // This is pretty similar to below, we're transforming:
@@ -1230,41 +1187,39 @@ fn exec_compiled_test(&self) -> ProcRes {
             // the process) and then report back the same result.
             _ if self.config.remote_test_client.is_some() => {
                 let aux_dir = self.aux_output_dir_name();
-                let mut args = self.make_run_args();
-                let mut program = args.prog.clone();
+                let ProcArgs { mut prog, args } = self.make_run_args();
                 if let Ok(entries) = aux_dir.read_dir() {
                     for entry in entries {
                         let entry = entry.unwrap();
                         if !entry.path().is_file() {
                             continue
                         }
-                        program.push_str(":");
-                        program.push_str(entry.path().to_str().unwrap());
+                        prog.push_str(":");
+                        prog.push_str(entry.path().to_str().unwrap());
                     }
                 }
-                args.args.insert(0, program);
-                args.args.insert(0, "run".to_string());
-                args.prog = self.config.remote_test_client.clone().unwrap()
-                                .into_os_string().into_string().unwrap();
-                self.compose_and_run(args,
-                                     env,
+                let mut test_client = Command::new(
+                    self.config.remote_test_client.as_ref().unwrap());
+                test_client
+                    .args(&["run", &prog])
+                    .args(args)
+                    .envs(env.clone());
+                self.compose_and_run(test_client,
                                      self.config.run_lib_path.to_str().unwrap(),
                                      Some(aux_dir.to_str().unwrap()),
-                                     None,
                                      None)
             }
             _ => {
                 let aux_dir = self.aux_output_dir_name();
-                let working_dir =
-                    Some(self.output_base_name()
-                             .parent().unwrap()
-                             .to_str().unwrap().to_owned());
-                self.compose_and_run(self.make_run_args(),
-                                     env,
+                let ProcArgs { prog, args } = self.make_run_args();
+                let mut program = Command::new(&prog);
+                program.args(args)
+                    .current_dir(&self.output_base_name().parent().unwrap())
+                    .envs(env.clone());
+                self.compose_and_run(program,
                                      self.config.run_lib_path.to_str().unwrap(),
                                      Some(aux_dir.to_str().unwrap()),
-                                     None,
-                                     working_dir)
+                                     None)
             }
         }
     }
@@ -1293,23 +1248,33 @@ fn compute_aux_test_paths(&self, rel_ab: &str) -> TestPaths {
         }
     }
 
-    fn compose_and_run_compiler(&self, args: ProcArgs, input: Option<String>) -> ProcRes {
+    fn compose_and_run_compiler(&self, mut rustc: Command, input: Option<String>) -> ProcRes {
         if !self.props.aux_builds.is_empty() {
             create_dir_all(&self.aux_output_dir_name()).unwrap();
         }
 
         let aux_dir = self.aux_output_dir_name();
-        // FIXME (#9639): This needs to handle non-utf8 paths
-        let extra_link_args = vec!["-L".to_owned(),
-                                   aux_dir.to_str().unwrap().to_owned()];
 
         for rel_ab in &self.props.aux_builds {
             let aux_testpaths = self.compute_aux_test_paths(rel_ab);
             let aux_props = self.props.from_aux_file(&aux_testpaths.file,
                                                      self.revision,
                                                      self.config);
-            let mut crate_type = if aux_props.no_prefer_dynamic {
-                Vec::new()
+            let aux_output = {
+                let f = self.make_lib_name(&self.testpaths.file);
+                let parent = f.parent().unwrap();
+                TargetLocation::ThisDirectory(parent.to_path_buf())
+            };
+            let aux_cx = TestCx {
+                config: self.config,
+                props: &aux_props,
+                testpaths: &aux_testpaths,
+                revision: self.revision
+            };
+            let mut aux_rustc = aux_cx.make_compile_args(&aux_testpaths.file, aux_output);
+
+            let crate_type = if aux_props.no_prefer_dynamic {
+                None
             } else if (self.config.target.contains("musl") && !aux_props.force_host) ||
                       self.config.target.contains("emscripten") {
                 // We primarily compile all auxiliary libraries as dynamic libraries
@@ -1321,28 +1286,20 @@ fn compose_and_run_compiler(&self, args: ProcArgs, input: Option<String>) -> Pro
                 // dynamic libraries so we just go back to building a normal library. Note,
                 // however, that for MUSL if the library is built with `force_host` then
                 // it's ok to be a dylib as the host should always support dylibs.
-                vec!["--crate-type=lib".to_owned()]
+                Some("lib")
             } else {
-                vec!["--crate-type=dylib".to_owned()]
-            };
-            crate_type.extend(extra_link_args.clone());
-            let aux_output = {
-                let f = self.make_lib_name(&self.testpaths.file);
-                let parent = f.parent().unwrap();
-                TargetLocation::ThisDirectory(parent.to_path_buf())
+                Some("dylib")
             };
-            let aux_cx = TestCx {
-                config: self.config,
-                props: &aux_props,
-                testpaths: &aux_testpaths,
-                revision: self.revision
-            };
-            let aux_args = aux_cx.make_compile_args(crate_type, &aux_testpaths.file, aux_output);
-            let auxres = aux_cx.compose_and_run(aux_args,
-                                                Vec::new(),
+
+            if let Some(crate_type) = crate_type {
+                aux_rustc.args(&["--crate-type", crate_type]);
+            }
+
+            aux_rustc.arg("-L").arg(&aux_dir);
+
+            let auxres = aux_cx.compose_and_run(aux_rustc,
                                                 aux_cx.config.compile_lib_path.to_str().unwrap(),
                                                 Some(aux_dir.to_str().unwrap()),
-                                                None,
                                                 None);
             if !auxres.status.success() {
                 self.fatal_proc_rec(
@@ -1352,40 +1309,65 @@ fn compose_and_run_compiler(&self, args: ProcArgs, input: Option<String>) -> Pro
             }
         }
 
-        self.compose_and_run(args,
-                             self.props.rustc_env.clone(),
+        rustc.envs(self.props.rustc_env.clone());
+        self.compose_and_run(rustc,
                              self.config.compile_lib_path.to_str().unwrap(),
                              Some(aux_dir.to_str().unwrap()),
-                             input,
-                             None)
+                             input)
     }
 
     fn compose_and_run(&self,
-                       ProcArgs{ args, prog }: ProcArgs,
-                       procenv: Vec<(String, String)> ,
+                       mut command: Command,
                        lib_path: &str,
                        aux_path: Option<&str>,
-                       input: Option<String>,
-                       working_dir: Option<String>) -> ProcRes {
-        self.program_output(lib_path, prog, aux_path, args, procenv, input, working_dir)
-    }
+                       input: Option<String>) -> ProcRes {
+        let cmdline =
+        {
+            let cmdline = self.make_cmdline(&command, lib_path);
+            logv(self.config, format!("executing {}", cmdline));
+            cmdline
+        };
 
-    fn make_compile_args(&self,
-                         extras: Vec<String> ,
-                         input_file: &Path,
-                         output_file: TargetLocation)
-                         -> ProcArgs
-    {
-        let target = if self.props.force_host {
-            &*self.config.host
-        } else {
-            &*self.config.target
+        command
+            .stdout(Stdio::piped())
+            .stderr(Stdio::piped())
+            .stdin(Stdio::piped());
+
+        // Need to be sure to put both the lib_path and the aux path in the dylib
+        // search path for the child.
+        let mut path = env::split_paths(&env::var_os(dylib_env_var()).unwrap_or(OsString::new()))
+            .collect::<Vec<_>>();
+        if let Some(p) = aux_path {
+            path.insert(0, PathBuf::from(p))
+        }
+        path.insert(0, PathBuf::from(lib_path));
+
+        // Add the new dylib search path var
+        let newpath = env::join_paths(&path).unwrap();
+        command.env(dylib_env_var(), newpath);
+
+        let mut child = command.spawn().expect(&format!("failed to exec `{:?}`", &command));
+        if let Some(input) = input {
+            child.stdin.as_mut().unwrap().write_all(input.as_bytes()).unwrap();
+        }
+        let Output { status, stdout, stderr } = child.wait_with_output().unwrap();
+
+        let result = ProcRes {
+            status,
+            stdout: String::from_utf8(stdout).unwrap(),
+            stderr: String::from_utf8(stderr).unwrap(),
+            cmdline,
         };
 
-        // FIXME (#9639): This needs to handle non-utf8 paths
-        let mut args = vec![input_file.to_str().unwrap().to_owned(),
-                            "-L".to_owned(),
-                            self.config.build_base.to_str().unwrap().to_owned()];
+        self.dump_output(&result.stdout, &result.stderr);
+
+        result
+    }
+
+    fn make_compile_args(&self, input_file: &Path, output_file: TargetLocation) -> Command {
+        let mut rustc = Command::new(&self.config.rustc_path);
+        rustc.arg(input_file)
+            .arg("-L").arg(&self.config.build_base);
 
         // Optionally prevent default --target if specified in test compile-flags.
         let custom_target = self.props.compile_flags
@@ -1393,26 +1375,23 @@ fn make_compile_args(&self,
             .fold(false, |acc, x| acc || x.starts_with("--target"));
 
         if !custom_target {
-            args.extend(vec![
-                format!("--target={}", target),
-            ]);
+            let target = if self.props.force_host {
+                &*self.config.host
+            } else {
+                &*self.config.target
+            };
+
+            rustc.arg(&format!("--target={}", target));
         }
 
         if let Some(revision) = self.revision {
-            args.extend(vec![
-                "--cfg".to_string(),
-                revision.to_string(),
-            ]);
+            rustc.args(&["--cfg", revision]);
         }
 
         if let Some(ref incremental_dir) = self.props.incremental_dir {
-            args.extend(vec![
-                "-Z".to_string(),
-                format!("incremental={}", incremental_dir.display()),
-            ]);
+            rustc.args(&["-Z", &format!("incremental={}", incremental_dir.display())]);
         }
 
-
         match self.config.mode {
             CompileFail |
             ParseFail |
@@ -1421,19 +1400,14 @@ fn make_compile_args(&self,
                 // fashion, then you want JSON mode. Old-skool error
                 // patterns still match the raw compiler output.
                 if self.props.error_patterns.is_empty() {
-                    args.extend(["--error-format",
-                                 "json"]
-                                .iter()
-                                .map(|s| s.to_string()));
+                    rustc.args(&["--error-format", "json"]);
                 }
             }
             MirOpt => {
-                args.extend(["-Zdump-mir=all",
-                             "-Zmir-opt-level=3",
-                             "-Zdump-mir-exclude-pass-number"]
-                            .iter()
-                            .map(|s| s.to_string()));
-
+                rustc.args(&[
+                    "-Zdump-mir=all",
+                    "-Zmir-opt-level=3",
+                    "-Zdump-mir-exclude-pass-number"]);
 
                 let mir_dump_dir = self.get_mir_dump_dir();
                 create_dir_all(mir_dump_dir.as_path()).unwrap();
@@ -1441,7 +1415,7 @@ fn make_compile_args(&self,
                 dir_opt.push_str(mir_dump_dir.to_str().unwrap());
                 debug!("dir_opt: {:?}", dir_opt);
 
-                args.push(dir_opt);
+                rustc.arg(dir_opt);
             }
             RunPass |
             RunFail |
@@ -1458,32 +1432,28 @@ fn make_compile_args(&self,
             }
         }
 
-        args.extend_from_slice(&extras);
         if !self.props.no_prefer_dynamic {
-            args.push("-C".to_owned());
-            args.push("prefer-dynamic".to_owned());
+            rustc.args(&["-C", "prefer-dynamic"]);
         }
-        let path = match output_file {
+
+        match output_file {
             TargetLocation::ThisFile(path) => {
-                args.push("-o".to_owned());
-                path
+                rustc.arg("-o").arg(path);
             }
             TargetLocation::ThisDirectory(path) => {
-                args.push("--out-dir".to_owned());
-                path
+                rustc.arg("--out-dir").arg(path);
             }
-        };
-        args.push(path.to_str().unwrap().to_owned());
+        }
+
         if self.props.force_host {
-            args.extend(self.split_maybe_args(&self.config.host_rustcflags));
+            rustc.args(self.split_maybe_args(&self.config.host_rustcflags));
         } else {
-            args.extend(self.split_maybe_args(&self.config.target_rustcflags));
-        }
-        args.extend(self.props.compile_flags.iter().cloned());
-        ProcArgs {
-            prog: self.config.rustc_path.to_str().unwrap().to_owned(),
-            args,
+            rustc.args(self.split_maybe_args(&self.config.target_rustcflags));
         }
+
+        rustc.args(&self.props.compile_flags);
+
+        rustc
     }
 
     fn make_lib_name(&self, auxfile: &Path) -> PathBuf {
@@ -1554,50 +1524,12 @@ fn split_maybe_args(&self, argstr: &Option<String>) -> Vec<String> {
         }
     }
 
-    fn program_output(&self,
-                      lib_path: &str,
-                      prog: String,
-                      aux_path: Option<&str>,
-                      args: Vec<String>,
-                      env: Vec<(String, String)>,
-                      input: Option<String>,
-                      working_dir: Option<String>)
-                      -> ProcRes {
-        let cmdline =
-        {
-            let cmdline = self.make_cmdline(lib_path,
-                                            &prog,
-                                            &args);
-            logv(self.config, format!("executing {}", cmdline));
-            cmdline
-        };
-
-        let procsrv::Result {
-            out,
-            err,
-            status
-        } = procsrv::run(lib_path,
-                         &prog,
-                         aux_path,
-                         &args,
-                         env,
-                         input,
-                         working_dir).expect(&format!("failed to exec `{}`", prog));
-        self.dump_output(&out, &err);
-        ProcRes {
-            status,
-            stdout: out,
-            stderr: err,
-            cmdline,
-        }
-    }
-
-    fn make_cmdline(&self, libpath: &str, prog: &str, args: &[String]) -> String {
+    fn make_cmdline(&self, command: &Command, libpath: &str) -> String {
         use util;
 
         // Linux and mac don't require adjusting the library search path
         if cfg!(unix) {
-            format!("{} {}", prog, args.join(" "))
+            format!("{:?}", command)
         } else {
             // Build the LD_LIBRARY_PATH variable as it would be seen on the command line
             // for diagnostic purposes
@@ -1605,7 +1537,7 @@ fn lib_path_cmd_prefix(path: &str) -> String {
                 format!("{}=\"{}\"", util::lib_path_env_var(), util::make_new_path(path))
             }
 
-            format!("{} {} {}", lib_path_cmd_prefix(libpath), prog, args.join(" "))
+            format!("{} {:?}", lib_path_cmd_prefix(libpath), command)
         }
     }
 
@@ -1723,30 +1655,22 @@ fn try_print_open_handles(&self) {
 
     fn compile_test_and_save_ir(&self) -> ProcRes {
         let aux_dir = self.aux_output_dir_name();
-        // FIXME (#9639): This needs to handle non-utf8 paths
-        let mut link_args = vec!["-L".to_owned(),
-                                 aux_dir.to_str().unwrap().to_owned()];
-        let llvm_args = vec!["--emit=llvm-ir".to_owned(),];
-        link_args.extend(llvm_args);
-        let args = self.make_compile_args(link_args,
-                                          &self.testpaths.file,
-                                          TargetLocation::ThisDirectory(
-                                              self.output_base_name().parent()
-                                                                     .unwrap()
-                                                                     .to_path_buf()));
-        self.compose_and_run_compiler(args, None)
+
+        let output_file = TargetLocation::ThisDirectory(
+            self.output_base_name().parent().unwrap().to_path_buf());
+        let mut rustc = self.make_compile_args(&self.testpaths.file, output_file);
+        rustc.arg("-L").arg(aux_dir)
+            .arg("--emit=llvm-ir");
+
+        self.compose_and_run_compiler(rustc, None)
     }
 
     fn check_ir_with_filecheck(&self) -> ProcRes {
         let irfile = self.output_base_name().with_extension("ll");
-        let prog = self.config.llvm_filecheck.as_ref().unwrap();
-        let proc_args = ProcArgs {
-            // FIXME (#9639): This needs to handle non-utf8 paths
-            prog: prog.to_str().unwrap().to_owned(),
-            args: vec![format!("-input-file={}", irfile.to_str().unwrap()),
-                       self.testpaths.file.to_str().unwrap().to_owned()]
-        };
-        self.compose_and_run(proc_args, Vec::new(), "", None, None, None)
+        let mut filecheck = Command::new(self.config.llvm_filecheck.as_ref().unwrap());
+        filecheck.arg("--input-file").arg(irfile)
+            .arg(&self.testpaths.file);
+        self.compose_and_run(filecheck, "", None, None)
     }
 
     fn run_codegen_test(&self) {
@@ -2179,7 +2103,7 @@ fn run_rmake_test(&self) {
            .env("RUSTDOC",
                cwd.join(&self.config.rustdoc_path.as_ref().expect("--rustdoc-path passed")))
            .env("TMPDIR", &tmpdir)
-           .env("LD_LIB_PATH_ENVVAR", procsrv::dylib_env_var())
+           .env("LD_LIB_PATH_ENVVAR", dylib_env_var())
            .env("HOST_RPATH_DIR", cwd.join(&self.config.compile_lib_path))
            .env("TARGET_RPATH_DIR", cwd.join(&self.config.run_lib_path))
            .env("LLVM_COMPONENTS", &self.config.llvm_components)
index 5d4bbd9052fe2af849a7d017b85df98ad002c20f..25ffb3a3d7809b4fa112f3e04e926eb539dd5e90 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 5d4bbd9052fe2af849a7d017b85df98ad002c20f
+Subproject commit 25ffb3a3d7809b4fa112f3e04e926eb539dd5e90