]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #51394 - nnethercote:NCA-depths, r=nikomatsakis
authorMark Rousskov <mark.simulacrum@gmail.com>
Fri, 8 Jun 2018 23:21:03 +0000 (17:21 -0600)
committerGitHub <noreply@github.com>
Fri, 8 Jun 2018 23:21:03 +0000 (17:21 -0600)
Use scope tree depths to speed up `nearest_common_ancestor`.

This patch adds depth markings to all entries in the `ScopeTree`'s
`parent_map`. This change increases memory usage somewhat, but permits a
much faster algorithm to be used:

- If one scope has a greater depth than the other, the deeper scope is
  moved upward until they are at equal depths.

- Then we move the two scopes upward in lockstep until they match.

This avoids the need to keep track of which scopes have already been
seen, which was the major part of the cost of the old algorithm. It also
reduces the number of child-to-parent moves (which are hash table
lookups) when the scopes start at different levels, because it never
goes past the nearest common ancestor the way the old algorithm did.

Finally, the case where one of the scopes is the root is now handled in
advance, because that is moderately common and lets us skip everything.

This change speeds up runs of several rust-perf benchmarks, the best by
6%.

A selection of the bigger improvements:
```
clap-rs-check
        avg: -2.6%      min: -6.6%      max: 0.0%
syn-check
        avg: -2.2%      min: -5.0%      max: 0.0%
style-servo-check
        avg: -2.9%?     min: -4.8%?     max: 0.0%?
cargo-check
        avg: -1.3%      min: -2.8%      max: 0.0%
sentry-cli-check
        avg: -1.0%      min: -2.1%      max: 0.0%
webrender-check
        avg: -0.9%      min: -2.0%      max: 0.0%
style-servo
        avg: -0.9%?     min: -1.8%?     max: -0.0%?
ripgrep-check
        avg: -0.7%      min: -1.8%      max: 0.1%
clap-rs
        avg: -0.9%      min: -1.6%      max: -0.2%
regex-check
        avg: -0.2%      min: -1.3%      max: 0.1%
syn
        avg: -0.6%      min: -1.3%      max: 0.1%
hyper-check
        avg: -0.5%      min: -1.1%      max: 0.0%
```
The idea came from multiple commenters on my blog and on Reddit. Thank you!

r? @nikomatsakis

210 files changed:
.travis.yml
src/Cargo.lock
src/ci/docker/run.sh
src/doc/rustdoc/src/documentation-tests.md
src/etc/htmldocck.py
src/liballoc/boxed.rs
src/liballoc/fmt.rs
src/liballoc/lib.rs
src/liballoc/task.rs [new file with mode: 0644]
src/libcore/fmt/mod.rs
src/libcore/future.rs [new file with mode: 0644]
src/libcore/lib.rs
src/libcore/task.rs [new file with mode: 0644]
src/librustc/Cargo.toml
src/librustc/ich/impls_ty.rs
src/librustc/lib.rs
src/librustc/lint/builtin.rs
src/librustc/lint/context.rs
src/librustc/middle/const_val.rs
src/librustc/mir/interpret/error.rs
src/librustc/traits/error_reporting.rs
src/librustc/traits/fulfill.rs
src/librustc/ty/context.rs
src/librustc/ty/maps/job.rs
src/librustc/ty/maps/mod.rs
src/librustc/ty/maps/plumbing.rs
src/librustc/ty/mod.rs
src/librustc/ty/structural_impls.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_codegen_llvm/mir/constant.rs
src/librustc_codegen_llvm/mir/operand.rs
src/librustc_data_structures/Cargo.toml
src/librustc_data_structures/lib.rs
src/librustc_data_structures/sync.rs
src/librustc_driver/Cargo.toml
src/librustc_driver/driver.rs
src/librustc_driver/lib.rs
src/librustc_errors/emitter.rs
src/librustc_lint/builtin.rs
src/librustc_lint/lib.rs
src/librustc_mir/Cargo.toml
src/librustc_mir/borrow_check/nll/mod.rs
src/librustc_mir/borrow_check/nll/type_check/liveness.rs
src/librustc_mir/hair/cx/expr.rs
src/librustc_mir/hair/pattern/check_match.rs
src/librustc_mir/hair/pattern/mod.rs
src/librustc_mir/interpret/const_eval.rs
src/librustc_mir/interpret/eval_context.rs
src/librustc_mir/interpret/memory.rs
src/librustc_mir/interpret/mod.rs
src/librustc_mir/interpret/place.rs
src/librustc_mir/interpret/terminator/mod.rs
src/librustc_mir/monomorphize/collector.rs
src/librustc_mir/transform/const_prop.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_typeck/Cargo.toml
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/mod.rs
src/librustdoc/clean/mod.rs
src/librustdoc/core.rs
src/librustdoc/html/item_type.rs
src/librustdoc/html/render.rs
src/librustdoc/html/static/main.js
src/librustdoc/html/static/rustdoc.css
src/librustdoc/html/static/themes/dark.css
src/librustdoc/html/static/themes/light.css
src/librustdoc/passes/mod.rs
src/librustdoc/visit_ast.rs
src/libstd/lib.rs
src/libstd/sys/redox/time.rs
src/libstd/sys/unix/time.rs
src/libsyntax/attr.rs
src/libsyntax/config.rs
src/libsyntax/ext/expand.rs
src/libsyntax/ext/tt/quoted.rs
src/libsyntax/feature_gate.rs
src/libsyntax/parse/parser.rs
src/libsyntax/test.rs
src/libsyntax_pos/symbol.rs
src/test/codegen/abi-main-signature-16bit-c-int.rs
src/test/codegen/fastcall-inreg.rs
src/test/codegen/repr-transparent-aggregates-2.rs
src/test/codegen/stack-probes.rs
src/test/codegen/x86_mmx.rs
src/test/compile-fail/asm-bad-clobber.rs
src/test/compile-fail/asm-in-bad-modifier.rs
src/test/compile-fail/asm-misplaced-option.rs
src/test/compile-fail/asm-out-no-modifier.rs
src/test/compile-fail/asm-out-read-uninit.rs
src/test/compile-fail/borrowck/borrowck-asm.rs
src/test/compile-fail/const-array-oob.rs
src/test/compile-fail/const-err-early.rs
src/test/compile-fail/const-err-multi.rs
src/test/compile-fail/const-err.rs
src/test/compile-fail/const-err2.rs
src/test/compile-fail/const-err3.rs
src/test/compile-fail/const-integer-bool-ops.rs
src/test/compile-fail/const-len-underflow-subspans.rs
src/test/compile-fail/const-match-check.rs
src/test/compile-fail/const-tup-index-span.rs
src/test/compile-fail/eval-enum.rs
src/test/compile-fail/feature-gate-termination_trait_test.rs [deleted file]
src/test/compile-fail/issue-39616.rs
src/test/compile-fail/issue-43105.rs
src/test/compile-fail/issue-8460-const.rs
src/test/compile-fail/panic_implementation-closures.rs [new file with mode: 0644]
src/test/compile-fail/privacy/restricted/tuple-struct-fields/test.rs [deleted file]
src/test/compile-fail/privacy/restricted/tuple-struct-fields/test2.rs [deleted file]
src/test/compile-fail/privacy/restricted/tuple-struct-fields/test3.rs [deleted file]
src/test/parse-fail/bind-struct-early-modifiers.rs
src/test/run-fail/mir_indexing_oob_1.rs
src/test/run-fail/mir_indexing_oob_2.rs
src/test/run-fail/mir_indexing_oob_3.rs
src/test/run-make-fulldeps/issue-19371/foo.rs
src/test/run-pass-fulldeps/compiler-calls.rs
src/test/run-pass/auxiliary/issue_38715.rs
src/test/run-pass/auxiliary/two_macros_2.rs [new file with mode: 0644]
src/test/run-pass/borrowck/borrowck-multiple-borrows-interior-boxes.rs [new file with mode: 0644]
src/test/run-pass/futures-api.rs [new file with mode: 0644]
src/test/run-pass/macro-at-most-once-rep.rs
src/test/run-pass/mod_dir_path.rs
src/test/run-pass/stack-probes-lto.rs
src/test/run-pass/stack-probes.rs
src/test/run-pass/trait-object-auto-dedup.rs [new file with mode: 0644]
src/test/rustdoc-ui/intra-links-warning.rs
src/test/rustdoc-ui/intra-links-warning.stderr
src/test/rustdoc/inline_cross/auxiliary/macros.rs [new file with mode: 0644]
src/test/rustdoc/inline_cross/macros.rs [new file with mode: 0644]
src/test/rustdoc/invalid.crate.name.rs [new file with mode: 0644]
src/test/rustdoc/keyword.rs [new file with mode: 0644]
src/test/ui/asm-out-assign-imm.rs
src/test/ui/asm-out-assign-imm.stderr
src/test/ui/borrowck/mut-borrow-of-mut-ref.nll.stderr [new file with mode: 0644]
src/test/ui/borrowck/mut-borrow-of-mut-ref.rs [new file with mode: 0644]
src/test/ui/borrowck/mut-borrow-of-mut-ref.stderr [new file with mode: 0644]
src/test/ui/const-eval-overflow-2.rs
src/test/ui/const-eval-overflow-2.stderr
src/test/ui/const-eval-overflow-4.rs
src/test/ui/const-eval-overflow-4.stderr
src/test/ui/const-eval/conditional_array_execution.nll.stderr [new file with mode: 0644]
src/test/ui/const-eval/conditional_array_execution.rs
src/test/ui/const-eval/conditional_array_execution.stderr
src/test/ui/const-eval/index_out_of_bound.rs [deleted file]
src/test/ui/const-eval/index_out_of_bound.stderr [deleted file]
src/test/ui/const-eval/index_out_of_bounds.rs [new file with mode: 0644]
src/test/ui/const-eval/index_out_of_bounds.stderr [new file with mode: 0644]
src/test/ui/const-eval/issue-43197.nll.stderr [new file with mode: 0644]
src/test/ui/const-eval/issue-43197.rs
src/test/ui/const-eval/issue-43197.stderr
src/test/ui/const-eval/issue-44578.nll.stderr [new file with mode: 0644]
src/test/ui/const-eval/issue-44578.rs
src/test/ui/const-eval/issue-44578.stderr
src/test/ui/const-eval/issue-50814-2.rs [new file with mode: 0644]
src/test/ui/const-eval/issue-50814-2.stderr [new file with mode: 0644]
src/test/ui/const-eval/issue-50814.rs [new file with mode: 0644]
src/test/ui/const-eval/issue-50814.stderr [new file with mode: 0644]
src/test/ui/const-eval/issue-51300.rs [new file with mode: 0644]
src/test/ui/const-eval/promoted_const_fn_fail.rs
src/test/ui/const-eval/promoted_const_fn_fail.stderr
src/test/ui/const-eval/promoted_errors.stderr
src/test/ui/const-eval/pub_const_err.stderr
src/test/ui/const-eval/pub_const_err_bin.stderr
src/test/ui/const-fn-error.rs
src/test/ui/const-fn-error.stderr
src/test/ui/const-len-underflow-separate-spans.rs
src/test/ui/const-len-underflow-separate-spans.stderr
src/test/ui/did_you_mean/issue-31424.stderr
src/test/ui/error-codes/E0080.stderr
src/test/ui/error-codes/E0423.rs
src/test/ui/error-codes/E0423.stderr
src/test/ui/feature-gate-doc_keyword.rs [new file with mode: 0644]
src/test/ui/feature-gate-doc_keyword.stderr [new file with mode: 0644]
src/test/ui/generator/pattern-borrow.nll.stderr [deleted file]
src/test/ui/infinite-recursion-const-fn.rs
src/test/ui/infinite-recursion-const-fn.stderr
src/test/ui/issue-38715.rs [new file with mode: 0644]
src/test/ui/issue-38715.stderr [new file with mode: 0644]
src/test/ui/issue-45697.nll.stderr [deleted file]
src/test/ui/issue-49257.rs
src/test/ui/issue-49257.stderr
src/test/ui/issue-51279.rs [new file with mode: 0644]
src/test/ui/issue-51279.stderr [new file with mode: 0644]
src/test/ui/macros/macro-at-most-once-rep-ambig.rs
src/test/ui/macros/macro-at-most-once-rep-ambig.stderr
src/test/ui/resolve/token-error-correct-3.stderr
src/test/ui/rfc-1937-termination-trait/termination-trait-in-test-should-panic.rs
src/test/ui/rfc-1937-termination-trait/termination-trait-in-test-should-panic.stderr
src/test/ui/rfc-1937-termination-trait/termination-trait-in-test.rs
src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.rs
src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr
src/test/ui/similar-tokens.rs
src/test/ui/similar-tokens.stderr
src/test/ui/target-feature-wrong.rs
src/test/ui/target-feature-wrong.stderr
src/test/ui/token/issue-10636-2.stderr
src/test/ui/trait-object-auto-dedup-in-impl.rs [new file with mode: 0644]
src/test/ui/trait-object-auto-dedup-in-impl.stderr [new file with mode: 0644]
src/test/ui/tuple-struct-fields/test.rs [new file with mode: 0644]
src/test/ui/tuple-struct-fields/test.stderr [new file with mode: 0644]
src/test/ui/tuple-struct-fields/test2.rs [new file with mode: 0644]
src/test/ui/tuple-struct-fields/test2.stderr [new file with mode: 0644]
src/test/ui/tuple-struct-fields/test3.rs [new file with mode: 0644]
src/test/ui/tuple-struct-fields/test3.stderr [new file with mode: 0644]
src/test/ui/type-dependent-def-issue-49241.rs
src/test/ui/type-dependent-def-issue-49241.stderr
src/tools/cargo
src/tools/rls
src/tools/rustdoc-js/tester.js
src/tools/rustfmt

index 9e62b895ed21eaa17a717a2c7508b75af055b57d..c154f3d8e251f33daeaed515db23de2ec565fdeb 100644 (file)
@@ -301,7 +301,6 @@ before_deploy:
           rm -rf obj/build/dist/doc &&
           cp -r obj/build/dist/* deploy/$TRAVIS_COMMIT;
       fi
-  - travis_retry gem update --system
   - ls -la deploy/$TRAVIS_COMMIT
 
 deploy:
index d5a1d18a676082094ca9213850c58a7908ea5add..d4544ffa3244fe73049385198b21d41df08a7382 100644 (file)
@@ -1456,10 +1456,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "polonius-engine"
-version = "0.4.0"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "datafrog 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1687,6 +1688,7 @@ dependencies = [
  "clippy_lints 0.0.205 (registry+https://github.com/rust-lang/crates.io-index)",
  "env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "json 0.11.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "jsonrpc-core 8.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "languageserver-types 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1698,10 +1700,10 @@ dependencies = [
  "rls-analysis 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-blacklist 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-data 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rls-rustc 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rls-rustc 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-vfs 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustfmt-nightly 0.8.2",
+ "rustfmt-nightly 0.8.2 (git+https://github.com/rust-lang-nursery/rustfmt?rev=f3906267)",
  "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1740,7 +1742,7 @@ dependencies = [
 
 [[package]]
 name = "rls-rustc"
-version = "0.3.0"
+version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -1785,12 +1787,16 @@ dependencies = [
  "jobserver 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "polonius-engine 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "polonius-engine 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "proc_macro 0.0.0",
+ "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_apfloat 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
  "rustc_target 0.0.0",
+ "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serialize 0.0.0",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
@@ -1799,24 +1805,58 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-arena"
-version = "147.0.0"
+version = "149.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rustc-ap-rustc_data_structures 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rustc-ap-arena"
+version = "156.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rustc-ap-rustc_data_structures 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rustc-ap-rustc_cratesio_shim"
-version = "147.0.0"
+version = "149.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "rustc-ap-rustc_cratesio_shim"
+version = "156.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rustc-ap-rustc_data_structures"
+version = "149.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ena 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_cratesio_shim 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "rustc-ap-rustc_data_structures"
-version = "147.0.0"
+version = "156.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1824,65 +1864,122 @@ dependencies = [
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_cratesio_shim 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_cratesio_shim 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-rayon 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rustc-ap-rustc_errors"
-version = "147.0.0"
+version = "149.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_data_structures 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax_pos 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rustc-ap-rustc_errors"
+version = "156.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rustc-ap-rustc_target"
-version = "147.0.0"
+version = "149.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_cratesio_shim 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_cratesio_shim 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rustc-ap-rustc_target"
+version = "156.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_cratesio_shim 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rustc-ap-serialize"
-version = "147.0.0"
+version = "149.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "rustc-ap-serialize"
+version = "156.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "rustc-ap-syntax"
-version = "147.0.0"
+version = "149.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_data_structures 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_errors 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_target 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax_pos 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_errors 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_target 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "rustc-ap-syntax"
+version = "156.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_errors 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_target 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax_pos 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "rustc-ap-syntax_pos"
+version = "149.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "rustc-ap-arena 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "rustc-ap-syntax_pos"
-version = "147.0.0"
+version = "156.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "rustc-ap-arena 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_data_structures 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-serialize 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-arena 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_data_structures 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-serialize 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1910,16 +2007,16 @@ dependencies = [
 
 [[package]]
 name = "rustc-rayon"
-version = "0.1.0"
+version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-rayon-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "rustc-rayon-core"
-version = "0.1.0"
+version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "crossbeam-deque 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2043,8 +2140,8 @@ dependencies = [
  "parking_lot 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot_core 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-rayon 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-rayon-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_cratesio_shim 0.0.0",
  "serialize 0.0.0",
  "stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2060,7 +2157,7 @@ dependencies = [
  "graphviz 0.0.0",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
- "rustc-rayon 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_allocator 0.0.0",
  "rustc_borrowck 0.0.0",
  "rustc_codegen_utils 0.0.0",
@@ -2174,7 +2271,7 @@ dependencies = [
  "graphviz 0.0.0",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "log_settings 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "polonius-engine 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "polonius-engine 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_apfloat 0.0.0",
  "rustc_data_structures 0.0.0",
@@ -2306,7 +2403,6 @@ name = "rustc_typeck"
 version = "0.0.0"
 dependencies = [
  "arena 0.0.0",
- "fmt_macros 0.0.0",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_data_structures 0.0.0",
@@ -2357,6 +2453,31 @@ dependencies = [
  "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "rustfmt-nightly"
+version = "0.8.2"
+source = "git+https://github.com/rust-lang-nursery/rustfmt?rev=f3906267#f390626778c1bbb13911556d585850eb2fa67923"
+dependencies = [
+ "cargo_metadata 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "derive-new 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "env_logger 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "failure 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
+ "isatty 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "regex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_target 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "toml 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "rustfmt-nightly"
 version = "0.8.2"
@@ -2373,8 +2494,8 @@ dependencies = [
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-rustc_target 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "rustc-ap-syntax 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-rustc_target 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rustc-ap-syntax 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3176,7 +3297,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6b07ffcc532ccc85e3afc45865469bf5d9e4ef5bfcf9622e3cfe80c2d275ec03"
 "checksum phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "07e24b0ca9643bdecd0632f2b3da6b1b89bbb0030e0b992afc1113b23a7bc2f2"
 "checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
-"checksum polonius-engine 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9385a6d8f8ff6fd7e48a803c6a77fb89cc929dc7e2af6bf972494bbc8ff8b9e4"
+"checksum polonius-engine 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b6b0a7f5f4278b991ffd14abce1d01b013121ad297460237ef0a2f08d43201"
 "checksum precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
 "checksum pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6"
 "checksum proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "49b6a521dc81b643e9a51e0d1cf05df46d5a2f3c0280ea72bcb68276ba64a118"
@@ -3201,24 +3322,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum rls-analysis 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "da9794cd1f80f2cb888c00641a32f9855d0226c954ee31cef145784914c7142e"
 "checksum rls-blacklist 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e4a9cc2545ccb7e05b355bfe047b8039a6ec12270d5f3c996b766b340a50f7d2"
 "checksum rls-data 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3dd20763e1c60ae8945384c8a8fa4ac44f8afa7b0a817511f5e8927e5d24f988"
-"checksum rls-rustc 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ed5342b2bbbe8663c04600af506c8902b6b4d3e627b006eb1bd65aa14805f4d"
+"checksum rls-rustc 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2c8c09117ae2887baaa4b17fe1cb572f9b22e4d2c6a5cda04093d8b366b0be99"
 "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a"
 "checksum rls-vfs 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "be231e1e559c315bc60ced5ad2cc2d7a9c208ed7d4e2c126500149836fda19bb"
-"checksum rustc-ap-arena 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1304956fbbdd070e4478672d040f0453374604a12a0938aaba4b38a2bd124667"
-"checksum rustc-ap-rustc_cratesio_shim 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6d1dcd0fafa3c7875b76e33feaf69b332870180475ba3eb8dd003bcc2a2dc069"
-"checksum rustc-ap-rustc_data_structures 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "76c1a3fe4a0104b922ffc8080bd7c703dc20f2874b7c982638f6adb6c378b77a"
-"checksum rustc-ap-rustc_errors 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2812e295d2930bf3b3c22dbe8ef0bb8ae98a497ae6ad379d0709434387a9004b"
-"checksum rustc-ap-rustc_target 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5bd371121f16da666f6d6d5e6ff57cd972cc8206cc80377ba411b99607d49cbd"
-"checksum rustc-ap-serialize 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bde493c1c16d724e42536117c385b69f2eae9b2ec38bab841c45373bce4a9d8f"
-"checksum rustc-ap-syntax 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "402c1f402e6d47defcd884d3f715aaa8c6f2cbdd5f13cb06fea70486d512426b"
-"checksum rustc-ap-syntax_pos 147.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb707a229093791dc3fc35aca61d9bf0e3708f23da4536683527857bc624b061"
+"checksum rustc-ap-arena 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e794b25832224eea9252ebfa9f94ab7070d0a60c977793112c611501cb56b48d"
+"checksum rustc-ap-arena 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83e91a01cd6c5a9e4f68c2b5c81b62b172aa9e00fc2fec862c0899e3fac1fd32"
+"checksum rustc-ap-rustc_cratesio_shim 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a78241b2ecb82ebb9221b4b7d37c024ff1f2e43f1b099f38a997f030fc7894b0"
+"checksum rustc-ap-rustc_cratesio_shim 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1e8ea8fadc5d66c1527771816e83f7e7599543bd2e1583e279855370ab2f18e5"
+"checksum rustc-ap-rustc_data_structures 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5529c3927f32b0b56d1f6449a34f2218dc2160c6a6dde0cf47954d83a9a45764"
+"checksum rustc-ap-rustc_data_structures 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "742ba74bc7d0f3ded56148329650f137fa5b90f7f0ecc4b4952150f32c66b147"
+"checksum rustc-ap-rustc_errors 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fb1fef44a7d63f5d204c981adb26a14e85fe7ee5962050a4f664df6f425f9b48"
+"checksum rustc-ap-rustc_errors 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3714046c6f8c1c259822aefcca21b1862710a6cec24fd34c0796117f074c6769"
+"checksum rustc-ap-rustc_target 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a3939a9f7bf063536dd646894ca43b1378ec6a56ac5b2698cc6ba0b42bfadbdc"
+"checksum rustc-ap-rustc_target 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b982c4517c18080895b06149ce8aa8279fd013f629030bb7a179bfcff6d74ef2"
+"checksum rustc-ap-serialize 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "692169d0bac8a4547f9778039460799e162664477a1eaec15d31507705f8c736"
+"checksum rustc-ap-serialize 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "27c7700595bff1a64ddb6f593c69db3f6d66b76b059b26137236c7e21e36db70"
+"checksum rustc-ap-syntax 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "22e93ee3817b007d56b5c5b151e6cd7c7063455a1facaf9e0ca01f9d9365b716"
+"checksum rustc-ap-syntax 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e6482d98c8be57d3cfe55dab744dd1a87f8462dc2ea0a8a4960f7bb1565be049"
+"checksum rustc-ap-syntax_pos 149.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fe5d24a137d6e202cd6eb96cb74f8cb4a2b257c42b74dd624e136b4e19f0a47d"
+"checksum rustc-ap-syntax_pos 156.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "20af5e200b61a3e5ba4f58ed3cbd7593569faf8f0956d5233f4f27fee51b4c81"
 "checksum rustc-demangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11fb43a206a04116ffd7cfcf9bcb941f8eb6cc7ff667272246b0a1c74259a3cb"
 "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8"
-"checksum rustc-rayon 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1aa5cd8c3a706edb19b6ec6aa7b056bdc635b6e99c5cf7014f9af9d92f15e99"
-"checksum rustc-rayon-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d69983f8613a9c3ba1a3bbf5e8bdf2fd5c42317b1d8dd8623ca8030173bf8a6b"
+"checksum rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c6d5a683c6ba4ed37959097e88d71c9e8e26659a3cb5be8b389078e7ad45306"
+"checksum rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40f06724db71e18d68b3b946fdf890ca8c921d9edccc1404fdfdb537b0d12649"
 "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
 "checksum rustc_version 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a54aa04a10c68c1c4eacb4337fd883b435997ede17a9385784b990777686b09a"
 "checksum rustfix 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9da3cf9b79dc889a2c9879643f26d7a53e37e9361c7566b7d2787d5ace0d8396"
+"checksum rustfmt-nightly 0.8.2 (git+https://github.com/rust-lang-nursery/rustfmt?rev=f3906267)" = "<none>"
 "checksum same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cfb6eded0b06a0b512c8ddbcf04089138c9b4362c2f696f3c3d76039d68f3637"
 "checksum schannel 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "85fd9df495640643ad2d00443b3d78aae69802ad488debab4f1dd52fc1806ade"
 "checksum scoped-tls 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8674d439c964889e2476f474a3bf198cc9e199e77499960893bac5de7e9218a4"
index 3465e386cd925c90c188a7cd27cd009c368c8beb..8913fdaa888e747efa3c955dc1886da2c64535c9 100755 (executable)
@@ -118,6 +118,10 @@ fi
 # goes ahead and sets it for all builders.
 args="$args --privileged"
 
+if [ "$CI" != "" ]; then
+    args="$args --dns 8.8.8.8 --dns 8.8.4.4 --dns 1.1.1.1 --dns 1.0.0.1"
+fi
+
 exec docker \
   run \
   --volume "$root_dir:/checkout:ro" \
index fd7d1713ca574eefeebff662b3f1f3d07088c064..cb233cc84cbed8fd95ddbce645dcabfe35a0cd45 100644 (file)
@@ -79,8 +79,9 @@ from your example, but are important to make the tests work. Consider
 an example block that looks like this:
 
 ```text
-/// Some documentation.
-# fn foo() {}
+/// /// Some documentation.
+/// # fn foo() {} // this function will be hidden
+/// println!("Hello, World!");
 ```
 
 It will render like this:
@@ -88,6 +89,7 @@ It will render like this:
 ```rust
 /// Some documentation.
 # fn foo() {}
+println!("Hello, World!");
 ```
 
 Yes, that's right: you can add lines that start with `# `, and they will
@@ -168,37 +170,56 @@ By repeating all parts of the example, you can ensure that your example still
 compiles, while only showing the parts that are relevant to that part of your
 explanation.
 
-Another case where the use of `#` is handy is when you want to ignore
-error handling. Lets say you want the following,
+
+## Using `?` in doc tests
+
+When writing an example, it is rarely useful to include a complete error
+handling, as it would add significant amounts of boilerplate code. Instead, you
+may want the following:
 
 ```ignore
+/// ```
 /// use std::io;
 /// let mut input = String::new();
 /// io::stdin().read_line(&mut input)?;
+/// ```
 ```
 
-The problem is that `?` returns a `Result<T, E>` and test functions
-don't return anything so this will give a mismatched types error.
+The problem is that `?` returns a `Result<T, E>` and test functions don't
+return anything, so this will give a mismatched types error.
+
+You can get around this limitation by manually adding a `main` that returns
+`Result<T, E>`, because `Result<T, E>` implements the `Termination` trait:
 
 ```ignore
 /// A doc test using ?
 ///
 /// ```
 /// use std::io;
-/// # fn foo() -> io::Result<()> {
+///
+/// fn main() -> io::Result<()> {
+///     let mut input = String::new();
+///     io::stdin().read_line(&mut input)?;
+///     Ok(())
+/// }
+/// ```
+```
+
+Together with the `# ` from the section above, you arrive at a solution that
+appears to the reader as the initial idea but works with doc tests:
+
+```ignore
+/// ```
+/// use std::io;
+/// # fn main() -> io::Result<()> {
 /// let mut input = String::new();
 /// io::stdin().read_line(&mut input)?;
 /// # Ok(())
 /// # }
 /// ```
-# fn foo() {}
 ```
 
-You can get around this by wrapping the code in a function. This catches
-and swallows the `Result<T, E>` when running tests on the docs. This
-pattern appears regularly in the standard library.
-
-### Documenting macros
+## Documenting macros
 
 Here’s an example of documenting a macro:
 
index 8a11c6f7cfc4c9d27950537feb79ab27572dc4ca..569788fe9c08a93cfca05915a7835ea629c34be0 100644 (file)
@@ -346,15 +346,19 @@ def check_tree_attr(tree, path, attr, pat, regexp):
 def check_tree_text(tree, path, pat, regexp):
     path = normalize_xpath(path)
     ret = False
-    for e in tree.findall(path):
-        try:
-            value = flatten(e)
-        except KeyError:
-            continue
-        else:
-            ret = check_string(value, pat, regexp)
-            if ret:
-                break
+    try:
+        for e in tree.findall(path):
+            try:
+                value = flatten(e)
+            except KeyError:
+                continue
+            else:
+                ret = check_string(value, pat, regexp)
+                if ret:
+                    break
+    except Exception as e:
+        print('Failed to get path "{}"'.format(path))
+        raise e
     return ret
 
 
index a83ce7f379fbc220063a3258b27be8ce112b58ee..a64b94b6517590e0c351750e102f2e49f99b5dc9 100644 (file)
 use core::borrow;
 use core::cmp::Ordering;
 use core::fmt;
+use core::future::Future;
 use core::hash::{Hash, Hasher};
 use core::iter::FusedIterator;
 use core::marker::{Unpin, Unsize};
 use core::mem::{self, PinMut};
 use core::ops::{CoerceUnsized, Deref, DerefMut, Generator, GeneratorState};
 use core::ptr::{self, NonNull, Unique};
+use core::task::{Context, Poll, UnsafePoll, TaskObj};
 use core::convert::From;
 
 use raw_vec::RawVec;
@@ -755,6 +757,7 @@ unsafe fn resume(&mut self) -> GeneratorState<Self::Yield, Self::Return> {
 /// A pinned, heap allocated reference.
 #[unstable(feature = "pin", issue = "49150")]
 #[fundamental]
+#[repr(transparent)]
 pub struct PinBox<T: ?Sized> {
     inner: Box<T>,
 }
@@ -771,14 +774,72 @@ pub fn new(data: T) -> PinBox<T> {
 #[unstable(feature = "pin", issue = "49150")]
 impl<T: ?Sized> PinBox<T> {
     /// Get a pinned reference to the data in this PinBox.
+    #[inline]
     pub fn as_pin_mut<'a>(&'a mut self) -> PinMut<'a, T> {
         unsafe { PinMut::new_unchecked(&mut *self.inner) }
     }
 
+    /// Constructs a `PinBox` from a raw pointer.
+    ///
+    /// After calling this function, the raw pointer is owned by the
+    /// resulting `PinBox`. Specifically, the `PinBox` destructor will call
+    /// the destructor of `T` and free the allocated memory. Since the
+    /// way `PinBox` allocates and releases memory is unspecified, the
+    /// only valid pointer to pass to this function is the one taken
+    /// from another `PinBox` via the [`PinBox::into_raw`] function.
+    ///
+    /// This function is unsafe because improper use may lead to
+    /// memory problems. For example, a double-free may occur if the
+    /// function is called twice on the same raw pointer.
+    ///
+    /// [`PinBox::into_raw`]: struct.PinBox.html#method.into_raw
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(pin)]
+    /// use std::boxed::PinBox;
+    /// let x = PinBox::new(5);
+    /// let ptr = PinBox::into_raw(x);
+    /// let x = unsafe { PinBox::from_raw(ptr) };
+    /// ```
+    #[inline]
+    pub unsafe fn from_raw(raw: *mut T) -> Self {
+        PinBox { inner: Box::from_raw(raw) }
+    }
+
+    /// Consumes the `PinBox`, returning the wrapped raw pointer.
+    ///
+    /// After calling this function, the caller is responsible for the
+    /// memory previously managed by the `PinBox`. In particular, the
+    /// caller should properly destroy `T` and release the memory. The
+    /// proper way to do so is to convert the raw pointer back into a
+    /// `PinBox` with the [`PinBox::from_raw`] function.
+    ///
+    /// Note: this is an associated function, which means that you have
+    /// to call it as `PinBox::into_raw(b)` instead of `b.into_raw()`. This
+    /// is so that there is no conflict with a method on the inner type.
+    ///
+    /// [`PinBox::from_raw`]: struct.PinBox.html#method.from_raw
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(pin)]
+    /// use std::boxed::PinBox;
+    /// let x = PinBox::new(5);
+    /// let ptr = PinBox::into_raw(x);
+    /// ```
+    #[inline]
+    pub fn into_raw(b: PinBox<T>) -> *mut T {
+        Box::into_raw(b.inner)
+    }
+
     /// Get a mutable reference to the data inside this PinBox.
     ///
     /// This function is unsafe. Users must guarantee that the data is never
     /// moved out of this reference.
+    #[inline]
     pub unsafe fn get_mut<'a>(this: &'a mut PinBox<T>) -> &'a mut T {
         &mut *this.inner
     }
@@ -787,6 +848,7 @@ pub unsafe fn get_mut<'a>(this: &'a mut PinBox<T>) -> &'a mut T {
     ///
     /// This function is unsafe. Users must guarantee that the data is never
     /// moved out of the box.
+    #[inline]
     pub unsafe fn unpin(this: PinBox<T>) -> Box<T> {
         this.inner
     }
@@ -851,3 +913,34 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<PinBox<U>> for PinBox<T> {}
 
 #[unstable(feature = "pin", issue = "49150")]
 impl<T: ?Sized> Unpin for PinBox<T> {}
+
+#[unstable(feature = "futures_api", issue = "50547")]
+unsafe impl<F: Future<Output = ()> + Send + 'static> UnsafePoll for PinBox<F> {
+    fn into_raw(self) -> *mut () {
+        PinBox::into_raw(self) as *mut ()
+    }
+
+    unsafe fn poll(task: *mut (), cx: &mut Context) -> Poll<()> {
+        let ptr = task as *mut F;
+        let pin: PinMut<F> = PinMut::new_unchecked(&mut *ptr);
+        pin.poll(cx)
+    }
+
+    unsafe fn drop(task: *mut ()) {
+        drop(PinBox::from_raw(task as *mut F))
+    }
+}
+
+#[unstable(feature = "futures_api", issue = "50547")]
+impl<F: Future<Output = ()> + Send + 'static> From<PinBox<F>> for TaskObj {
+    fn from(boxed: PinBox<F>) -> Self {
+        TaskObj::from_poll_task(boxed)
+    }
+}
+
+#[unstable(feature = "futures_api", issue = "50547")]
+impl<F: Future<Output = ()> + Send + 'static> From<Box<F>> for TaskObj {
+    fn from(boxed: Box<F>) -> Self {
+        TaskObj::from_poll_task(PinBox::from(boxed))
+    }
+}
index a4e5373d90757b9f3f4ad48da50147835a0717cb..b49ec0ae25212d05787ad7df0f845cebd52e8405 100644 (file)
 pub use core::fmt::{write, ArgumentV1, Arguments};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::fmt::{DebugList, DebugMap, DebugSet, DebugStruct, DebugTuple};
+#[stable(feature = "fmt_flags_align", since = "1.28.0")]
+pub use core::fmt::{Alignment};
 
 use string;
 
index a56420d52d0d5528afb8f6ed09fd761f66bdce8a..242c7d2e70f85ea74487fd47822470015b692454 100644 (file)
@@ -95,6 +95,7 @@
 #![feature(fmt_internals)]
 #![feature(from_ref)]
 #![feature(fundamental)]
+#![feature(futures_api)]
 #![feature(lang_items)]
 #![feature(libc)]
 #![feature(needs_allocator)]
 #![feature(pin)]
 #![feature(ptr_internals)]
 #![feature(ptr_offset_from)]
+#![feature(repr_transparent)]
 #![feature(rustc_attrs)]
 #![feature(specialization)]
 #![feature(staged_api)]
@@ -155,6 +157,10 @@ pub mod heap {
     pub use alloc::*;
 }
 
+#[unstable(feature = "futures_api",
+           reason = "futures in libcore are unstable",
+           issue = "50547")]
+pub mod task;
 
 // Primitive types using the heaps above
 
diff --git a/src/liballoc/task.rs b/src/liballoc/task.rs
new file mode 100644 (file)
index 0000000..7b1947b
--- /dev/null
@@ -0,0 +1,140 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Types and Traits for working with asynchronous tasks.
+
+pub use core::task::*;
+
+#[cfg(target_has_atomic = "ptr")]
+pub use self::if_arc::*;
+
+#[cfg(target_has_atomic = "ptr")]
+mod if_arc {
+    use super::*;
+    use arc::Arc;
+    use core::marker::PhantomData;
+    use core::mem;
+    use core::ptr::{self, NonNull};
+
+    /// A way of waking up a specific task.
+    ///
+    /// Any task executor must provide a way of signaling that a task it owns
+    /// is ready to be `poll`ed again. Executors do so by implementing this trait.
+    pub trait Wake: Send + Sync {
+        /// Indicates that the associated task is ready to make progress and should
+        /// be `poll`ed.
+        ///
+        /// Executors generally maintain a queue of "ready" tasks; `wake` should place
+        /// the associated task onto this queue.
+        fn wake(arc_self: &Arc<Self>);
+
+        /// Indicates that the associated task is ready to make progress and should
+        /// be `poll`ed. This function is like `wake`, but can only be called from the
+        /// thread on which this `Wake` was created.
+        ///
+        /// Executors generally maintain a queue of "ready" tasks; `wake_local` should place
+        /// the associated task onto this queue.
+        #[inline]
+        unsafe fn wake_local(arc_self: &Arc<Self>) {
+            Self::wake(arc_self);
+        }
+    }
+
+    #[cfg(target_has_atomic = "ptr")]
+    struct ArcWrapped<T>(PhantomData<T>);
+
+    unsafe impl<T: Wake + 'static> UnsafeWake for ArcWrapped<T> {
+        #[inline]
+        unsafe fn clone_raw(&self) -> Waker {
+            let me: *const ArcWrapped<T> = self;
+            let arc = (*(&me as *const *const ArcWrapped<T> as *const Arc<T>)).clone();
+            Waker::from(arc)
+        }
+
+        #[inline]
+        unsafe fn drop_raw(&self) {
+            let mut me: *const ArcWrapped<T> = self;
+            let me = &mut me as *mut *const ArcWrapped<T> as *mut Arc<T>;
+            ptr::drop_in_place(me);
+        }
+
+        #[inline]
+        unsafe fn wake(&self) {
+            let me: *const ArcWrapped<T> = self;
+            T::wake(&*(&me as *const *const ArcWrapped<T> as *const Arc<T>))
+        }
+
+        #[inline]
+        unsafe fn wake_local(&self) {
+            let me: *const ArcWrapped<T> = self;
+            T::wake_local(&*(&me as *const *const ArcWrapped<T> as *const Arc<T>))
+        }
+    }
+
+    impl<T> From<Arc<T>> for Waker
+        where T: Wake + 'static,
+    {
+        fn from(rc: Arc<T>) -> Self {
+            unsafe {
+                let ptr = mem::transmute::<Arc<T>, NonNull<ArcWrapped<T>>>(rc);
+                Waker::new(ptr)
+            }
+        }
+    }
+
+    /// Creates a `LocalWaker` from a local `wake`.
+    ///
+    /// This function requires that `wake` is "local" (created on the current thread).
+    /// The resulting `LocalWaker` will call `wake.wake_local()` when awoken, and
+    /// will call `wake.wake()` if awoken after being converted to a `Waker`.
+    #[inline]
+    pub unsafe fn local_waker<W: Wake + 'static>(wake: Arc<W>) -> LocalWaker {
+        let ptr = mem::transmute::<Arc<W>, NonNull<ArcWrapped<W>>>(wake);
+        LocalWaker::new(ptr)
+    }
+
+    struct NonLocalAsLocal<T>(ArcWrapped<T>);
+
+    unsafe impl<T: Wake + 'static> UnsafeWake for NonLocalAsLocal<T> {
+        #[inline]
+        unsafe fn clone_raw(&self) -> Waker {
+            self.0.clone_raw()
+        }
+
+        #[inline]
+        unsafe fn drop_raw(&self) {
+            self.0.drop_raw()
+        }
+
+        #[inline]
+        unsafe fn wake(&self) {
+            self.0.wake()
+        }
+
+        #[inline]
+        unsafe fn wake_local(&self) {
+            // Since we're nonlocal, we can't call wake_local
+            self.0.wake()
+        }
+    }
+
+    /// Creates a `LocalWaker` from a non-local `wake`.
+    ///
+    /// This function is similar to `local_waker`, but does not require that `wake`
+    /// is local to the current thread. The resulting `LocalWaker` will call
+    /// `wake.wake()` when awoken.
+    #[inline]
+    pub fn local_waker_from_nonlocal<W: Wake + 'static>(wake: Arc<W>) -> LocalWaker {
+        unsafe {
+            let ptr = mem::transmute::<Arc<W>, NonNull<NonLocalAsLocal<W>>>(wake);
+            LocalWaker::new(ptr)
+        }
+    }
+}
index 0515eeed30b626532a107f9d2caecc7cf1aa4c85..d91bf4633833716da7c7d89c653e52bc67f26698 100644 (file)
@@ -1436,8 +1436,7 @@ pub fn fill(&self) -> char { self.fill }
     /// ```
     /// extern crate core;
     ///
-    /// use std::fmt;
-    /// use core::fmt::Alignment;
+    /// use std::fmt::{self, Alignment};
     ///
     /// struct Foo;
     ///
diff --git a/src/libcore/future.rs b/src/libcore/future.rs
new file mode 100644 (file)
index 0000000..b4d087f
--- /dev/null
@@ -0,0 +1,93 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![unstable(feature = "futures_api",
+            reason = "futures in libcore are unstable",
+            issue = "50547")]
+
+//! Asynchronous values.
+
+use mem::PinMut;
+use task::{self, Poll};
+
+/// A future represents an asychronous computation.
+///
+/// A future is a value that may not have finished computing yet. This kind of
+/// "asynchronous value" makes it possible for a thread to continue doing useful
+/// work while it waits for the value to become available.
+///
+/// # The `poll` method
+///
+/// The core method of future, `poll`, *attempts* to resolve the future into a
+/// final value. This method does not block if the value is not ready. Instead,
+/// the current task is scheduled to be woken up when it's possible to make
+/// further progress by `poll`ing again. The wake up is performed using
+/// `cx.waker()`, a handle for waking up the current task.
+///
+/// When using a future, you generally won't call `poll` directly, but instead
+/// `await!` the value.
+pub trait Future {
+    /// The result of the `Future`.
+    type Output;
+
+    /// Attempt to resolve the future to a final value, registering
+    /// the current task for wakeup if the value is not yet available.
+    ///
+    /// # Return value
+    ///
+    /// This function returns:
+    ///
+    /// - `Poll::Pending` if the future is not ready yet
+    /// - `Poll::Ready(val)` with the result `val` of this future if it finished
+    /// successfully.
+    ///
+    /// Once a future has finished, clients should not `poll` it again.
+    ///
+    /// When a future is not ready yet, `poll` returns
+    /// [`Poll::Pending`](::task::Poll). The future will *also* register the
+    /// interest of the current task in the value being produced. For example,
+    /// if the future represents the availability of data on a socket, then the
+    /// task is recorded so that when data arrives, it is woken up (via
+    /// [`cx.waker()`](::task::Context::waker)). Once a task has been woken up,
+    /// it should attempt to `poll` the future again, which may or may not
+    /// produce a final value.
+    ///
+    /// Note that if `Pending` is returned it only means that the *current* task
+    /// (represented by the argument `cx`) will receive a notification. Tasks
+    /// from previous calls to `poll` will *not* receive notifications.
+    ///
+    /// # Runtime characteristics
+    ///
+    /// Futures alone are *inert*; they must be *actively* `poll`ed to make
+    /// progress, meaning that each time the current task is woken up, it should
+    /// actively re-`poll` pending futures that it still has an interest in.
+    ///
+    /// The `poll` function is not called repeatedly in a tight loop for
+    /// futures, but only whenever the future itself is ready, as signaled via
+    /// the `Waker` inside `task::Context`. If you're familiar with the
+    /// `poll(2)` or `select(2)` syscalls on Unix it's worth noting that futures
+    /// typically do *not* suffer the same problems of "all wakeups must poll
+    /// all events"; they are more like `epoll(4)`.
+    ///
+    /// An implementation of `poll` should strive to return quickly, and must
+    /// *never* block. Returning quickly prevents unnecessarily clogging up
+    /// threads or event loops. If it is known ahead of time that a call to
+    /// `poll` may end up taking awhile, the work should be offloaded to a
+    /// thread pool (or something similar) to ensure that `poll` can return
+    /// quickly.
+    ///
+    /// # Panics
+    ///
+    /// Once a future has completed (returned `Ready` from `poll`),
+    /// then any future calls to `poll` may panic, block forever, or otherwise
+    /// cause bad behavior. The `Future` trait itself provides no guarantees
+    /// about the behavior of `poll` after a future has completed.
+    fn poll(self: PinMut<Self>, cx: &mut task::Context) -> Poll<Self::Output>;
+}
index b27552651a08743cc7e8d12aea8c530d038bec4c..912cf2bc1e970e0b8d2da6a7965d3997b48833e9 100644 (file)
 #![feature(optin_builtin_traits)]
 #![feature(prelude_import)]
 #![feature(repr_simd, platform_intrinsics)]
+#![feature(repr_transparent)]
 #![feature(rustc_attrs)]
 #![feature(rustc_const_unstable)]
 #![feature(simd_ffi)]
 
 pub mod unicode;
 
+/* Async */
+pub mod future;
+pub mod task;
+
 /* Heap memory allocator trait */
 #[allow(missing_docs)]
 pub mod alloc;
diff --git a/src/libcore/task.rs b/src/libcore/task.rs
new file mode 100644 (file)
index 0000000..e46a6d4
--- /dev/null
@@ -0,0 +1,513 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![unstable(feature = "futures_api",
+            reason = "futures in libcore are unstable",
+            issue = "50547")]
+
+//! Types and Traits for working with asynchronous tasks.
+
+use fmt;
+use ptr::NonNull;
+
+/// Indicates whether a value is available or if the current task has been
+/// scheduled to receive a wakeup instead.
+#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
+pub enum Poll<T> {
+    /// Represents that a value is immediately ready.
+    Ready(T),
+
+    /// Represents that a value is not ready yet.
+    ///
+    /// When a function returns `Pending`, the function *must* also
+    /// ensure that the current task is scheduled to be awoken when
+    /// progress can be made.
+    Pending,
+}
+
+/// A `Waker` is a handle for waking up a task by notifying its executor that it
+/// is ready to be run.
+///
+/// This handle contains a trait object pointing to an instance of the `UnsafeWake`
+/// trait, allowing notifications to get routed through it.
+#[repr(transparent)]
+pub struct Waker {
+    inner: NonNull<UnsafeWake>,
+}
+
+unsafe impl Send for Waker {}
+unsafe impl Sync for Waker {}
+
+impl Waker {
+    /// Constructs a new `Waker` directly.
+    ///
+    /// Note that most code will not need to call this. Implementers of the
+    /// `UnsafeWake` trait will typically provide a wrapper that calls this
+    /// but you otherwise shouldn't call it directly.
+    ///
+    /// If you're working with the standard library then it's recommended to
+    /// use the `Waker::from` function instead which works with the safe
+    /// `Arc` type and the safe `Wake` trait.
+    #[inline]
+    pub unsafe fn new(inner: NonNull<UnsafeWake>) -> Self {
+        Waker { inner: inner }
+    }
+
+    /// Wake up the task associated with this `Waker`.
+    #[inline]
+    pub fn wake(&self) {
+        unsafe { self.inner.as_ref().wake() }
+    }
+
+    /// Returns whether or not this `Waker` and `other` awaken the same task.
+    ///
+    /// This function works on a best-effort basis, and may return false even
+    /// when the `Waker`s would awaken the same task. However, if this function
+    /// returns true, it is guaranteed that the `Waker`s will awaken the same
+    /// task.
+    ///
+    /// This function is primarily used for optimization purposes.
+    #[inline]
+    pub fn will_wake(&self, other: &Waker) -> bool {
+        self.inner == other.inner
+    }
+}
+
+impl Clone for Waker {
+    #[inline]
+    fn clone(&self) -> Self {
+        unsafe {
+            self.inner.as_ref().clone_raw()
+        }
+    }
+}
+
+impl fmt::Debug for Waker {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("Waker")
+            .finish()
+    }
+}
+
+impl Drop for Waker {
+    #[inline]
+    fn drop(&mut self) {
+        unsafe {
+            self.inner.as_ref().drop_raw()
+        }
+    }
+}
+
+/// A `LocalWaker` is a handle for waking up a task by notifying its executor that it
+/// is ready to be run.
+///
+/// This is similar to the `Waker` type, but cannot be sent across threads.
+/// Task executors can use this type to implement more optimized singlethreaded wakeup
+/// behavior.
+#[repr(transparent)]
+pub struct LocalWaker {
+    inner: NonNull<UnsafeWake>,
+}
+
+impl !Send for LocalWaker {}
+impl !Sync for LocalWaker {}
+
+impl LocalWaker {
+    /// Constructs a new `LocalWaker` directly.
+    ///
+    /// Note that most code will not need to call this. Implementers of the
+    /// `UnsafeWake` trait will typically provide a wrapper that calls this
+    /// but you otherwise shouldn't call it directly.
+    ///
+    /// If you're working with the standard library then it's recommended to
+    /// use the `LocalWaker::from` function instead which works with the safe
+    /// `Rc` type and the safe `LocalWake` trait.
+    ///
+    /// For this function to be used safely, it must be sound to call `inner.wake_local()`
+    /// on the current thread.
+    #[inline]
+    pub unsafe fn new(inner: NonNull<UnsafeWake>) -> Self {
+        LocalWaker { inner: inner }
+    }
+
+    /// Wake up the task associated with this `LocalWaker`.
+    #[inline]
+    pub fn wake(&self) {
+        unsafe { self.inner.as_ref().wake_local() }
+    }
+
+    /// Returns whether or not this `LocalWaker` and `other` `LocalWaker` awaken the same task.
+    ///
+    /// This function works on a best-effort basis, and may return false even
+    /// when the `LocalWaker`s would awaken the same task. However, if this function
+    /// returns true, it is guaranteed that the `LocalWaker`s will awaken the same
+    /// task.
+    ///
+    /// This function is primarily used for optimization purposes.
+    #[inline]
+    pub fn will_wake(&self, other: &LocalWaker) -> bool {
+        self.inner == other.inner
+    }
+
+    /// Returns whether or not this `LocalWaker` and `other` `Waker` awaken the same task.
+    ///
+    /// This function works on a best-effort basis, and may return false even
+    /// when the `Waker`s would awaken the same task. However, if this function
+    /// returns true, it is guaranteed that the `LocalWaker`s will awaken the same
+    /// task.
+    ///
+    /// This function is primarily used for optimization purposes.
+    #[inline]
+    pub fn will_wake_nonlocal(&self, other: &Waker) -> bool {
+        self.inner == other.inner
+    }
+}
+
+impl From<LocalWaker> for Waker {
+    #[inline]
+    fn from(local_waker: LocalWaker) -> Self {
+        Waker { inner: local_waker.inner }
+    }
+}
+
+impl Clone for LocalWaker {
+    #[inline]
+    fn clone(&self) -> Self {
+        unsafe {
+            LocalWaker { inner: self.inner.as_ref().clone_raw().inner }
+        }
+    }
+}
+
+impl fmt::Debug for LocalWaker {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("Waker")
+            .finish()
+    }
+}
+
+impl Drop for LocalWaker {
+    #[inline]
+    fn drop(&mut self) {
+        unsafe {
+            self.inner.as_ref().drop_raw()
+        }
+    }
+}
+
+/// An unsafe trait for implementing custom memory management for a `Waker` or `LocalWaker`.
+///
+/// A `Waker` conceptually is a cloneable trait object for `Wake`, and is
+/// most often essentially just `Arc<dyn Wake>`. However, in some contexts
+/// (particularly `no_std`), it's desirable to avoid `Arc` in favor of some
+/// custom memory management strategy. This trait is designed to allow for such
+/// customization.
+///
+/// When using `std`, a default implementation of the `UnsafeWake` trait is provided for
+/// `Arc<T>` where `T: Wake` and `Rc<T>` where `T: LocalWake`.
+///
+/// Although the methods on `UnsafeWake` take pointers rather than references,
+pub unsafe trait UnsafeWake: Send + Sync {
+    /// Creates a clone of this `UnsafeWake` and stores it behind a `Waker`.
+    ///
+    /// This function will create a new uniquely owned handle that under the
+    /// hood references the same notification instance. In other words calls
+    /// to `wake` on the returned handle should be equivalent to calls to
+    /// `wake` on this handle.
+    ///
+    /// # Unsafety
+    ///
+    /// This function is unsafe to call because it's asserting the `UnsafeWake`
+    /// value is in a consistent state, i.e. hasn't been dropped.
+    unsafe fn clone_raw(&self) -> Waker;
+
+    /// Drops this instance of `UnsafeWake`, deallocating resources
+    /// associated with it.
+    ///
+    /// FIXME(cramertj)
+    /// This method is intended to have a signature such as:
+    ///
+    /// ```ignore (not-a-doctest)
+    /// fn drop_raw(self: *mut Self);
+    /// ```
+    ///
+    /// Unfortunately in Rust today that signature is not object safe.
+    /// Nevertheless it's recommended to implement this function *as if* that
+    /// were its signature. As such it is not safe to call on an invalid
+    /// pointer, nor is the validity of the pointer guaranteed after this
+    /// function returns.
+    ///
+    /// # Unsafety
+    ///
+    /// This function is unsafe to call because it's asserting the `UnsafeWake`
+    /// value is in a consistent state, i.e. hasn't been dropped.
+    unsafe fn drop_raw(&self);
+
+    /// Indicates that the associated task is ready to make progress and should
+    /// be `poll`ed.
+    ///
+    /// Executors generally maintain a queue of "ready" tasks; `wake` should place
+    /// the associated task onto this queue.
+    ///
+    /// # Panics
+    ///
+    /// Implementations should avoid panicking, but clients should also be prepared
+    /// for panics.
+    ///
+    /// # Unsafety
+    ///
+    /// This function is unsafe to call because it's asserting the `UnsafeWake`
+    /// value is in a consistent state, i.e. hasn't been dropped.
+    unsafe fn wake(&self);
+
+    /// Indicates that the associated task is ready to make progress and should
+    /// be `poll`ed. This function is the same as `wake`, but can only be called
+    /// from the thread that this `UnsafeWake` is "local" to. This allows for
+    /// implementors to provide specialized wakeup behavior specific to the current
+    /// thread. This function is called by `LocalWaker::wake`.
+    ///
+    /// Executors generally maintain a queue of "ready" tasks; `wake_local` should place
+    /// the associated task onto this queue.
+    ///
+    /// # Panics
+    ///
+    /// Implementations should avoid panicking, but clients should also be prepared
+    /// for panics.
+    ///
+    /// # Unsafety
+    ///
+    /// This function is unsafe to call because it's asserting the `UnsafeWake`
+    /// value is in a consistent state, i.e. hasn't been dropped, and that the
+    /// `UnsafeWake` hasn't moved from the thread on which it was created.
+    unsafe fn wake_local(&self) {
+        self.wake()
+    }
+}
+
+/// Information about the currently-running task.
+///
+/// Contexts are always tied to the stack, since they are set up specifically
+/// when performing a single `poll` step on a task.
+pub struct Context<'a> {
+    local_waker: &'a LocalWaker,
+    executor: &'a mut Executor,
+}
+
+impl<'a> fmt::Debug for Context<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("Context")
+            .finish()
+    }
+}
+
+impl<'a> Context<'a> {
+    /// Create a new task `Context` with the provided `local_waker`, `waker`, and `executor`.
+    #[inline]
+    pub fn new(local_waker: &'a LocalWaker, executor: &'a mut Executor) -> Context<'a> {
+        Context {
+            local_waker,
+            executor,
+        }
+    }
+
+    /// Get the `LocalWaker` associated with the current task.
+    #[inline]
+    pub fn local_waker(&self) -> &'a LocalWaker {
+        self.local_waker
+    }
+
+    /// Get the `Waker` associated with the current task.
+    #[inline]
+    pub fn waker(&self) -> &'a Waker {
+        unsafe { &*(self.local_waker as *const LocalWaker as *const Waker) }
+    }
+
+    /// Get the default executor associated with this task.
+    ///
+    /// This method is useful primarily if you want to explicitly handle
+    /// spawn failures.
+    #[inline]
+    pub fn executor(&mut self) -> &mut Executor {
+        self.executor
+    }
+
+    /// Produce a context like the current one, but using the given waker instead.
+    ///
+    /// This advanced method is primarily used when building "internal
+    /// schedulers" within a task, where you want to provide some customized
+    /// wakeup logic.
+    #[inline]
+    pub fn with_waker<'b>(&'b mut self, local_waker: &'b LocalWaker) -> Context<'b> {
+        Context {
+            local_waker,
+            executor: self.executor,
+        }
+    }
+
+    /// Produce a context like the current one, but using the given executor
+    /// instead.
+    ///
+    /// This advanced method is primarily used when building "internal
+    /// schedulers" within a task.
+    #[inline]
+    pub fn with_executor<'b, E>(&'b mut self, executor: &'b mut E) -> Context<'b>
+        where E: Executor
+    {
+        Context {
+            local_waker: self.local_waker,
+            executor: executor,
+        }
+    }
+}
+
+/// A task executor.
+///
+/// A *task* is a `()`-producing async value that runs at the top level, and will
+/// be `poll`ed until completion. It's also the unit at which wake-up
+/// notifications occur. Executors, such as thread pools, allow tasks to be
+/// spawned and are responsible for putting tasks onto ready queues when
+/// they are woken up, and polling them when they are ready.
+pub trait Executor {
+    /// Spawn the given task, polling it until completion.
+    ///
+    /// # Errors
+    ///
+    /// The executor may be unable to spawn tasks, either because it has
+    /// been shut down or is resource-constrained.
+    fn spawn_obj(&mut self, task: TaskObj) -> Result<(), SpawnObjError>;
+
+    /// Determine whether the executor is able to spawn new tasks.
+    ///
+    /// # Returns
+    ///
+    /// An `Ok` return means the executor is *likely* (but not guaranteed)
+    /// to accept a subsequent spawn attempt. Likewise, an `Err` return
+    /// means that `spawn` is likely, but not guaranteed, to yield an error.
+    #[inline]
+    fn status(&self) -> Result<(), SpawnErrorKind> {
+        Ok(())
+    }
+}
+
+/// A custom trait object for polling tasks, roughly akin to
+/// `Box<Future<Output = ()> + Send>`.
+pub struct TaskObj {
+    ptr: *mut (),
+    poll: unsafe fn(*mut (), &mut Context) -> Poll<()>,
+    drop: unsafe fn(*mut ()),
+}
+
+impl fmt::Debug for TaskObj {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("TaskObj")
+            .finish()
+    }
+}
+
+unsafe impl Send for TaskObj {}
+unsafe impl Sync for TaskObj {}
+
+/// A custom implementation of a task trait object for `TaskObj`, providing
+/// a hand-rolled vtable.
+///
+/// This custom representation is typically used only in `no_std` contexts,
+/// where the default `Box`-based implementation is not available.
+///
+/// The implementor must guarantee that it is safe to call `poll` repeatedly (in
+/// a non-concurrent fashion) with the result of `into_raw` until `drop` is
+/// called.
+pub unsafe trait UnsafePoll: Send + 'static {
+    /// Convert a owned instance into a (conceptually owned) void pointer.
+    fn into_raw(self) -> *mut ();
+
+    /// Poll the task represented by the given void pointer.
+    ///
+    /// # Safety
+    ///
+    /// The trait implementor must guarantee that it is safe to repeatedly call
+    /// `poll` with the result of `into_raw` until `drop` is called; such calls
+    /// are not, however, allowed to race with each other or with calls to `drop`.
+    unsafe fn poll(task: *mut (), cx: &mut Context) -> Poll<()>;
+
+    /// Drops the task represented by the given void pointer.
+    ///
+    /// # Safety
+    ///
+    /// The trait implementor must guarantee that it is safe to call this
+    /// function once per `into_raw` invocation; that call cannot race with
+    /// other calls to `drop` or `poll`.
+    unsafe fn drop(task: *mut ());
+}
+
+impl TaskObj {
+    /// Create a `TaskObj` from a custom trait object representation.
+    #[inline]
+    pub fn from_poll_task<T: UnsafePoll>(t: T) -> TaskObj {
+        TaskObj {
+            ptr: t.into_raw(),
+            poll: T::poll,
+            drop: T::drop,
+        }
+    }
+
+    /// Poll the task.
+    ///
+    /// The semantics here are identical to that for futures, but unlike
+    /// futures only an `&mut self` reference is needed here.
+    #[inline]
+    pub fn poll_task(&mut self, cx: &mut Context) -> Poll<()> {
+        unsafe {
+            (self.poll)(self.ptr, cx)
+        }
+    }
+}
+
+impl Drop for TaskObj {
+    fn drop(&mut self) {
+        unsafe {
+            (self.drop)(self.ptr)
+        }
+    }
+}
+
+/// Provides the reason that an executor was unable to spawn.
+pub struct SpawnErrorKind {
+    _hidden: (),
+}
+
+impl fmt::Debug for SpawnErrorKind {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_tuple("SpawnErrorKind")
+            .field(&"shutdown")
+            .finish()
+    }
+}
+
+impl SpawnErrorKind {
+    /// Spawning is failing because the executor has been shut down.
+    pub fn shutdown() -> SpawnErrorKind {
+        SpawnErrorKind { _hidden: () }
+    }
+
+    /// Check whether this error is the `shutdown` error.
+    pub fn is_shutdown(&self) -> bool {
+        true
+    }
+}
+
+/// The result of a failed spawn
+#[derive(Debug)]
+pub struct SpawnObjError {
+    /// The kind of error
+    pub kind: SpawnErrorKind,
+
+    /// The task for which spawning was attempted
+    pub task: TaskObj,
+}
index df68bf1fd9aabe98c09b7977de39183ee745b971..0ff4dc2eace816f45e55c43f1a380339108ba511 100644 (file)
@@ -15,9 +15,12 @@ fmt_macros = { path = "../libfmt_macros" }
 graphviz = { path = "../libgraphviz" }
 jobserver = "0.1"
 lazy_static = "1.0.0"
+scoped-tls = { version = "0.1.1", features = ["nightly"] }
 log = { version = "0.4", features = ["release_max_level_info", "std"] }
-polonius-engine = "0.4.0"
+polonius-engine = "0.5.0"
 proc_macro = { path = "../libproc_macro" }
+rustc-rayon = "0.1.1"
+rustc-rayon-core = "0.1.1"
 rustc_apfloat = { path = "../librustc_apfloat" }
 rustc_target = { path = "../librustc_target" }
 rustc_data_structures = { path = "../librustc_data_structures" }
@@ -26,6 +29,7 @@ serialize = { path = "../libserialize" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
 backtrace = "0.3.3"
+parking_lot = "0.5.5"
 byteorder = { version = "1.1", features = ["i128"]}
 chalk-engine = { version = "0.6.0", default-features=false }
 
index 04e57883c77530b0055abbac1eb97f725150293f..5e67065d1c13fcbf1656b29f3c2c54c596f55ac8 100644 (file)
@@ -510,6 +510,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 
 impl_stable_hash_for!(struct ::middle::const_val::FrameInfo {
     span,
+    lint_root,
     location
 });
 
@@ -523,21 +524,11 @@ fn hash_stable<W: StableHasherResult>(&self,
         mem::discriminant(self).hash_stable(hcx, hasher);
 
         match *self {
-            NonConstPath |
             TypeckError |
+            CouldNotResolve |
             CheckMatchError => {
                 // nothing to do
             }
-            UnimplementedConstVal(s) => {
-                s.hash_stable(hcx, hasher);
-            }
-            IndexOutOfBounds { len, index } => {
-                len.hash_stable(hcx, hasher);
-                index.hash_stable(hcx, hasher);
-            }
-            LayoutError(ref layout_error) => {
-                layout_error.hash_stable(hcx, hasher);
-            }
             Miri(ref err, ref trace) => {
                 err.hash_stable(hcx, hasher);
                 trace.hash_stable(hcx, hasher);
@@ -608,8 +599,8 @@ fn hash_stable<W: StableHasherResult>(&self,
             RemainderByZero |
             DivisionByZero |
             GeneratorResumedAfterReturn |
-            GeneratorResumedAfterPanic |
-            ReferencedConstant => {}
+            GeneratorResumedAfterPanic => {}
+            ReferencedConstant(ref err) => err.hash_stable(hcx, hasher),
             MachineError(ref err) => err.hash_stable(hcx, hasher),
             FunctionPointerTyMismatch(a, b) => {
                 a.hash_stable(hcx, hasher);
index 10e8905054d11399c8e6246c2ecebf14e6edab8e..a006856f58b7dac16624f573b1b253a06b9380cf 100644 (file)
@@ -67,6 +67,7 @@
 #![feature(unboxed_closures)]
 #![feature(trace_macros)]
 #![feature(trusted_len)]
+#![feature(vec_remove_item)]
 #![feature(catch_expr)]
 #![feature(integer_atomics)]
 #![feature(test)]
 extern crate getopts;
 extern crate graphviz;
 #[macro_use] extern crate lazy_static;
+#[macro_use] extern crate scoped_tls;
 #[cfg(windows)]
 extern crate libc;
 extern crate polonius_engine;
 extern crate rustc_target;
 #[macro_use] extern crate rustc_data_structures;
 extern crate serialize;
+extern crate parking_lot;
 extern crate rustc_errors as errors;
+extern crate rustc_rayon as rayon;
+extern crate rustc_rayon_core as rayon_core;
 #[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
 extern crate syntax_pos;
index de583e81ca83185b730a07769ac94294d6e0294e..d0cf30b6e069da927cfcf247cbdbabfe5341d003 100644 (file)
@@ -17,6 +17,7 @@
 use errors::{Applicability, DiagnosticBuilder};
 use lint::{LintPass, LateLintPass, LintArray};
 use session::Session;
+use syntax::ast;
 use syntax::codemap::Span;
 
 declare_lint! {
     "warns about duplicate associated type bindings in generics"
 }
 
+declare_lint! {
+    pub DUPLICATE_MACRO_EXPORTS,
+    Deny,
+    "detects duplicate macro exports"
+}
+
 /// Does nothing as a lint pass, but registers some `Lint`s
 /// which are used by other parts of the compiler.
 #[derive(Copy, Clone)]
@@ -337,6 +344,7 @@ fn get_lints(&self) -> LintArray {
             ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
             UNSTABLE_NAME_COLLISIONS,
             DUPLICATE_ASSOCIATED_TYPE_BINDINGS,
+            DUPLICATE_MACRO_EXPORTS,
         )
     }
 }
@@ -348,6 +356,7 @@ pub enum BuiltinLintDiagnostics {
     Normal,
     BareTraitObject(Span, /* is_global */ bool),
     AbsPathWithModule(Span),
+    DuplicatedMacroExports(ast::Ident, Span, Span),
 }
 
 impl BuiltinLintDiagnostics {
@@ -380,6 +389,10 @@ pub fn run(self, sess: &Session, db: &mut DiagnosticBuilder) {
                 };
                 db.span_suggestion_with_applicability(span, "use `crate`", sugg, app);
             }
+            BuiltinLintDiagnostics::DuplicatedMacroExports(ident, earlier_span, later_span) => {
+                db.span_label(later_span, format!("`{}` already exported", ident));
+                db.span_note(earlier_span, "previous macro export is now shadowed");
+            }
         }
     }
 }
index 381bb161e4205c5c77a9e8f82e54529f954da3ca..824930a7eb00007766e052d0992bbaf0ff494032 100644 (file)
@@ -655,6 +655,9 @@ fn with_param_env<F>(&mut self, id: ast::NodeId, f: F)
         f(self);
         self.param_env = old_param_env;
     }
+    pub fn current_lint_root(&self) -> ast::NodeId {
+        self.last_ast_node_with_lint_attrs
+    }
 }
 
 impl<'a, 'tcx> LayoutOf for &'a LateContext<'a, 'tcx> {
index d7f116705113e02e28730c06110fde0dc0252bb4..88275b3c18cc1172f83fd736a02c362d129e52f3 100644 (file)
@@ -9,13 +9,15 @@
 // except according to those terms.
 
 use hir::def_id::DefId;
-use ty::{self, TyCtxt, layout};
+use ty;
 use ty::subst::Substs;
+use ty::maps::TyCtxtAt;
 use mir::interpret::ConstValue;
 use errors::DiagnosticBuilder;
 
 use graphviz::IntoCow;
 use syntax_pos::Span;
+use syntax::ast;
 
 use std::borrow::Cow;
 use rustc_data_structures::sync::Lrc;
@@ -28,30 +30,26 @@ pub enum ConstVal<'tcx> {
     Value(ConstValue<'tcx>),
 }
 
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
 pub struct ConstEvalErr<'tcx> {
     pub span: Span,
     pub kind: Lrc<ErrKind<'tcx>>,
 }
 
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
 pub enum ErrKind<'tcx> {
 
-    NonConstPath,
-    UnimplementedConstVal(&'static str),
-    IndexOutOfBounds { len: u64, index: u64 },
-
-    LayoutError(layout::LayoutError<'tcx>),
-
+    CouldNotResolve,
     TypeckError,
     CheckMatchError,
     Miri(::mir::interpret::EvalError<'tcx>, Vec<FrameInfo>),
 }
 
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
 pub struct FrameInfo {
     pub span: Span,
     pub location: String,
+    pub lint_root: Option<ast::NodeId>,
 }
 
 #[derive(Clone, Debug)]
@@ -83,16 +81,7 @@ macro_rules! simple {
         }
 
         match *self.kind {
-            NonConstPath        => simple!("non-constant path in constant expression"),
-            UnimplementedConstVal(what) =>
-                simple!("unimplemented constant expression: {}", what),
-            IndexOutOfBounds { len, index } => {
-                simple!("index out of bounds: the len is {} but the index is {}",
-                        len, index)
-            }
-
-            LayoutError(ref err) => Simple(err.to_string().into_cow()),
-
+            CouldNotResolve => simple!("could not resolve"),
             TypeckError => simple!("type-checking failed"),
             CheckMatchError => simple!("match-checking failed"),
             Miri(ref err, ref trace) => Backtrace(err, trace),
@@ -100,64 +89,90 @@ macro_rules! simple {
     }
 
     pub fn struct_error(&self,
-        tcx: TyCtxt<'a, 'gcx, 'tcx>,
-        primary_span: Span,
-        primary_kind: &str)
-        -> DiagnosticBuilder<'gcx>
+        tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
+        message: &str)
+        -> Option<DiagnosticBuilder<'tcx>>
     {
-        let mut diag = struct_error(tcx, self.span, "constant evaluation error");
-        self.note(tcx, primary_span, primary_kind, &mut diag);
-        diag
+        self.struct_generic(tcx, message, None, true)
     }
 
-    pub fn note(&self,
-        _tcx: TyCtxt<'a, 'gcx, 'tcx>,
-        primary_span: Span,
-        primary_kind: &str,
-        diag: &mut DiagnosticBuilder)
-    {
-        match self.description() {
-            ConstEvalErrDescription::Simple(message) => {
-                diag.span_label(self.span, message);
-            }
-            ConstEvalErrDescription::Backtrace(miri, frames) => {
-                diag.span_label(self.span, format!("{}", miri));
-                for frame in frames {
-                    diag.span_label(frame.span, format!("inside call to `{}`", frame.location));
-                }
-            }
+    pub fn report_as_error(&self,
+        tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
+        message: &str
+    ) {
+        let err = self.struct_generic(tcx, message, None, true);
+        if let Some(mut err) = err {
+            err.emit();
         }
+    }
 
-        if !primary_span.contains(self.span) {
-            diag.span_note(primary_span,
-                        &format!("for {} here", primary_kind));
+    pub fn report_as_lint(&self,
+        tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
+        message: &str,
+        lint_root: ast::NodeId,
+    ) {
+        let lint = self.struct_generic(
+            tcx,
+            message,
+            Some(lint_root),
+            false,
+        );
+        if let Some(mut lint) = lint {
+            lint.emit();
         }
     }
 
-    pub fn report(&self,
-        tcx: TyCtxt<'a, 'gcx, 'tcx>,
-        primary_span: Span,
-        primary_kind: &str)
-    {
-        match *self.kind {
-            ErrKind::TypeckError | ErrKind::CheckMatchError => return,
-            ErrKind::Miri(ref miri, _) => {
+    fn struct_generic(
+        &self,
+        tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
+        message: &str,
+        lint_root: Option<ast::NodeId>,
+        as_err: bool,
+    ) -> Option<DiagnosticBuilder<'tcx>> {
+        let (msg, frames): (_, &[_]) = match *self.kind {
+            ErrKind::TypeckError | ErrKind::CheckMatchError => return None,
+            ErrKind::Miri(ref miri, ref frames) => {
                 match miri.kind {
                     ::mir::interpret::EvalErrorKind::TypeckError |
-                    ::mir::interpret::EvalErrorKind::Layout(_) => return,
-                    _ => {},
+                    ::mir::interpret::EvalErrorKind::Layout(_) => return None,
+                    ::mir::interpret::EvalErrorKind::ReferencedConstant(ref inner) => {
+                        inner.struct_generic(tcx, "referenced constant", lint_root, as_err)?.emit();
+                        (miri.to_string(), frames)
+                    },
+                    _ => (miri.to_string(), frames),
                 }
             }
-            _ => {}
+            _ => (self.description().into_oneline().to_string(), &[]),
+        };
+        trace!("reporting const eval failure at {:?}", self.span);
+        let mut err = if as_err {
+            struct_error(tcx, message)
+        } else {
+            let node_id = frames
+                .iter()
+                .rev()
+                .filter_map(|frame| frame.lint_root)
+                .next()
+                .or(lint_root)
+                .expect("some part of a failing const eval must be local");
+            tcx.struct_span_lint_node(
+                ::rustc::lint::builtin::CONST_ERR,
+                node_id,
+                tcx.span,
+                message,
+            )
+        };
+        err.span_label(self.span, msg);
+        for FrameInfo { span, location, .. } in frames {
+            err.span_label(*span, format!("inside call to `{}`", location));
         }
-        self.struct_error(tcx, primary_span, primary_kind).emit();
+        Some(err)
     }
 }
 
 pub fn struct_error<'a, 'gcx, 'tcx>(
-    tcx: TyCtxt<'a, 'gcx, 'tcx>,
-    span: Span,
+    tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
     msg: &str,
-) -> DiagnosticBuilder<'gcx> {
-    struct_span_err!(tcx.sess, span, E0080, "{}", msg)
+) -> DiagnosticBuilder<'tcx> {
+    struct_span_err!(tcx.sess, tcx.span, E0080, "{}", msg)
 }
index 45819afca3f5c0dc9d840ec94caa04e8590a0550..bf5bae6b20c429ef15aaf6abf518c9f59fbea389 100644 (file)
@@ -1,6 +1,7 @@
 use std::{fmt, env};
 
 use mir;
+use middle::const_val::ConstEvalErr;
 use ty::{FnSig, Ty, layout};
 use ty::layout::{Size, Align};
 
 
 use backtrace::Backtrace;
 
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, RustcEncodable, RustcDecodable)]
 pub struct EvalError<'tcx> {
     pub kind: EvalErrorKind<'tcx, u64>,
-    pub backtrace: Option<Backtrace>,
 }
 
 impl<'tcx> From<EvalErrorKind<'tcx, u64>> for EvalError<'tcx> {
     fn from(kind: EvalErrorKind<'tcx, u64>) -> Self {
-        let backtrace = match env::var("MIRI_BACKTRACE") {
-            Ok(ref val) if !val.is_empty() => Some(Backtrace::new_unresolved()),
-            _ => None
-        };
+        match env::var("MIRI_BACKTRACE") {
+            Ok(ref val) if !val.is_empty() => {
+                let backtrace = Backtrace::new();
+
+                use std::fmt::Write;
+                let mut trace_text = "\n\nAn error occurred in miri:\n".to_string();
+                write!(trace_text, "backtrace frames: {}\n", backtrace.frames().len()).unwrap();
+                'frames: for (i, frame) in backtrace.frames().iter().enumerate() {
+                    if frame.symbols().is_empty() {
+                        write!(trace_text, "{}: no symbols\n", i).unwrap();
+                    }
+                    for symbol in frame.symbols() {
+                        write!(trace_text, "{}: ", i).unwrap();
+                        if let Some(name) = symbol.name() {
+                            write!(trace_text, "{}\n", name).unwrap();
+                        } else {
+                            write!(trace_text, "<unknown>\n").unwrap();
+                        }
+                        write!(trace_text, "\tat ").unwrap();
+                        if let Some(file_path) = symbol.filename() {
+                            write!(trace_text, "{}", file_path.display()).unwrap();
+                        } else {
+                            write!(trace_text, "<unknown_file>").unwrap();
+                        }
+                        if let Some(line) = symbol.lineno() {
+                            write!(trace_text, ":{}\n", line).unwrap();
+                        } else {
+                            write!(trace_text, "\n").unwrap();
+                        }
+                    }
+                }
+                error!("{}", trace_text);
+            },
+            _ => {},
+        }
         EvalError {
             kind,
-            backtrace,
         }
     }
 }
@@ -122,7 +152,7 @@ pub enum EvalErrorKind<'tcx, O> {
     TypeckError,
     /// Cannot compute this constant because it depends on another one
     /// which already produced an error
-    ReferencedConstant,
+    ReferencedConstant(ConstEvalErr<'tcx>),
     GeneratorResumedAfterReturn,
     GeneratorResumedAfterPanic,
 }
@@ -238,7 +268,7 @@ pub fn description(&self) -> &str {
                 "there were unresolved type arguments during trait selection",
             TypeckError =>
                 "encountered constants with type errors, stopping evaluation",
-            ReferencedConstant =>
+            ReferencedConstant(_) =>
                 "referenced constant has errors",
             Overflow(mir::BinOp::Add) => "attempt to add with overflow",
             Overflow(mir::BinOp::Sub) => "attempt to subtract with overflow",
index dc4233436c6604799b35a880b8567e5b196a8409..f76b312ee530daebf773f2c4c9acf66b5175b026 100644 (file)
@@ -827,10 +827,13 @@ pub fn report_selection_error(&self,
             }
 
             ConstEvalFailure(ref err) => {
-                if let ::middle::const_val::ErrKind::TypeckError = *err.kind {
-                    return;
+                match err.struct_error(
+                    self.tcx.at(span),
+                    "could not evaluate constant expression",
+                ) {
+                    Some(err) => err,
+                    None => return,
                 }
-                err.struct_error(self.tcx, span, "constant expression")
             }
 
             Overflow => {
index 4447a2b6ed14081086f05b13cf1adfea05674f08..dff89f3c888a73d54e5fcb17348b625d943347a2 100644 (file)
@@ -534,8 +534,7 @@ fn process_predicate<'a, 'gcx, 'tcx>(
                             } else {
                                 Err(CodeSelectionError(ConstEvalFailure(ConstEvalErr {
                                     span: obligation.cause.span,
-                                    kind: ErrKind::UnimplementedConstVal("could not resolve")
-                                        .into(),
+                                    kind: ErrKind::CouldNotResolve.into(),
                                 })))
                             }
                         },
index 35b2ce50da79d07f0ee74bbe52e6fa93cebf0450..e66ad24231094967b43876bf1fa448ae996d8c30 100644 (file)
@@ -1699,16 +1699,21 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
 pub mod tls {
     use super::{GlobalCtxt, TyCtxt};
 
-    use std::cell::Cell;
     use std::fmt;
     use std::mem;
     use syntax_pos;
     use ty::maps;
     use errors::{Diagnostic, TRACK_DIAGNOSTICS};
     use rustc_data_structures::OnDrop;
-    use rustc_data_structures::sync::{self, Lrc};
+    use rustc_data_structures::sync::{self, Lrc, Lock};
     use dep_graph::OpenTask;
 
+    #[cfg(not(parallel_queries))]
+    use std::cell::Cell;
+
+    #[cfg(parallel_queries)]
+    use rayon_core;
+
     /// This is the implicit state of rustc. It contains the current
     /// TyCtxt and query. It is updated when creating a local interner or
     /// executing a new query. Whenever there's a TyCtxt value available
@@ -1732,9 +1737,29 @@ pub struct ImplicitCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
         pub task: &'a OpenTask,
     }
 
-    // A thread local value which stores a pointer to the current ImplicitCtxt
+    /// Sets Rayon's thread local variable which is preserved for Rayon jobs
+    /// to `value` during the call to `f`. It is restored to its previous value after.
+    /// This is used to set the pointer to the new ImplicitCtxt.
+    #[cfg(parallel_queries)]
+    fn set_tlv<F: FnOnce() -> R, R>(value: usize, f: F) -> R {
+        rayon_core::tlv::with(value, f)
+    }
+
+    /// Gets Rayon's thread local variable which is preserved for Rayon jobs.
+    /// This is used to get the pointer to the current ImplicitCtxt.
+    #[cfg(parallel_queries)]
+    fn get_tlv() -> usize {
+        rayon_core::tlv::get()
+    }
+
+    /// A thread local variable which stores a pointer to the current ImplicitCtxt
+    #[cfg(not(parallel_queries))]
     thread_local!(static TLV: Cell<usize> = Cell::new(0));
 
+    /// Sets TLV to `value` during the call to `f`.
+    /// It is restored to its previous value after.
+    /// This is used to set the pointer to the new ImplicitCtxt.
+    #[cfg(not(parallel_queries))]
     fn set_tlv<F: FnOnce() -> R, R>(value: usize, f: F) -> R {
         let old = get_tlv();
         let _reset = OnDrop(move || TLV.with(|tlv| tlv.set(old)));
@@ -1742,6 +1767,8 @@ fn set_tlv<F: FnOnce() -> R, R>(value: usize, f: F) -> R {
         f()
     }
 
+    /// This is used to get the pointer to the current ImplicitCtxt.
+    #[cfg(not(parallel_queries))]
     fn get_tlv() -> usize {
         TLV.with(|tlv| tlv.get())
     }
@@ -1810,6 +1837,15 @@ pub fn enter_global<'gcx, F, R>(gcx: &GlobalCtxt<'gcx>, f: F) -> R
         where F: for<'a> FnOnce(TyCtxt<'a, 'gcx, 'gcx>) -> R
     {
         with_thread_locals(|| {
+            // Update GCX_PTR to indicate there's a GlobalCtxt available
+            GCX_PTR.with(|lock| {
+                *lock.lock() = gcx as *const _ as usize;
+            });
+            // Set GCX_PTR back to 0 when we exit
+            let _on_drop = OnDrop(move || {
+                GCX_PTR.with(|lock| *lock.lock() = 0);
+            });
+
             let tcx = TyCtxt {
                 gcx,
                 interners: &gcx.global_interners,
@@ -1826,6 +1862,32 @@ pub fn enter_global<'gcx, F, R>(gcx: &GlobalCtxt<'gcx>, f: F) -> R
         })
     }
 
+    /// Stores a pointer to the GlobalCtxt if one is available.
+    /// This is used to access the GlobalCtxt in the deadlock handler
+    /// given to Rayon.
+    scoped_thread_local!(pub static GCX_PTR: Lock<usize>);
+
+    /// Creates a TyCtxt and ImplicitCtxt based on the GCX_PTR thread local.
+    /// This is used in the deadlock handler.
+    pub unsafe fn with_global<F, R>(f: F) -> R
+        where F: for<'a, 'gcx, 'tcx> FnOnce(TyCtxt<'a, 'gcx, 'tcx>) -> R
+    {
+        let gcx = GCX_PTR.with(|lock| *lock.lock());
+        assert!(gcx != 0);
+        let gcx = &*(gcx as *const GlobalCtxt<'_>);
+        let tcx = TyCtxt {
+            gcx,
+            interners: &gcx.global_interners,
+        };
+        let icx = ImplicitCtxt {
+            query: None,
+            tcx,
+            layout_depth: 0,
+            task: &OpenTask::Ignore,
+        };
+        enter_context(&icx, |_| f(tcx))
+    }
+
     /// Allows access to the current ImplicitCtxt in a closure if one is available
     pub fn with_context_opt<F, R>(f: F) -> R
         where F: for<'a, 'gcx, 'tcx> FnOnce(Option<&ImplicitCtxt<'a, 'gcx, 'tcx>>) -> R
index 3b6af018d6b789d839c4bb2a2f84781bc867cc9a..3da73d47a0bf5d9a7cd4d6d7b3513d653d4c5f98 100644 (file)
@@ -8,13 +8,31 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use rustc_data_structures::sync::{Lock, Lrc};
+#![allow(warnings)]
+
+use std::mem;
+use rustc_data_structures::sync::{Lock, LockGuard, Lrc, Weak};
+use rustc_data_structures::OnDrop;
 use syntax_pos::Span;
 use ty::tls;
 use ty::maps::Query;
 use ty::maps::plumbing::CycleError;
 use ty::context::TyCtxt;
 use errors::Diagnostic;
+use std::process;
+use std::fmt;
+use std::collections::HashSet;
+#[cfg(parallel_queries)]
+use {
+    rayon_core,
+    parking_lot::{Mutex, Condvar},
+    std::sync::atomic::Ordering,
+    std::thread,
+    std::iter,
+    std::iter::FromIterator,
+    syntax_pos::DUMMY_SP,
+    rustc_data_structures::stable_hasher::{StableHasherResult, StableHasher, HashStable},
+};
 
 /// Indicates the state of a query for a given key in a query map
 pub(super) enum QueryResult<'tcx> {
@@ -42,6 +60,10 @@ pub struct QueryJob<'tcx> {
 
     /// Diagnostic messages which are emitted while the query executes
     pub diagnostics: Lock<Vec<Diagnostic>>,
+
+    /// The latch which is used to wait on this job
+    #[cfg(parallel_queries)]
+    latch: QueryLatch<'tcx>,
 }
 
 impl<'tcx> QueryJob<'tcx> {
@@ -51,6 +73,8 @@ pub fn new(info: QueryInfo<'tcx>, parent: Option<Lrc<QueryJob<'tcx>>>) -> Self {
             diagnostics: Lock::new(Vec::new()),
             info,
             parent,
+            #[cfg(parallel_queries)]
+            latch: QueryLatch::new(),
         }
     }
 
@@ -62,6 +86,36 @@ pub(super) fn await<'lcx>(
         &self,
         tcx: TyCtxt<'_, 'tcx, 'lcx>,
         span: Span,
+    ) -> Result<(), CycleError<'tcx>> {
+        #[cfg(not(parallel_queries))]
+        {
+            self.find_cycle_in_stack(tcx, span)
+        }
+
+        #[cfg(parallel_queries)]
+        {
+            tls::with_related_context(tcx, move |icx| {
+                let mut waiter = Lrc::new(QueryWaiter {
+                    query: icx.query.clone(),
+                    span,
+                    cycle: Lock::new(None),
+                    condvar: Condvar::new(),
+                });
+                self.latch.await(&waiter);
+
+                match Lrc::get_mut(&mut waiter).unwrap().cycle.get_mut().take() {
+                    None => Ok(()),
+                    Some(cycle) => Err(cycle)
+                }
+            })
+        }
+    }
+
+    #[cfg(not(parallel_queries))]
+    fn find_cycle_in_stack<'lcx>(
+        &self,
+        tcx: TyCtxt<'_, 'tcx, 'lcx>,
+        span: Span,
     ) -> Result<(), CycleError<'tcx>> {
         // Get the current executing query (waiter) and find the waitee amongst its parents
         let mut current_job = tls::with_related_context(tcx, |icx| icx.query.clone());
@@ -93,5 +147,379 @@ pub(super) fn await<'lcx>(
     ///
     /// This does nothing for single threaded rustc,
     /// as there are no concurrent jobs which could be waiting on us
-    pub fn signal_complete(&self) {}
+    pub fn signal_complete(&self) {
+        #[cfg(parallel_queries)]
+        self.latch.set();
+    }
+
+    fn as_ptr(&self) -> *const QueryJob<'tcx> {
+        self as *const _
+    }
+}
+
+#[cfg(parallel_queries)]
+struct QueryWaiter<'tcx> {
+    query: Option<Lrc<QueryJob<'tcx>>>,
+    condvar: Condvar,
+    span: Span,
+    cycle: Lock<Option<CycleError<'tcx>>>,
+}
+
+#[cfg(parallel_queries)]
+impl<'tcx> QueryWaiter<'tcx> {
+    fn notify(&self, registry: &rayon_core::Registry) {
+        rayon_core::mark_unblocked(registry);
+        self.condvar.notify_one();
+    }
+}
+
+#[cfg(parallel_queries)]
+struct QueryLatchInfo<'tcx> {
+    complete: bool,
+    waiters: Vec<Lrc<QueryWaiter<'tcx>>>,
+}
+
+#[cfg(parallel_queries)]
+struct QueryLatch<'tcx> {
+    info: Mutex<QueryLatchInfo<'tcx>>,
+}
+
+#[cfg(parallel_queries)]
+impl<'tcx> QueryLatch<'tcx> {
+    fn new() -> Self {
+        QueryLatch {
+            info: Mutex::new(QueryLatchInfo {
+                complete: false,
+                waiters: Vec::new(),
+            }),
+        }
+    }
+
+    /// Awaits the caller on this latch by blocking the current thread.
+    fn await(&self, waiter: &Lrc<QueryWaiter<'tcx>>) {
+        let mut info = self.info.lock();
+        if !info.complete {
+            // We push the waiter on to the `waiters` list. It can be accessed inside
+            // the `wait` call below, by 1) the `set` method or 2) by deadlock detection.
+            // Both of these will remove it from the `waiters` list before resuming
+            // this thread.
+            info.waiters.push(waiter.clone());
+
+            // If this detects a deadlock and the deadlock handler wants to resume this thread
+            // we have to be in the `wait` call. This is ensured by the deadlock handler
+            // getting the self.info lock.
+            rayon_core::mark_blocked();
+            waiter.condvar.wait(&mut info);
+        }
+    }
+
+    /// Sets the latch and resumes all waiters on it
+    fn set(&self) {
+        let mut info = self.info.lock();
+        debug_assert!(!info.complete);
+        info.complete = true;
+        let registry = rayon_core::Registry::current();
+        for waiter in info.waiters.drain(..) {
+            waiter.notify(&registry);
+        }
+    }
+
+    /// Remove a single waiter from the list of waiters.
+    /// This is used to break query cycles.
+    fn extract_waiter(
+        &self,
+        waiter: usize,
+    ) -> Lrc<QueryWaiter<'tcx>> {
+        let mut info = self.info.lock();
+        debug_assert!(!info.complete);
+        // Remove the waiter from the list of waiters
+        info.waiters.remove(waiter)
+    }
+}
+
+/// A resumable waiter of a query. The usize is the index into waiters in the query's latch
+#[cfg(parallel_queries)]
+type Waiter<'tcx> = (Lrc<QueryJob<'tcx>>, usize);
+
+/// Visits all the non-resumable and resumable waiters of a query.
+/// Only waiters in a query are visited.
+/// `visit` is called for every waiter and is passed a query waiting on `query_ref`
+/// and a span indicating the reason the query waited on `query_ref`.
+/// If `visit` returns Some, this function returns.
+/// For visits of non-resumable waiters it returns the return value of `visit`.
+/// For visits of resumable waiters it returns Some(Some(Waiter)) which has the
+/// required information to resume the waiter.
+/// If all `visit` calls returns None, this function also returns None.
+#[cfg(parallel_queries)]
+fn visit_waiters<'tcx, F>(query: Lrc<QueryJob<'tcx>>, mut visit: F) -> Option<Option<Waiter<'tcx>>>
+where
+    F: FnMut(Span, Lrc<QueryJob<'tcx>>) -> Option<Option<Waiter<'tcx>>>
+{
+    // Visit the parent query which is a non-resumable waiter since it's on the same stack
+    if let Some(ref parent) = query.parent {
+        if let Some(cycle) = visit(query.info.span, parent.clone()) {
+            return Some(cycle);
+        }
+    }
+
+    // Visit the explict waiters which use condvars and are resumable
+    for (i, waiter) in query.latch.info.lock().waiters.iter().enumerate() {
+        if let Some(ref waiter_query) = waiter.query {
+            if visit(waiter.span, waiter_query.clone()).is_some() {
+                // Return a value which indicates that this waiter can be resumed
+                return Some(Some((query.clone(), i)));
+            }
+        }
+    }
+    None
+}
+
+/// Look for query cycles by doing a depth first search starting at `query`.
+/// `span` is the reason for the `query` to execute. This is initially DUMMY_SP.
+/// If a cycle is detected, this initial value is replaced with the span causing
+/// the cycle.
+#[cfg(parallel_queries)]
+fn cycle_check<'tcx>(query: Lrc<QueryJob<'tcx>>,
+                     span: Span,
+                     stack: &mut Vec<(Span, Lrc<QueryJob<'tcx>>)>,
+                     visited: &mut HashSet<*const QueryJob<'tcx>>
+) -> Option<Option<Waiter<'tcx>>> {
+    if visited.contains(&query.as_ptr()) {
+        return if let Some(p) = stack.iter().position(|q| q.1.as_ptr() == query.as_ptr()) {
+            // We detected a query cycle, fix up the initial span and return Some
+
+            // Remove previous stack entries
+            stack.splice(0..p, iter::empty());
+            // Replace the span for the first query with the cycle cause
+            stack[0].0 = span;
+            Some(None)
+        } else {
+            None
+        }
+    }
+
+    // Mark this query is visited and add it to the stack
+    visited.insert(query.as_ptr());
+    stack.push((span, query.clone()));
+
+    // Visit all the waiters
+    let r = visit_waiters(query, |span, successor| {
+        cycle_check(successor, span, stack, visited)
+    });
+
+    // Remove the entry in our stack if we didn't find a cycle
+    if r.is_none() {
+        stack.pop();
+    }
+
+    r
+}
+
+/// Finds out if there's a path to the compiler root (aka. code which isn't in a query)
+/// from `query` without going through any of the queries in `visited`.
+/// This is achieved with a depth first search.
+#[cfg(parallel_queries)]
+fn connected_to_root<'tcx>(
+    query: Lrc<QueryJob<'tcx>>,
+    visited: &mut HashSet<*const QueryJob<'tcx>>
+) -> bool {
+    // We already visited this or we're deliberately ignoring it
+    if visited.contains(&query.as_ptr()) {
+        return false;
+    }
+
+    // This query is connected to the root (it has no query parent), return true
+    if query.parent.is_none() {
+        return true;
+    }
+
+    visited.insert(query.as_ptr());
+
+    let mut connected = false;
+
+    visit_waiters(query, |_, successor| {
+        if connected_to_root(successor, visited) {
+            Some(None)
+        } else {
+            None
+        }
+    }).is_some()
+}
+
+/// Looks for query cycles starting from the last query in `jobs`.
+/// If a cycle is found, all queries in the cycle is removed from `jobs` and
+/// the function return true.
+/// If a cycle was not found, the starting query is removed from `jobs` and
+/// the function returns false.
+#[cfg(parallel_queries)]
+fn remove_cycle<'tcx>(
+    jobs: &mut Vec<Lrc<QueryJob<'tcx>>>,
+    wakelist: &mut Vec<Lrc<QueryWaiter<'tcx>>>,
+    tcx: TyCtxt<'_, 'tcx, '_>
+) -> bool {
+    let mut visited = HashSet::new();
+    let mut stack = Vec::new();
+    // Look for a cycle starting with the last query in `jobs`
+    if let Some(waiter) = cycle_check(jobs.pop().unwrap(),
+                                      DUMMY_SP,
+                                      &mut stack,
+                                      &mut visited) {
+        // Reverse the stack so earlier entries require later entries
+        stack.reverse();
+
+        // Extract the spans and queries into separate arrays
+        let mut spans: Vec<_> = stack.iter().map(|e| e.0).collect();
+        let queries = stack.into_iter().map(|e| e.1);
+
+        // Shift the spans so that queries are matched with the span for their waitee
+        let last = spans.pop().unwrap();
+        spans.insert(0, last);
+
+        // Zip them back together
+        let mut stack: Vec<_> = spans.into_iter().zip(queries).collect();
+
+        // Remove the queries in our cycle from the list of jobs to look at
+        for r in &stack {
+            if let Some(pos) = jobs.iter().position(|j| j.as_ptr() == r.1.as_ptr()) {
+                jobs.remove(pos);
+            }
+        }
+
+        // Find the queries in the cycle which are
+        // connected to queries outside the cycle
+        let entry_points: Vec<Lrc<QueryJob<'tcx>>> = stack.iter().filter_map(|query| {
+            // Mark all the other queries in the cycle as already visited
+            let mut visited = HashSet::from_iter(stack.iter().filter_map(|q| {
+                if q.1.as_ptr() != query.1.as_ptr() {
+                    Some(q.1.as_ptr())
+                } else {
+                    None
+                }
+            }));
+
+            if connected_to_root(query.1.clone(), &mut visited) {
+                Some(query.1.clone())
+            } else {
+                None
+            }
+        }).collect();
+
+        // Deterministically pick an entry point
+        // FIXME: Sort this instead
+        let mut hcx = tcx.create_stable_hashing_context();
+        let entry_point = entry_points.iter().min_by_key(|q| {
+            let mut stable_hasher = StableHasher::<u64>::new();
+            q.info.query.hash_stable(&mut hcx, &mut stable_hasher);
+            stable_hasher.finish()
+        }).unwrap().as_ptr();
+
+        // Shift the stack until our entry point is first
+        while stack[0].1.as_ptr() != entry_point {
+            let last = stack.pop().unwrap();
+            stack.insert(0, last);
+        }
+
+        // Create the cycle error
+        let mut error = CycleError {
+            usage: None,
+            cycle: stack.iter().map(|&(s, ref q)| QueryInfo {
+                span: s,
+                query: q.info.query.clone(),
+            } ).collect(),
+        };
+
+        // We unwrap `waiter` here since there must always be one
+        // edge which is resumeable / waited using a query latch
+        let (waitee_query, waiter_idx) = waiter.unwrap();
+
+        // Extract the waiter we want to resume
+        let waiter = waitee_query.latch.extract_waiter(waiter_idx);
+
+        // Set the cycle error so it will be picked up when resumed
+        *waiter.cycle.lock() = Some(error);
+
+        // Put the waiter on the list of things to resume
+        wakelist.push(waiter);
+
+        true
+    } else {
+        false
+    }
+}
+
+/// Creates a new thread and forwards information in thread locals to it.
+/// The new thread runs the deadlock handler.
+/// Must only be called when a deadlock is about to happen.
+#[cfg(parallel_queries)]
+pub unsafe fn handle_deadlock() {
+    use syntax;
+    use syntax_pos;
+
+    let registry = rayon_core::Registry::current();
+
+    let gcx_ptr = tls::GCX_PTR.with(|gcx_ptr| {
+        gcx_ptr as *const _
+    });
+    let gcx_ptr = &*gcx_ptr;
+
+    let syntax_globals = syntax::GLOBALS.with(|syntax_globals| {
+        syntax_globals as *const _
+    });
+    let syntax_globals = &*syntax_globals;
+
+    let syntax_pos_globals = syntax_pos::GLOBALS.with(|syntax_pos_globals| {
+        syntax_pos_globals as *const _
+    });
+    let syntax_pos_globals = &*syntax_pos_globals;
+    thread::spawn(move || {
+        tls::GCX_PTR.set(gcx_ptr, || {
+            syntax_pos::GLOBALS.set(syntax_pos_globals, || {
+                syntax_pos::GLOBALS.set(syntax_pos_globals, || {
+                    tls::with_thread_locals(|| {
+                        tls::with_global(|tcx| deadlock(tcx, &registry))
+                    })
+                })
+            })
+        })
+    });
+}
+
+/// Detects query cycles by using depth first search over all active query jobs.
+/// If a query cycle is found it will break the cycle by finding an edge which
+/// uses a query latch and then resuming that waiter.
+/// There may be multiple cycles involved in a deadlock, so this searches
+/// all active queries for cycles before finally resuming all the waiters at once.
+#[cfg(parallel_queries)]
+fn deadlock(tcx: TyCtxt<'_, '_, '_>, registry: &rayon_core::Registry) {
+    let on_panic = OnDrop(|| {
+        eprintln!("deadlock handler panicked, aborting process");
+        process::abort();
+    });
+
+    let mut wakelist = Vec::new();
+    let mut jobs: Vec<_> = tcx.maps.collect_active_jobs();
+
+    let mut found_cycle = false;
+
+    while jobs.len() > 0 {
+        if remove_cycle(&mut jobs, &mut wakelist, tcx) {
+            found_cycle = true;
+        }
+    }
+
+    // Check that a cycle was found. It is possible for a deadlock to occur without
+    // a query cycle if a query which can be waited on uses Rayon to do multithreading
+    // internally. Such a query (X) may be executing on 2 threads (A and B) and A may
+    // wait using Rayon on B. Rayon may then switch to executing another query (Y)
+    // which in turn will wait on X causing a deadlock. We have a false dependency from
+    // X to Y due to Rayon waiting and a true dependency from Y to X. The algorithm here
+    // only considers the true dependency and won't detect a cycle.
+    assert!(found_cycle);
+
+    // FIXME: Ensure this won't cause a deadlock before we return
+    for waiter in wakelist.into_iter() {
+        waiter.notify(registry);
+    }
+
+    on_panic.disable();
 }
index 6556e47720c6239404371850cb7dd3b483f6f050..b50b43aace760d2797f3821fa54321358eda0bbb 100644 (file)
 #[macro_use]
 mod plumbing;
 use self::plumbing::*;
-pub use self::plumbing::force_from_dep_node;
+pub use self::plumbing::{force_from_dep_node, CycleError};
 
 mod job;
 pub use self::job::{QueryJob, QueryInfo};
+#[cfg(parallel_queries)]
+pub use self::job::handle_deadlock;
 
 mod keys;
 pub use self::keys::Key;
index 4a9d44b7403b9a09a3fb688712ad96aacd4d776e..13d2a13e5ddc519e3e8ac193f8dccca02221d362 100644 (file)
@@ -223,7 +223,7 @@ fn drop(&mut self) {
 }
 
 #[derive(Clone)]
-pub(super) struct CycleError<'tcx> {
+pub struct CycleError<'tcx> {
     /// The query and related span which uses the cycle
     pub(super) usage: Option<(Span, Query<'tcx>)>,
     pub(super) cycle: Vec<QueryInfo<'tcx>>,
@@ -632,7 +632,15 @@ macro_rules! define_maps {
      $($(#[$attr:meta])*
        [$($modifiers:tt)*] fn $name:ident: $node:ident($K:ty) -> $V:ty,)*) => {
 
+        use std::mem;
+        use ty::maps::job::QueryResult;
         use rustc_data_structures::sync::Lock;
+        use {
+            rustc_data_structures::stable_hasher::HashStable,
+            rustc_data_structures::stable_hasher::StableHasherResult,
+            rustc_data_structures::stable_hasher::StableHasher,
+            ich::StableHashingContext
+        };
 
         define_map_struct! {
             tcx: $tcx,
@@ -647,10 +655,25 @@ pub fn new(providers: IndexVec<CrateNum, Providers<$tcx>>)
                     $($name: Lock::new(QueryMap::new())),*
                 }
             }
+
+            pub fn collect_active_jobs(&self) -> Vec<Lrc<QueryJob<$tcx>>> {
+                let mut jobs = Vec::new();
+
+                // We use try_lock here since we are only called from the
+                // deadlock handler, and this shouldn't be locked
+                $(for v in self.$name.try_lock().unwrap().active.values() {
+                    match *v {
+                        QueryResult::Started(ref job) => jobs.push(job.clone()),
+                        _ => (),
+                    }
+                })*
+
+                return jobs;
+            }
         }
 
         #[allow(bad_style)]
-        #[derive(Copy, Clone, Debug, PartialEq, Eq)]
+        #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
         pub enum Query<$tcx> {
             $($(#[$attr])* $name($K)),*
         }
@@ -692,6 +715,17 @@ pub fn default_span(&self, tcx: TyCtxt<'_, $tcx, '_>, span: Span) -> Span {
             }
         }
 
+        impl<'a, $tcx> HashStable<StableHashingContext<'a>> for Query<$tcx> {
+            fn hash_stable<W: StableHasherResult>(&self,
+                                                hcx: &mut StableHashingContext<'a>,
+                                                hasher: &mut StableHasher<W>) {
+                mem::discriminant(self).hash_stable(hcx, hasher);
+                match *self {
+                    $(Query::$name(key) => key.hash_stable(hcx, hasher),)*
+                }
+            }
+        }
+
         pub mod queries {
             use std::marker::PhantomData;
 
index 0bb0208e2a1b4a2d0b2737b60ca61f4f4a800e2f..f947ed456862451ed361eac87bc11b993c84c7fd 100644 (file)
@@ -2075,15 +2075,17 @@ pub fn eval_explicit_discr(
                 } else {
                     info!("invalid enum discriminant: {:#?}", val);
                     ::middle::const_val::struct_error(
-                        tcx,
-                        tcx.def_span(expr_did),
+                        tcx.at(tcx.def_span(expr_did)),
                         "constant evaluation of enum discriminant resulted in non-integer",
                     ).emit();
                     None
                 }
             }
             Err(err) => {
-                err.report(tcx, tcx.def_span(expr_did), "enum discriminant");
+                err.report_as_error(
+                    tcx.at(tcx.def_span(expr_did)),
+                    "could not evaluate enum discriminant",
+                );
                 if !expr_did.is_local() {
                     span_bug!(tcx.def_span(expr_did),
                         "variant discriminant evaluation succeeded \
index e77ede72143b1afd819f169f0d5355dbf7bc0373..79a6311185076a0b5366661722871d48ba463b25 100644 (file)
@@ -476,7 +476,6 @@ impl<'a, 'tcx> Lift<'tcx> for interpret::EvalError<'a> {
     fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
         Some(interpret::EvalError {
             kind: tcx.lift(&self.kind)?,
-            backtrace: self.backtrace.clone(),
         })
     }
 }
@@ -578,7 +577,7 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
             PathNotFound(ref v) => PathNotFound(v.clone()),
             UnimplementedTraitSelection => UnimplementedTraitSelection,
             TypeckError => TypeckError,
-            ReferencedConstant => ReferencedConstant,
+            ReferencedConstant(ref err) => ReferencedConstant(tcx.lift(err)?),
             OverflowNeg => OverflowNeg,
             Overflow(op) => Overflow(op),
             DivisionByZero => DivisionByZero,
@@ -595,14 +594,7 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
         use middle::const_val::ErrKind::*;
 
         Some(match *self {
-            NonConstPath => NonConstPath,
-            UnimplementedConstVal(s) => UnimplementedConstVal(s),
-            IndexOutOfBounds { len, index } => IndexOutOfBounds { len, index },
-
-            LayoutError(ref e) => {
-                return tcx.lift(e).map(LayoutError)
-            }
-
+            CouldNotResolve => CouldNotResolve,
             TypeckError => TypeckError,
             CheckMatchError => CheckMatchError,
             Miri(ref e, ref frames) => return tcx.lift(e).map(|e| Miri(e, frames.clone())),
index 9d0d8c2f909af7caa63f45243ed11a2f441bf624..e063880028fc9a1c4d3b6069f4f3853adb94cc63 100644 (file)
@@ -899,7 +899,7 @@ fn report_bckerr(&self, err: &BckError<'a, 'tcx>) {
                 };
 
                 self.note_and_explain_mutbl_error(&mut db, &err, &error_span);
-                self.note_immutability_blame(&mut db, err.cmt.immutability_blame());
+                self.note_immutability_blame(&mut db, err.cmt.immutability_blame(), err.cmt.id);
                 db.emit();
             }
             err_out_of_scope(super_scope, sub_scope, cause) => {
@@ -1105,7 +1105,7 @@ pub fn report_aliasability_violation(&self,
                                                             Origin::Ast)
             }
         };
-        self.note_immutability_blame(&mut err, blame);
+        self.note_immutability_blame(&mut err, blame, cmt.id);
 
         if is_closure {
             err.help("closures behind references must be called via `&mut`");
@@ -1184,25 +1184,13 @@ fn local_ty(&self, node_id: ast::NodeId) -> (Option<&hir::Ty>, bool) {
 
     fn note_immutability_blame(&self,
                                db: &mut DiagnosticBuilder,
-                               blame: Option<ImmutabilityBlame>) {
+                               blame: Option<ImmutabilityBlame>,
+                               error_node_id: ast::NodeId) {
         match blame {
             None => {}
             Some(ImmutabilityBlame::ClosureEnv(_)) => {}
             Some(ImmutabilityBlame::ImmLocal(node_id)) => {
-                let let_span = self.tcx.hir.span(node_id);
-                if let ty::BindByValue(..) = self.local_binding_mode(node_id) {
-                    if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(let_span) {
-                        let (_, is_implicit_self) = self.local_ty(node_id);
-                        if is_implicit_self && snippet != "self" {
-                            // avoid suggesting `mut &self`.
-                            return
-                        }
-                        db.span_label(
-                            let_span,
-                            format!("consider changing this to `mut {}`", snippet)
-                        );
-                    }
-                }
+                self.note_immutable_local(db, error_node_id, node_id)
             }
             Some(ImmutabilityBlame::LocalDeref(node_id)) => {
                 let let_span = self.tcx.hir.span(node_id);
@@ -1242,6 +1230,46 @@ fn note_immutability_blame(&self,
         }
     }
 
+     // Suggest a fix when trying to mutably borrow an immutable local
+     // binding: either to make the binding mutable (if its type is
+     // not a mutable reference) or to avoid borrowing altogether
+    fn note_immutable_local(&self,
+                            db: &mut DiagnosticBuilder,
+                            borrowed_node_id: ast::NodeId,
+                            binding_node_id: ast::NodeId) {
+        let let_span = self.tcx.hir.span(binding_node_id);
+        if let ty::BindByValue(..) = self.local_binding_mode(binding_node_id) {
+            if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(let_span) {
+                let (ty, is_implicit_self) = self.local_ty(binding_node_id);
+                if is_implicit_self && snippet != "self" {
+                    // avoid suggesting `mut &self`.
+                    return
+                }
+                if let Some(&hir::TyRptr(
+                    _,
+                    hir::MutTy {
+                        mutbl: hir::MutMutable,
+                        ..
+                    },
+                )) = ty.map(|t| &t.node)
+                {
+                    let borrow_expr_id = self.tcx.hir.get_parent_node(borrowed_node_id);
+                    db.span_suggestion(
+                        self.tcx.hir.span(borrow_expr_id),
+                        "consider removing the `&mut`, as it is an \
+                        immutable binding to a mutable reference",
+                        snippet
+                    );
+                } else {
+                    db.span_label(
+                        let_span,
+                        format!("consider changing this to `mut {}`", snippet),
+                    );
+                }
+            }
+        }
+    }
+
     fn report_out_of_scope_escaping_closure_capture(&self,
                                                     err: &BckError<'a, 'tcx>,
                                                     capture_span: Span)
index ef0bc3ed3306a9c561904fe6c1a24123b400b42c..7c1035e2fcb8882f190d3e5e2f274bbcf834e98d 100644 (file)
@@ -217,7 +217,10 @@ pub fn simd_shuffle_indices(
                 Ok((llval, constant.ty))
             })
             .unwrap_or_else(|e| {
-                e.report(bx.tcx(), constant.span, "shuffle_indices");
+                e.report_as_error(
+                    bx.tcx().at(constant.span),
+                    "could not evaluate shuffle_indices at compile time",
+                );
                 // We've errored, so we don't have to produce working code.
                 let ty = self.monomorphize(&constant.ty);
                 let llty = bx.cx.layout_of(ty).llvm_type(bx.cx);
index 98383e882c4e8eeeb01ef9326e46a669825e85e4..9f32b41cb13e7913b9f8d6e5d7f0fc6a84d5e091 100644 (file)
@@ -416,7 +416,10 @@ pub fn codegen_operand(&mut self,
                                 // FIXME: generate a panic here
                             },
                             mir::Literal::Value { .. } => {
-                                err.report(bx.tcx(), constant.span, "const operand");
+                                err.report_as_error(
+                                    bx.tcx().at(constant.span),
+                                    "could not evaluate constant operand",
+                                );
                             },
                         }
                         // We've errored, so we don't have to produce working code.
index 17ee771e5294083cfb93dda2698b5f7080cf808c..fc5fe91c977d410057d189a3bd9ab425e9ed5b47 100644 (file)
@@ -16,8 +16,8 @@ serialize = { path = "../libserialize" }
 cfg-if = "0.1.2"
 stable_deref_trait = "1.0.0"
 parking_lot_core = "0.2.8"
-rustc-rayon = "0.1.0"
-rustc-rayon-core = "0.1.0"
+rustc-rayon = "0.1.1"
+rustc-rayon-core = "0.1.1"
 rustc-hash = "1.0.1"
 
 [dependencies.parking_lot]
index 7046a2a2a493d1f752f52657d09eda96ac2dbbdf..5844edf000a8b7837ea8a1d781fd63fa0677e667 100644 (file)
 
 pub struct OnDrop<F: Fn()>(pub F);
 
+impl<F: Fn()> OnDrop<F> {
+      /// Forgets the function which prevents it from running.
+      /// Ensure that the function owns no memory, otherwise it will be leaked.
+      pub fn disable(self) {
+            std::mem::forget(self);
+      }
+}
+
 impl<F: Fn()> Drop for OnDrop<F> {
       fn drop(&mut self) {
             (self.0)();
index 6f7d9e1b54b1ead0237398c50b6262bbd27664f5..33f6eda2a8753696658b61c3951cb5682df09d03 100644 (file)
@@ -519,6 +519,18 @@ pub fn get_mut(&mut self) -> &mut T {
         self.0.get_mut()
     }
 
+    #[cfg(parallel_queries)]
+    #[inline(always)]
+    pub fn try_lock(&self) -> Option<LockGuard<T>> {
+        self.0.try_lock()
+    }
+
+    #[cfg(not(parallel_queries))]
+    #[inline(always)]
+    pub fn try_lock(&self) -> Option<LockGuard<T>> {
+        self.0.try_borrow_mut().ok()
+    }
+
     #[cfg(parallel_queries)]
     #[inline(always)]
     pub fn lock(&self) -> LockGuard<T> {
index 24bf07d793f3d280a40011c991bc31797fd1fdd9..5b75912c18f50dac3973bcff7df157ac66213bee 100644 (file)
@@ -13,7 +13,7 @@ arena = { path = "../libarena" }
 graphviz = { path = "../libgraphviz" }
 log = "0.4"
 env_logger = { version = "0.5", default-features = false }
-rustc-rayon = "0.1.0"
+rustc-rayon = "0.1.1"
 scoped-tls = { version = "0.1.1", features = ["nightly"] }
 rustc = { path = "../librustc" }
 rustc_allocator = { path = "../librustc_allocator" }
index ed28b05c12551a5e28174eb7e7d99f7080f87b22..37f8bff964f5b1e880ae08684b17e67c133f9453 100644 (file)
@@ -49,7 +49,7 @@
 use std::io::{self, Write};
 use std::iter;
 use std::path::{Path, PathBuf};
-use rustc_data_structures::sync::{self, Lrc};
+use rustc_data_structures::sync::{self, Lrc, Lock};
 use std::sync::mpsc;
 use syntax::{self, ast, attr, diagnostics, visit};
 use syntax::ext::base::ExtCtxt;
@@ -69,7 +69,9 @@ pub fn spawn_thread_pool<F: FnOnce(config::Options) -> R + sync::Send, R: sync::
     opts: config::Options,
     f: F
 ) -> R {
-    f(opts)
+    ty::tls::GCX_PTR.set(&Lock::new(0), || {
+        f(opts)
+    })
 }
 
 #[cfg(parallel_queries)]
@@ -81,8 +83,12 @@ pub fn spawn_thread_pool<F: FnOnce(config::Options) -> R + sync::Send, R: sync::
     use syntax_pos;
     use rayon::{ThreadPoolBuilder, ThreadPool};
 
-    let config = ThreadPoolBuilder::new().num_threads(Session::query_threads_from_opts(&opts))
-                                         .stack_size(16 * 1024 * 1024);
+    let gcx_ptr = &Lock::new(0);
+
+    let config = ThreadPoolBuilder::new()
+        .num_threads(Session::query_threads_from_opts(&opts))
+        .deadlock_handler(|| unsafe { ty::maps::handle_deadlock() })
+        .stack_size(16 * 1024 * 1024);
 
     let with_pool = move |pool: &ThreadPool| {
         pool.install(move || f(opts))
@@ -98,7 +104,9 @@ pub fn spawn_thread_pool<F: FnOnce(config::Options) -> R + sync::Send, R: sync::
                 syntax::GLOBALS.set(syntax_globals, || {
                     syntax_pos::GLOBALS.set(syntax_pos_globals, || {
                         ty::tls::with_thread_locals(|| {
-                            worker()
+                            ty::tls::GCX_PTR.set(gcx_ptr, || {
+                                worker()
+                            })
                         })
                     })
                 })
@@ -414,6 +422,75 @@ pub fn basic() -> CompileController<'a> {
     }
 }
 
+/// This implementation makes it easier to create a custom driver when you only want to hook
+/// into callbacks from `CompileController`.
+///
+/// # Example
+///
+/// ```no_run
+/// # extern crate rustc_driver;
+/// # use rustc_driver::driver::CompileController;
+/// let mut controller = CompileController::basic();
+/// controller.after_analysis.callback = Box::new(move |_state| {});
+/// rustc_driver::run_compiler(&[], Box::new(controller), None, None);
+/// ```
+impl<'a> ::CompilerCalls<'a> for CompileController<'a> {
+    fn early_callback(
+        &mut self,
+        matches: &::getopts::Matches,
+        sopts: &config::Options,
+        cfg: &ast::CrateConfig,
+        descriptions: &::errors::registry::Registry,
+        output: ::ErrorOutputType,
+    ) -> Compilation {
+        ::RustcDefaultCalls.early_callback(
+            matches,
+            sopts,
+            cfg,
+            descriptions,
+            output,
+        )
+    }
+    fn no_input(
+        &mut self,
+        matches: &::getopts::Matches,
+        sopts: &config::Options,
+        cfg: &ast::CrateConfig,
+        odir: &Option<PathBuf>,
+        ofile: &Option<PathBuf>,
+        descriptions: &::errors::registry::Registry,
+    ) -> Option<(Input, Option<PathBuf>)> {
+        ::RustcDefaultCalls.no_input(
+            matches,
+            sopts,
+            cfg,
+            odir,
+            ofile,
+            descriptions,
+        )
+    }
+    fn late_callback(
+        &mut self,
+        codegen_backend: &::CodegenBackend,
+        matches: &::getopts::Matches,
+        sess: &Session,
+        cstore: &::CrateStore,
+        input: &Input,
+        odir: &Option<PathBuf>,
+        ofile: &Option<PathBuf>,
+    ) -> Compilation {
+        ::RustcDefaultCalls
+            .late_callback(codegen_backend, matches, sess, cstore, input, odir, ofile)
+    }
+    fn build_controller(
+        self: Box<Self>,
+        _: &Session,
+        _: &::getopts::Matches
+    ) -> CompileController<'a> {
+        *self
+    }
+}
+
 pub struct PhaseController<'a> {
     pub stop: Compilation,
     // If true then the compiler will try to run the callback even if the phase
index 2f89814032ef6eb55c43b3ce7986ca4c0c9477f1..67fd5da8c92d9e69e5154cd9d28061ee84075b3f 100644 (file)
@@ -454,7 +454,7 @@ fn GetModuleFileNameW(hModule: usize,
 // See comments on CompilerCalls below for details about the callbacks argument.
 // The FileLoader provides a way to load files from sources other than the file system.
 pub fn run_compiler<'a>(args: &[String],
-                        callbacks: &mut (CompilerCalls<'a> + sync::Send),
+                        callbacks: Box<CompilerCalls<'a> + sync::Send + 'a>,
                         file_loader: Option<Box<FileLoader + Send + Sync + 'static>>,
                         emitter_dest: Option<Box<Write + Send>>)
                         -> (CompileResult, Option<Session>)
@@ -478,7 +478,7 @@ fn run_compiler_with_pool<'a>(
     matches: getopts::Matches,
     sopts: config::Options,
     cfg: ast::CrateConfig,
-    callbacks: &mut (CompilerCalls<'a> + sync::Send),
+    mut callbacks: Box<CompilerCalls<'a> + sync::Send + 'a>,
     file_loader: Option<Box<FileLoader + Send + Sync + 'static>>,
     emitter_dest: Option<Box<Write + Send>>
 ) -> (CompileResult, Option<Session>) {
@@ -642,12 +642,12 @@ pub fn and_then<F: FnOnce() -> Compilation>(self, next: F) -> Compilation {
     }
 }
 
-// A trait for customising the compilation process. Offers a number of hooks for
-// executing custom code or customising input.
+/// A trait for customising the compilation process. Offers a number of hooks for
+/// executing custom code or customising input.
 pub trait CompilerCalls<'a> {
-    // Hook for a callback early in the process of handling arguments. This will
-    // be called straight after options have been parsed but before anything
-    // else (e.g., selecting input and output).
+    /// Hook for a callback early in the process of handling arguments. This will
+    /// be called straight after options have been parsed but before anything
+    /// else (e.g., selecting input and output).
     fn early_callback(&mut self,
                       _: &getopts::Matches,
                       _: &config::Options,
@@ -658,9 +658,9 @@ fn early_callback(&mut self,
         Compilation::Continue
     }
 
-    // Hook for a callback late in the process of handling arguments. This will
-    // be called just before actual compilation starts (and before build_controller
-    // is called), after all arguments etc. have been completely handled.
+    /// Hook for a callback late in the process of handling arguments. This will
+    /// be called just before actual compilation starts (and before build_controller
+    /// is called), after all arguments etc. have been completely handled.
     fn late_callback(&mut self,
                      _: &CodegenBackend,
                      _: &getopts::Matches,
@@ -673,9 +673,9 @@ fn late_callback(&mut self,
         Compilation::Continue
     }
 
-    // Called after we extract the input from the arguments. Gives the implementer
-    // an opportunity to change the inputs or to add some custom input handling.
-    // The default behaviour is to simply pass through the inputs.
+    /// Called after we extract the input from the arguments. Gives the implementer
+    /// an opportunity to change the inputs or to add some custom input handling.
+    /// The default behaviour is to simply pass through the inputs.
     fn some_input(&mut self,
                   input: Input,
                   input_path: Option<PathBuf>)
@@ -683,11 +683,11 @@ fn some_input(&mut self,
         (input, input_path)
     }
 
-    // Called after we extract the input from the arguments if there is no valid
-    // input. Gives the implementer an opportunity to supply alternate input (by
-    // returning a Some value) or to add custom behaviour for this error such as
-    // emitting error messages. Returning None will cause compilation to stop
-    // at this point.
+    /// Called after we extract the input from the arguments if there is no valid
+    /// input. Gives the implementer an opportunity to supply alternate input (by
+    /// returning a Some value) or to add custom behaviour for this error such as
+    /// emitting error messages. Returning None will cause compilation to stop
+    /// at this point.
     fn no_input(&mut self,
                 _: &getopts::Matches,
                 _: &config::Options,
@@ -701,10 +701,14 @@ fn no_input(&mut self,
 
     // Create a CompilController struct for controlling the behaviour of
     // compilation.
-    fn build_controller(&mut self, _: &Session, _: &getopts::Matches) -> CompileController<'a>;
+    fn build_controller(
+        self: Box<Self>,
+        _: &Session,
+        _: &getopts::Matches
+    ) -> CompileController<'a>;
 }
 
-// CompilerCalls instance for a regular rustc build.
+/// CompilerCalls instance for a regular rustc build.
 #[derive(Copy, Clone)]
 pub struct RustcDefaultCalls;
 
@@ -878,7 +882,7 @@ fn late_callback(&mut self,
             .and_then(|| RustcDefaultCalls::list_metadata(sess, cstore, matches, input))
     }
 
-    fn build_controller(&mut self,
+    fn build_controller(self: Box<Self>,
                         sess: &Session,
                         matches: &getopts::Matches)
                         -> CompileController<'a> {
@@ -1693,7 +1697,7 @@ pub fn main() {
             }))
             .collect::<Vec<_>>();
         run_compiler(&args,
-                     &mut RustcDefaultCalls,
+                     Box::new(RustcDefaultCalls),
                      None,
                      None)
     });
index f65acf08c86d8f3ad109829c5b264a4c4fe5efa6..92e72fe91d3e8dad19aca526b966492f3ab4211f 100644 (file)
@@ -1287,7 +1287,7 @@ fn emit_suggestion_default(&mut self,
                         });
 
                         // length of the code to be substituted
-                        let snippet_len = (span_end_pos - span_start_pos) as isize;
+                        let snippet_len = span_end_pos as isize - span_start_pos as isize;
                         // For multiple substitutions, use the position *after* the previous
                         // substitutions have happened.
                         offset += full_sub_len - snippet_len;
index 79c7a79114761785fc8e1cb9e8ce99ae88b01055..d788e312d155abe79fa4dab0840288bd8d41eab8 100644 (file)
@@ -1501,24 +1501,11 @@ fn check_const(cx: &LateContext, body_id: hir::BodyId, what: &str) {
     };
     if let Err(err) = cx.tcx.const_eval(param_env.and(cid)) {
         let span = cx.tcx.def_span(def_id);
-        let mut diag = cx.struct_span_lint(
-            CONST_ERR,
-            span,
+        err.report_as_lint(
+            cx.tcx.at(span),
             &format!("this {} cannot be used", what),
+            cx.current_lint_root(),
         );
-        use rustc::middle::const_val::ConstEvalErrDescription;
-        match err.description() {
-            ConstEvalErrDescription::Simple(message) => {
-                diag.span_label(span, message);
-            }
-            ConstEvalErrDescription::Backtrace(miri, frames) => {
-                diag.span_label(span, format!("{}", miri));
-                for frame in frames {
-                    diag.span_label(frame.span, format!("inside call to `{}`", frame.location));
-                }
-            }
-        }
-        diag.emit()
     }
 }
 
index d6ce5b2ea57fe2228b2f0c6acf3aafda399b3098..ad8e003b6176804e5940a045940f6d1812abe158 100644 (file)
@@ -211,6 +211,11 @@ macro_rules! add_lint_group {
             reference: "issue #35203 <https://github.com/rust-lang/rust/issues/35203>",
             edition: None,
         },
+        FutureIncompatibleInfo {
+            id: LintId::of(DUPLICATE_MACRO_EXPORTS),
+            reference: "issue #35896 <https://github.com/rust-lang/rust/issues/35896>",
+            edition: Some(Edition::Edition2018),
+        },
         FutureIncompatibleInfo {
             id: LintId::of(SAFE_EXTERN_STATICS),
             reference: "issue #36247 <https://github.com/rust-lang/rust/issues/36247>",
index 512ab53f401a6910bea2144f699af0a91de011cd..0fd1f92a516278e06669a63bc9d3e02f8cba4a84 100644 (file)
@@ -15,7 +15,7 @@ either = "1.5.0"
 graphviz = { path = "../libgraphviz" }
 log = "0.4"
 log_settings = "0.1.1"
-polonius-engine = "0.4.0"
+polonius-engine = "0.5.0"
 rustc = { path = "../librustc" }
 rustc_target = { path = "../librustc_target" }
 rustc_data_structures = { path = "../librustc_data_structures" }
index ec1f3dbaeebf5aa6b768257bc8e8974e2d8b52b9..c3d9dd8378d4a80c7a4f228411356838026d5ed0 100644 (file)
 use rustc::util::nodemap::FxHashMap;
 use std::collections::BTreeSet;
 use std::fmt::Debug;
+use std::env;
 use std::io;
 use std::path::PathBuf;
 use std::rc::Rc;
+use std::str::FromStr;
 use transform::MirSource;
 use util::liveness::{LivenessResults, LocalSet};
 
@@ -156,9 +158,13 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
         }
 
         if infcx.tcx.sess.opts.debugging_opts.polonius {
+            let algorithm = env::var("POLONIUS_ALGORITHM")
+                .unwrap_or(String::from("DatafrogOpt"));
+            let algorithm = Algorithm::from_str(&algorithm).unwrap();
+            debug!("compute_regions: using polonius algorithm {:?}", algorithm);
             Some(Rc::new(Output::compute(
                 &all_facts,
-                Algorithm::DatafrogOpt,
+                algorithm,
                 false,
             )))
         } else {
index d19fd2bb5969dfc353142cfda186e5f93c19e8da..76320c6a2eacc96912c70f3ae3579ebb474bad0f 100644 (file)
@@ -104,13 +104,15 @@ fn add_liveness_constraints(&mut self, bb: BasicBlock) {
                     location, live_local
                 );
 
-                self.flow_inits.each_state_bit(|mpi_init| {
-                    debug!(
-                        "add_liveness_constraints: location={:?} initialized={:?}",
-                        location,
-                        &self.flow_inits.operator().move_data().move_paths[mpi_init]
-                    );
-                });
+                if log_enabled!(::log::Level::Debug) {
+                    self.flow_inits.each_state_bit(|mpi_init| {
+                        debug!(
+                            "add_liveness_constraints: location={:?} initialized={:?}",
+                            location,
+                            &self.flow_inits.operator().move_data().move_paths[mpi_init]
+                        );
+                    });
+                }
 
                 let mpi = self.move_data.rev_lookup.find_local(live_local);
                 if let Some(initialized_child) = self.flow_inits.has_any_child_of(mpi) {
index f6f98f0732e3ae525a96f8b313c75cc00c8d8bf9..f23e10ae5d2d80071fc65fef0780a993eb0d6864 100644 (file)
@@ -523,7 +523,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
             let count = match cx.tcx.at(span).const_eval(cx.param_env.and(global_id)) {
                 Ok(cv) => cv.unwrap_usize(cx.tcx),
                 Err(e) => {
-                    e.report(cx.tcx, cx.tcx.def_span(def_id), "array length");
+                    e.report_as_error(cx.tcx.at(span), "could not evaluate array length");
                     0
                 },
             };
index 0a1139700984d13ca580404a6f37c43a7588305c..7cef8a75aa6baf90d881b038c6a06ca43a55baba 100644 (file)
@@ -141,13 +141,13 @@ fn report_inlining_errors(&self, pat_span: Span) {
                 PatternError::FloatBug => {
                     // FIXME(#31407) this is only necessary because float parsing is buggy
                     ::rustc::middle::const_val::struct_error(
-                        self.tcx, pat_span,
+                        self.tcx.at(pat_span),
                         "could not evaluate float literal (see issue #31407)",
                     ).emit();
                 }
                 PatternError::NonConstPath(span) => {
                     ::rustc::middle::const_val::struct_error(
-                        self.tcx, span,
+                        self.tcx.at(span),
                         "runtime values cannot be referenced in patterns",
                     ).emit();
                 }
index 4cfe74413dfa5b2d1a7c3fc101d296610cca2348..7dae79530c488d6a8abba1111479e831729fe9c4 100644 (file)
@@ -695,7 +695,10 @@ fn lower_path(&mut self,
                                 return self.const_to_pat(instance, value, id, span)
                             },
                             Err(err) => {
-                                err.report(self.tcx, span, "pattern");
+                                err.report_as_error(
+                                    self.tcx.at(span),
+                                    "could not evaluate constant pattern",
+                                );
                                 PatternKind::Wild
                             },
                         }
index 44832df824064a769d063eb897a2a1efc7a63c12..3fcf1b5c8ed599e84d4b442cbf67ed7e63536f06 100644 (file)
@@ -65,34 +65,12 @@ pub fn eval_promoted<'a, 'mir, 'tcx>(
     cid: GlobalId<'tcx>,
     mir: &'mir mir::Mir<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-) -> Option<(Value, Scalar, Ty<'tcx>)> {
+) -> EvalResult<'tcx, (Value, Scalar, Ty<'tcx>)> {
     ecx.with_fresh_body(|ecx| {
-        let res = eval_body_using_ecx(ecx, cid, Some(mir), param_env);
-        match res {
-            Ok(val) => Some(val),
-            Err(mut err) => {
-                ecx.report(&mut err, false, None);
-                None
-            }
-        }
+        eval_body_using_ecx(ecx, cid, Some(mir), param_env)
     })
 }
 
-pub fn eval_body<'a, 'tcx>(
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    cid: GlobalId<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-) -> Option<(Value, Scalar, Ty<'tcx>)> {
-    let (res, ecx) = eval_body_and_ecx(tcx, cid, None, param_env);
-    match res {
-        Ok(val) => Some(val),
-        Err(mut err) => {
-            ecx.report(&mut err, true, None);
-            None
-        }
-    }
-}
-
 pub fn value_to_const_value<'tcx>(
     ecx: &EvalContext<'_, '_, 'tcx, CompileTimeEvaluator>,
     val: Value,
@@ -124,9 +102,17 @@ pub fn value_to_const_value<'tcx>(
     })();
     match val {
         Ok(val) => ty::Const::from_const_value(ecx.tcx.tcx, val, ty),
-        Err(mut err) => {
-            ecx.report(&mut err, true, None);
-            bug!("miri error occured when converting Value to ConstValue")
+        Err(err) => {
+            let (frames, span) = ecx.generate_stacktrace(None);
+            let err = ConstEvalErr {
+                span,
+                kind: ErrKind::Miri(err, frames).into(),
+            };
+            err.report_as_error(
+                ecx.tcx,
+                "failed to convert Value to ConstValue, this is a bug",
+            );
+            span_bug!(span, "miri error occured when converting Value to ConstValue")
         }
     }
 }
@@ -578,16 +564,17 @@ pub fn const_eval_provider<'a, 'tcx>(
             val = ecx.try_read_by_ref(val, miri_ty)?;
         }
         Ok(value_to_const_value(&ecx, val, miri_ty))
-    }).map_err(|mut err| {
-        if tcx.is_static(def_id).is_some() {
-            ecx.report(&mut err, true, None);
-        }
+    }).map_err(|err| {
         let (trace, span) = ecx.generate_stacktrace(None);
         let err = ErrKind::Miri(err, trace);
-        ConstEvalErr {
+        let err = ConstEvalErr {
             kind: err.into(),
             span,
+        };
+        if tcx.is_static(def_id).is_some() {
+            err.report_as_error(ecx.tcx, "could not evaluate static initializer");
         }
+        err
     })
 }
 
index 632f7abfdb499bc7ac3d0918e4f9c7d70ed7cba6..3e91fa72cae58c0903f7b4f90c283a260c98ee61 100644 (file)
@@ -3,7 +3,7 @@
 use rustc::hir::def_id::DefId;
 use rustc::hir::def::Def;
 use rustc::hir::map::definitions::DefPathData;
-use rustc::middle::const_val::{ConstVal, ErrKind};
+use rustc::middle::const_val::ConstVal;
 use rustc::mir;
 use rustc::ty::layout::{self, Size, Align, HasDataLayout, IntegerExt, LayoutOf, TyLayout};
 use rustc::ty::subst::{Subst, Substs};
@@ -15,7 +15,7 @@
 use syntax::ast::Mutability;
 use rustc::mir::interpret::{
     GlobalId, Value, Scalar,
-    EvalError, EvalResult, EvalErrorKind, Pointer, ConstValue,
+    EvalResult, EvalErrorKind, Pointer, ConstValue,
 };
 use std::mem;
 
@@ -1056,15 +1056,7 @@ pub fn const_eval(&self, gid: GlobalId<'tcx>) -> EvalResult<'tcx, &'tcx ty::Cons
         } else {
             self.param_env
         };
-        self.tcx.const_eval(param_env.and(gid)).map_err(|err| match *err.kind {
-            ErrKind::Miri(ref err, _) => match err.kind {
-                EvalErrorKind::TypeckError |
-                EvalErrorKind::Layout(_) => EvalErrorKind::TypeckError.into(),
-                _ => EvalErrorKind::ReferencedConstant.into(),
-            },
-            ErrKind::TypeckError => EvalErrorKind::TypeckError.into(),
-            ref other => bug!("const eval returned {:?}", other),
-        })
+        self.tcx.const_eval(param_env.and(gid)).map_err(|err| EvalErrorKind::ReferencedConstant(err).into())
     }
 
     pub fn force_allocation(&mut self, place: Place) -> EvalResult<'tcx, Place> {
@@ -1626,7 +1618,7 @@ pub fn generate_stacktrace(&self, explicit_span: Option<Span>) -> (Vec<FrameInfo
         let mut last_span = None;
         let mut frames = Vec::new();
         // skip 1 because the last frame is just the environment of the constant
-        for &Frame { instance, span, .. } in self.stack().iter().skip(1).rev() {
+        for &Frame { instance, span, mir, block, stmt, .. } in self.stack().iter().skip(1).rev() {
             // make sure we don't emit frames that are duplicates of the previous
             if explicit_span == Some(span) {
                 last_span = Some(span);
@@ -1644,82 +1636,20 @@ pub fn generate_stacktrace(&self, explicit_span: Option<Span>) -> (Vec<FrameInfo
             } else {
                 instance.to_string()
             };
-            frames.push(FrameInfo { span, location });
-        }
-        trace!("generate stacktrace: {:#?}, {:?}", frames, explicit_span);
-        (frames, self.tcx.span)
-    }
-
-    pub fn report(&self, e: &mut EvalError, as_err: bool, explicit_span: Option<Span>) {
-        match e.kind {
-            EvalErrorKind::Layout(_) |
-            EvalErrorKind::TypeckError => return,
-            _ => {},
-        }
-        if let Some(ref mut backtrace) = e.backtrace {
-            let mut trace_text = "\n\nAn error occurred in miri:\n".to_string();
-            backtrace.resolve();
-            write!(trace_text, "backtrace frames: {}\n", backtrace.frames().len()).unwrap();
-            'frames: for (i, frame) in backtrace.frames().iter().enumerate() {
-                if frame.symbols().is_empty() {
-                    write!(trace_text, "{}: no symbols\n", i).unwrap();
-                }
-                for symbol in frame.symbols() {
-                    write!(trace_text, "{}: ", i).unwrap();
-                    if let Some(name) = symbol.name() {
-                        write!(trace_text, "{}\n", name).unwrap();
-                    } else {
-                        write!(trace_text, "<unknown>\n").unwrap();
-                    }
-                    write!(trace_text, "\tat ").unwrap();
-                    if let Some(file_path) = symbol.filename() {
-                        write!(trace_text, "{}", file_path.display()).unwrap();
-                    } else {
-                        write!(trace_text, "<unknown_file>").unwrap();
-                    }
-                    if let Some(line) = symbol.lineno() {
-                        write!(trace_text, ":{}\n", line).unwrap();
-                    } else {
-                        write!(trace_text, "\n").unwrap();
-                    }
-                }
-            }
-            error!("{}", trace_text);
-        }
-        if let Some(frame) = self.stack().last() {
-            let block = &frame.mir.basic_blocks()[frame.block];
-            let span = explicit_span.unwrap_or_else(|| if frame.stmt < block.statements.len() {
-                block.statements[frame.stmt].source_info.span
-            } else {
-                block.terminator().source_info.span
-            });
-            trace!("reporting const eval failure at {:?}", span);
-            let mut err = if as_err {
-                ::rustc::middle::const_val::struct_error(*self.tcx, span, "constant evaluation error")
+            let block = &mir.basic_blocks()[block];
+            let source_info = if stmt < block.statements.len() {
+                block.statements[stmt].source_info
             } else {
-                let node_id = self
-                    .stack()
-                    .iter()
-                    .rev()
-                    .filter_map(|frame| self.tcx.hir.as_local_node_id(frame.instance.def_id()))
-                    .next()
-                    .expect("some part of a failing const eval must be local");
-                self.tcx.struct_span_lint_node(
-                    ::rustc::lint::builtin::CONST_ERR,
-                    node_id,
-                    span,
-                    "constant evaluation error",
-                )
+                block.terminator().source_info
             };
-            let (frames, span) = self.generate_stacktrace(explicit_span);
-            err.span_label(span, e.to_string());
-            for FrameInfo { span, location } in frames {
-                err.span_note(span, &format!("inside call to `{}`", location));
-            }
-            err.emit();
-        } else {
-            self.tcx.sess.err(&e.to_string());
+            let lint_root = match mir.source_scope_local_data {
+                mir::ClearCrossCrate::Set(ref ivs) => Some(ivs[source_info.scope].lint_root),
+                mir::ClearCrossCrate::Clear => None,
+            };
+            frames.push(FrameInfo { span, location, lint_root });
         }
+        trace!("generate stacktrace: {:#?}, {:?}", frames, explicit_span);
+        (frames, self.tcx.span)
     }
 
     pub fn sign_extend(&self, value: u128, ty: Ty<'tcx>) -> EvalResult<'tcx, u128> {
index dc56de47fbf63c902d4bd1d1bded7f98980aa6ab..ec308c2193d567bcecc937af5a7f3fd24084850a 100644 (file)
@@ -7,7 +7,7 @@
 use rustc::ty::maps::TyCtxtAt;
 use rustc::ty::layout::{self, Align, TargetDataLayout, Size};
 use syntax::ast::Mutability;
-use rustc::middle::const_val::{ConstVal, ErrKind};
+use rustc::middle::const_val::ConstVal;
 
 use rustc_data_structures::fx::{FxHashSet, FxHashMap};
 use rustc::mir::interpret::{Pointer, AllocId, Allocation, AccessKind, Value,
@@ -285,16 +285,10 @@ fn const_eval_static(&self, def_id: DefId) -> EvalResult<'tcx, &'tcx Allocation>
             instance,
             promoted: None,
         };
-        self.tcx.const_eval(ParamEnv::reveal_all().and(gid)).map_err(|err| {
-            match *err.kind {
-                ErrKind::Miri(ref err, _) => match err.kind {
-                    EvalErrorKind::TypeckError |
-                    EvalErrorKind::Layout(_) => EvalErrorKind::TypeckError.into(),
-                    _ => EvalErrorKind::ReferencedConstant.into(),
-                },
-                ErrKind::TypeckError => EvalErrorKind::TypeckError.into(),
-                ref other => bug!("const eval returned {:?}", other),
-            }
+        self.tcx.const_eval(ParamEnv::reveal_all().and(gid)).map_err(|_| {
+            // no need to report anything, the const_eval call takes care of that for statics
+            assert!(self.tcx.is_static(def_id).is_some());
+            EvalErrorKind::TypeckError.into()
         }).map(|val| {
             let const_val = match val.val {
                 ConstVal::Value(val) => val,
index b5b4ac6df6b5e00caef78f555e1f8ec56d294556..3afcd6f2d9bb562bd4af5ce4d8c3ef60288c7aa8 100644 (file)
@@ -21,7 +21,6 @@
 pub use self::const_eval::{
     eval_promoted,
     mk_borrowck_eval_cx,
-    eval_body,
     CompileTimeEvaluator,
     const_value_to_allocation_provider,
     const_eval_provider,
index c1bcffe7e9aa5812b2956a61a9b7360f24a1a29f..51b33fa54b249e517d44f2674b704d66ddb42ab8 100644 (file)
@@ -120,7 +120,7 @@ pub fn read_field(
         variant: Option<usize>,
         field: mir::Field,
         base_ty: Ty<'tcx>,
-    ) -> EvalResult<'tcx, Option<(Value, Ty<'tcx>)>> {
+    ) -> EvalResult<'tcx, ValTy<'tcx>> {
         let mut base_layout = self.layout_of(base_ty)?;
         if let Some(variant_index) = variant {
             base_layout = base_layout.for_variant(self, variant_index);
@@ -128,21 +128,34 @@ pub fn read_field(
         let field_index = field.index();
         let field = base_layout.field(self, field_index)?;
         if field.size.bytes() == 0 {
-            return Ok(Some((Value::Scalar(Scalar::undef()), field.ty)))
+            return Ok(ValTy {
+                value: Value::Scalar(Scalar::undef()),
+                ty: field.ty,
+            });
         }
         let offset = base_layout.fields.offset(field_index);
-        match base {
+        let value = match base {
             // the field covers the entire type
             Value::ScalarPair(..) |
-            Value::Scalar(_) if offset.bytes() == 0 && field.size == base_layout.size => Ok(Some((base, field.ty))),
-            // split fat pointers, 2 element tuples, ...
-            Value::ScalarPair(a, b) if base_layout.fields.count() == 2 => {
-                let val = [a, b][field_index];
-                Ok(Some((Value::Scalar(val), field.ty)))
+            Value::Scalar(_) if offset.bytes() == 0 && field.size == base_layout.size => base,
+            // extract fields from types with `ScalarPair` ABI
+            Value::ScalarPair(a, b) => {
+                let val = if offset.bytes() == 0 { a } else { b };
+                Value::Scalar(val)
             },
-            // FIXME(oli-obk): figure out whether we should be calling `try_read_value` here
-            _ => Ok(None),
-        }
+            Value::ByRef(base_ptr, align) => {
+                let offset = base_layout.fields.offset(field_index);
+                let ptr = base_ptr.ptr_offset(offset, self)?;
+                let align = align.min(base_layout.align).min(field.align);
+                assert!(!field.is_unsized());
+                Value::ByRef(ptr, align)
+            },
+            Value::Scalar(val) => bug!("field access on non aggregate {:?}, {:?}", val, base_ty),
+        };
+        Ok(ValTy {
+            value,
+            ty: field.ty,
+        })
     }
 
     fn try_read_place_projection(
@@ -156,7 +169,7 @@ fn try_read_place_projection(
         };
         let base_ty = self.place_ty(&proj.base);
         match proj.elem {
-            Field(field, _) => Ok(self.read_field(base, None, field, base_ty)?.map(|(f, _)| f)),
+            Field(field, _) => Ok(Some(self.read_field(base, None, field, base_ty)?.value)),
             // The NullablePointer cases should work fine, need to take care for normal enums
             Downcast(..) |
             Subslice { .. } |
index 9151bfbdd1b3c57cc7757dc806e98f272cf4de35..2994b1b387f3fa37c2e47a3621246da76bfbaef9 100644 (file)
@@ -4,7 +4,7 @@
 use syntax::codemap::Span;
 use rustc_target::spec::abi::Abi;
 
-use rustc::mir::interpret::{EvalResult, Scalar, Value};
+use rustc::mir::interpret::EvalResult;
 use super::{EvalContext, Place, Machine, ValTy};
 
 use rustc_data_structures::indexed_vec::Idx;
@@ -338,65 +338,17 @@ fn eval_fn_call(
 
                         // unpack and write all other args
                         let layout = self.layout_of(args[1].ty)?;
-                        if let ty::TyTuple(..) = args[1].ty.sty {
+                        if let ty::TyTuple(_) = args[1].ty.sty {
+                            if layout.is_zst() {
+                                // Nothing to do, no need to unpack zsts
+                                return Ok(());
+                            }
                             if self.frame().mir.args_iter().count() == layout.fields.count() + 1 {
-                                match args[1].value {
-                                    Value::ByRef(ptr, align) => {
-                                        for (i, arg_local) in arg_locals.enumerate() {
-                                            let field = layout.field(&self, i)?;
-                                            let offset = layout.fields.offset(i);
-                                            let arg = Value::ByRef(ptr.ptr_offset(offset, &self)?,
-                                                                   align.min(field.align));
-                                            let dest =
-                                                self.eval_place(&mir::Place::Local(arg_local))?;
-                                            trace!(
-                                                "writing arg {:?} to {:?} (type: {})",
-                                                arg,
-                                                dest,
-                                                field.ty
-                                            );
-                                            let valty = ValTy {
-                                                value: arg,
-                                                ty: field.ty,
-                                            };
-                                            self.write_value(valty, dest)?;
-                                        }
-                                    }
-                                    Value::Scalar(Scalar::Bits { defined: 0, .. }) => {}
-                                    other => {
-                                        trace!("{:#?}, {:#?}", other, layout);
-                                        let mut layout = layout;
-                                        'outer: loop {
-                                            for i in 0..layout.fields.count() {
-                                                let field = layout.field(&self, i)?;
-                                                if layout.fields.offset(i).bytes() == 0 && layout.size == field.size {
-                                                    layout = field;
-                                                    continue 'outer;
-                                                }
-                                            }
-                                            break;
-                                        }
-                                        {
-                                            let mut write_next = |value| {
-                                                let dest = self.eval_place(&mir::Place::Local(
-                                                    arg_locals.next().unwrap(),
-                                                ))?;
-                                                let valty = ValTy {
-                                                    value: Value::Scalar(value),
-                                                    ty: layout.ty,
-                                                };
-                                                self.write_value(valty, dest)
-                                            };
-                                            match other {
-                                                Value::Scalar(value) | Value::ScalarPair(value, _) => write_next(value)?,
-                                                _ => unreachable!(),
-                                            }
-                                            if let Value::ScalarPair(_, value) = other {
-                                                write_next(value)?;
-                                            }
-                                        }
-                                        assert!(arg_locals.next().is_none());
-                                    }
+                                for (i, arg_local) in arg_locals.enumerate() {
+                                    let field = mir::Field::new(i);
+                                    let valty = self.read_field(args[1].value, None, field, args[1].ty)?;
+                                    let dest = self.eval_place(&mir::Place::Local(arg_local))?;
+                                    self.write_value(valty, dest)?;
                                 }
                             } else {
                                 trace!("manual impl of rust-call ABI");
index a8a50e14c68225788edd9876d45513015c9ee4f4..a8a50c50f592e844ca5468bba3bd7d6e179bed00 100644 (file)
@@ -388,7 +388,10 @@ fn collect_items_rec<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 Ok(val) => collect_const(tcx, val, instance.substs, &mut neighbors),
                 Err(err) => {
                     let span = tcx.def_span(def_id);
-                    err.report(tcx, span, "static");
+                    err.report_as_error(
+                        tcx.at(span),
+                        "could not evaluate static initializer",
+                    );
                 }
             }
         }
@@ -1187,13 +1190,25 @@ fn collect_neighbours<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let param_env = ty::ParamEnv::reveal_all();
     for i in 0..mir.promoted.len() {
         use rustc_data_structures::indexed_vec::Idx;
+        let i = Promoted::new(i);
         let cid = GlobalId {
             instance,
-            promoted: Some(Promoted::new(i)),
+            promoted: Some(i),
         };
         match tcx.const_eval(param_env.and(cid)) {
             Ok(val) => collect_const(tcx, val, instance.substs, output),
-            Err(_) => {},
+            Err(err) => {
+                use rustc::middle::const_val::ErrKind;
+                use rustc::mir::interpret::EvalErrorKind;
+                if let ErrKind::Miri(ref miri, ..) = *err.kind {
+                    if let EvalErrorKind::ReferencedConstant(_) = miri.kind {
+                        err.report_as_error(
+                            tcx.at(mir.promoted[i].span),
+                            "erroneous constant used",
+                        );
+                    }
+                }
+            },
         }
     }
 }
@@ -1236,7 +1251,10 @@ fn collect_const<'a, 'tcx>(
                 Ok(val) => val.val,
                 Err(err) => {
                     let span = tcx.def_span(def_id);
-                    err.report(tcx, span, "constant");
+                    err.report_as_error(
+                        tcx.at(span),
+                        "constant evaluation error",
+                    );
                     return;
                 }
             }
index ef61fe099bfb1a35a5372cc416b799c042aad9ba..24382815084619dee7a74c01d18979e26b5309a1 100644 (file)
@@ -17,7 +17,7 @@
 use rustc::mir::{NullOp, StatementKind, Statement, BasicBlock, LocalKind};
 use rustc::mir::{TerminatorKind, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem};
 use rustc::mir::visit::{Visitor, PlaceContext};
-use rustc::middle::const_val::ConstVal;
+use rustc::middle::const_val::{ConstVal, ConstEvalErr, ErrKind};
 use rustc::ty::{TyCtxt, self, Instance};
 use rustc::mir::interpret::{Value, Scalar, GlobalId, EvalResult};
 use interpret::EvalContext;
@@ -29,7 +29,7 @@
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc::ty::ParamEnv;
 use rustc::ty::layout::{
-    LayoutOf, TyLayout, LayoutError, LayoutCx,
+    LayoutOf, TyLayout, LayoutError,
     HasTyCtxt, TargetDataLayout, HasDataLayout,
 };
 
@@ -121,17 +121,37 @@ fn new(
 
     fn use_ecx<F, T>(
         &mut self,
-        span: Span,
+        source_info: SourceInfo,
         f: F
     ) -> Option<T>
     where
         F: FnOnce(&mut Self) -> EvalResult<'tcx, T>,
     {
-        self.ecx.tcx.span = span;
+        self.ecx.tcx.span = source_info.span;
+        let lint_root = match self.mir.source_scope_local_data {
+            ClearCrossCrate::Set(ref ivs) => {
+                use rustc_data_structures::indexed_vec::Idx;
+                //FIXME(#51314): remove this check
+                if source_info.scope.index() >= ivs.len() {
+                    return None;
+                }
+                ivs[source_info.scope].lint_root
+            },
+            ClearCrossCrate::Clear => return None,
+        };
         let r = match f(self) {
             Ok(val) => Some(val),
-            Err(mut err) => {
-                self.ecx.report(&mut err, false, Some(span));
+            Err(err) => {
+                let (frames, span) = self.ecx.generate_stacktrace(None);
+                let err = ConstEvalErr {
+                    span,
+                    kind: ErrKind::Miri(err, frames).into(),
+                };
+                err.report_as_lint(
+                    self.ecx.tcx,
+                    "this expression will panic at runtime",
+                    lint_root,
+                );
                 None
             },
         };
@@ -139,30 +159,37 @@ fn use_ecx<F, T>(
         r
     }
 
-    fn const_eval(&mut self, cid: GlobalId<'tcx>, span: Span) -> Option<Const<'tcx>> {
+    fn const_eval(&mut self, cid: GlobalId<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
         let value = match self.tcx.const_eval(self.param_env.and(cid)) {
             Ok(val) => val,
             Err(err) => {
-                err.report(self.tcx, err.span, "constant propagated");
+                err.report_as_error(
+                    self.tcx.at(err.span),
+                    "constant evaluation error",
+                );
                 return None;
             },
         };
         let val = match value.val {
             ConstVal::Value(v) => {
-                self.use_ecx(span, |this| this.ecx.const_value_to_value(v, value.ty))?
+                self.use_ecx(source_info, |this| this.ecx.const_value_to_value(v, value.ty))?
             },
             _ => bug!("eval produced: {:?}", value),
         };
-        let val = (val, value.ty, span);
+        let val = (val, value.ty, source_info.span);
         trace!("evaluated {:?} to {:?}", cid, val);
         Some(val)
     }
 
-    fn eval_constant(&mut self, c: &Constant<'tcx>) -> Option<Const<'tcx>> {
+    fn eval_constant(
+        &mut self,
+        c: &Constant<'tcx>,
+        source_info: SourceInfo,
+    ) -> Option<Const<'tcx>> {
         match c.literal {
             Literal::Value { value } => match value.val {
                 ConstVal::Value(v) => {
-                    let v = self.use_ecx(c.span, |this| {
+                    let v = self.use_ecx(source_info, |this| {
                         this.ecx.const_value_to_value(v, value.ty)
                     })?;
                     Some((v, value.ty, c.span))
@@ -178,7 +205,7 @@ fn eval_constant(&mut self, c: &Constant<'tcx>) -> Option<Const<'tcx>> {
                         instance,
                         promoted: None,
                     };
-                    self.const_eval(cid, c.span)
+                    self.const_eval(cid, source_info)
                 },
             },
             // evaluate the promoted and replace the constant with the evaluated result
@@ -196,10 +223,9 @@ fn eval_constant(&mut self, c: &Constant<'tcx>) -> Option<Const<'tcx>> {
                 };
                 // cannot use `const_eval` here, because that would require having the MIR
                 // for the current function available, but we're producing said MIR right now
-                let span = self.mir.span;
-                let (value, _, ty) = self.use_ecx(span, |this| {
-                    Ok(eval_promoted(&mut this.ecx, cid, this.mir, this.param_env))
-                })??;
+                let (value, _, ty) = self.use_ecx(source_info, |this| {
+                    eval_promoted(&mut this.ecx, cid, this.mir, this.param_env)
+                })?;
                 let val = (value, ty, c.span);
                 trace!("evaluated {:?} to {:?}", c, val);
                 Some(val)
@@ -207,31 +233,17 @@ fn eval_constant(&mut self, c: &Constant<'tcx>) -> Option<Const<'tcx>> {
         }
     }
 
-    fn eval_place(&mut self, place: &Place<'tcx>) -> Option<Const<'tcx>> {
+    fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
         match *place {
             Place::Local(loc) => self.places[loc].clone(),
             Place::Projection(ref proj) => match proj.elem {
                 ProjectionElem::Field(field, _) => {
                     trace!("field proj on {:?}", proj.base);
-                    let (base, ty, span) = self.eval_place(&proj.base)?;
-                    match base {
-                        Value::ScalarPair(a, b) => {
-                            trace!("by val pair: {:?}, {:?}", a, b);
-                            let base_layout = self.tcx.layout_of(self.param_env.and(ty)).ok()?;
-                            trace!("layout computed");
-                            use rustc_data_structures::indexed_vec::Idx;
-                            let field_index = field.index();
-                            let val = [a, b][field_index];
-                            let cx = LayoutCx {
-                                tcx: self.tcx,
-                                param_env: self.param_env,
-                            };
-                            let field = base_layout.field(cx, field_index).ok()?;
-                            trace!("projection resulted in: {:?}", val);
-                            Some((Value::Scalar(val), field.ty, span))
-                        },
-                        _ => None,
-                    }
+                    let (base, ty, span) = self.eval_place(&proj.base, source_info)?;
+                    let valty = self.use_ecx(source_info, |this| {
+                        this.ecx.read_field(base, None, field, ty)
+                    })?;
+                    Some((valty.value, valty.ty, span))
                 },
                 _ => None,
             },
@@ -239,10 +251,11 @@ fn eval_place(&mut self, place: &Place<'tcx>) -> Option<Const<'tcx>> {
         }
     }
 
-    fn eval_operand(&mut self, op: &Operand<'tcx>) -> Option<Const<'tcx>> {
+    fn eval_operand(&mut self, op: &Operand<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
         match *op {
-            Operand::Constant(ref c) => self.eval_constant(c),
-            Operand::Move(ref place) | Operand::Copy(ref place) => self.eval_place(place),
+            Operand::Constant(ref c) => self.eval_constant(c, source_info),
+            | Operand::Move(ref place)
+            | Operand::Copy(ref place) => self.eval_place(place, source_info),
         }
     }
 
@@ -254,23 +267,13 @@ fn const_prop(
     ) -> Option<Const<'tcx>> {
         let span = source_info.span;
         match *rvalue {
-            // No need to overwrite an already evaluated constant
-            Rvalue::Use(Operand::Constant(box Constant {
-                literal: Literal::Value {
-                    value: &ty::Const {
-                        val: ConstVal::Value(_),
-                        ..
-                    },
-                },
-                ..
-            })) => None,
             // This branch exists for the sanity type check
             Rvalue::Use(Operand::Constant(ref c)) => {
                 assert_eq!(c.ty, place_ty);
-                self.eval_constant(c)
+                self.eval_constant(c, source_info)
             },
             Rvalue::Use(ref op) => {
-                self.eval_operand(op)
+                self.eval_operand(op, source_info)
             },
             Rvalue::Repeat(..) |
             Rvalue::Ref(..) |
@@ -303,17 +306,17 @@ fn const_prop(
                     return None;
                 }
 
-                let val = self.eval_operand(arg)?;
-                let prim = self.use_ecx(span, |this| {
+                let val = self.eval_operand(arg, source_info)?;
+                let prim = self.use_ecx(source_info, |this| {
                     this.ecx.value_to_scalar(ValTy { value: val.0, ty: val.1 })
                 })?;
-                let val = self.use_ecx(span, |this| this.ecx.unary_op(op, prim, val.1))?;
+                let val = self.use_ecx(source_info, |this| this.ecx.unary_op(op, prim, val.1))?;
                 Some((Value::Scalar(val), place_ty, span))
             }
             Rvalue::CheckedBinaryOp(op, ref left, ref right) |
             Rvalue::BinaryOp(op, ref left, ref right) => {
                 trace!("rvalue binop {:?} for {:?} and {:?}", op, left, right);
-                let right = self.eval_operand(right)?;
+                let right = self.eval_operand(right, source_info)?;
                 let def_id = if self.tcx.is_closure(self.source.def_id) {
                     self.tcx.closure_base_def_id(self.source.def_id)
                 } else {
@@ -325,7 +328,7 @@ fn const_prop(
                     return None;
                 }
 
-                let r = self.use_ecx(span, |this| {
+                let r = self.use_ecx(source_info, |this| {
                     this.ecx.value_to_scalar(ValTy { value: right.0, ty: right.1 })
                 })?;
                 if op == BinOp::Shr || op == BinOp::Shl {
@@ -356,12 +359,12 @@ fn const_prop(
                         return None;
                     }
                 }
-                let left = self.eval_operand(left)?;
-                let l = self.use_ecx(span, |this| {
+                let left = self.eval_operand(left, source_info)?;
+                let l = self.use_ecx(source_info, |this| {
                     this.ecx.value_to_scalar(ValTy { value: left.0, ty: left.1 })
                 })?;
                 trace!("const evaluating {:?} for {:?} and {:?}", op, left, right);
-                let (val, overflow) = self.use_ecx(span, |this| {
+                let (val, overflow) = self.use_ecx(source_info, |this| {
                     this.ecx.binary_op(op, l, left.1, r, right.1)
                 })?;
                 let val = if let Rvalue::CheckedBinaryOp(..) = *rvalue {
@@ -372,11 +375,8 @@ fn const_prop(
                 } else {
                     if overflow {
                         use rustc::mir::interpret::EvalErrorKind;
-                        let mut err = EvalErrorKind::Overflow(op).into();
-                        self.use_ecx(span, |this| {
-                            this.ecx.report(&mut err, false, Some(span));
-                            Ok(())
-                        });
+                        let err = EvalErrorKind::Overflow(op).into();
+                        let _: Option<()> = self.use_ecx(source_info, |_| Err(err));
                         return None;
                     }
                     Value::Scalar(val)
@@ -455,7 +455,8 @@ fn visit_constant(
     ) {
         trace!("visit_constant: {:?}", constant);
         self.super_constant(constant, location);
-        self.eval_constant(constant);
+        let source_info = *self.mir.source_info(location);
+        self.eval_constant(constant, source_info);
     }
 
     fn visit_statement(
@@ -490,8 +491,9 @@ fn visit_terminator_kind(
         location: Location,
     ) {
         self.super_terminator_kind(block, kind, location);
+        let source_info = *self.mir.source_info(location);
         if let TerminatorKind::Assert { expected, msg, cond, .. } = kind {
-            if let Some(value) = self.eval_operand(cond) {
+            if let Some(value) = self.eval_operand(cond, source_info) {
                 trace!("assertion on {:?} should be {:?}", value, expected);
                 if Value::Scalar(Scalar::from_bool(*expected)) != value.0 {
                     // poison all places this operand references so that further code
@@ -526,13 +528,15 @@ fn visit_terminator_kind(
                         DivisionByZero |
                         RemainderByZero => msg.description().to_owned(),
                         BoundsCheck { ref len, ref index } => {
-                            let len = self.eval_operand(len).expect("len must be const");
+                            let len = self
+                                .eval_operand(len, source_info)
+                                .expect("len must be const");
                             let len = match len.0 {
                                 Value::Scalar(Scalar::Bits { bits, ..}) => bits,
                                 _ => bug!("const len not primitive: {:?}", len),
                             };
                             let index = self
-                                .eval_operand(index)
+                                .eval_operand(index, source_info)
                                 .expect("index must be const");
                             let index = match index.0 {
                                 Value::Scalar(Scalar::Bits { bits, .. }) => bits,
index 453627f3c36b99636308526bbdc1b1f520764287..7bb7f2fffbc694e165c47364243619d7b5a2d038 100644 (file)
@@ -2934,8 +2934,38 @@ fn smart_resolve_path_fragment(&mut self,
                                                               here due to private fields"));
                             }
                         } else {
-                            err.span_label(span, format!("did you mean `{} {{ /* fields */ }}`?",
-                                                         path_str));
+                            // HACK(estebank): find a better way to figure out that this was a
+                            // parser issue where a struct literal is being used on an expression
+                            // where a brace being opened means a block is being started. Look
+                            // ahead for the next text to see if `span` is followed by a `{`.
+                            let cm = this.session.codemap();
+                            let mut sp = span;
+                            loop {
+                                sp = cm.next_point(sp);
+                                match cm.span_to_snippet(sp) {
+                                    Ok(ref snippet) => {
+                                        if snippet.chars().any(|c| { !c.is_whitespace() }) {
+                                            break;
+                                        }
+                                    }
+                                    _ => break,
+                                }
+                            }
+                            let followed_by_brace = match cm.span_to_snippet(sp) {
+                                Ok(ref snippet) if snippet == "{" => true,
+                                _ => false,
+                            };
+                            if let (PathSource::Expr(None), true) = (source, followed_by_brace) {
+                                err.span_label(
+                                    span,
+                                    format!("did you mean `({} {{ /* fields */ }})`?", path_str),
+                                );
+                            } else {
+                                err.span_label(
+                                    span,
+                                    format!("did you mean `{} {{ /* fields */ }}`?", path_str),
+                                );
+                            }
                         }
                         return (err, candidates);
                     }
index c44f330128a2323cf28b69c5be869ccef4746b49..3fdac8f6afdc4149400edcd960147fcaeb86ee18 100644 (file)
 use {resolve_error, ResolutionError};
 
 use rustc::ty;
-use rustc::lint::builtin::PUB_USE_OF_PRIVATE_EXTERN_CRATE;
+use rustc::lint::builtin::BuiltinLintDiagnostics;
+use rustc::lint::builtin::{DUPLICATE_MACRO_EXPORTS, PUB_USE_OF_PRIVATE_EXTERN_CRATE};
 use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
 use rustc::hir::def::*;
 use rustc::session::DiagnosticMessageId;
 use rustc::util::nodemap::{FxHashMap, FxHashSet};
 
-use syntax::ast::{Ident, Name, NodeId};
+use syntax::ast::{Ident, Name, NodeId, CRATE_NODE_ID};
 use syntax::ext::base::Determinacy::{self, Determined, Undetermined};
 use syntax::ext::hygiene::Mark;
 use syntax::symbol::keywords;
@@ -974,7 +975,16 @@ fn finalize_resolutions_in(&mut self, module: Module<'b>) {
         if module as *const _ == self.graph_root as *const _ {
             let macro_exports = mem::replace(&mut self.macro_exports, Vec::new());
             for export in macro_exports.into_iter().rev() {
-                if exported_macro_names.insert(export.ident.modern(), export.span).is_none() {
+                if let Some(later_span) = exported_macro_names.insert(export.ident.modern(),
+                                                                      export.span) {
+                    self.session.buffer_lint_with_diagnostic(
+                        DUPLICATE_MACRO_EXPORTS,
+                        CRATE_NODE_ID,
+                        later_span,
+                        &format!("a macro named `{}` has already been exported", export.ident),
+                        BuiltinLintDiagnostics::DuplicatedMacroExports(
+                            export.ident, export.span, later_span));
+                } else {
                     reexports.push(export);
                 }
             }
index c426533779c9be18721ec458e7114feca16e048f..184cb9826ba680a96152a87e7aee7b942b9a9536 100644 (file)
@@ -13,7 +13,6 @@ test = false
 log = "0.4"
 syntax = { path = "../libsyntax" }
 arena = { path = "../libarena" }
-fmt_macros = { path = "../libfmt_macros" }
 rustc = { path = "../librustc" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_platform_intrinsics = { path = "../librustc_platform_intrinsics" }
index 7ef510f41254f1e19c452f625ffebad608858eab..f29e29c1fb2bf849bf752f9f023da8dfde19bede 100644 (file)
@@ -30,6 +30,7 @@
 use util::nodemap::{FxHashSet, FxHashMap};
 use errors::FatalError;
 
+// use std::cmp::Ordering;
 use std::iter;
 use syntax::ast;
 use syntax::feature_gate::{GateIssue, emit_feature_err};
@@ -646,7 +647,7 @@ fn conv_object_ty_poly_trait_ref(&self,
                                             &mut vec![]);
         }
 
-        let (auto_traits, trait_bounds) = split_auto_traits(tcx, &trait_bounds[1..]);
+        let (mut auto_traits, trait_bounds) = split_auto_traits(tcx, &trait_bounds[1..]);
 
         if !trait_bounds.is_empty() {
             let b = &trait_bounds[0];
@@ -707,6 +708,10 @@ fn conv_object_ty_poly_trait_ref(&self,
                         .emit();
         }
 
+        // Dedup auto traits so that `dyn Trait + Send + Send` is the same as `dyn Trait + Send`.
+        auto_traits.sort();
+        auto_traits.dedup();
+
         // skip_binder is okay, because the predicates are re-bound.
         let mut v =
             iter::once(ty::ExistentialPredicate::Trait(*existential_principal.skip_binder()))
@@ -1319,7 +1324,7 @@ fn compute_object_lifetime_bound(&self,
     }
 }
 
-/// Divides a list of general trait bounds into two groups: builtin bounds (Sync/Send) and the
+/// Divides a list of general trait bounds into two groups: auto traits (e.g. Sync and Send) and the
 /// remaining general trait bounds.
 fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                                          trait_bounds: &'b [hir::PolyTraitRef])
index c2c71d90f06744e30ffaa93589c97e355a4d2ad3..533faadc3a45dce50cbcc6d5157b53d95ce6b514 100644 (file)
@@ -1131,7 +1131,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
 
     // Check that a function marked as `#[panic_implementation]` has signature `fn(&PanicInfo) -> !`
     if let Some(panic_impl_did) = fcx.tcx.lang_items().panic_impl() {
-        if panic_impl_did == fn_hir_id.owner_def_id() {
+        if panic_impl_did == fcx.tcx.hir.local_def_id(fn_id) {
             if let Some(panic_info_did) = fcx.tcx.lang_items().panic_info() {
                 if declared_ret_ty.sty != ty::TyNever {
                     fcx.tcx.sess.span_err(
@@ -4040,7 +4040,10 @@ fn check_expr_kind(&self,
             let count = tcx.const_eval(param_env.and(global_id));
 
             if let Err(ref err) = count {
-                err.report(tcx, tcx.def_span(count_def_id), "constant expression");
+                err.report_as_error(
+                    tcx.at(tcx.def_span(count_def_id)),
+                    "could not evaluate repeat length",
+                );
             }
 
             let uty = match expected {
index 1c1ba208678ed0e418faac4eba8cbd3025321142..3f883eab172db57aa737066a5408409a1ee4b2bc 100644 (file)
@@ -26,7 +26,7 @@
 use syntax::codemap::{dummy_spanned, Spanned};
 use syntax::feature_gate::UnstableFeatures;
 use syntax::ptr::P;
-use syntax::symbol::keywords;
+use syntax::symbol::keywords::{self, Keyword};
 use syntax::symbol::{Symbol, InternedString};
 use syntax_pos::{self, DUMMY_SP, Pos, FileName};
 
@@ -54,6 +54,7 @@
 use std::iter::{FromIterator, once};
 use rustc_data_structures::sync::Lrc;
 use std::rc::Rc;
+use std::str::FromStr;
 use std::cell::RefCell;
 use std::sync::Arc;
 use std::u32;
@@ -177,7 +178,7 @@ fn clean(&self, cx: &DocContext) -> Crate {
             _ => unreachable!(),
         }
 
-        let ExternalCrate { name, src, primitives, .. } = LOCAL_CRATE.clean(cx);
+        let ExternalCrate { name, src, primitives, keywords, .. } = LOCAL_CRATE.clean(cx);
         {
             let m = match module.inner {
                 ModuleItem(ref mut m) => m,
@@ -195,6 +196,18 @@ fn clean(&self, cx: &DocContext) -> Crate {
                     inner: PrimitiveItem(prim),
                 }
             }));
+            m.items.extend(keywords.into_iter().map(|(def_id, kw, attrs)| {
+                Item {
+                    source: Span::empty(),
+                    name: Some(kw.clone()),
+                    attrs: attrs,
+                    visibility: Some(Public),
+                    stability: get_stability(cx, def_id),
+                    deprecation: get_deprecation(cx, def_id),
+                    def_id,
+                    inner: KeywordItem(kw),
+                }
+            }));
         }
 
         let mut access_levels = cx.access_levels.borrow_mut();
@@ -220,6 +233,7 @@ pub struct ExternalCrate {
     pub src: FileName,
     pub attrs: Attributes,
     pub primitives: Vec<(DefId, PrimitiveType, Attributes)>,
+    pub keywords: Vec<(DefId, String, Attributes)>,
 }
 
 impl Clean<ExternalCrate> for CrateNum {
@@ -286,11 +300,53 @@ fn clean(&self, cx: &DocContext) -> ExternalCrate {
               .filter_map(as_primitive).collect()
         };
 
+        let as_keyword = |def: Def| {
+            if let Def::Mod(def_id) = def {
+                let attrs = cx.tcx.get_attrs(def_id).clean(cx);
+                let mut keyword = None;
+                for attr in attrs.lists("doc") {
+                    if let Some(v) = attr.value_str() {
+                        if attr.check_name("keyword") {
+                            keyword = Keyword::from_str(&v.as_str()).ok()
+                                                                    .map(|x| x.name().to_string());
+                            if keyword.is_some() {
+                                break
+                            }
+                            // FIXME: should warn on unknown keywords?
+                        }
+                    }
+                }
+                return keyword.map(|p| (def_id, p, attrs));
+            }
+            None
+        };
+        let keywords = if root.is_local() {
+            cx.tcx.hir.krate().module.item_ids.iter().filter_map(|&id| {
+                let item = cx.tcx.hir.expect_item(id.id);
+                match item.node {
+                    hir::ItemMod(_) => {
+                        as_keyword(Def::Mod(cx.tcx.hir.local_def_id(id.id)))
+                    }
+                    hir::ItemUse(ref path, hir::UseKind::Single)
+                    if item.vis == hir::Visibility::Public => {
+                        as_keyword(path.def).map(|(_, prim, attrs)| {
+                            (cx.tcx.hir.local_def_id(id.id), prim, attrs)
+                        })
+                    }
+                    _ => None
+                }
+            }).collect()
+        } else {
+            cx.tcx.item_children(root).iter().map(|item| item.def)
+              .filter_map(as_keyword).collect()
+        };
+
         ExternalCrate {
             name: cx.tcx.crate_name(*self).to_string(),
             src: krate_src,
             attrs: cx.tcx.get_attrs(root).clean(cx),
             primitives,
+            keywords,
         }
     }
 }
@@ -397,6 +453,9 @@ pub fn is_import(&self) -> bool {
     pub fn is_extern_crate(&self) -> bool {
         self.type_() == ItemType::ExternCrate
     }
+    pub fn is_keyword(&self) -> bool {
+        self.type_() == ItemType::Keyword
+    }
 
     pub fn is_stripped(&self) -> bool {
         match self.inner { StrippedItem(..) => true, _ => false }
@@ -475,6 +534,7 @@ pub enum ItemEnum {
     AssociatedTypeItem(Vec<TyParamBound>, Option<Type>),
     /// An item that has been stripped by a rustdoc pass
     StrippedItem(Box<ItemEnum>),
+    KeywordItem(String),
 }
 
 impl ItemEnum {
@@ -1191,30 +1251,60 @@ fn resolution_failure(
     link_range: Option<Range<usize>>,
 ) {
     let sp = span_of_attrs(attrs);
-    let mut diag = cx.sess()
-        .struct_span_warn(sp, &format!("[{}] cannot be resolved, ignoring it...", path_str));
+    let msg = format!("`[{}]` cannot be resolved, ignoring it...", path_str);
+
+    let code_dox = sp.to_src(cx);
 
-    if let Some(link_range) = link_range {
+    let doc_comment_padding = 3;
+    let mut diag = if let Some(link_range) = link_range {
         // blah blah blah\nblah\nblah [blah] blah blah\nblah blah
         //                       ^    ~~~~~~
         //                       |    link_range
         //                       last_new_line_offset
 
-        let last_new_line_offset = dox[..link_range.start].rfind('\n').map_or(0, |n| n + 1);
-        let line = dox[last_new_line_offset..].lines().next().unwrap_or("");
-
-        // Print the line containing the `link_range` and manually mark it with '^'s
-        diag.note(&format!(
-            "the link appears in this line:\n\n{line}\n{indicator: <before$}{indicator:^<found$}",
-            line=line,
-            indicator="",
-            before=link_range.start - last_new_line_offset,
-            found=link_range.len(),
-        ));
-    } else {
+        let mut diag;
+        if dox.lines().count() == code_dox.lines().count() {
+            let line_offset = dox[..link_range.start].lines().count();
+            // The span starts in the `///`, so we don't have to account for the leading whitespace
+            let code_dox_len = if line_offset <= 1 {
+                doc_comment_padding
+            } else {
+                // The first `///`
+                doc_comment_padding +
+                    // Each subsequent leading whitespace and `///`
+                    code_dox.lines().skip(1).take(line_offset - 1).fold(0, |sum, line| {
+                        sum + doc_comment_padding + line.len() - line.trim().len()
+                    })
+            };
 
-    }
+            // Extract the specific span
+            let sp = sp.from_inner_byte_pos(
+                link_range.start + code_dox_len,
+                link_range.end + code_dox_len,
+            );
 
+            diag = cx.sess().struct_span_warn(sp, &msg);
+            diag.span_label(sp, "cannot be resolved, ignoring");
+        } else {
+            diag = cx.sess().struct_span_warn(sp, &msg);
+
+            let last_new_line_offset = dox[..link_range.start].rfind('\n').map_or(0, |n| n + 1);
+            let line = dox[last_new_line_offset..].lines().next().unwrap_or("");
+
+            // Print the line containing the `link_range` and manually mark it with '^'s
+            diag.note(&format!(
+                "the link appears in this line:\n\n{line}\n\
+                 {indicator: <before$}{indicator:^<found$}",
+                line=line,
+                indicator="",
+                before=link_range.start - last_new_line_offset,
+                found=link_range.len(),
+            ));
+        }
+        diag
+    } else {
+        cx.sess().struct_span_warn(sp, &msg)
+    };
     diag.emit();
 }
 
index 458ed105d2650b04c54cc56658c94988f06cf2b8..bad5ff2596fd3496f2086729a34ffd2288106577 100644 (file)
@@ -230,7 +230,10 @@ pub fn run_core(search_paths: SearchPaths,
 
         let krate = panictry!(driver::phase_1_parse_input(control, &sess, &input));
 
-        let name = ::rustc_codegen_utils::link::find_crate_name(Some(&sess), &krate.attrs, &input);
+        let name = match crate_name {
+            Some(ref crate_name) => crate_name.clone(),
+            None => ::rustc_codegen_utils::link::find_crate_name(Some(&sess), &krate.attrs, &input),
+        };
 
         let mut crate_loader = CrateLoader::new(&sess, &cstore, &name);
 
index 537828de2c7f35fd56bdabc7a4e89b5400c60675..9b8ada1f6e6b29968e9db708499584b8a01ce396 100644 (file)
@@ -42,6 +42,7 @@ pub enum ItemType {
     AssociatedConst = 18,
     Union           = 19,
     ForeignType     = 20,
+    Keyword         = 21,
 }
 
 
@@ -50,6 +51,7 @@ pub enum NameSpace {
     Type,
     Value,
     Macro,
+    Keyword,
 }
 
 impl<'a> From<&'a clean::Item> for ItemType {
@@ -83,6 +85,7 @@ fn from(item: &'a clean::Item) -> ItemType {
             clean::AssociatedConstItem(..) => ItemType::AssociatedConst,
             clean::AssociatedTypeItem(..)  => ItemType::AssociatedType,
             clean::ForeignTypeItem         => ItemType::ForeignType,
+            clean::KeywordItem(..)         => ItemType::Keyword,
             clean::StrippedItem(..)        => unreachable!(),
         }
     }
@@ -131,6 +134,7 @@ pub fn css_class(&self) -> &'static str {
             ItemType::Constant        => "constant",
             ItemType::AssociatedConst => "associatedconstant",
             ItemType::ForeignType     => "foreigntype",
+            ItemType::Keyword         => "keyword",
         }
     }
 
@@ -159,6 +163,8 @@ pub fn name_space(&self) -> NameSpace {
             ItemType::AssociatedConst => NameSpace::Value,
 
             ItemType::Macro => NameSpace::Macro,
+
+            ItemType::Keyword => NameSpace::Keyword,
         }
     }
 }
@@ -172,6 +178,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 pub const NAMESPACE_TYPE: &'static str = "t";
 pub const NAMESPACE_VALUE: &'static str = "v";
 pub const NAMESPACE_MACRO: &'static str = "m";
+pub const NAMESPACE_KEYWORD: &'static str = "k";
 
 impl NameSpace {
     pub fn to_static_str(&self) -> &'static str {
@@ -179,6 +186,7 @@ pub fn to_static_str(&self) -> &'static str {
             NameSpace::Type => NAMESPACE_TYPE,
             NameSpace::Value => NAMESPACE_VALUE,
             NameSpace::Macro => NAMESPACE_MACRO,
+            NameSpace::Keyword => NAMESPACE_KEYWORD,
         }
     }
 }
index 5377cd9a39143a4faeb40298897cc5b595aa6c34..5c2ec2058ee9d703d0723b6cda9c8dc3a6592ee6 100644 (file)
@@ -1541,6 +1541,7 @@ struct AllTypes {
     typedefs: HashSet<ItemEntry>,
     statics: HashSet<ItemEntry>,
     constants: HashSet<ItemEntry>,
+    keywords: HashSet<ItemEntry>,
 }
 
 impl AllTypes {
@@ -1556,6 +1557,7 @@ fn new() -> AllTypes {
             typedefs: HashSet::with_capacity(100),
             statics: HashSet::with_capacity(100),
             constants: HashSet::with_capacity(100),
+            keywords: HashSet::with_capacity(100),
         }
     }
 
@@ -2063,12 +2065,13 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
             clean::StaticItem(..) | clean::ForeignStaticItem(..) => write!(fmt, "Static ")?,
             clean::ConstantItem(..) => write!(fmt, "Constant ")?,
             clean::ForeignTypeItem => write!(fmt, "Foreign Type ")?,
+            clean::KeywordItem(..) => write!(fmt, "Keyword ")?,
             _ => {
                 // We don't generate pages for any other type.
                 unreachable!();
             }
         }
-        if !self.item.is_primitive() {
+        if !self.item.is_primitive() && !self.item.is_keyword() {
             let cur = &self.cx.current;
             let amt = if self.item.is_mod() { cur.len() - 1 } else { cur.len() };
             for (i, component) in cur.iter().enumerate().take(amt) {
@@ -2126,6 +2129,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
                 item_static(fmt, self.cx, self.item, i),
             clean::ConstantItem(ref c) => item_constant(fmt, self.cx, self.item, c),
             clean::ForeignTypeItem => item_foreign_type(fmt, self.cx, self.item),
+            clean::KeywordItem(ref k) => item_keyword(fmt, self.cx, self.item, k),
             _ => {
                 // We don't generate pages for any other type.
                 unreachable!();
@@ -2353,29 +2357,7 @@ fn cmp(i1: &clean::Item, i2: &clean::Item, idx1: usize, idx2: usize) -> Ordering
                 write!(w, "</table>")?;
             }
             curty = myty;
-            let (short, name) = match myty.unwrap() {
-                ItemType::ExternCrate |
-                ItemType::Import          => ("reexports", "Re-exports"),
-                ItemType::Module          => ("modules", "Modules"),
-                ItemType::Struct          => ("structs", "Structs"),
-                ItemType::Union           => ("unions", "Unions"),
-                ItemType::Enum            => ("enums", "Enums"),
-                ItemType::Function        => ("functions", "Functions"),
-                ItemType::Typedef         => ("types", "Type Definitions"),
-                ItemType::Static          => ("statics", "Statics"),
-                ItemType::Constant        => ("constants", "Constants"),
-                ItemType::Trait           => ("traits", "Traits"),
-                ItemType::Impl            => ("impls", "Implementations"),
-                ItemType::TyMethod        => ("tymethods", "Type Methods"),
-                ItemType::Method          => ("methods", "Methods"),
-                ItemType::StructField     => ("fields", "Struct Fields"),
-                ItemType::Variant         => ("variants", "Variants"),
-                ItemType::Macro           => ("macros", "Macros"),
-                ItemType::Primitive       => ("primitives", "Primitive Types"),
-                ItemType::AssociatedType  => ("associated-types", "Associated Types"),
-                ItemType::AssociatedConst => ("associated-consts", "Associated Constants"),
-                ItemType::ForeignType     => ("foreign-types", "Foreign Types"),
-            };
+            let (short, name) = item_ty_to_strs(&myty.unwrap());
             write!(w, "<h2 id='{id}' class='section-header'>\
                        <a href=\"#{id}\">{name}</a></h2>\n<table>",
                    id = derive_id(short.to_owned()), name = name)?;
@@ -4360,6 +4342,33 @@ fn sidebar_enum(fmt: &mut fmt::Formatter, it: &clean::Item,
     Ok(())
 }
 
+fn item_ty_to_strs(ty: &ItemType) -> (&'static str, &'static str) {
+    match *ty {
+        ItemType::ExternCrate |
+        ItemType::Import          => ("reexports", "Re-exports"),
+        ItemType::Module          => ("modules", "Modules"),
+        ItemType::Struct          => ("structs", "Structs"),
+        ItemType::Union           => ("unions", "Unions"),
+        ItemType::Enum            => ("enums", "Enums"),
+        ItemType::Function        => ("functions", "Functions"),
+        ItemType::Typedef         => ("types", "Type Definitions"),
+        ItemType::Static          => ("statics", "Statics"),
+        ItemType::Constant        => ("constants", "Constants"),
+        ItemType::Trait           => ("traits", "Traits"),
+        ItemType::Impl            => ("impls", "Implementations"),
+        ItemType::TyMethod        => ("tymethods", "Type Methods"),
+        ItemType::Method          => ("methods", "Methods"),
+        ItemType::StructField     => ("fields", "Struct Fields"),
+        ItemType::Variant         => ("variants", "Variants"),
+        ItemType::Macro           => ("macros", "Macros"),
+        ItemType::Primitive       => ("primitives", "Primitive Types"),
+        ItemType::AssociatedType  => ("associated-types", "Associated Types"),
+        ItemType::AssociatedConst => ("associated-consts", "Associated Constants"),
+        ItemType::ForeignType     => ("foreign-types", "Foreign Types"),
+        ItemType::Keyword         => ("keywords", "Keywords"),
+    }
+}
+
 fn sidebar_module(fmt: &mut fmt::Formatter, _it: &clean::Item,
                   items: &[clean::Item]) -> fmt::Result {
     let mut sidebar = String::new();
@@ -4379,29 +4388,7 @@ fn sidebar_module(fmt: &mut fmt::Formatter, _it: &clean::Item,
                    ItemType::TyMethod, ItemType::Method, ItemType::StructField, ItemType::Variant,
                    ItemType::AssociatedType, ItemType::AssociatedConst, ItemType::ForeignType] {
         if items.iter().any(|it| !it.is_stripped() && it.type_() == myty) {
-            let (short, name) = match myty {
-                ItemType::ExternCrate |
-                ItemType::Import          => ("reexports", "Re-exports"),
-                ItemType::Module          => ("modules", "Modules"),
-                ItemType::Struct          => ("structs", "Structs"),
-                ItemType::Union           => ("unions", "Unions"),
-                ItemType::Enum            => ("enums", "Enums"),
-                ItemType::Function        => ("functions", "Functions"),
-                ItemType::Typedef         => ("types", "Type Definitions"),
-                ItemType::Static          => ("statics", "Statics"),
-                ItemType::Constant        => ("constants", "Constants"),
-                ItemType::Trait           => ("traits", "Traits"),
-                ItemType::Impl            => ("impls", "Implementations"),
-                ItemType::TyMethod        => ("tymethods", "Type Methods"),
-                ItemType::Method          => ("methods", "Methods"),
-                ItemType::StructField     => ("fields", "Struct Fields"),
-                ItemType::Variant         => ("variants", "Variants"),
-                ItemType::Macro           => ("macros", "Macros"),
-                ItemType::Primitive       => ("primitives", "Primitive Types"),
-                ItemType::AssociatedType  => ("associated-types", "Associated Types"),
-                ItemType::AssociatedConst => ("associated-consts", "Associated Constants"),
-                ItemType::ForeignType     => ("foreign-types", "Foreign Types"),
-            };
+            let (short, name) = item_ty_to_strs(&myty);
             sidebar.push_str(&format!("<li><a href=\"#{id}\">{name}</a></li>",
                                       id = short,
                                       name = name));
@@ -4462,6 +4449,12 @@ fn item_primitive(w: &mut fmt::Formatter, cx: &Context,
     render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All)
 }
 
+fn item_keyword(w: &mut fmt::Formatter, cx: &Context,
+                it: &clean::Item,
+                _p: &str) -> fmt::Result {
+    document(w, cx, it)
+}
+
 const BASIC_KEYWORDS: &'static str = "rust, rustlang, rust-lang";
 
 fn make_item_keywords(it: &clean::Item) -> String {
index 0c937759120ef47e39df76218cffe5b6ab9cb6fd..983da51779ca25a6094a245a30ebf896a5adf85f 100644 (file)
@@ -38,7 +38,8 @@
                      "constant",
                      "associatedconstant",
                      "union",
-                     "foreigntype"];
+                     "foreigntype",
+                     "keyword"];
 
     var search_input = document.getElementsByClassName('search-input')[0];
 
 
     // used for special search precedence
     var TY_PRIMITIVE = itemTypes.indexOf("primitive");
+    var TY_KEYWORD = itemTypes.indexOf("keyword");
 
     onEach(document.getElementsByClassName('js-only'), function(e) {
         removeClass(e, 'js-only');
                     b = bbb.index;
                     if (a !== b) { return a - b; }
 
-                    // special precedence for primitive pages
-                    if ((aaa.item.ty === TY_PRIMITIVE) && (bbb.item.ty !== TY_PRIMITIVE)) {
+                    // special precedence for primitive and keyword pages
+                    if ((aaa.item.ty === TY_PRIMITIVE && bbb.item.ty !== TY_KEYWORD) ||
+                        (aaa.item.ty === TY_KEYWORD && bbb.item.ty !== TY_PRIMITIVE)) {
                         return -1;
                     }
-                    if ((bbb.item.ty === TY_PRIMITIVE) && (aaa.item.ty !== TY_PRIMITIVE)) {
+                    if ((bbb.item.ty === TY_PRIMITIVE && aaa.item.ty !== TY_PRIMITIVE) ||
+                        (bbb.item.ty === TY_KEYWORD && aaa.item.ty !== TY_KEYWORD)) {
                         return 1;
                     }
 
                 displayPath = item.path + '::';
                 href = rootPath + item.path.replace(/::/g, '/') + '/' +
                        name + '/index.html';
-            } else if (type === "primitive") {
+            } else if (type === "primitive" || type === "keyword") {
                 displayPath = "";
                 href = rootPath + item.path.replace(/::/g, '/') +
                        '/' + type + '.' + name + '.html';
         block("fn", "Functions");
         block("type", "Type Definitions");
         block("foreigntype", "Foreign Types");
+        block("keyword", "Keywords");
     }
 
     window.initSidebarItems = initSidebarItems;
index 773b8174e56bc98b20c07298e3c96249d940493b..d684db152df0129aff972b2570da44eb8a0555fd 100644 (file)
@@ -628,6 +628,11 @@ tr.result span.primitive::after {
        font-style: italic;
 }
 
+tr.result span.keyword::after {
+       content: ' (keyword)';
+       font-style: italic;
+}
+
 body.blur > :not(#help) {
        filter: blur(8px);
        -webkit-filter: blur(8px);
index f96dcd9ec1c888bbfe6a8f5991a214b64ab7c5f2..7add0e21f548c7b4f16e361f2ee21a6721b1246a 100644 (file)
@@ -128,6 +128,7 @@ pre {
 .content .highlighted.constant,
 .content .highlighted.static { background-color: #0063cc; }
 .content .highlighted.primitive { background-color: #00708a; }
+.content .highlighted.keyword { background-color: #884719; }
 
 .content span.enum, .content a.enum, .block a.current.enum { color: #82b089; }
 .content span.struct, .content a.struct, .block a.current.struct { color: #2dbfb8; }
@@ -145,6 +146,7 @@ pre {
 .content span.method, .content a.method, .block a.current.method,
 .content span.tymethod, .content a.tymethod, .block a.current.tymethod,
 .content .fnname{ color: #2BAB63; }
+.content span.keyword, .content a.keyword, .block a.current.keyword { color: #de5249; }
 
 pre.rust .comment { color: #8d8d8b; }
 pre.rust .doccomment { color: #8ca375; }
@@ -209,7 +211,7 @@ a.test-arrow {
        color: grey;
 }
 
-tr.result span.primitive::after {
+tr.result span.primitive::after, tr.result span.keyword::after {
        color: #ddd;
 }
 
index 54cf50cfffd1e030467aa6bcc705aebab2c819ef..7d9980363de9c582021c6b311a401209abc76177 100644 (file)
@@ -128,6 +128,7 @@ pre {
 .content .highlighted.constant,
 .content .highlighted.static { background-color: #c3e0ff; }
 .content .highlighted.primitive { background-color: #9aecff; }
+.content .highlighted.keyword { background-color: #f99650; }
 
 .content span.enum, .content a.enum, .block a.current.enum { color: #508157; }
 .content span.struct, .content a.struct, .block a.current.struct { color: #ad448e; }
@@ -145,6 +146,7 @@ pre {
 .content span.method, .content a.method, .block a.current.method,
 .content span.tymethod, .content a.tymethod, .block a.current.tymethod,
 .content .fnname { color: #9a6e31; }
+.content span.keyword, .content a.keyword, .block a.current.keyword { color: #de5249; }
 
 pre.rust .comment { color: #8E908C; }
 pre.rust .doccomment { color: #4D4D4C; }
@@ -203,7 +205,7 @@ a.test-arrow {
        color: grey;
 }
 
-tr.result span.primitive::after {
+tr.result span.primitive::after, tr.result span.keyword::after {
        color: black;
 }
 
index 32f0bcada1d20924414211dcdd462dc7c7bdbe0c..fe116a22eccbfa4e465a8a9d21471f8931add8c1 100644 (file)
@@ -126,6 +126,9 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
 
             // Associated types are never stripped
             clean::AssociatedTypeItem(..) => {}
+
+            // Keywords are never stripped
+            clean::KeywordItem(..) => {}
         }
 
         let fastreturn = match i.inner {
index 8c2555c4b3de27ce9cd9cbf7dd7239be25f0ebda..f05cbbfd7a2b6e77be8f5bb32c03ccc5aecd9baf 100644 (file)
@@ -244,10 +244,10 @@ pub fn visit_mod_contents(&mut self, span: Span, attrs: hir::HirVec<ast::Attribu
                         def_id,
                         attrs: def.attrs.clone().into(),
                         name: def.ident.name,
-                        whence: def.span,
+                        whence: self.cx.tcx.def_span(def_id),
                         matchers,
-                        stab: self.stability(def.id),
-                        depr: self.deprecation(def.id),
+                        stab: self.cx.tcx.lookup_stability(def_id).cloned(),
+                        depr: self.cx.tcx.lookup_deprecation(def_id),
                         imported_from: Some(imported_from),
                     })
                 }
index c576245edb755c1d271fbf04f431951efe50a265..7bbc99b83be5665f91a74c2d401220fec362183a 100644 (file)
 #![feature(float_from_str_radix)]
 #![feature(fn_traits)]
 #![feature(fnbox)]
+#![feature(futures_api)]
 #![feature(hashmap_internals)]
 #![feature(heap_api)]
 #![feature(int_error_internals)]
 #![feature(panic_internals)]
 #![feature(panic_unwind)]
 #![feature(peek)]
+#![feature(pin)]
 #![feature(placement_new_protocol)]
 #![feature(prelude_import)]
 #![feature(ptr_internals)]
 #![cfg_attr(test, feature(update_panic_count))]
 #![cfg_attr(windows, feature(used))]
 #![feature(doc_alias)]
+#![feature(doc_keyword)]
 #![feature(float_internals)]
 #![feature(panic_info_message)]
 #![cfg_attr(not(stage0), feature(panic_implementation))]
 #[stable(feature = "core_hint", since = "1.27.0")]
 pub use core::hint;
 
+#[unstable(feature = "futures_api",
+           reason = "futures in libcore are unstable",
+           issue = "50547")]
+pub mod task {
+    //! Types and Traits for working with asynchronous tasks.
+    pub use core::task::*;
+    pub use alloc_crate::task::*;
+}
+
+#[unstable(feature = "futures_api",
+           reason = "futures in libcore are unstable",
+           issue = "50547")]
+pub use core::future;
+
 pub mod f32;
 pub mod f64;
 
index cf798500b7fd2d716dcccaaa7adb62250b879a88..5c491115c55160dafcc356c2082699454b9b29f4 100644 (file)
@@ -144,7 +144,7 @@ pub fn now() -> Instant {
 
     pub fn sub_instant(&self, other: &Instant) -> Duration {
         self.t.sub_timespec(&other.t).unwrap_or_else(|_| {
-            panic!("other was less than the current instant")
+            panic!("specified instant was later than self")
         })
     }
 
index 83127935909931211957d8df0e34e7c599e92ceb..89786eb2a6c486005c27ba46da3375fa3fd79aa7 100644 (file)
@@ -289,7 +289,7 @@ pub fn now() -> Instant {
 
         pub fn sub_instant(&self, other: &Instant) -> Duration {
             self.t.sub_timespec(&other.t).unwrap_or_else(|_| {
-                panic!("other was less than the current instant")
+                panic!("specified instant was later than self")
             })
         }
 
index 076b6d1765848104aecc0fe2e6fae18eb0aa2c05..2389ed799cfcc268301e70275aac9b3c190f029f 100644 (file)
@@ -17,7 +17,7 @@
 use ast;
 use ast::{AttrId, Attribute, Name, Ident, Path, PathSegment};
 use ast::{MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind};
-use ast::{Lit, LitKind, Expr, ExprKind, Item, Local, Stmt, StmtKind};
+use ast::{Lit, LitKind, Expr, ExprKind, Item, Local, Stmt, StmtKind, GenericParam};
 use codemap::{BytePos, Spanned, respan, dummy_spanned};
 use syntax_pos::Span;
 use errors::{Applicability, Handler};
@@ -1444,6 +1444,22 @@ fn map_attrs<F: FnOnce(Vec<ast::Attribute>) -> Vec<ast::Attribute>>(self, f: F)
     }
 }
 
+impl HasAttrs for GenericParam {
+    fn attrs(&self) -> &[ast::Attribute] {
+        match self {
+            GenericParam::Lifetime(lifetime) => lifetime.attrs(),
+            GenericParam::Type(ty) => ty.attrs(),
+        }
+    }
+
+    fn map_attrs<F: FnOnce(Vec<Attribute>) -> Vec<Attribute>>(self, f: F) -> Self {
+        match self {
+            GenericParam::Lifetime(lifetime) => GenericParam::Lifetime(lifetime.map_attrs(f)),
+            GenericParam::Type(ty) => GenericParam::Type(ty.map_attrs(f)),
+        }
+    }
+}
+
 macro_rules! derive_has_attrs {
     ($($ty:path),*) => { $(
         impl HasAttrs for $ty {
@@ -1463,5 +1479,5 @@ fn map_attrs<F>(mut self, f: F) -> Self
 
 derive_has_attrs! {
     Item, Expr, Local, ast::ForeignItem, ast::StructField, ast::ImplItem, ast::TraitItem, ast::Arm,
-    ast::Field, ast::FieldPat, ast::Variant_
+    ast::Field, ast::FieldPat, ast::Variant_, ast::LifetimeDef, ast::TyParam
 }
index 36911683a0e7785654cd7c88a642cec1c106814f..3364378913952deabb76eacf3ae07d463028beb0 100644 (file)
@@ -278,6 +278,22 @@ pub fn configure_pat(&mut self, pattern: P<ast::Pat>) -> P<ast::Pat> {
             pattern
         })
     }
+
+    // deny #[cfg] on generic parameters until we decide what to do with it.
+    // see issue #51279.
+    pub fn disallow_cfg_on_generic_param(&mut self, param: &ast::GenericParam) {
+        for attr in param.attrs() {
+            let offending_attr = if attr.check_name("cfg") {
+                "cfg"
+            } else if attr.check_name("cfg_attr") {
+                "cfg_attr"
+            } else {
+                continue;
+            };
+            let msg = format!("#[{}] cannot be applied on a generic parameter", offending_attr);
+            self.sess.span_diagnostic.span_err(attr.span, &msg);
+        }
+    }
 }
 
 impl<'a> fold::Folder for StripUnconfigured<'a> {
index 83e7dd84cbff2a443b9419041fa269adde70f05e..29030783ca6b848d0c253c019fb30f126f76e4a7 100644 (file)
@@ -1412,6 +1412,11 @@ fn fold_item_kind(&mut self, item: ast::ItemKind) -> ast::ItemKind {
         }
     }
 
+    fn fold_generic_param(&mut self, param: ast::GenericParam) -> ast::GenericParam {
+        self.cfg.disallow_cfg_on_generic_param(&param);
+        noop_fold_generic_param(param, self)
+    }
+
     fn fold_attribute(&mut self, at: ast::Attribute) -> Option<ast::Attribute> {
         // turn `#[doc(include="filename")]` attributes into `#[doc(include(file="filename",
         // contents="file contents")]` attributes
index 77c6afa1c64a60883af2be338312117888fc1a6b..01b971976a763c3d49bf72f5283e2303e52f0442 100644 (file)
@@ -386,26 +386,72 @@ fn parse_sep_and_kleene_op<I>(
 {
     // We basically look at two token trees here, denoted as #1 and #2 below
     let span = match parse_kleene_op(input, span) {
-        // #1 is any KleeneOp (`?`)
-        Ok(Ok(op)) if op == KleeneOp::ZeroOrOne => {
-            if !features.macro_at_most_once_rep
-                && !attr::contains_name(attrs, "allow_internal_unstable")
-            {
-                let explain = feature_gate::EXPLAIN_MACRO_AT_MOST_ONCE_REP;
-                emit_feature_err(
-                    sess,
-                    "macro_at_most_once_rep",
-                    span,
-                    GateIssue::Language,
-                    explain,
-                );
+        // #1 is a `+` or `*` KleeneOp
+        //
+        // `?` is ambiguous: it could be a separator or a Kleene::ZeroOrOne, so we need to look
+        // ahead one more token to be sure.
+        Ok(Ok(op)) if op != KleeneOp::ZeroOrOne => return (None, op),
+
+        // #1 is `?` token, but it could be a Kleene::ZeroOrOne without a separator or it could
+        // be a `?` separator followed by any Kleene operator. We need to look ahead 1 token to
+        // find out which.
+        Ok(Ok(op)) => {
+            assert_eq!(op, KleeneOp::ZeroOrOne);
+
+            // Lookahead at #2. If it is a KleenOp, then #1 is a separator.
+            let is_1_sep = if let Some(&tokenstream::TokenTree::Token(_, ref tok2)) = input.peek() {
+                kleene_op(tok2).is_some()
+            } else {
+                false
+            };
+
+            if is_1_sep {
+                // #1 is a separator and #2 should be a KleepeOp::*
+                // (N.B. We need to advance the input iterator.)
+                match parse_kleene_op(input, span) {
+                    // #2 is a KleeneOp (this is the only valid option) :)
+                    Ok(Ok(op)) if op == KleeneOp::ZeroOrOne => {
+                        if !features.macro_at_most_once_rep
+                            && !attr::contains_name(attrs, "allow_internal_unstable")
+                        {
+                            let explain = feature_gate::EXPLAIN_MACRO_AT_MOST_ONCE_REP;
+                            emit_feature_err(
+                                sess,
+                                "macro_at_most_once_rep",
+                                span,
+                                GateIssue::Language,
+                                explain,
+                            );
+                        }
+                        return (Some(token::Question), op);
+                    }
+                    Ok(Ok(op)) => return (Some(token::Question), op),
+
+                    // #2 is a random token (this is an error) :(
+                    Ok(Err((_, span))) => span,
+
+                    // #2 is not even a token at all :(
+                    Err(span) => span,
+                }
+            } else {
+                if !features.macro_at_most_once_rep
+                    && !attr::contains_name(attrs, "allow_internal_unstable")
+                {
+                    let explain = feature_gate::EXPLAIN_MACRO_AT_MOST_ONCE_REP;
+                    emit_feature_err(
+                        sess,
+                        "macro_at_most_once_rep",
+                        span,
+                        GateIssue::Language,
+                        explain,
+                    );
+                }
+
+                // #2 is a random tree and #1 is KleeneOp::ZeroOrOne
+                return (None, op);
             }
-            return (None, op);
         }
 
-        // #1 is any KleeneOp (`+`, `*`)
-        Ok(Ok(op)) => return (None, op),
-
         // #1 is a separator followed by #2, a KleeneOp
         Ok(Err((tok, span))) => match parse_kleene_op(input, span) {
             // #2 is a KleeneOp :D
@@ -421,11 +467,8 @@ fn parse_sep_and_kleene_op<I>(
                         GateIssue::Language,
                         explain,
                     );
-                } else {
-                    sess.span_diagnostic
-                        .span_err(span, "`?` macro repetition does not allow a separator");
                 }
-                return (None, op);
+                return (Some(tok), op);
             }
             Ok(Ok(op)) => return (Some(tok), op),
 
@@ -440,7 +483,9 @@ fn parse_sep_and_kleene_op<I>(
         Err(span) => span,
     };
 
-    if !features.macro_at_most_once_rep && !attr::contains_name(attrs, "allow_internal_unstable") {
+    if !features.macro_at_most_once_rep
+        && !attr::contains_name(attrs, "allow_internal_unstable")
+    {
         sess.span_diagnostic
             .span_err(span, "expected one of: `*`, `+`, or `?`");
     } else {
index 7349745fefea100b1b9b1c6de4739e7ee089dd49..5f0cf49cd96cf73acda7aa6204ea9935f7041e26 100644 (file)
@@ -398,9 +398,6 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     // `foo.rs` as an alternative to `foo/mod.rs`
     (active, non_modrs_mods, "1.24.0", Some(44660), Some(Edition::Edition2018)),
 
-    // Termination trait in tests (RFC 1937)
-    (active, termination_trait_test, "1.24.0", Some(48854), Some(Edition::Edition2018)),
-
     // `extern` in paths
     (active, extern_in_paths, "1.23.0", Some(44660), None),
 
@@ -476,8 +473,12 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     // 'a: { break 'a; }
     (active, label_break_value, "1.28.0", Some(48594), None),
 
+
     // #[panic_implementation]
     (active, panic_implementation, "1.28.0", Some(44489), None),
+
+    // #[doc(keyword = "...")]
+    (active, doc_keyword, "1.28.0", Some(51315), None),
 );
 
 declare_features! (
@@ -601,7 +602,7 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     // allow `'_` placeholder lifetimes
     (accepted, underscore_lifetimes, "1.26.0", Some(44524), None),
     // Allows attributes on lifetime/type formal parameters in generics (RFC 1327)
-    (accepted, generic_param_attrs, "1.26.0", Some(48848), None),
+    (accepted, generic_param_attrs, "1.27.0", Some(48848), None),
     // Allows cfg(target_feature = "...").
     (accepted, cfg_target_feature, "1.27.0", Some(29717), None),
     // Allows #[target_feature(...)]
@@ -612,6 +613,8 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     (accepted, fn_must_use, "1.27.0", Some(43302), None),
     // Allows use of the :lifetime macro fragment specifier
     (accepted, macro_lifetime_matcher, "1.27.0", Some(34303), None),
+    // Termination trait in tests (RFC 1937)
+    (accepted, termination_trait_test, "1.27.0", Some(48854), None),
 );
 
 // If you change this, please modify src/doc/unstable-book as well. You must
@@ -1506,6 +1509,10 @@ fn visit_attribute(&mut self, attr: &ast::Attribute) {
                     gate_feature_post!(&self, doc_alias, attr.span,
                         "#[doc(alias = \"...\")] is experimental"
                     );
+                } else if content.iter().any(|c| c.check_name("keyword")) {
+                    gate_feature_post!(&self, doc_keyword, attr.span,
+                        "#[doc(keyword = \"...\")] is experimental"
+                    );
                 }
             }
         }
index 28f93328e953466b01f7c650d3d4ff1d7e9f12f7..dd3559798ec0c6381196c5dd2fb2edd8e22babf0 100644 (file)
@@ -652,7 +652,7 @@ pub fn expect(&mut self, t: &token::Token) -> PResult<'a,  ()> {
                 Err(err)
             }
         } else {
-            self.expect_one_of(unsafe { slice::from_raw_parts(t, 1) }, &[])
+            self.expect_one_of(slice::from_ref(t), &[])
         }
     }
 
@@ -1108,7 +1108,12 @@ fn parse_seq_to_before_tokens<T, F>(&mut self,
     {
         let mut first: bool = true;
         let mut v = vec![];
-        while !kets.contains(&&self.token) {
+        while !kets.iter().any(|k| {
+                match expect {
+                    TokenExpectType::Expect => self.check(k),
+                    TokenExpectType::NoExpect => self.token == **k,
+                }
+            }) {
             match self.token {
                 token::CloseDelim(..) | token::Eof => break,
                 _ => {}
@@ -3710,26 +3715,89 @@ fn parse_pat_vec_elements(
         Ok((before, slice, after))
     }
 
+    fn parse_pat_field(
+        &mut self,
+        lo: Span,
+        attrs: Vec<Attribute>
+    ) -> PResult<'a, codemap::Spanned<ast::FieldPat>> {
+        // Check if a colon exists one ahead. This means we're parsing a fieldname.
+        let hi;
+        let (subpat, fieldname, is_shorthand) = if self.look_ahead(1, |t| t == &token::Colon) {
+            // Parsing a pattern of the form "fieldname: pat"
+            let fieldname = self.parse_field_name()?;
+            self.bump();
+            let pat = self.parse_pat()?;
+            hi = pat.span;
+            (pat, fieldname, false)
+        } else {
+            // Parsing a pattern of the form "(box) (ref) (mut) fieldname"
+            let is_box = self.eat_keyword(keywords::Box);
+            let boxed_span = self.span;
+            let is_ref = self.eat_keyword(keywords::Ref);
+            let is_mut = self.eat_keyword(keywords::Mut);
+            let fieldname = self.parse_ident()?;
+            hi = self.prev_span;
+
+            let bind_type = match (is_ref, is_mut) {
+                (true, true) => BindingMode::ByRef(Mutability::Mutable),
+                (true, false) => BindingMode::ByRef(Mutability::Immutable),
+                (false, true) => BindingMode::ByValue(Mutability::Mutable),
+                (false, false) => BindingMode::ByValue(Mutability::Immutable),
+            };
+            let fieldpat = P(Pat {
+                id: ast::DUMMY_NODE_ID,
+                node: PatKind::Ident(bind_type, fieldname, None),
+                span: boxed_span.to(hi),
+            });
+
+            let subpat = if is_box {
+                P(Pat {
+                    id: ast::DUMMY_NODE_ID,
+                    node: PatKind::Box(fieldpat),
+                    span: lo.to(hi),
+                })
+            } else {
+                fieldpat
+            };
+            (subpat, fieldname, true)
+        };
+
+        Ok(codemap::Spanned {
+            span: lo.to(hi),
+            node: ast::FieldPat {
+                ident: fieldname,
+                pat: subpat,
+                is_shorthand,
+                attrs: attrs.into(),
+           }
+        })
+    }
+
     /// Parse the fields of a struct-like pattern
     fn parse_pat_fields(&mut self) -> PResult<'a, (Vec<codemap::Spanned<ast::FieldPat>>, bool)> {
         let mut fields = Vec::new();
         let mut etc = false;
-        let mut first = true;
-        while self.token != token::CloseDelim(token::Brace) {
-            if first {
-                first = false;
-            } else {
-                self.expect(&token::Comma)?;
-                // accept trailing commas
-                if self.check(&token::CloseDelim(token::Brace)) { break }
-            }
+        let mut ate_comma = true;
+        let mut delayed_err: Option<DiagnosticBuilder<'a>> = None;
+        let mut etc_span = None;
 
+        while self.token != token::CloseDelim(token::Brace) {
             let attrs = self.parse_outer_attributes()?;
             let lo = self.span;
-            let hi;
+
+            // check that a comma comes after every field
+            if !ate_comma {
+                let err = self.struct_span_err(self.prev_span, "expected `,`");
+                return Err(err);
+            }
+            ate_comma = false;
 
             if self.check(&token::DotDot) || self.token == token::DotDotDot {
+                etc = true;
+                let mut etc_sp = self.span;
+
                 if self.token == token::DotDotDot { // Issue #46718
+                    // Accept `...` as if it were `..` to avoid further errors
                     let mut err = self.struct_span_err(self.span,
                                                        "expected field pattern, found `...`");
                     err.span_suggestion_with_applicability(
@@ -3740,73 +3808,76 @@ fn parse_pat_fields(&mut self) -> PResult<'a, (Vec<codemap::Spanned<ast::FieldPa
                     );
                     err.emit();
                 }
+                self.bump();  // `..` || `...`:w
 
-                self.bump();
-                if self.token != token::CloseDelim(token::Brace) {
-                    let token_str = self.this_token_to_string();
-                    let mut err = self.fatal(&format!("expected `{}`, found `{}`", "}", token_str));
-                    if self.token == token::Comma { // Issue #49257
-                        err.span_label(self.span,
-                                       "`..` must be in the last position, \
-                                        and cannot have a trailing comma");
+                if self.token == token::CloseDelim(token::Brace) {
+                    etc_span = Some(etc_sp);
+                    break;
+                }
+                let token_str = self.this_token_to_string();
+                let mut err = self.fatal(&format!("expected `}}`, found `{}`", token_str));
+
+                err.span_label(self.span, "expected `}`");
+                let mut comma_sp = None;
+                if self.token == token::Comma { // Issue #49257
+                    etc_sp = etc_sp.to(self.sess.codemap().span_until_non_whitespace(self.span));
+                    err.span_label(etc_sp,
+                                   "`..` must be at the end and cannot have a trailing comma");
+                    comma_sp = Some(self.span);
+                    self.bump();
+                    ate_comma = true;
+                }
+
+                etc_span = Some(etc_sp);
+                if self.token == token::CloseDelim(token::Brace) {
+                    // If the struct looks otherwise well formed, recover and continue.
+                    if let Some(sp) = comma_sp {
+                        err.span_suggestion_short(sp, "remove this comma", "".into());
+                    }
+                    err.emit();
+                    break;
+                } else if self.token.is_ident() && ate_comma {
+                    // Accept fields coming after `..,`.
+                    // This way we avoid "pattern missing fields" errors afterwards.
+                    // We delay this error until the end in order to have a span for a
+                    // suggested fix.
+                    if let Some(mut delayed_err) = delayed_err {
+                        delayed_err.emit();
+                        return Err(err);
                     } else {
-                        err.span_label(self.span, "expected `}`");
+                        delayed_err = Some(err);
+                    }
+                } else {
+                    if let Some(mut err) = delayed_err {
+                        err.emit();
                     }
                     return Err(err);
                 }
-                etc = true;
-                break;
             }
 
-            // Check if a colon exists one ahead. This means we're parsing a fieldname.
-            let (subpat, fieldname, is_shorthand) = if self.look_ahead(1, |t| t == &token::Colon) {
-                // Parsing a pattern of the form "fieldname: pat"
-                let fieldname = self.parse_field_name()?;
-                self.bump();
-                let pat = self.parse_pat()?;
-                hi = pat.span;
-                (pat, fieldname, false)
-            } else {
-                // Parsing a pattern of the form "(box) (ref) (mut) fieldname"
-                let is_box = self.eat_keyword(keywords::Box);
-                let boxed_span = self.span;
-                let is_ref = self.eat_keyword(keywords::Ref);
-                let is_mut = self.eat_keyword(keywords::Mut);
-                let fieldname = self.parse_ident()?;
-                hi = self.prev_span;
-
-                let bind_type = match (is_ref, is_mut) {
-                    (true, true) => BindingMode::ByRef(Mutability::Mutable),
-                    (true, false) => BindingMode::ByRef(Mutability::Immutable),
-                    (false, true) => BindingMode::ByValue(Mutability::Mutable),
-                    (false, false) => BindingMode::ByValue(Mutability::Immutable),
-                };
-                let fieldpat = P(Pat {
-                    id: ast::DUMMY_NODE_ID,
-                    node: PatKind::Ident(bind_type, fieldname, None),
-                    span: boxed_span.to(hi),
-                });
-
-                let subpat = if is_box {
-                    P(Pat {
-                        id: ast::DUMMY_NODE_ID,
-                        node: PatKind::Box(fieldpat),
-                        span: lo.to(hi),
-                    })
-                } else {
-                    fieldpat
-                };
-                (subpat, fieldname, true)
-            };
-
-            fields.push(codemap::Spanned { span: lo.to(hi),
-                                           node: ast::FieldPat {
-                                               ident: fieldname,
-                                               pat: subpat,
-                                               is_shorthand,
-                                               attrs: attrs.into(),
-                                           }
+            fields.push(match self.parse_pat_field(lo, attrs) {
+                Ok(field) => field,
+                Err(err) => {
+                    if let Some(mut delayed_err) = delayed_err {
+                        delayed_err.emit();
+                    }
+                    return Err(err);
+                }
             });
+            ate_comma = self.eat(&token::Comma);
+        }
+
+        if let Some(mut err) = delayed_err {
+            if let Some(etc_span) = etc_span {
+                err.multipart_suggestion(
+                    "move the `..` to the end of the field list",
+                    vec![
+                        (etc_span, "".into()),
+                        (self.span, format!("{}.. }}", if ate_comma { "" } else { ", " })),
+                    ],
+                );
+            }
+            err.emit();
         }
         return Ok((fields, etc));
     }
@@ -5190,36 +5261,36 @@ fn parse_self_arg(&mut self) -> PResult<'a, Option<Arg>> {
         // Only a limited set of initial token sequences is considered self parameters, anything
         // else is parsed as a normal function parameter list, so some lookahead is required.
         let eself_lo = self.span;
-        let (eself, eself_ident) = match self.token {
+        let (eself, eself_ident, eself_hi) = match self.token {
             token::BinOp(token::And) => {
                 // &self
                 // &mut self
                 // &'lt self
                 // &'lt mut self
                 // &not_self
-                if isolated_self(self, 1) {
+                (if isolated_self(self, 1) {
                     self.bump();
-                    (SelfKind::Region(None, Mutability::Immutable), expect_ident(self))
+                    SelfKind::Region(None, Mutability::Immutable)
                 } else if self.look_ahead(1, |t| t.is_keyword(keywords::Mut)) &&
                           isolated_self(self, 2) {
                     self.bump();
                     self.bump();
-                    (SelfKind::Region(None, Mutability::Mutable), expect_ident(self))
+                    SelfKind::Region(None, Mutability::Mutable)
                 } else if self.look_ahead(1, |t| t.is_lifetime()) &&
                           isolated_self(self, 2) {
                     self.bump();
                     let lt = self.expect_lifetime();
-                    (SelfKind::Region(Some(lt), Mutability::Immutable), expect_ident(self))
+                    SelfKind::Region(Some(lt), Mutability::Immutable)
                 } else if self.look_ahead(1, |t| t.is_lifetime()) &&
                           self.look_ahead(2, |t| t.is_keyword(keywords::Mut)) &&
                           isolated_self(self, 3) {
                     self.bump();
                     let lt = self.expect_lifetime();
                     self.bump();
-                    (SelfKind::Region(Some(lt), Mutability::Mutable), expect_ident(self))
+                    SelfKind::Region(Some(lt), Mutability::Mutable)
                 } else {
                     return Ok(None);
-                }
+                }, expect_ident(self), self.prev_span)
             }
             token::BinOp(token::Star) => {
                 // *self
@@ -5227,43 +5298,45 @@ fn parse_self_arg(&mut self) -> PResult<'a, Option<Arg>> {
                 // *mut self
                 // *not_self
                 // Emit special error for `self` cases.
-                if isolated_self(self, 1) {
+                (if isolated_self(self, 1) {
                     self.bump();
                     self.span_err(self.span, "cannot pass `self` by raw pointer");
-                    (SelfKind::Value(Mutability::Immutable), expect_ident(self))
+                    SelfKind::Value(Mutability::Immutable)
                 } else if self.look_ahead(1, |t| t.is_mutability()) &&
                           isolated_self(self, 2) {
                     self.bump();
                     self.bump();
                     self.span_err(self.span, "cannot pass `self` by raw pointer");
-                    (SelfKind::Value(Mutability::Immutable), expect_ident(self))
+                    SelfKind::Value(Mutability::Immutable)
                 } else {
                     return Ok(None);
-                }
+                }, expect_ident(self), self.prev_span)
             }
             token::Ident(..) => {
                 if isolated_self(self, 0) {
                     // self
                     // self: TYPE
                     let eself_ident = expect_ident(self);
-                    if self.eat(&token::Colon) {
+                    let eself_hi = self.prev_span;
+                    (if self.eat(&token::Colon) {
                         let ty = self.parse_ty()?;
-                        (SelfKind::Explicit(ty, Mutability::Immutable), eself_ident)
+                        SelfKind::Explicit(ty, Mutability::Immutable)
                     } else {
-                        (SelfKind::Value(Mutability::Immutable), eself_ident)
-                    }
+                        SelfKind::Value(Mutability::Immutable)
+                    }, eself_ident, eself_hi)
                 } else if self.token.is_keyword(keywords::Mut) &&
                           isolated_self(self, 1) {
                     // mut self
                     // mut self: TYPE
                     self.bump();
                     let eself_ident = expect_ident(self);
-                    if self.eat(&token::Colon) {
+                    let eself_hi = self.prev_span;
+                    (if self.eat(&token::Colon) {
                         let ty = self.parse_ty()?;
-                        (SelfKind::Explicit(ty, Mutability::Mutable), eself_ident)
+                        SelfKind::Explicit(ty, Mutability::Mutable)
                     } else {
-                        (SelfKind::Value(Mutability::Mutable), eself_ident)
-                    }
+                        SelfKind::Value(Mutability::Mutable)
+                    }, eself_ident, eself_hi)
                 } else {
                     return Ok(None);
                 }
@@ -5271,7 +5344,7 @@ fn parse_self_arg(&mut self) -> PResult<'a, Option<Arg>> {
             _ => return Ok(None),
         };
 
-        let eself = codemap::respan(eself_lo.to(self.prev_span), eself);
+        let eself = codemap::respan(eself_lo.to(eself_hi), eself);
         Ok(Some(Arg::from_self(eself, eself_ident)))
     }
 
index e63a3d47a828fdfde53e4e649b0c61e43e7261b3..0c7f70a578a2687477b4fe12e1ac3144f987bf11 100644 (file)
@@ -335,7 +335,7 @@ enum BadTestSignature {
 fn is_test_fn(cx: &TestCtxt, i: &ast::Item) -> bool {
     let has_test_attr = attr::contains_name(&i.attrs, "test");
 
-    fn has_test_signature(cx: &TestCtxt, i: &ast::Item) -> HasTestSignature {
+    fn has_test_signature(_cx: &TestCtxt, i: &ast::Item) -> HasTestSignature {
         let has_should_panic_attr = attr::contains_name(&i.attrs, "should_panic");
         match i.node {
             ast::ItemKind::Fn(ref decl, _, _, _, ref generics, _) => {
@@ -351,15 +351,14 @@ fn has_test_signature(cx: &TestCtxt, i: &ast::Item) -> HasTestSignature {
                     return No(BadTestSignature::NoArgumentsAllowed);
                 }
 
-                match (has_output, cx.features.termination_trait_test, has_should_panic_attr) {
-                    (true, true, true) => No(BadTestSignature::ShouldPanicOnlyWithNoArgs),
-                    (true, true, false) => if generics.is_parameterized() {
+                match (has_output, has_should_panic_attr) {
+                    (true, true) => No(BadTestSignature::ShouldPanicOnlyWithNoArgs),
+                    (true, false) => if generics.is_parameterized() {
                         No(BadTestSignature::WrongTypeSignature)
                     } else {
                         Yes
                     },
-                    (true, false, _) => No(BadTestSignature::WrongTypeSignature),
-                    (false, _, _) => Yes
+                    (false, _) => Yes
                 }
             }
             _ => No(BadTestSignature::NotEvenAFunction),
@@ -395,31 +394,12 @@ fn has_test_signature(cx: &TestCtxt, i: &ast::Item) -> HasTestSignature {
 fn is_bench_fn(cx: &TestCtxt, i: &ast::Item) -> bool {
     let has_bench_attr = attr::contains_name(&i.attrs, "bench");
 
-    fn has_bench_signature(cx: &TestCtxt, i: &ast::Item) -> bool {
+    fn has_bench_signature(_cx: &TestCtxt, i: &ast::Item) -> bool {
         match i.node {
-            ast::ItemKind::Fn(ref decl, _, _, _, ref generics, _) => {
-                let input_cnt = decl.inputs.len();
-
-                // If the termination trait is active, the compiler will check that the output
-                // type implements the `Termination` trait as `libtest` enforces that.
-                let output_matches = if cx.features.termination_trait_test {
-                    true
-                } else {
-                    let no_output = match decl.output {
-                        ast::FunctionRetTy::Default(..) => true,
-                        ast::FunctionRetTy::Ty(ref t) if t.node == ast::TyKind::Tup(vec![]) => true,
-                        _ => false
-                    };
-                    let tparm_cnt = generics.params.iter()
-                        .filter(|param| param.is_type_param())
-                        .count();
-
-                    no_output && tparm_cnt == 0
-                };
-
+            ast::ItemKind::Fn(ref decl, _, _, _, _, _) => {
                 // NB: inadequate check, but we're running
                 // well before resolve, can't get too deep.
-                input_cnt == 1 && output_matches
+                decl.inputs.len() == 1
             }
             _ => false
         }
@@ -430,13 +410,8 @@ fn has_bench_signature(cx: &TestCtxt, i: &ast::Item) -> bool {
     if has_bench_attr && !has_bench_signature {
         let diag = cx.span_diagnostic;
 
-        if cx.features.termination_trait_test {
-            diag.span_err(i.span, "functions used as benches must have signature \
+        diag.span_err(i.span, "functions used as benches must have signature \
                                    `fn(&mut Bencher) -> impl Termination`");
-        } else {
-            diag.span_err(i.span, "functions used as benches must have signature \
-                                   `fn(&mut Bencher) -> ()`");
-        }
     }
 
     has_bench_attr && has_bench_signature
index a4b2d9de932a71194994202cfa4fc548b29dcce1..283b41e5725a95959383d8295885633e5e8d084d 100644 (file)
@@ -311,6 +311,17 @@ impl Keyword {
                 ident: Ident::with_empty_ctxt(super::Symbol($index))
             };
         )*
+
+        impl ::std::str::FromStr for Keyword {
+            type Err = ();
+
+            fn from_str(s: &str) -> Result<Self, ()> {
+                match s {
+                    $($string => Ok($konst),)*
+                    _ => Err(()),
+                }
+            }
+        }
     }
 
     impl Interner {
index 367d509cadfe3755e38ad0f17a79bbe3dfc80b3f..df5cba1c244b8fbcc4961503b6b9590ec4389241 100644 (file)
@@ -22,6 +22,7 @@
 // ignore-powerpc64
 // ignore-s390x
 // ignore-sparc
+// ignore-sparc64
 // ignore-wasm32
 // ignore-x86
 // ignore-x86_64
index d6dd3f356b5fe7b363d4799ab2f6c7eb75f45fb8..77e3781961f4d8cc30b5050c8ecc3fd9f08732c0 100644 (file)
@@ -29,6 +29,7 @@
 // ignore-r600
 // ignore-amdgcn
 // ignore-sparc
+// ignore-sparc64
 // ignore-sparcv9
 // ignore-sparcel
 // ignore-s390x
index 9605ded569ef6128bebd7f196be5072a28dd4673..25750a6513f73662cb370279da6487118d01fe31 100644 (file)
@@ -14,6 +14,8 @@
 // ignore-asmjs
 // ignore-mips64
 // ignore-s390x
+// ignore-sparc
+// ignore-sparc64
 // ignore-wasm
 // ignore-x86
 // ignore-x86_64
index 51ebc42a0dd6f53b241abaf20188c62c75e1a6b5..2c86e609e7b21d24e39b0a51f69a365822caccd8 100644 (file)
@@ -14,6 +14,8 @@
 // ignore-mips64
 // ignore-powerpc
 // ignore-s390x
+// ignore-sparc
+// ignore-sparc64
 // ignore-wasm
 // ignore-emscripten
 // ignore-windows
index 30777c6214ec94848cc11dcdfb732f295b4b183f..ba51004a791b7b7c7e68c6e685829355e4354e84 100644 (file)
@@ -13,6 +13,8 @@
 // ignore-emscripten
 // ignore-mips
 // ignore-mips64
+// ignore-sparc
+// ignore-sparc64
 // compile-flags: -O
 
 #![feature(repr_simd)]
index aa77e7f46e50da720f26235b17ef4d6effc4cfe4..900f5cce13b2611ba5c228165dc399b62740a14a 100644 (file)
@@ -15,6 +15,7 @@
 // ignore-emscripten
 // ignore-powerpc
 // ignore-sparc
+// ignore-sparc64
 // ignore-mips
 // ignore-mips64
 
index 5e9278c7c35fc63e19537b3967fd5e1d4d53f446..3960fd50e1737faeb5bd136acf111e0ade469550 100644 (file)
@@ -12,6 +12,7 @@
 // ignore-emscripten
 // ignore-powerpc
 // ignore-sparc
+// ignore-sparc64
 // ignore-mips
 // ignore-mips64
 
index abd55ea101189ab7d039e94b37dc43f43e6fee55..77798201ff341cd23d689600ca968d66586aa7f8 100644 (file)
@@ -15,6 +15,7 @@
 // ignore-emscripten
 // ignore-powerpc
 // ignore-sparc
+// ignore-sparc64
 // ignore-mips
 // ignore-mips64
 
index 55d8970008f9a94eaa069d9d68d2541de6d641f2..e38112a256694117726fc6bc228c08a1197fb397 100644 (file)
@@ -12,6 +12,7 @@
 // ignore-emscripten
 // ignore-powerpc
 // ignore-sparc
+// ignore-sparc64
 // ignore-mips
 // ignore-mips64
 
index c606c5a80e58dbd35ffec4c8086a2a2ea63cef07..bd0301e6cf93b6f4cf8ae249c69369a9a8f7d75c 100644 (file)
@@ -12,6 +12,7 @@
 // ignore-emscripten
 // ignore-powerpc
 // ignore-sparc
+// ignore-sparc64
 // ignore-mips
 // ignore-mips64
 
index 0b230be85ad97c2ab68d97220eb720159c6172d2..4cd74117ef74cad59c590950f91f635fef5ac02e 100644 (file)
@@ -12,6 +12,7 @@
 // ignore-emscripten
 // ignore-powerpc
 // ignore-sparc
+// ignore-sparc64
 
 // revisions: ast mir
 //[mir]compile-flags: -Z borrowck=mir
index 108b7948dfcc20c981cc9ba88abebca27c909d5b..22a3c5ceeb7142893ddfd504cc06792767256b91 100644 (file)
@@ -16,7 +16,7 @@
 const BAR: usize = FOO[5]; // no error, because the error below occurs before regular const eval
 
 const BLUB: [u32; FOO[4]] = [5, 6];
-//~^ ERROR constant evaluation error [E0080]
+//~^ ERROR could not evaluate constant expression [E0080]
 //~| index out of bounds: the len is 3 but the index is 4
 
 fn main() {
index 6caec159d019ce39ce7f9bd1d65f64a561aa9b53..92c6b1fd0b5822a0125c3d8e6bf7dad3f08821dc 100644 (file)
 
 pub const A: i8 = -std::i8::MIN; //~ ERROR const_err
 //~^ ERROR this constant cannot be used
-//~| ERROR constant evaluation error
+//~| ERROR this expression will panic at runtime
 pub const B: u8 = 200u8 + 200u8; //~ ERROR const_err
 //~^ ERROR this constant cannot be used
 pub const C: u8 = 200u8 * 4; //~ ERROR const_err
 //~^ ERROR this constant cannot be used
 pub const D: u8 = 42u8 - (42u8 + 1); //~ ERROR const_err
 //~^ ERROR this constant cannot be used
-pub const E: u8 = [5u8][1];
-//~^ ERROR const_err
+pub const E: u8 = [5u8][1]; //~ ERROR const_err
+//~| ERROR this constant cannot be used
 
 fn main() {
     let _a = A;
index 6f0281b8bd0ca7382bf595d54137dae3a5b852a7..4a5e78b381ed049bdace21dc842ded1f758f6ed9 100644 (file)
 pub const A: i8 = -std::i8::MIN;
 //~^ ERROR E0080
 //~| ERROR attempt to negate with overflow
-//~| ERROR constant evaluation error
+//~| ERROR this expression will panic at runtime
 //~| ERROR this constant cannot be used
 pub const B: i8 = A;
 //~^ ERROR const_err
+//~| ERROR const_err
 pub const C: u8 = A as u8;
 //~^ ERROR const_err
+//~| ERROR const_err
 pub const D: i8 = 50 - A;
 //~^ ERROR const_err
+//~| ERROR const_err
 
 fn main() {
     let _ = (A, B, C, D);
index f6a64bcba21c3a6b15f0ce0eeafa3dacc49350d0..f77603b3ebafcf83a884e12316dec5e278220fd5 100644 (file)
@@ -23,6 +23,7 @@ fn black_box<T>(_: T) {
 // Make sure that the two uses get two errors.
 const FOO: u8 = [5u8][1];
 //~^ ERROR constant evaluation error
+//~| ERROR constant evaluation error
 //~| index out of bounds: the len is 1 but the index is 1
 
 fn main() {
index 46b73371e56cf554ee652cb136a67b9d28132877..9a5cb5a4a83fac6fdd10a4ba4930688ff7531609 100644 (file)
@@ -31,6 +31,7 @@ fn main() {
     let d = 42u8 - (42u8 + 1);
     //~^ ERROR const_err
     let _e = [5u8][1];
+    //~^ ERROR const_err
     black_box(a);
     black_box(b);
     black_box(c);
index 9656af6002442c6369dd86120e9cb3008cb96b6f..f5e43b57e7775082022d99b3291b3765c03da23b 100644 (file)
@@ -23,6 +23,7 @@ fn main() {
     let d = 42u8 - (42u8 + 1);
     //~^ ERROR const_err
     let _e = [5u8][1];
+    //~^ ERROR const_err
     black_box(b);
     black_box(c);
     black_box(d);
index 3065122af6a94fb334e6015d132c0b6d2aa421ee..29bc665a22e7bbe5ed3c4b071ae847d2a3719f5e 100644 (file)
@@ -16,7 +16,6 @@
 //~| ERROR mismatched types
 //~| expected usize, found bool
 const ARR: [i32; X] = [99; 34];
-//~^ ERROR constant evaluation error
 
 const X1: usize = 42 || 39;
 //~^ ERROR mismatched types
@@ -26,7 +25,6 @@
 //~| ERROR mismatched types
 //~| expected usize, found bool
 const ARR1: [i32; X1] = [99; 47];
-//~^ ERROR constant evaluation error
 
 const X2: usize = -42 || -39;
 //~^ ERROR mismatched types
@@ -36,7 +34,6 @@
 //~| ERROR mismatched types
 //~| expected usize, found bool
 const ARR2: [i32; X2] = [99; 18446744073709551607];
-//~^ ERROR constant evaluation error
 
 const X3: usize = -42 && -39;
 //~^ ERROR mismatched types
 //~| ERROR mismatched types
 //~| expected usize, found bool
 const ARR3: [i32; X3] = [99; 6];
-//~^ ERROR constant evaluation error
 
 const Y: usize = 42.0 == 42.0;
 //~^ ERROR mismatched types
 //~| expected usize, found bool
 const ARRR: [i32; Y] = [99; 1];
-//~^ ERROR constant evaluation error
 
 const Y1: usize = 42.0 >= 42.0;
 //~^ ERROR mismatched types
 //~| expected usize, found bool
 const ARRR1: [i32; Y1] = [99; 1];
-//~^ ERROR constant evaluation error
 
 const Y2: usize = 42.0 <= 42.0;
 //~^ ERROR mismatched types
 //~| expected usize, found bool
 const ARRR2: [i32; Y2] = [99; 1];
-//~^ ERROR constant evaluation error
 
 const Y3: usize = 42.0 > 42.0;
 //~^ ERROR mismatched types
 //~| expected usize, found bool
 const ARRR3: [i32; Y3] = [99; 0];
-//~^ ERROR constant evaluation error
 
 const Y4: usize = 42.0 < 42.0;
 //~^ ERROR mismatched types
 //~| expected usize, found bool
 const ARRR4: [i32; Y4] = [99; 0];
-//~^ ERROR constant evaluation error
 
 const Y5: usize = 42.0 != 42.0;
 //~^ ERROR mismatched types
 //~| expected usize, found bool
 const ARRR5: [i32; Y5] = [99; 0];
-//~^ ERROR constant evaluation error
 
 fn main() {
     let _ = ARR;
index 85cc893aa133c543457018af5bbec0c5edfb15be..054c272a3d321f6f5e740d8baf06711c1e063a37 100644 (file)
@@ -16,6 +16,6 @@
 
 fn main() {
     let a: [i8; ONE - TWO] = unimplemented!();
-    //~^ ERROR constant evaluation error
+    //~^ ERROR could not evaluate constant expression
     //~| attempt to subtract with overflow
 }
index 36a6600b62d98d29fd7d85bf214d2eb14df0f39c..304eef7847c9195aafe65d3b47ecceba7ff073fc 100644 (file)
@@ -40,5 +40,4 @@ fn main() {
     #[cfg(eval2)]
     let x: [i32; { let 0 = 0; 0 }] = [];
     //[eval2]~^ ERROR refutable pattern in local binding
-    //[eval2]~| ERROR constant evaluation error
 }
index 7596881ef9b9af1e03762dda451dca620cc3b1a3..b42c440f87d74e3678dfc6bf79c8d32a5e5ee7d8 100644 (file)
@@ -14,7 +14,6 @@
 //~^ ERROR mismatched types
 //~| expected tuple, found usize
 const ARR: [i32; TUP.0] = [];
-//~^ ERROR constant evaluation error
 
 fn main() {
 }
index 7315616860293c17389097a4ebbce2e4de8aab85..ada038114d8d095d0d7e2deb5c3091581be51a0b 100644 (file)
 enum Test {
     DivZero = 1/0,
     //~^ attempt to divide by zero
-    //~| ERROR constant evaluation error
-    //~| ERROR constant evaluation error
+    //~| ERROR could not evaluate enum discriminant
+    //~| ERROR this expression will panic at runtime
     RemZero = 1%0,
     //~^ attempt to calculate the remainder with a divisor of zero
-    //~| ERROR constant evaluation error
-    //~| ERROR constant evaluation error
+    //~| ERROR could not evaluate enum discriminant
+    //~| ERROR this expression will panic at runtime
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/feature-gate-termination_trait_test.rs b/src/test/compile-fail/feature-gate-termination_trait_test.rs
deleted file mode 100644 (file)
index 4af7e94..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-// 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: --test
-
-fn main() {}
-
-#[cfg(test)]
-mod tests {
-    #[test]
-    fn it_works() -> Result<(), ()> {
-    //~^ ERROR functions used as tests must have signature fn() -> ()
-        Ok(())
-    }
-}
index d601249c036b1a1654dd912b924bb80597fc9b48..13b4c0896e75c443d8fe5be74e26bc12296df0f9 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 fn foo(a: [0; 1]) {} //~ ERROR expected type, found `0`
-//~| ERROR expected one of `->`, `where`, or `{`, found `]`
+//~| ERROR expected one of `)`, `,`, `->`, `where`, or `{`, found `]`
 // FIXME(jseyfried): avoid emitting the second error (preexisting)
 
 fn main() {}
index 6fa65a541b39bdcc5a356df13cbb607564a970c4..8a0471135afc43f73ba93889702077c80382c0eb 100644 (file)
@@ -12,11 +12,11 @@ fn xyz() -> u8 { 42 }
 
 const NUM: u8 = xyz();
 //~^ ERROR calls in constants are limited to constant functions, tuple structs and tuple variants
-//~| ERROR constant evaluation error
 
 fn main() {
     match 1 {
         NUM => unimplemented!(),
+        //~^ ERROR could not evaluate constant pattern
         _ => unimplemented!(),
     }
 }
index 1d59e75a0f0f028874ee69aa71269f949edf13c5..b0d6cb5df875a32acf7adf89aaf222e9b3e0b8cd 100644 (file)
 fn main() {
     assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err());
     //~^ ERROR attempt to divide with overflow
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err());
     //~^ ERROR attempt to divide with overflow
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err());
     //~^ ERROR attempt to divide with overflow
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err());
     //~^ ERROR attempt to divide with overflow
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err());
     //~^ ERROR attempt to divide with overflow
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err());
     //~^ ERROR attempt to divide by zero
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err());
     //~^ ERROR attempt to divide by zero
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err());
     //~^ ERROR attempt to divide by zero
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err());
     //~^ ERROR attempt to divide by zero
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err());
     //~^ ERROR attempt to divide by zero
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err());
     //~^ ERROR attempt to calculate the remainder with overflow
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err());
     //~^ ERROR attempt to calculate the remainder with overflow
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err());
     //~^ ERROR attempt to calculate the remainder with overflow
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err());
     //~^ ERROR attempt to calculate the remainder with overflow
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err());
     //~^ ERROR attempt to calculate the remainder with overflow
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err());
     //~^ ERROR attempt to calculate the remainder with a divisor of zero
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err());
     //~^ ERROR attempt to calculate the remainder with a divisor of zero
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err());
     //~^ ERROR attempt to calculate the remainder with a divisor of zero
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err());
     //~^ ERROR attempt to calculate the remainder with a divisor of zero
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err());
     //~^ ERROR attempt to calculate the remainder with a divisor of zero
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
 }
diff --git a/src/test/compile-fail/panic_implementation-closures.rs b/src/test/compile-fail/panic_implementation-closures.rs
new file mode 100644 (file)
index 0000000..4fa9a63
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-pass
+
+#![crate_type = "rlib"]
+#![no_std]
+#![feature(panic_implementation)]
+
+#[panic_implementation]
+pub fn panic_fmt(_: &::core::panic::PanicInfo) -> ! {
+    |x: u8| x;
+    loop {}
+}
diff --git a/src/test/compile-fail/privacy/restricted/tuple-struct-fields/test.rs b/src/test/compile-fail/privacy/restricted/tuple-struct-fields/test.rs
deleted file mode 100644 (file)
index d4ea76d..0000000
+++ /dev/null
@@ -1,17 +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.
-
-mod foo {
-    type T = ();
-    struct S1(pub(in foo) (), pub(T), pub(crate) (), pub(((), T)));
-    struct S2(pub((foo)) ());
-    //~^ ERROR expected `,`, found `(`
-    //~| ERROR cannot find type `foo` in this scope
-}
diff --git a/src/test/compile-fail/privacy/restricted/tuple-struct-fields/test2.rs b/src/test/compile-fail/privacy/restricted/tuple-struct-fields/test2.rs
deleted file mode 100644 (file)
index fed9432..0000000
+++ /dev/null
@@ -1,22 +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.
-
-macro_rules! define_struct {
-    ($t:ty) => {
-        struct S1(pub $t);
-        struct S2(pub (in foo) ());
-        struct S3(pub $t ());
-        //~^ ERROR expected `,`, found `(`
-    }
-}
-
-mod foo {
-    define_struct! { (foo) }
-}
diff --git a/src/test/compile-fail/privacy/restricted/tuple-struct-fields/test3.rs b/src/test/compile-fail/privacy/restricted/tuple-struct-fields/test3.rs
deleted file mode 100644 (file)
index dd2cb0e..0000000
+++ /dev/null
@@ -1,22 +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.
-
-macro_rules! define_struct {
-    ($t:ty) => {
-        struct S1(pub($t));
-        struct S2(pub (in foo) ());
-        struct S3(pub($t) ());
-        //~^ ERROR expected `,`, found `(`
-    }
-}
-
-mod foo {
-    define_struct! { foo }
-}
index 25348a3bfd18fc864dd79adfb4f7b19cc87d14a3..e9e76af11a530a7c26056fe0205cbae229868aea 100644 (file)
@@ -13,7 +13,7 @@
 fn main() {
     struct Foo { x: isize }
     match (Foo { x: 10 }) {
-        Foo { ref x: ref x } => {}, //~ ERROR expected `,`, found `:`
+        Foo { ref x: ref x } => {}, //~ ERROR expected `,`
         _ => {}
     }
 }
index 41ff466f810ea262d8cd9237e50b0f7172c4e9ac..cf342ad94f990271e34c8f0eedfd5fac33727c2f 100644 (file)
@@ -12,6 +12,7 @@
 
 const C: [u32; 5] = [0; 5];
 
+#[allow(const_err)]
 fn test() -> u32 {
     C[10]
 }
index c5c823428bc94edfcf26095d60614c990252e7f1..3eb94682b20471d05a05eead80d74f9ef0009573 100644 (file)
@@ -12,6 +12,7 @@
 
 const C: &'static [u8; 5] = b"hello";
 
+#[allow(const_err)]
 fn test() -> u8 {
     C[10]
 }
index 9bc4b0025e55ad46f604fddd34a0438430a48d85..06bb6d4d2871378cc173b75cd81f49f8d26235be 100644 (file)
@@ -12,6 +12,7 @@
 
 const C: &'static [u8; 5] = b"hello";
 
+#[allow(const_err)]
 fn mir() -> u8 {
     C[10]
 }
index 403f4f79843e8c93020e5bad461a50d21712b55e..6f5e2affdbd3c3d33726a441350d7223ce98090e 100644 (file)
@@ -19,9 +19,9 @@
 extern crate syntax;
 
 use rustc::session::{build_session, Session};
-use rustc::session::config::{basic_options, Input,
+use rustc::session::config::{basic_options, Input, Options,
                              OutputType, OutputTypes};
-use rustc_driver::driver::{compile_input, CompileController};
+use rustc_driver::driver::{self, compile_input, CompileController};
 use rustc_metadata::cstore::CStore;
 use rustc_errors::registry::Registry;
 use syntax::codemap::FileName;
@@ -52,14 +52,7 @@ fn main() {}
     compile(src.to_string(), tmpdir.join("out"), sysroot.clone());
 }
 
-fn basic_sess(sysroot: PathBuf) -> (Session, Rc<CStore>, Box<CodegenBackend>) {
-    let mut opts = basic_options();
-    opts.output_types = OutputTypes::new(&[(OutputType::Exe, None)]);
-    opts.maybe_sysroot = Some(sysroot);
-    if let Ok(linker) = std::env::var("RUSTC_LINKER") {
-        opts.cg.linker = Some(linker.into());
-    }
-
+fn basic_sess(opts: Options) -> (Session, Rc<CStore>, Box<CodegenBackend>) {
     let descriptions = Registry::new(&rustc::DIAGNOSTICS);
     let sess = build_session(opts, None, descriptions);
     let codegen_backend = rustc_driver::get_codegen_backend(&sess);
@@ -70,19 +63,27 @@ fn basic_sess(sysroot: PathBuf) -> (Session, Rc<CStore>, Box<CodegenBackend>) {
 
 fn compile(code: String, output: PathBuf, sysroot: PathBuf) {
     syntax::with_globals(|| {
-        let (sess, cstore, codegen_backend) = basic_sess(sysroot);
-        let control = CompileController::basic();
-        let input = Input::Str { name: FileName::Anon, input: code };
-        let _ = compile_input(
-            codegen_backend,
-            &sess,
-            &cstore,
-            &None,
-            &input,
-            &None,
-            &Some(output),
-            None,
-            &control
-        );
+        let mut opts = basic_options();
+        opts.output_types = OutputTypes::new(&[(OutputType::Exe, None)]);
+        opts.maybe_sysroot = Some(sysroot);
+        if let Ok(linker) = std::env::var("RUSTC_LINKER") {
+            opts.cg.linker = Some(linker.into());
+        }
+        driver::spawn_thread_pool(opts, |opts| {
+            let (sess, cstore, codegen_backend) = basic_sess(opts);
+            let control = CompileController::basic();
+            let input = Input::Str { name: FileName::Anon, input: code };
+            let _ = compile_input(
+                codegen_backend,
+                &sess,
+                &cstore,
+                &None,
+                &input,
+                &None,
+                &Some(output),
+                None,
+                &control
+            );
+        });
     });
 }
index 9aa4f42c8ac86b2d71048801d723b990de5ed811..b3a6fb4d590ae279925001b94b39f85eaacdc8bd 100644 (file)
 
 use std::path::PathBuf;
 
-struct TestCalls {
-    count: u32
+struct TestCalls<'a> {
+    count: &'a mut u32
 }
 
-impl<'a> CompilerCalls<'a> for TestCalls {
+impl<'a> CompilerCalls<'a> for TestCalls<'a> {
     fn early_callback(&mut self,
                       _: &getopts::Matches,
                       _: &config::Options,
@@ -43,7 +43,7 @@ fn early_callback(&mut self,
                       _: &errors::registry::Registry,
                       _: config::ErrorOutputType)
                       -> Compilation {
-        self.count *= 2;
+        *self.count *= 2;
         Compilation::Continue
     }
 
@@ -56,13 +56,13 @@ fn late_callback(&mut self,
                      _: &Option<PathBuf>,
                      _: &Option<PathBuf>)
                      -> Compilation {
-        self.count *= 3;
+        *self.count *= 3;
         Compilation::Stop
     }
 
     fn some_input(&mut self, input: Input, input_path: Option<PathBuf>)
                   -> (Input, Option<PathBuf>) {
-        self.count *= 5;
+        *self.count *= 5;
         (input, input_path)
     }
 
@@ -77,7 +77,7 @@ fn no_input(&mut self,
         panic!("This shouldn't happen");
     }
 
-    fn build_controller(&mut self,
+    fn build_controller(self: Box<Self>,
                         _: &Session,
                         _: &getopts::Matches)
                         -> driver::CompileController<'a> {
@@ -87,9 +87,12 @@ fn build_controller(&mut self,
 
 
 fn main() {
-    let mut tc = TestCalls { count: 1 };
-    // we should never get use this filename, but lets make sure they are valid args.
-    let args = vec!["compiler-calls".to_string(), "foo.rs".to_string()];
-    rustc_driver::run_compiler(&args, &mut tc, None, None);
-    assert_eq!(tc.count, 30);
+    let mut count = 1;
+    {
+        let tc = TestCalls { count: &mut count };
+        // we should never get use this filename, but lets make sure they are valid args.
+        let args = vec!["compiler-calls".to_string(), "foo.rs".to_string()];
+        rustc_driver::run_compiler(&args, Box::new(tc), None, None);
+    }
+    assert_eq!(count, 30);
 }
index cad3996eadbfb3f6aad22eab1b8b14774c2170ff..cf4fee0e515c9b522f47b791d8c78c6cdf8db8df 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![allow(duplicate_macro_exports)]
+
 #[macro_export]
 macro_rules! foo { ($i:ident) => {} }
 
diff --git a/src/test/run-pass/auxiliary/two_macros_2.rs b/src/test/run-pass/auxiliary/two_macros_2.rs
new file mode 100644 (file)
index 0000000..b16cd3a
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+macro_rules! macro_one { ($($t:tt)*) => ($($t)*) }
+
+macro_rules! macro_two { ($($t:tt)*) => ($($t)*) }
diff --git a/src/test/run-pass/borrowck/borrowck-multiple-borrows-interior-boxes.rs b/src/test/run-pass/borrowck/borrowck-multiple-borrows-interior-boxes.rs
new file mode 100644 (file)
index 0000000..f57a7bd
--- /dev/null
@@ -0,0 +1,29 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test case from #39963.
+
+#![feature(nll)]
+
+#[derive(Clone)]
+struct Foo(Option<Box<Foo>>, Option<Box<Foo>>);
+
+fn test(f: &mut Foo) {
+  match *f {
+    Foo(Some(ref mut left), Some(ref mut right)) => match **left {
+      Foo(Some(ref mut left), Some(ref mut right)) => panic!(),
+      _ => panic!(),
+    },
+    _ => panic!(),
+  }
+}
+
+fn main() {
+}
diff --git a/src/test/run-pass/futures-api.rs b/src/test/run-pass/futures-api.rs
new file mode 100644 (file)
index 0000000..3b5a172
--- /dev/null
@@ -0,0 +1,95 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(arbitrary_self_types, futures_api, pin)]
+#![allow(unused)]
+
+use std::boxed::PinBox;
+use std::future::Future;
+use std::mem::PinMut;
+use std::rc::Rc;
+use std::sync::{
+    Arc,
+    atomic::{self, AtomicUsize},
+};
+use std::task::{
+    Context, Poll,
+    Wake, Waker, LocalWaker,
+    Executor, TaskObj, SpawnObjError,
+    local_waker, local_waker_from_nonlocal,
+};
+
+struct Counter {
+    local_wakes: AtomicUsize,
+    nonlocal_wakes: AtomicUsize,
+}
+
+impl Wake for Counter {
+    fn wake(this: &Arc<Self>) {
+        this.nonlocal_wakes.fetch_add(1, atomic::Ordering::SeqCst);
+    }
+
+    unsafe fn wake_local(this: &Arc<Self>) {
+        this.local_wakes.fetch_add(1, atomic::Ordering::SeqCst);
+    }
+}
+
+struct NoopExecutor;
+
+impl Executor for NoopExecutor {
+    fn spawn_obj(&mut self, _: TaskObj) -> Result<(), SpawnObjError> {
+        Ok(())
+    }
+}
+
+struct MyFuture;
+
+impl Future for MyFuture {
+    type Output = ();
+    fn poll(self: PinMut<Self>, cx: &mut Context) -> Poll<Self::Output> {
+        // Ensure all the methods work appropriately
+        cx.waker().wake();
+        cx.waker().wake();
+        cx.local_waker().wake();
+        cx.executor().spawn_obj(PinBox::new(MyFuture).into()).unwrap();
+        Poll::Ready(())
+    }
+}
+
+fn test_local_waker() {
+    let counter = Arc::new(Counter {
+        local_wakes: AtomicUsize::new(0),
+        nonlocal_wakes: AtomicUsize::new(0),
+    });
+    let waker = unsafe { local_waker(counter.clone()) };
+    let executor = &mut NoopExecutor;
+    let cx = &mut Context::new(&waker, executor);
+    assert_eq!(Poll::Ready(()), PinMut::new(&mut MyFuture).poll(cx));
+    assert_eq!(1, counter.local_wakes.load(atomic::Ordering::SeqCst));
+    assert_eq!(2, counter.nonlocal_wakes.load(atomic::Ordering::SeqCst));
+}
+
+fn test_local_as_nonlocal_waker() {
+    let counter = Arc::new(Counter {
+        local_wakes: AtomicUsize::new(0),
+        nonlocal_wakes: AtomicUsize::new(0),
+    });
+    let waker: LocalWaker = local_waker_from_nonlocal(counter.clone());
+    let executor = &mut NoopExecutor;
+    let cx = &mut Context::new(&waker, executor);
+    assert_eq!(Poll::Ready(()), PinMut::new(&mut MyFuture).poll(cx));
+    assert_eq!(0, counter.local_wakes.load(atomic::Ordering::SeqCst));
+    assert_eq!(3, counter.nonlocal_wakes.load(atomic::Ordering::SeqCst));
+}
+
+fn main() {
+    test_local_waker();
+    test_local_as_nonlocal_waker();
+}
index c08effe549328705ae5843475b2c4f54c5032033..b7e942f938321ae8f033a65909cea38975d856e2 100644 (file)
@@ -32,13 +32,25 @@ macro_rules! foo {
     } }
 }
 
+macro_rules! baz {
+    ($($a:ident),? ; $num:expr) => { { // comma separator is meaningless for `?`
+        let mut x = 0;
+
+        $(
+            x += $a;
+         )?
+
+        assert_eq!(x, $num);
+    } }
+}
+
 macro_rules! barplus {
     ($($a:ident)?+ ; $num:expr) => { {
         let mut x = 0;
 
         $(
             x += $a;
-         )?
+         )+
 
         assert_eq!(x, $num);
     } }
@@ -50,7 +62,7 @@ macro_rules! barstar {
 
         $(
             x += $a;
-         )?
+         )*
 
         assert_eq!(x, $num);
     } }
@@ -62,10 +74,15 @@ pub fn main() {
     // accept 0 or 1 repetitions
     foo!( ; 0);
     foo!(a ; 1);
+    baz!( ; 0);
+    baz!(a ; 1);
 
     // Make sure using ? as a separator works as before
-    barplus!(+ ; 0);
-    barplus!(a + ; 1);
-    barstar!(* ; 0);
-    barstar!(a * ; 1);
+    barplus!(a ; 1);
+    barplus!(a?a ; 2);
+    barplus!(a?a?a ; 3);
+    barstar!( ; 0);
+    barstar!(a ; 1);
+    barstar!(a?a ; 2);
+    barstar!(a?a?a ; 3);
 }
index e2f33963c4bad25318bc35eabe38dd7236fc9d26..fc91ea870d51af8c2beb270d708f896f1fd829d9 100644 (file)
@@ -20,12 +20,12 @@ pub fn main() {
 
     #[path = "auxiliary"]
     mod foo {
-        mod two_macros;
+        mod two_macros_2;
     }
 
     #[path = "auxiliary"]
     mod bar {
-        macro_rules! m { () => { mod two_macros; } }
+        macro_rules! m { () => { mod two_macros_2; } }
         m!();
     }
 }
index d1cb75909c155c81ef2f1fe0b16f6ca934de85e1..3fef19c51bd288722bb95fb8ec7a3cb765102f99 100644 (file)
@@ -14,6 +14,8 @@
 // ignore-mips64
 // ignore-powerpc
 // ignore-s390x
+// ignore-sparc
+// ignore-sparc64
 // ignore-wasm
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
index 78c5782be383368b2116a9d5323826a5fd8cee53..c93dcf019397b34eef0a91adc26ec9a92f805dd2 100644 (file)
@@ -14,6 +14,8 @@
 // ignore-mips64
 // ignore-powerpc
 // ignore-s390x
+// ignore-sparc
+// ignore-sparc64
 // ignore-wasm
 // ignore-cloudabi no processes
 // ignore-emscripten no processes
diff --git a/src/test/run-pass/trait-object-auto-dedup.rs b/src/test/run-pass/trait-object-auto-dedup.rs
new file mode 100644 (file)
index 0000000..9f5845f
--- /dev/null
@@ -0,0 +1,53 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that duplicate auto trait bounds in trait objects don't create new types.
+#[allow(unused_assignments)]
+
+use std::marker::Send as SendAlias;
+
+// A dummy trait for the non-auto trait.
+trait Trait {}
+
+// A dummy struct to implement Trait, Send, and .
+struct Struct;
+
+impl Trait for Struct {}
+
+// These three functions should be equivalent.
+fn takes_dyn_trait_send(_: Box<dyn Trait + Send>) {}
+fn takes_dyn_trait_send_send(_: Box<dyn Trait + Send + Send>) {}
+fn takes_dyn_trait_send_sendalias(_: Box<dyn Trait + Send + SendAlias>) {}
+
+impl dyn Trait + Send + Send {
+    fn do_nothing(&self) {}
+}
+
+fn main() {
+    // 1. Moving into a variable with more Sends and back.
+    let mut dyn_trait_send = Box::new(Struct) as Box<dyn Trait + Send>;
+    let dyn_trait_send_send: Box<dyn Trait + Send + Send> = dyn_trait_send;
+    dyn_trait_send = dyn_trait_send_send;
+
+    // 2. Calling methods with different number of Sends.
+    let dyn_trait_send = Box::new(Struct) as Box<dyn Trait + Send>;
+    takes_dyn_trait_send_send(dyn_trait_send);
+
+    let dyn_trait_send_send = Box::new(Struct) as Box<dyn Trait + Send + Send>;
+    takes_dyn_trait_send(dyn_trait_send_send);
+
+    // 3. Aliases to the trait are transparent.
+    let dyn_trait_send = Box::new(Struct) as Box<dyn Trait + Send>;
+    takes_dyn_trait_send_sendalias(dyn_trait_send);
+
+    // 4. Calling an impl that duplicates an auto trait.
+    let dyn_trait_send = Box::new(Struct) as Box<dyn Trait + Send>;
+    dyn_trait_send.do_nothing();
+}
index 830aaabf9d231c801fd9fac3f18e03d104fd1ccf..d6bc275b57a6a2e05420c996eea31b437362e0cf 100644 (file)
 
 // compile-pass
 
-//! Test with [Foo::baz], [Bar::foo], ...
-//!
-//! and [Uniooon::X].
+       //! Test with [Foo::baz], [Bar::foo], ...
+     //! , [Uniooon::X] and [Qux::Z].
+       //!
+      //! , [Uniooon::X] and [Qux::Z].
 
+       /// [Qux:Y]
 pub struct Foo {
     pub bar: usize,
 }
+
+/// Foo
+/// bar [BarA] bar
+/// baz
+pub fn a() {}
+
+/**
+ * Foo
+ * bar [BarB] bar
+ * baz
+ */
+pub fn b() {}
+
+/** Foo
+
+bar [BarC] bar
+baz
+
+    let bar_c_1 = 0;
+    let bar_c_2 = 0;
+    let g = [bar_c_1];
+    let h = g[bar_c_2];
+
+*/
+pub fn c() {}
+
+#[doc = "Foo\nbar [BarD] bar\nbaz"]
+pub fn d() {}
+
+macro_rules! f {
+    ($f:expr) => {
+        #[doc = $f]
+        pub fn f() {}
+    }
+}
+f!("Foo\nbar [BarF] bar\nbaz");
index 1e8e9f04c26ace303e17597274859488e1cee8f9..52adba5679fe0eb67a2996c57d958fc280694c05 100644 (file)
-warning: [Foo::baz] cannot be resolved, ignoring it...
-  --> $DIR/intra-links-warning.rs:13:1
+warning: `[Foo::baz]` cannot be resolved, ignoring it...
+  --> $DIR/intra-links-warning.rs:13:23
    |
-13 | / //! Test with [Foo::baz], [Bar::foo], ...
-14 | | //!
-15 | | //! and [Uniooon::X].
-   | |_____________________^
+13 |        //! Test with [Foo::baz], [Bar::foo], ...
+   |                       ^^^^^^^^ cannot be resolved, ignoring
+
+warning: `[Bar::foo]` cannot be resolved, ignoring it...
+  --> $DIR/intra-links-warning.rs:13:35
+   |
+13 |        //! Test with [Foo::baz], [Bar::foo], ...
+   |                                   ^^^^^^^^ cannot be resolved, ignoring
+
+warning: `[Uniooon::X]` cannot be resolved, ignoring it...
+  --> $DIR/intra-links-warning.rs:14:13
+   |
+14 |      //! , [Uniooon::X] and [Qux::Z].
+   |             ^^^^^^^^^^ cannot be resolved, ignoring
+
+warning: `[Qux::Z]` cannot be resolved, ignoring it...
+  --> $DIR/intra-links-warning.rs:14:30
+   |
+14 |      //! , [Uniooon::X] and [Qux::Z].
+   |                              ^^^^^^ cannot be resolved, ignoring
+
+warning: `[Uniooon::X]` cannot be resolved, ignoring it...
+  --> $DIR/intra-links-warning.rs:16:14
+   |
+16 |       //! , [Uniooon::X] and [Qux::Z].
+   |              ^^^^^^^^^^ cannot be resolved, ignoring
+
+warning: `[Qux::Z]` cannot be resolved, ignoring it...
+  --> $DIR/intra-links-warning.rs:16:31
+   |
+16 |       //! , [Uniooon::X] and [Qux::Z].
+   |                               ^^^^^^ cannot be resolved, ignoring
+
+warning: `[Qux:Y]` cannot be resolved, ignoring it...
+  --> $DIR/intra-links-warning.rs:18:13
+   |
+18 |        /// [Qux:Y]
+   |             ^^^^^ cannot be resolved, ignoring
+
+warning: `[BarA]` cannot be resolved, ignoring it...
+  --> $DIR/intra-links-warning.rs:24:10
+   |
+24 | /// bar [BarA] bar
+   |          ^^^^ cannot be resolved, ignoring
+
+warning: `[BarB]` cannot be resolved, ignoring it...
+  --> $DIR/intra-links-warning.rs:28:1
+   |
+28 | / /**
+29 | |  * Foo
+30 | |  * bar [BarB] bar
+31 | |  * baz
+32 | |  */
+   | |___^
+   |
+   = note: the link appears in this line:
+           
+            bar [BarB] bar
+                 ^^^^
+
+warning: `[BarC]` cannot be resolved, ignoring it...
+  --> $DIR/intra-links-warning.rs:35:1
+   |
+35 | / /** Foo
+36 | |
+37 | | bar [BarC] bar
+38 | | baz
+...  |
+44 | |
+45 | | */
+   | |__^
    |
    = note: the link appears in this line:
            
-            Test with [Foo::baz], [Bar::foo], ...
-                       ^^^^^^^^
+           bar [BarC] bar
+                ^^^^
 
-warning: [Bar::foo] cannot be resolved, ignoring it...
-  --> $DIR/intra-links-warning.rs:13:1
+warning: `[BarD]` cannot be resolved, ignoring it...
+  --> $DIR/intra-links-warning.rs:48:1
    |
-13 | / //! Test with [Foo::baz], [Bar::foo], ...
-14 | | //!
-15 | | //! and [Uniooon::X].
-   | |_____________________^
+48 | #[doc = "Foo/nbar [BarD] bar/nbaz"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the link appears in this line:
            
-            Test with [Foo::baz], [Bar::foo], ...
-                                   ^^^^^^^^
+           bar [BarD] bar
+                ^^^^
 
-warning: [Uniooon::X] cannot be resolved, ignoring it...
-  --> $DIR/intra-links-warning.rs:13:1
+warning: `[BarF]` cannot be resolved, ignoring it...
+  --> $DIR/intra-links-warning.rs:53:9
    |
-13 | / //! Test with [Foo::baz], [Bar::foo], ...
-14 | | //!
-15 | | //! and [Uniooon::X].
-   | |_____________________^
+53 |         #[doc = $f]
+   |         ^^^^^^^^^^^
+...
+57 | f!("Foo/nbar [BarF] bar/nbaz");
+   | ------------------------------- in this macro invocation
    |
    = note: the link appears in this line:
            
-            and [Uniooon::X].
-                 ^^^^^^^^^^
+           bar [BarF] bar
+                ^^^^
 
diff --git a/src/test/rustdoc/inline_cross/auxiliary/macros.rs b/src/test/rustdoc/inline_cross/auxiliary/macros.rs
new file mode 100644 (file)
index 0000000..39b52d6
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(staged_api)]
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+/// docs for my_macro
+#[unstable(feature = "macro_test", issue = "0")]
+#[rustc_deprecated(since = "1.2.3", reason = "text")]
+#[macro_export]
+macro_rules! my_macro {
+    () => ()
+}
diff --git a/src/test/rustdoc/inline_cross/macros.rs b/src/test/rustdoc/inline_cross/macros.rs
new file mode 100644 (file)
index 0000000..8d2f7d1
--- /dev/null
@@ -0,0 +1,28 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:macros.rs
+// build-aux-docs
+
+#![feature(macro_test)]
+#![feature(use_extern_macros)]
+
+#![crate_name = "foo"]
+
+extern crate macros;
+
+// @has foo/index.html '//*[@class="docblock-short"]' '[Deprecated] [Experimental]'
+
+// @has foo/macro.my_macro.html
+// @has - '//*[@class="docblock"]' 'docs for my_macro'
+// @has - '//*[@class="stab deprecated"]' 'Deprecated since 1.2.3: text'
+// @has - '//*[@class="stab unstable"]' 'macro_test'
+// @has - '//a/@href' '../src/macros/macros.rs.html#19-21'
+pub use macros::my_macro;
diff --git a/src/test/rustdoc/invalid.crate.name.rs b/src/test/rustdoc/invalid.crate.name.rs
new file mode 100644 (file)
index 0000000..4e4946a
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: --crate-name foo
+
+pub fn foo() {}
diff --git a/src/test/rustdoc/keyword.rs b/src/test/rustdoc/keyword.rs
new file mode 100644 (file)
index 0000000..b255ffd
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_name = "foo"]
+
+#![feature(doc_keyword)]
+
+// @has foo/index.html '//h2[@id="keywords"]' 'Keywords'
+// @has foo/index.html '//a[@href="keyword.match.html"]' 'match'
+// @has foo/keyword.match.html '//a[@class="keyword"]' 'match'
+// @has foo/keyword.match.html '//section[@id="main"]//div[@class="docblock"]//p' 'this is a test!'
+// @!has foo/index.html '//a/@href' 'foo/index.html'
+// @!has foo/foo/index.html
+// @!has-dir foo/foo
+#[doc(keyword = "match")]
+/// this is a test!
+mod foo{}
index 055a169deda74da9b934a2fd8a7a030a2f49b6a6..73a709b168613a35a361c8097ac6aabaa5885ef6 100644 (file)
@@ -12,6 +12,7 @@
 // ignore-emscripten
 // ignore-powerpc
 // ignore-sparc
+// ignore-sparc64
 // ignore-mips
 
 #![feature(asm)]
index d9fd4b26c390015f2e284ac87a94f140743c70e7..324dec77adcce8dbaa016c4dfeab71dd8233f81f 100644 (file)
@@ -1,5 +1,5 @@
 error[E0384]: cannot assign twice to immutable variable `x`
-  --> $DIR/asm-out-assign-imm.rs:30:9
+  --> $DIR/asm-out-assign-imm.rs:31:9
    |
 LL |     x = 1;
    |     ----- first assignment to `x`
diff --git a/src/test/ui/borrowck/mut-borrow-of-mut-ref.nll.stderr b/src/test/ui/borrowck/mut-borrow-of-mut-ref.nll.stderr
new file mode 100644 (file)
index 0000000..f8b84bc
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0596]: cannot borrow immutable item `b` as mutable
+  --> $DIR/mut-borrow-of-mut-ref.rs:18:7
+   |
+LL |     g(&mut b) //~ ERROR cannot borrow
+   |       ^^^^^^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/src/test/ui/borrowck/mut-borrow-of-mut-ref.rs b/src/test/ui/borrowck/mut-borrow-of-mut-ref.rs
new file mode 100644 (file)
index 0000000..75b9da5
--- /dev/null
@@ -0,0 +1,21 @@
+// 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.
+
+// Suggest not mutably borrowing a mutable reference
+
+fn main() {
+    f(&mut 0)
+}
+
+fn f(b: &mut i32) {
+    g(&mut b) //~ ERROR cannot borrow
+}
+
+fn g(_: &mut i32) {}
diff --git a/src/test/ui/borrowck/mut-borrow-of-mut-ref.stderr b/src/test/ui/borrowck/mut-borrow-of-mut-ref.stderr
new file mode 100644 (file)
index 0000000..885164c
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0596]: cannot borrow immutable argument `b` as mutable
+  --> $DIR/mut-borrow-of-mut-ref.rs:18:12
+   |
+LL |     g(&mut b) //~ ERROR cannot borrow
+   |            ^ cannot borrow mutably
+help: consider removing the `&mut`, as it is an immutable binding to a mutable reference
+   |
+LL |     g(b) //~ ERROR cannot borrow
+   |       ^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
index 63f33cafaf827f9440d3e3411a85dee82a3e678d..ce3d54ee46d933168f1774ed3cc99e00dde73f98 100644 (file)
 
 const NEG_128: i8 = -128;
 const NEG_NEG_128: i8 = -NEG_128;
-//~^ ERROR E0080
 
 fn main() {
     match -128i8 {
         NEG_NEG_128 => println!("A"),
+        //~^ ERROR could not evaluate constant pattern
         _ => println!("B"),
     }
 }
index 9cee718c286b6079599e531292990af90b245d57..e99d409880e072fdd07ae6810c3070d3e8caaef0 100644 (file)
@@ -1,12 +1,9 @@
-error[E0080]: constant evaluation error
-  --> $DIR/const-eval-overflow-2.rs:21:25
+error[E0080]: could not evaluate constant pattern
+  --> $DIR/const-eval-overflow-2.rs:25:9
    |
 LL | const NEG_NEG_128: i8 = -NEG_128;
-   |                         ^^^^^^^^ attempt to negate with overflow
-   |
-note: for pattern here
-  --> $DIR/const-eval-overflow-2.rs:26:9
-   |
+   |                         -------- attempt to negate with overflow
+...
 LL |         NEG_NEG_128 => println!("A"),
    |         ^^^^^^^^^^^
 
index ed14036b0b4cb85d47e6325ae5702bf5d2b4f4b1..9fc31b7c7278174d52773255dc3009f615e30c57 100644 (file)
@@ -20,9 +20,9 @@
 use std::{u8, u16, u32, u64, usize};
 
 const A_I8_T
+    //~^ ERROR could not evaluate constant expression
     : [u32; (i8::MAX as i8 + 1i8) as usize]
-    //~^ ERROR E0080
-    //~| ERROR attempt to add with overflow
+    //~^ ERROR attempt to add with overflow
     = [0; (i8::MAX as usize) + 1];
 
 fn main() {
index fc4762f0554f7828e09c9133e3befac80052f3bb..058c8730d7c9e23422da03814d608204a1d1e96d 100644 (file)
@@ -1,16 +1,21 @@
 error: attempt to add with overflow
-  --> $DIR/const-eval-overflow-4.rs:23:13
+  --> $DIR/const-eval-overflow-4.rs:24:13
    |
 LL |     : [u32; (i8::MAX as i8 + 1i8) as usize]
    |             ^^^^^^^^^^^^^^^^^^^^^
    |
    = note: #[deny(const_err)] on by default
 
-error[E0080]: constant evaluation error
-  --> $DIR/const-eval-overflow-4.rs:23:13
+error[E0080]: could not evaluate constant expression
+  --> $DIR/const-eval-overflow-4.rs:22:1
    |
-LL |     : [u32; (i8::MAX as i8 + 1i8) as usize]
-   |             ^^^^^^^^^^^^^^^^^^^^^ attempt to add with overflow
+LL | / const A_I8_T
+LL | |     //~^ ERROR could not evaluate constant expression
+LL | |     : [u32; (i8::MAX as i8 + 1i8) as usize]
+   | |             --------------------- attempt to add with overflow
+LL | |     //~^ ERROR attempt to add with overflow
+LL | |     = [0; (i8::MAX as usize) + 1];
+   | |__________________________________^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/const-eval/conditional_array_execution.nll.stderr b/src/test/ui/const-eval/conditional_array_execution.nll.stderr
new file mode 100644 (file)
index 0000000..3580950
--- /dev/null
@@ -0,0 +1,74 @@
+warning: attempt to subtract with overflow
+  --> $DIR/conditional_array_execution.rs:15:19
+   |
+LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
+   |                   ^^^^^
+   |
+note: lint level defined here
+  --> $DIR/conditional_array_execution.rs:11:9
+   |
+LL | #![warn(const_err)]
+   |         ^^^^^^^^^
+
+warning: this constant cannot be used
+  --> $DIR/conditional_array_execution.rs:15:1
+   |
+LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
+   | ^^^^^^^^^^^^^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                   |
+   |                   attempt to subtract with overflow
+
+warning: referenced constant
+  --> $DIR/conditional_array_execution.rs:20:20
+   |
+LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
+   |                   ----- attempt to subtract with overflow
+...
+LL |     println!("{}", FOO);
+   |                    ^^^
+
+warning: this expression will panic at runtime
+  --> $DIR/conditional_array_execution.rs:20:20
+   |
+LL |     println!("{}", FOO);
+   |                    ^^^ referenced constant has errors
+
+error[E0080]: referenced constant
+  --> $DIR/conditional_array_execution.rs:20:5
+   |
+LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
+   |                   ----- attempt to subtract with overflow
+...
+LL |     println!("{}", FOO);
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error[E0080]: erroneous constant used
+  --> $DIR/conditional_array_execution.rs:20:5
+   |
+LL |     println!("{}", FOO);
+   |     ^^^^^^^^^^^^^^^---^^
+   |                    |
+   |                    referenced constant has errors
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error[E0080]: referenced constant
+  --> $DIR/conditional_array_execution.rs:20:20
+   |
+LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
+   |                   ----- attempt to subtract with overflow
+...
+LL |     println!("{}", FOO);
+   |                    ^^^
+
+error[E0080]: erroneous constant used
+  --> $DIR/conditional_array_execution.rs:20:20
+   |
+LL |     println!("{}", FOO);
+   |                    ^^^ referenced constant has errors
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
index 8952a8386d7b8100bbcdb5f4d89796fc8343d214..ac555b25afdcd60647c1ec6200190777c544fa0a 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-pass
 #![warn(const_err)]
 
 const X: u32 = 5;
@@ -19,5 +18,8 @@
 
 fn main() {
     println!("{}", FOO);
-    //~^ WARN constant evaluation error
+    //~^ WARN this expression will panic at runtime
+    //~| WARN referenced constant
+    //~| ERROR erroneous constant used
+    //~| E0080
 }
index 5cf73b9fad66df9e23b5c416a71e728d753cc4d9..64010c946a7f1de863670d6d429a076f2b1f8846 100644 (file)
@@ -1,24 +1,53 @@
 warning: attempt to subtract with overflow
-  --> $DIR/conditional_array_execution.rs:16:19
+  --> $DIR/conditional_array_execution.rs:15:19
    |
 LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
    |                   ^^^^^
    |
 note: lint level defined here
-  --> $DIR/conditional_array_execution.rs:12:9
+  --> $DIR/conditional_array_execution.rs:11:9
    |
 LL | #![warn(const_err)]
    |         ^^^^^^^^^
 
 warning: this constant cannot be used
-  --> $DIR/conditional_array_execution.rs:16:1
+  --> $DIR/conditional_array_execution.rs:15:1
    |
 LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow
+   | ^^^^^^^^^^^^^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                   |
+   |                   attempt to subtract with overflow
 
-warning: constant evaluation error
-  --> $DIR/conditional_array_execution.rs:21:20
+warning: referenced constant
+  --> $DIR/conditional_array_execution.rs:20:20
+   |
+LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
+   |                   ----- attempt to subtract with overflow
+...
+LL |     println!("{}", FOO);
+   |                    ^^^
+
+warning: this expression will panic at runtime
+  --> $DIR/conditional_array_execution.rs:20:20
    |
 LL |     println!("{}", FOO);
    |                    ^^^ referenced constant has errors
 
+error[E0080]: referenced constant
+  --> $DIR/conditional_array_execution.rs:20:20
+   |
+LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
+   |                   ----- attempt to subtract with overflow
+...
+LL |     println!("{}", FOO);
+   |                    ^^^
+
+error[E0080]: erroneous constant used
+  --> $DIR/conditional_array_execution.rs:20:20
+   |
+LL |     println!("{}", FOO);
+   |                    ^^^ referenced constant has errors
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/const-eval/index_out_of_bound.rs b/src/test/ui/const-eval/index_out_of_bound.rs
deleted file mode 100644 (file)
index e7ffbe8..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-static FOO: i32 = [][0];
-//~^ ERROR E0080
-
-fn main() {}
diff --git a/src/test/ui/const-eval/index_out_of_bound.stderr b/src/test/ui/const-eval/index_out_of_bound.stderr
deleted file mode 100644 (file)
index d16231c..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0080]: constant evaluation error
-  --> $DIR/index_out_of_bound.rs:11:19
-   |
-LL | static FOO: i32 = [][0];
-   |                   ^^^^^ index out of bounds: the len is 0 but the index is 0
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/const-eval/index_out_of_bounds.rs b/src/test/ui/const-eval/index_out_of_bounds.rs
new file mode 100644 (file)
index 0000000..55c64d2
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+static FOO: i32 = [][0];
+//~^ ERROR E0080
+//~| ERROR E0080
+
+fn main() {
+    let array = [std::env::args().len()];
+    array[1]; //~ ERROR index out of bounds
+}
diff --git a/src/test/ui/const-eval/index_out_of_bounds.stderr b/src/test/ui/const-eval/index_out_of_bounds.stderr
new file mode 100644 (file)
index 0000000..828fba5
--- /dev/null
@@ -0,0 +1,25 @@
+error[E0080]: could not evaluate static initializer
+  --> $DIR/index_out_of_bounds.rs:11:19
+   |
+LL | static FOO: i32 = [][0];
+   |                   ^^^^^ index out of bounds: the len is 0 but the index is 0
+
+error[E0080]: could not evaluate static initializer
+  --> $DIR/index_out_of_bounds.rs:11:1
+   |
+LL | static FOO: i32 = [][0];
+   | ^^^^^^^^^^^^^^^^^^-----^
+   |                   |
+   |                   index out of bounds: the len is 0 but the index is 0
+
+error: index out of bounds: the len is 1 but the index is 1
+  --> $DIR/index_out_of_bounds.rs:17:5
+   |
+LL |     array[1]; //~ ERROR index out of bounds
+   |     ^^^^^^^^
+   |
+   = note: #[deny(const_err)] on by default
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/const-eval/issue-43197.nll.stderr b/src/test/ui/const-eval/issue-43197.nll.stderr
new file mode 100644 (file)
index 0000000..3bde12a
--- /dev/null
@@ -0,0 +1,118 @@
+warning: attempt to subtract with overflow
+  --> $DIR/issue-43197.rs:20:20
+   |
+LL |     const X: u32 = 0-1;
+   |                    ^^^
+   |
+note: lint level defined here
+  --> $DIR/issue-43197.rs:11:9
+   |
+LL | #![warn(const_err)]
+   |         ^^^^^^^^^
+
+warning: this constant cannot be used
+  --> $DIR/issue-43197.rs:20:5
+   |
+LL |     const X: u32 = 0-1;
+   |     ^^^^^^^^^^^^^^^---^
+   |                    |
+   |                    attempt to subtract with overflow
+
+warning: attempt to subtract with overflow
+  --> $DIR/issue-43197.rs:23:24
+   |
+LL |     const Y: u32 = foo(0-1);
+   |                        ^^^
+
+warning: this constant cannot be used
+  --> $DIR/issue-43197.rs:23:5
+   |
+LL |     const Y: u32 = foo(0-1);
+   |     ^^^^^^^^^^^^^^^^^^^---^^
+   |                        |
+   |                        attempt to subtract with overflow
+
+warning: referenced constant
+  --> $DIR/issue-43197.rs:26:23
+   |
+LL |     const X: u32 = 0-1;
+   |                    --- attempt to subtract with overflow
+...
+LL |     println!("{} {}", X, Y);
+   |                       ^
+
+warning: this expression will panic at runtime
+  --> $DIR/issue-43197.rs:26:23
+   |
+LL |     println!("{} {}", X, Y);
+   |                       ^ referenced constant has errors
+
+warning: referenced constant
+  --> $DIR/issue-43197.rs:26:26
+   |
+LL |     const Y: u32 = foo(0-1);
+   |                        --- attempt to subtract with overflow
+...
+LL |     println!("{} {}", X, Y);
+   |                          ^
+
+warning: this expression will panic at runtime
+  --> $DIR/issue-43197.rs:26:26
+   |
+LL |     println!("{} {}", X, Y);
+   |                          ^ referenced constant has errors
+
+error[E0080]: referenced constant
+  --> $DIR/issue-43197.rs:26:5
+   |
+LL |     const X: u32 = 0-1;
+   |                    --- attempt to subtract with overflow
+...
+LL |     println!("{} {}", X, Y);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error[E0080]: erroneous constant used
+  --> $DIR/issue-43197.rs:26:5
+   |
+LL |     println!("{} {}", X, Y);
+   |     ^^^^^^^^^^^^^^^^^^-^^^^^
+   |                       |
+   |                       referenced constant has errors
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error[E0080]: referenced constant
+  --> $DIR/issue-43197.rs:26:26
+   |
+LL |     const Y: u32 = foo(0-1);
+   |                        --- attempt to subtract with overflow
+...
+LL |     println!("{} {}", X, Y);
+   |                          ^
+
+error[E0080]: erroneous constant used
+  --> $DIR/issue-43197.rs:26:26
+   |
+LL |     println!("{} {}", X, Y);
+   |                          ^ referenced constant has errors
+
+error[E0080]: referenced constant
+  --> $DIR/issue-43197.rs:26:23
+   |
+LL |     const X: u32 = 0-1;
+   |                    --- attempt to subtract with overflow
+...
+LL |     println!("{} {}", X, Y);
+   |                       ^
+
+error[E0080]: erroneous constant used
+  --> $DIR/issue-43197.rs:26:23
+   |
+LL |     println!("{} {}", X, Y);
+   |                       ^ referenced constant has errors
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
index 7ec100e411b36d6b26222398d6acb0729ff8b626..03aa65eb274671716088717e03ab1db03b76693e 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-pass
 #![warn(const_err)]
 
 #![feature(const_fn)]
@@ -25,6 +24,12 @@ fn main() {
     //~^ WARN attempt to subtract with overflow
     //~| WARN this constant cannot be used
     println!("{} {}", X, Y);
-    //~^ WARN constant evaluation error
-    //~| WARN constant evaluation error
+    //~^ WARN this expression will panic at runtime
+    //~| WARN this expression will panic at runtime
+    //~| ERROR erroneous constant used
+    //~| ERROR erroneous constant used
+    //~| ERROR E0080
+    //~| ERROR E0080
+    //~| WARN referenced constant
+    //~| WARN referenced constant
 }
index d0e13d5657e754866e6d497eab91e7137b1fc700..071d878730744b409a2b47cb32040ef5ab4a91eb 100644 (file)
@@ -1,42 +1,97 @@
 warning: attempt to subtract with overflow
-  --> $DIR/issue-43197.rs:21:20
+  --> $DIR/issue-43197.rs:20:20
    |
 LL |     const X: u32 = 0-1;
    |                    ^^^
    |
 note: lint level defined here
-  --> $DIR/issue-43197.rs:12:9
+  --> $DIR/issue-43197.rs:11:9
    |
 LL | #![warn(const_err)]
    |         ^^^^^^^^^
 
 warning: this constant cannot be used
-  --> $DIR/issue-43197.rs:21:5
+  --> $DIR/issue-43197.rs:20:5
    |
 LL |     const X: u32 = 0-1;
-   |     ^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow
+   |     ^^^^^^^^^^^^^^^---^
+   |                    |
+   |                    attempt to subtract with overflow
 
 warning: attempt to subtract with overflow
-  --> $DIR/issue-43197.rs:24:24
+  --> $DIR/issue-43197.rs:23:24
    |
 LL |     const Y: u32 = foo(0-1);
    |                        ^^^
 
 warning: this constant cannot be used
-  --> $DIR/issue-43197.rs:24:5
+  --> $DIR/issue-43197.rs:23:5
    |
 LL |     const Y: u32 = foo(0-1);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow
+   |     ^^^^^^^^^^^^^^^^^^^---^^
+   |                        |
+   |                        attempt to subtract with overflow
 
-warning: constant evaluation error
-  --> $DIR/issue-43197.rs:27:23
+warning: referenced constant
+  --> $DIR/issue-43197.rs:26:23
+   |
+LL |     const X: u32 = 0-1;
+   |                    --- attempt to subtract with overflow
+...
+LL |     println!("{} {}", X, Y);
+   |                       ^
+
+warning: this expression will panic at runtime
+  --> $DIR/issue-43197.rs:26:23
    |
 LL |     println!("{} {}", X, Y);
    |                       ^ referenced constant has errors
 
-warning: constant evaluation error
-  --> $DIR/issue-43197.rs:27:26
+warning: referenced constant
+  --> $DIR/issue-43197.rs:26:26
+   |
+LL |     const Y: u32 = foo(0-1);
+   |                        --- attempt to subtract with overflow
+...
+LL |     println!("{} {}", X, Y);
+   |                          ^
+
+warning: this expression will panic at runtime
+  --> $DIR/issue-43197.rs:26:26
    |
 LL |     println!("{} {}", X, Y);
    |                          ^ referenced constant has errors
 
+error[E0080]: referenced constant
+  --> $DIR/issue-43197.rs:26:26
+   |
+LL |     const Y: u32 = foo(0-1);
+   |                        --- attempt to subtract with overflow
+...
+LL |     println!("{} {}", X, Y);
+   |                          ^
+
+error[E0080]: erroneous constant used
+  --> $DIR/issue-43197.rs:26:26
+   |
+LL |     println!("{} {}", X, Y);
+   |                          ^ referenced constant has errors
+
+error[E0080]: referenced constant
+  --> $DIR/issue-43197.rs:26:23
+   |
+LL |     const X: u32 = 0-1;
+   |                    --- attempt to subtract with overflow
+...
+LL |     println!("{} {}", X, Y);
+   |                       ^
+
+error[E0080]: erroneous constant used
+  --> $DIR/issue-43197.rs:26:23
+   |
+LL |     println!("{} {}", X, Y);
+   |                       ^ referenced constant has errors
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/const-eval/issue-44578.nll.stderr b/src/test/ui/const-eval/issue-44578.nll.stderr
new file mode 100644 (file)
index 0000000..ad4f089
--- /dev/null
@@ -0,0 +1,39 @@
+error[E0080]: referenced constant
+  --> $DIR/issue-44578.rs:35:5
+   |
+LL |     const AMT: usize = [A::AMT][(A::AMT > B::AMT) as usize];
+   |                        ------------------------------------ index out of bounds: the len is 1 but the index is 1
+...
+LL |     println!("{}", <Bar<u16, u8> as Foo>::AMT);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error[E0080]: erroneous constant used
+  --> $DIR/issue-44578.rs:35:5
+   |
+LL |     println!("{}", <Bar<u16, u8> as Foo>::AMT);
+   |     ^^^^^^^^^^^^^^^--------------------------^^
+   |                    |
+   |                    referenced constant has errors
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error[E0080]: referenced constant
+  --> $DIR/issue-44578.rs:35:20
+   |
+LL |     const AMT: usize = [A::AMT][(A::AMT > B::AMT) as usize];
+   |                        ------------------------------------ index out of bounds: the len is 1 but the index is 1
+...
+LL |     println!("{}", <Bar<u16, u8> as Foo>::AMT);
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0080]: erroneous constant used
+  --> $DIR/issue-44578.rs:35:20
+   |
+LL |     println!("{}", <Bar<u16, u8> as Foo>::AMT);
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
index 4133a8864f619b39088ed3ad696be37be27c1787..59ac4ab311c6cc19163ab10ae70a3b86d00b5517 100644 (file)
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-pass
-#![warn(const_err)]
+#![allow(const_err)]
 
 trait Foo {
     const AMT: usize;
@@ -33,6 +32,7 @@ impl Foo for u16 {
 }
 
 fn main() {
-    println!("{}", <Bar<u16, u8> as Foo>::AMT); //~ WARN const_err
-    //~^ WARN const_err
+    println!("{}", <Bar<u16, u8> as Foo>::AMT);
+    //~^ ERROR erroneous constant used
+    //~| ERROR E0080
 }
index ce6ff86610aa5d4a08f0dcb9aee512bfecd26c74..28a723a069edf5eda39331c0c3c14158d6198571 100644 (file)
@@ -1,18 +1,18 @@
-warning: constant evaluation error
-  --> $DIR/issue-44578.rs:36:20
+error[E0080]: referenced constant
+  --> $DIR/issue-44578.rs:35:20
    |
-LL |     println!("{}", <Bar<u16, u8> as Foo>::AMT); //~ WARN const_err
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
-   |
-note: lint level defined here
-  --> $DIR/issue-44578.rs:12:9
-   |
-LL | #![warn(const_err)]
-   |         ^^^^^^^^^
+LL |     const AMT: usize = [A::AMT][(A::AMT > B::AMT) as usize];
+   |                        ------------------------------------ index out of bounds: the len is 1 but the index is 1
+...
+LL |     println!("{}", <Bar<u16, u8> as Foo>::AMT);
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: constant evaluation error
-  --> $DIR/issue-44578.rs:36:20
+error[E0080]: erroneous constant used
+  --> $DIR/issue-44578.rs:35:20
    |
-LL |     println!("{}", <Bar<u16, u8> as Foo>::AMT); //~ WARN const_err
+LL |     println!("{}", <Bar<u16, u8> as Foo>::AMT);
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
 
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/const-eval/issue-50814-2.rs b/src/test/ui/const-eval/issue-50814-2.rs
new file mode 100644 (file)
index 0000000..af627ee
--- /dev/null
@@ -0,0 +1,43 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait C {
+    const BOO: usize;
+}
+
+trait Foo<T> {
+    const BAR: usize;
+}
+
+struct A<T>(T);
+
+impl<T: C> Foo<T> for A<T> {
+    const BAR: usize = [5, 6, 7][T::BOO];
+}
+
+fn foo<T: C>() -> &'static usize {
+    &<A<T> as Foo<T>>::BAR //~ ERROR erroneous constant used
+//~| ERROR E0080
+}
+
+impl C for () {
+    const BOO: usize = 42;
+}
+
+impl C for u32 {
+    const BOO: usize = 1;
+}
+
+fn main() {
+    println!("{:x}", foo::<()>() as *const usize as usize);
+    println!("{:x}", foo::<u32>() as *const usize as usize);
+    println!("{:x}", foo::<()>());
+    println!("{:x}", foo::<u32>());
+}
diff --git a/src/test/ui/const-eval/issue-50814-2.stderr b/src/test/ui/const-eval/issue-50814-2.stderr
new file mode 100644 (file)
index 0000000..3c59cb0
--- /dev/null
@@ -0,0 +1,20 @@
+error[E0080]: referenced constant
+  --> $DIR/issue-50814-2.rs:26:5
+   |
+LL |     const BAR: usize = [5, 6, 7][T::BOO];
+   |                        ----------------- index out of bounds: the len is 3 but the index is 42
+...
+LL |     &<A<T> as Foo<T>>::BAR //~ ERROR erroneous constant used
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0080]: erroneous constant used
+  --> $DIR/issue-50814-2.rs:26:5
+   |
+LL |     &<A<T> as Foo<T>>::BAR //~ ERROR erroneous constant used
+   |     ^---------------------
+   |      |
+   |      referenced constant has errors
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/const-eval/issue-50814.rs b/src/test/ui/const-eval/issue-50814.rs
new file mode 100644 (file)
index 0000000..8f27524
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Unsigned {
+    const MAX: u8;
+}
+
+struct U8(u8);
+impl Unsigned for U8 {
+    const MAX: u8 = 0xff;
+}
+
+struct Sum<A,B>(A,B);
+
+impl<A: Unsigned, B: Unsigned> Unsigned for Sum<A,B> {
+    const MAX: u8 = A::MAX + B::MAX;
+}
+
+fn foo<T>(_: T) -> &'static u8 {
+    &Sum::<U8,U8>::MAX //~ ERROR erroneous constant used
+//~| ERROR E0080
+}
+
+fn main() {
+    foo(0);
+}
diff --git a/src/test/ui/const-eval/issue-50814.stderr b/src/test/ui/const-eval/issue-50814.stderr
new file mode 100644 (file)
index 0000000..145279c
--- /dev/null
@@ -0,0 +1,20 @@
+error[E0080]: referenced constant
+  --> $DIR/issue-50814.rs:27:5
+   |
+LL |     const MAX: u8 = A::MAX + B::MAX;
+   |                     --------------- attempt to add with overflow
+...
+LL |     &Sum::<U8,U8>::MAX //~ ERROR erroneous constant used
+   |     ^^^^^^^^^^^^^^^^^^
+
+error[E0080]: erroneous constant used
+  --> $DIR/issue-50814.rs:27:5
+   |
+LL |     &Sum::<U8,U8>::MAX //~ ERROR erroneous constant used
+   |     ^-----------------
+   |      |
+   |      referenced constant has errors
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/const-eval/issue-51300.rs b/src/test/ui/const-eval/issue-51300.rs
new file mode 100644 (file)
index 0000000..f91711c
--- /dev/null
@@ -0,0 +1,41 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-pass
+// https://github.com/rust-lang/rust/issues/51300
+
+#[derive(PartialEq, Eq, Clone, Copy)]
+pub struct Stat {
+    pub id: u8,
+    pub index: usize,
+}
+
+impl Stat {
+    pub const STUDENT_HAPPINESS: Stat = Stat{
+        id: 0,
+        index: 0,
+    };
+    pub const STUDENT_HUNGER: Stat = Stat{
+        id: 0,
+        index: Self::STUDENT_HAPPINESS.index + 1,
+    };
+
+}
+
+pub fn from_index(id: u8, index: usize) -> Option<Stat> {
+    let stat = Stat{id, index};
+    match stat {
+        Stat::STUDENT_HAPPINESS => Some(Stat::STUDENT_HAPPINESS),
+        Stat::STUDENT_HUNGER => Some(Stat::STUDENT_HUNGER),
+        _ => None,
+    }
+}
+
+fn main() { }
index 5ced2c9dd8f59861968732026fe866bdcf3e7adf..4888ed6e8dc7b3822ae92fae9da914ff6ef4897c 100644 (file)
@@ -23,8 +23,8 @@ const fn bar() -> u8 {
         // is run on a system whose pointers need more
         // than 8 bits
         Bar { a: &42 }.b as u8
-        //~^ constant evaluation error
-        //~| constant evaluation error
+        //~^ ERROR this expression will panic at runtime
+        //~| ERROR this expression will panic at runtime
     }
 }
 
index f910705bb7b3ce02cabd42ef4fccbdc1fa6e75e5..d805e1a27c9938811c43fc73f14c1d70afae2584 100644 (file)
@@ -1,4 +1,4 @@
-error: constant evaluation error
+error: this expression will panic at runtime
   --> $DIR/promoted_const_fn_fail.rs:25:9
    |
 LL |         Bar { a: &42 }.b as u8
@@ -9,23 +9,12 @@ note: lint level defined here
    |
 LL | #![deny(const_err)]
    |         ^^^^^^^^^
-note: inside call to `bar`
-  --> $DIR/promoted_const_fn_fail.rs:35:28
-   |
-LL |     let x: &'static u8 = &(bar() + 1);
-   |                            ^^^^^
 
-error: constant evaluation error
+error: this expression will panic at runtime
   --> $DIR/promoted_const_fn_fail.rs:25:9
    |
 LL |         Bar { a: &42 }.b as u8
    |         ^^^^^^^^^^^^^^^^^^^^^^ a raw memory access tried to access part of a pointer value as raw bytes
-   |
-note: inside call to `bar`
-  --> $DIR/promoted_const_fn_fail.rs:35:28
-   |
-LL |     let x: &'static u8 = &(bar() + 1);
-   |                            ^^^^^
 
 error: aborting due to 2 previous errors
 
index 683ee5375fbf6eed3c56e8ad5787d86de59fb359..a4c1c48a03dfe30f1a5a5f6f3076b9e7ccd884a8 100644 (file)
@@ -1,4 +1,4 @@
-warning: constant evaluation error
+warning: this expression will panic at runtime
   --> $DIR/promoted_errors.rs:17:14
    |
 LL |     let _x = 0u32 - 1;
@@ -16,7 +16,7 @@ warning: attempt to divide by zero
 LL |     println!("{}", 1/(1-1));
    |                    ^^^^^^^
 
-warning: constant evaluation error
+warning: this expression will panic at runtime
   --> $DIR/promoted_errors.rs:19:20
    |
 LL |     println!("{}", 1/(1-1));
@@ -28,13 +28,13 @@ warning: attempt to divide by zero
 LL |     let _x = 1/(1-1);
    |              ^^^^^^^
 
-warning: constant evaluation error
+warning: this expression will panic at runtime
   --> $DIR/promoted_errors.rs:22:14
    |
 LL |     let _x = 1/(1-1);
    |              ^^^^^^^ attempt to divide by zero
 
-warning: constant evaluation error
+warning: this expression will panic at runtime
   --> $DIR/promoted_errors.rs:25:20
    |
 LL |     println!("{}", 1/(false as u32));
index 068825f1cd3106871f62c388bf84df8e9927fe37..352289417547e20a562e339df3b2460bb93e2c96 100644 (file)
@@ -14,7 +14,9 @@ warning: this constant cannot be used
   --> $DIR/pub_const_err.rs:16:1
    |
 LL | pub const Z: u32 = 0 - 1;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow
+   | ^^^^^^^^^^^^^^^^^^^-----^
+   |                    |
+   |                    attempt to subtract with overflow
 
 warning: attempt to subtract with overflow
   --> $DIR/pub_const_err.rs:20:22
index dcb8125fc55bcf4aee646145d33a44fde4850e09..a6db2176011d598e61ba6147d5350c8b4aa220ea 100644 (file)
@@ -14,7 +14,9 @@ warning: this constant cannot be used
   --> $DIR/pub_const_err_bin.rs:14:1
    |
 LL | pub const Z: u32 = 0 - 1;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow
+   | ^^^^^^^^^^^^^^^^^^^-----^
+   |                    |
+   |                    attempt to subtract with overflow
 
 warning: attempt to subtract with overflow
   --> $DIR/pub_const_err_bin.rs:18:22
index 17dc9f94fe19c80c4ed26e877e121b5b34e43c3e..6eda41730b3073e6052a6b39ff58959b8e175d7d 100644 (file)
@@ -19,7 +19,6 @@ const fn f(x: usize) -> usize {
     for i in 0..x {
         //~^ ERROR E0015
         //~| ERROR E0019
-        //~| ERROR E0080
         sum += i;
     }
     sum
@@ -27,5 +26,5 @@ const fn f(x: usize) -> usize {
 
 #[allow(unused_variables)]
 fn main() {
-    let a : [i32; f(X)];
+    let a : [i32; f(X)]; //~ ERROR E0080
 }
index 29edc2756afff2fa1978f8bd26c7f154111abef6..cdbf86f42ecc03592cf383d4db9bcda1b20fc2dd 100644 (file)
@@ -26,20 +26,16 @@ error[E0019]: constant function contains unimplemented expression type
 LL |     for i in 0..x {
    |              ^^^^
 
-error[E0080]: constant evaluation error
-  --> $DIR/const-fn-error.rs:19:14
+error[E0080]: could not evaluate constant expression
+  --> $DIR/const-fn-error.rs:29:13
    |
 LL |     for i in 0..x {
-   |              ^^^^ calling non-const fn `<I as std::iter::IntoIterator><std::ops::Range<usize>>::into_iter`
+   |              ---- calling non-const fn `<I as std::iter::IntoIterator><std::ops::Range<usize>>::into_iter`
 ...
-LL |     let a : [i32; f(X)];
-   |                   ---- inside call to `f`
-   |
-note: for constant expression here
-  --> $DIR/const-fn-error.rs:30:13
-   |
-LL |     let a : [i32; f(X)];
-   |             ^^^^^^^^^^^
+LL |     let a : [i32; f(X)]; //~ ERROR E0080
+   |             ^^^^^^----^
+   |                   |
+   |                   inside call to `f`
 
 error: aborting due to 5 previous errors
 
index 453e332a903c7bbdffe559e55fc1d553f033702b..20b8865767459793351b132fe896878a2543496c 100644 (file)
@@ -21,4 +21,5 @@
 fn main() {
     let a: [i8; LEN] = unimplemented!();
 //~^ ERROR E0080
+//~| ERROR E0080
 }
index 48ff7a81c24ee1fe491f94316e51dc2b952b77a3..630828ef8f5178adbacc2bc7a9b4d55c4069e824 100644 (file)
@@ -12,12 +12,23 @@ error[E0080]: constant evaluation error
 LL | const LEN: usize = ONE - TWO;
    |                    ^^^^^^^^^ attempt to subtract with overflow
 
-error[E0080]: constant evaluation error
-  --> $DIR/const-len-underflow-separate-spans.rs:22:17
+error[E0080]: referenced constant
+  --> $DIR/const-len-underflow-separate-spans.rs:22:12
+   |
+LL | const LEN: usize = ONE - TWO;
+   |                    --------- attempt to subtract with overflow
+...
+LL |     let a: [i8; LEN] = unimplemented!();
+   |            ^^^^^^^^^
+
+error[E0080]: could not evaluate constant expression
+  --> $DIR/const-len-underflow-separate-spans.rs:22:12
    |
 LL |     let a: [i8; LEN] = unimplemented!();
-   |                 ^^^ referenced constant has errors
+   |            ^^^^^---^
+   |                 |
+   |                 referenced constant has errors
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
index a80593e05f1056d01dfafdba42a06dbfe7ca8402..9d0ab21ffaf0e3259157dab6b3acf1a8dc995ca7 100644 (file)
@@ -10,10 +10,12 @@ LL |         (&mut self).bar(); //~ ERROR cannot borrow
 error[E0596]: cannot borrow immutable argument `self` as mutable
   --> $DIR/issue-31424.rs:23:15
    |
-LL |     fn bar(self: &mut Self) {
-   |            --------------- consider changing this to `mut self: &mut Self`
 LL |         (&mut self).bar(); //~ ERROR cannot borrow
    |               ^^^^ cannot borrow mutably
+help: consider removing the `&mut`, as it is an immutable binding to a mutable reference
+   |
+LL |         self.bar(); //~ ERROR cannot borrow
+   |         ^^^^
 
 error: aborting due to 2 previous errors
 
index 25ec5c458312d8eb21cce4f1c8d6f56e7568ce54..a213c2b1b208e5294612026c31b0adcec654f39d 100644 (file)
@@ -6,7 +6,7 @@ LL |     X = (1 << 500), //~ ERROR E0080
    |
    = note: #[deny(exceeding_bitshifts)] on by default
 
-error[E0080]: constant evaluation error
+error[E0080]: could not evaluate enum discriminant
   --> $DIR/E0080.rs:12:9
    |
 LL |     X = (1 << 500), //~ ERROR E0080
@@ -20,13 +20,13 @@ LL |     Y = (1 / 0) //~ ERROR E0080
    |
    = note: #[deny(const_err)] on by default
 
-error: constant evaluation error
+error: this expression will panic at runtime
   --> $DIR/E0080.rs:14:9
    |
 LL |     Y = (1 / 0) //~ ERROR E0080
    |         ^^^^^^^ attempt to divide by zero
 
-error[E0080]: constant evaluation error
+error[E0080]: could not evaluate enum discriminant
   --> $DIR/E0080.rs:14:9
    |
 LL |     Y = (1 / 0) //~ ERROR E0080
index f5fea77cf9639a001500ece7b31521280b88a88e..7d71499d3186b2839158eb63b3b01cf9971236e2 100644 (file)
@@ -13,3 +13,22 @@ fn main () {
 
     let f = Foo(); //~ ERROR E0423
 }
+
+fn bar() {
+    struct S { x: i32, y: i32 }
+    #[derive(PartialEq)]
+    struct T {}
+
+    if let S { x: _x, y: 2 } = S { x: 1, y: 2 } { println!("Ok"); }
+    //~^ ERROR E0423
+    //~|  expected type, found `1`
+    if T {} == T {} { println!("Ok"); }
+    //~^ ERROR E0423
+    //~| ERROR expected expression, found `==`
+}
+
+fn foo() {
+    for _ in std::ops::Range { start: 0, end: 10 } {}
+    //~^ ERROR E0423
+    //~| ERROR expected type, found `0`
+}
index ef24295332d515e3bebbb72d6e813f5b5b515f13..477c698ac9af1be647489fab6eac8f67d8fae0ad 100644 (file)
@@ -1,9 +1,48 @@
+error: expected type, found `1`
+  --> $DIR/E0423.rs:22:39
+   |
+LL |     if let S { x: _x, y: 2 } = S { x: 1, y: 2 } { println!("Ok"); }
+   |                                       ^ expecting a type here because of type ascription
+
+error: expected expression, found `==`
+  --> $DIR/E0423.rs:25:13
+   |
+LL |     if T {} == T {} { println!("Ok"); }
+   |             ^^ expected expression
+
+error: expected type, found `0`
+  --> $DIR/E0423.rs:31:39
+   |
+LL |     for _ in std::ops::Range { start: 0, end: 10 } {}
+   |                                       ^ expecting a type here because of type ascription
+
 error[E0423]: expected function, found struct `Foo`
   --> $DIR/E0423.rs:14:13
    |
 LL |     let f = Foo(); //~ ERROR E0423
-   |             ^^^ did you mean `Foo { /* fields */ }`?
+   |             ^^^
+   |             |
+   |             did you mean `foo`?
+   |             did you mean `Foo { /* fields */ }`?
+
+error[E0423]: expected value, found struct `S`
+  --> $DIR/E0423.rs:22:32
+   |
+LL |     if let S { x: _x, y: 2 } = S { x: 1, y: 2 } { println!("Ok"); }
+   |                                ^ did you mean `(S { /* fields */ })`?
+
+error[E0423]: expected value, found struct `T`
+  --> $DIR/E0423.rs:25:8
+   |
+LL |     if T {} == T {} { println!("Ok"); }
+   |        ^ did you mean `(T { /* fields */ })`?
+
+error[E0423]: expected value, found struct `std::ops::Range`
+  --> $DIR/E0423.rs:31:14
+   |
+LL |     for _ in std::ops::Range { start: 0, end: 10 } {}
+   |              ^^^^^^^^^^^^^^^ did you mean `(std::ops::Range { /* fields */ })`?
 
-error: aborting due to previous error
+error: aborting due to 7 previous errors
 
 For more information about this error, try `rustc --explain E0423`.
diff --git a/src/test/ui/feature-gate-doc_keyword.rs b/src/test/ui/feature-gate-doc_keyword.rs
new file mode 100644 (file)
index 0000000..2ff4462
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[doc(keyword = "match")] //~ ERROR: #[doc(keyword = "...")] is experimental
+/// wonderful
+mod foo{}
diff --git a/src/test/ui/feature-gate-doc_keyword.stderr b/src/test/ui/feature-gate-doc_keyword.stderr
new file mode 100644 (file)
index 0000000..e4f5109
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0658]: #[doc(keyword = "...")] is experimental (see issue #51315)
+  --> $DIR/feature-gate-doc_keyword.rs:11:1
+   |
+LL | #[doc(keyword = "match")] //~ ERROR: #[doc(keyword = "...")] is experimental
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(doc_keyword)] to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/generator/pattern-borrow.nll.stderr b/src/test/ui/generator/pattern-borrow.nll.stderr
deleted file mode 100644 (file)
index 48f2348..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0626]: borrow may still be in use when generator yields
-  --> $DIR/pattern-borrow.rs:19:24
-   |
-LL |         if let Test::A(ref _a) = test { //~ ERROR borrow may still be in use when generator yields
-   |                        ^^^^^^
-LL |             yield ();
-   |             -------- possible yield occurs here
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0626`.
index f98074bc554bbc857b364bb2108db676fd19cc33..4f1f67214509e5bb1c8c48f6915a9088ffc1b7b6 100644 (file)
@@ -11,8 +11,8 @@
 //https://github.com/rust-lang/rust/issues/31364
 
 #![feature(const_fn)]
-const fn a() -> usize { b() } //~ ERROR constant evaluation error
+const fn a() -> usize { b() }
 const fn b() -> usize { a() }
-const ARR: [i32; a()] = [5; 6];
+const ARR: [i32; a()] = [5; 6]; //~ ERROR could not evaluate constant expression
 
 fn main(){}
index 81717fe1f09291978ea6c968f366aec13eea6af0..fb7c1be75413e189bdb2ee94d474e0e7c4574768 100644 (file)
@@ -1,8 +1,8 @@
-error[E0080]: constant evaluation error
-  --> $DIR/infinite-recursion-const-fn.rs:14:25
+error[E0080]: could not evaluate constant expression
+  --> $DIR/infinite-recursion-const-fn.rs:16:1
    |
-LL | const fn a() -> usize { b() } //~ ERROR constant evaluation error
-   |                         ^^^
+LL | const fn a() -> usize { b() }
+   |                         ---
    |                         |
    |                         reached the configured maximum number of stack frames
    |                         inside call to `b`
@@ -58,14 +58,10 @@ LL | const fn b() -> usize { a() }
    |                         inside call to `a`
    |                         inside call to `a`
    |                         inside call to `a`
-LL | const ARR: [i32; a()] = [5; 6];
-   |                  --- inside call to `a`
-   |
-note: for constant expression here
-  --> $DIR/infinite-recursion-const-fn.rs:16:1
-   |
-LL | const ARR: [i32; a()] = [5; 6];
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | const ARR: [i32; a()] = [5; 6]; //~ ERROR could not evaluate constant expression
+   | ^^^^^^^^^^^^^^^^^---^^^^^^^^^^^
+   |                  |
+   |                  inside call to `a`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issue-38715.rs b/src/test/ui/issue-38715.rs
new file mode 100644 (file)
index 0000000..552653c
--- /dev/null
@@ -0,0 +1,16 @@
+// 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.
+
+#[macro_export]
+macro_rules! foo { ($i:ident) => {} }
+
+#[macro_export]
+macro_rules! foo { () => {} } //~ ERROR a macro named `foo` has already been exported
+                              //~| WARN this was previously accepted
diff --git a/src/test/ui/issue-38715.stderr b/src/test/ui/issue-38715.stderr
new file mode 100644 (file)
index 0000000..a0dbcbd
--- /dev/null
@@ -0,0 +1,22 @@
+error: a macro named `foo` has already been exported
+  --> $DIR/issue-38715.rs:15:1
+   |
+LL | macro_rules! foo { () => {} } //~ ERROR a macro named `foo` has already been exported
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `foo` already exported
+   |
+   = note: #[deny(duplicate_macro_exports)] on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition!
+   = note: for more information, see issue #35896 <https://github.com/rust-lang/rust/issues/35896>
+note: previous macro export is now shadowed
+  --> $DIR/issue-38715.rs:12:1
+   |
+LL | macro_rules! foo { ($i:ident) => {} }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0601]: `main` function not found in crate `issue_38715`
+   |
+   = note: consider adding a `main` function to `$DIR/issue-38715.rs`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0601`.
diff --git a/src/test/ui/issue-45697.nll.stderr b/src/test/ui/issue-45697.nll.stderr
deleted file mode 100644 (file)
index a85972f..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-error[E0506]: cannot assign to `*y.pointer` because it is borrowed (Ast)
-  --> $DIR/issue-45697.rs:30:9
-   |
-LL |         let z = copy_borrowed_ptr(&mut y);
-   |                                        - borrow of `*y.pointer` occurs here
-LL |         *y.pointer += 1;
-   |         ^^^^^^^^^^^^^^^ assignment to borrowed `*y.pointer` occurs here
-
-error[E0503]: cannot use `*y.pointer` because it was mutably borrowed (Mir)
-  --> $DIR/issue-45697.rs:30:9
-   |
-LL |         let z = copy_borrowed_ptr(&mut y);
-   |                                   ------ borrow of `y` occurs here
-LL |         *y.pointer += 1;
-   |         ^^^^^^^^^^^^^^^ use of borrowed `y`
-...
-LL |         *z.pointer += 1;
-   |         --------------- borrow later used here
-
-error[E0506]: cannot assign to `*y.pointer` because it is borrowed (Mir)
-  --> $DIR/issue-45697.rs:30:9
-   |
-LL |         let z = copy_borrowed_ptr(&mut y);
-   |                                   ------ borrow of `*y.pointer` occurs here
-LL |         *y.pointer += 1;
-   |         ^^^^^^^^^^^^^^^ assignment to borrowed `*y.pointer` occurs here
-...
-LL |         *z.pointer += 1;
-   |         --------------- borrow later used here
-
-error: aborting due to 3 previous errors
-
-Some errors occurred: E0503, E0506.
-For more information about an error, try `rustc --explain E0503`.
index a319849223740c47cc6f06982fcdb738e53f1745..f288a2b2174289b506c5f0171d7914334c0fcc51 100644 (file)
@@ -17,6 +17,8 @@ struct Point { x: u8, y: u8 }
 
 fn main() {
     let p = Point { x: 0, y: 0 };
+    let Point { .., y, } = p; //~ ERROR expected `}`, found `,`
     let Point { .., y } = p; //~ ERROR expected `}`, found `,`
-    //~| ERROR pattern does not mention fields `x`, `y`
+    let Point { .., } = p; //~ ERROR expected `}`, found `,`
+    let Point { .. } = p;
 }
index fec990764bb1427ea4ffd49ff237de8282d4cf96..40179832b49b271bee71a2151c2ec9ecc1a6775a 100644 (file)
@@ -1,15 +1,38 @@
 error: expected `}`, found `,`
   --> $DIR/issue-49257.rs:20:19
    |
-LL |     let Point { .., y } = p; //~ ERROR expected `}`, found `,`
-   |                   ^ `..` must be in the last position, and cannot have a trailing comma
+LL |     let Point { .., y, } = p; //~ ERROR expected `}`, found `,`
+   |                 --^
+   |                 | |
+   |                 | expected `}`
+   |                 `..` must be at the end and cannot have a trailing comma
+help: move the `..` to the end of the field list
+   |
+LL |     let Point {  y, .. } = p; //~ ERROR expected `}`, found `,`
+   |                --   ^^^^
 
-error[E0027]: pattern does not mention fields `x`, `y`
-  --> $DIR/issue-49257.rs:20:9
+error: expected `}`, found `,`
+  --> $DIR/issue-49257.rs:21:19
    |
 LL |     let Point { .., y } = p; //~ ERROR expected `}`, found `,`
-   |         ^^^^^^^^^^^^^^^ missing fields `x`, `y`
+   |                 --^
+   |                 | |
+   |                 | expected `}`
+   |                 `..` must be at the end and cannot have a trailing comma
+help: move the `..` to the end of the field list
+   |
+LL |     let Point {  y , .. } = p; //~ ERROR expected `}`, found `,`
+   |                --  ^^^^^^
+
+error: expected `}`, found `,`
+  --> $DIR/issue-49257.rs:22:19
+   |
+LL |     let Point { .., } = p; //~ ERROR expected `}`, found `,`
+   |                 --^
+   |                 | |
+   |                 | expected `}`
+   |                 | help: remove this comma
+   |                 `..` must be at the end and cannot have a trailing comma
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0027`.
diff --git a/src/test/ui/issue-51279.rs b/src/test/ui/issue-51279.rs
new file mode 100644 (file)
index 0000000..4639d73
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub struct X<#[cfg(none)] 'a, #[cfg(none)] T>(&'a T);
+//~^ ERROR #[cfg] cannot be applied on a generic parameter
+//~^^ ERROR #[cfg] cannot be applied on a generic parameter
+
+impl<#[cfg(none)] 'a, #[cfg(none)] T> X<'a, T> {}
+//~^ ERROR #[cfg] cannot be applied on a generic parameter
+//~^^ ERROR #[cfg] cannot be applied on a generic parameter
+
+pub fn f<#[cfg(none)] 'a, #[cfg(none)] T>(_: &'a T) {}
+//~^ ERROR #[cfg] cannot be applied on a generic parameter
+//~^^ ERROR #[cfg] cannot be applied on a generic parameter
+
+#[cfg(none)]
+pub struct Y<#[cfg(none)] T>(T); // shouldn't care when the entire item is stripped out
+
+struct M<T>(*const T);
+
+unsafe impl<#[cfg_attr(none, may_dangle)] T> Drop for M<T> {
+    //~^ ERROR #[cfg_attr] cannot be applied on a generic parameter
+    fn drop(&mut self) {}
+}
+
+type Z<#[ignored] 'a, #[cfg(none)] T> = X<'a, T>;
+//~^ ERROR #[cfg] cannot be applied on a generic parameter
diff --git a/src/test/ui/issue-51279.stderr b/src/test/ui/issue-51279.stderr
new file mode 100644 (file)
index 0000000..38d5a5a
--- /dev/null
@@ -0,0 +1,50 @@
+error: #[cfg] cannot be applied on a generic parameter
+  --> $DIR/issue-51279.rs:11:14
+   |
+LL | pub struct X<#[cfg(none)] 'a, #[cfg(none)] T>(&'a T);
+   |              ^^^^^^^^^^^^
+
+error: #[cfg] cannot be applied on a generic parameter
+  --> $DIR/issue-51279.rs:11:31
+   |
+LL | pub struct X<#[cfg(none)] 'a, #[cfg(none)] T>(&'a T);
+   |                               ^^^^^^^^^^^^
+
+error: #[cfg] cannot be applied on a generic parameter
+  --> $DIR/issue-51279.rs:15:6
+   |
+LL | impl<#[cfg(none)] 'a, #[cfg(none)] T> X<'a, T> {}
+   |      ^^^^^^^^^^^^
+
+error: #[cfg] cannot be applied on a generic parameter
+  --> $DIR/issue-51279.rs:15:23
+   |
+LL | impl<#[cfg(none)] 'a, #[cfg(none)] T> X<'a, T> {}
+   |                       ^^^^^^^^^^^^
+
+error: #[cfg] cannot be applied on a generic parameter
+  --> $DIR/issue-51279.rs:19:10
+   |
+LL | pub fn f<#[cfg(none)] 'a, #[cfg(none)] T>(_: &'a T) {}
+   |          ^^^^^^^^^^^^
+
+error: #[cfg] cannot be applied on a generic parameter
+  --> $DIR/issue-51279.rs:19:27
+   |
+LL | pub fn f<#[cfg(none)] 'a, #[cfg(none)] T>(_: &'a T) {}
+   |                           ^^^^^^^^^^^^
+
+error: #[cfg_attr] cannot be applied on a generic parameter
+  --> $DIR/issue-51279.rs:28:13
+   |
+LL | unsafe impl<#[cfg_attr(none, may_dangle)] T> Drop for M<T> {
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: #[cfg] cannot be applied on a generic parameter
+  --> $DIR/issue-51279.rs:33:23
+   |
+LL | type Z<#[ignored] 'a, #[cfg(none)] T> = X<'a, T>;
+   |                       ^^^^^^^^^^^^
+
+error: aborting due to 8 previous errors
+
index e25c3ccfcd980d36b67d63a0e7cb885ef5332792..a5660f8b41f8da43aeeea29deefa8607dc764bf4 100644 (file)
@@ -8,26 +8,30 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Tests the behavior of various Kleene operators in macros with respect to `?` terminals. In
-// particular, `?` in the position of a separator and of a Kleene operator is tested.
+// The logic for parsing Kleene operators in macros has a special case to disambiguate `?`.
+// Specifically, `$(pat)?` is the ZeroOrOne operator whereas `$(pat)?+` or `$(pat)?*` are the
+// ZeroOrMore and OneOrMore operators using `?` as a separator. These tests are intended to
+// exercise that logic in the macro parser.
+//
+// Moreover, we also throw in some tests for using a separator with `?`, which is meaningless but
+// included for consistency with `+` and `*`.
+//
+// This test focuses on error cases.
 
 #![feature(macro_at_most_once_rep)]
 
-// should match `` and `a`
 macro_rules! foo {
     ($(a)?) => {}
 }
 
 macro_rules! baz {
-    ($(a),?) => {} //~ ERROR `?` macro repetition does not allow a separator
+    ($(a),?) => {} // comma separator is meaningless for `?`
 }
 
-// should match `+` and `a+`
 macro_rules! barplus {
     ($(a)?+) => {}
 }
 
-// should match `*` and `a*`
 macro_rules! barstar {
     ($(a)?*) => {}
 }
@@ -36,14 +40,14 @@ pub fn main() {
     foo!(a?a?a); //~ ERROR no rules expected the token `?`
     foo!(a?a); //~ ERROR no rules expected the token `?`
     foo!(a?); //~ ERROR no rules expected the token `?`
+    baz!(a?a?a); //~ ERROR no rules expected the token `?`
+    baz!(a?a); //~ ERROR no rules expected the token `?`
+    baz!(a?); //~ ERROR no rules expected the token `?`
+    baz!(a,); //~ ERROR unexpected end of macro invocation
+    baz!(a?a?a,); //~ ERROR no rules expected the token `?`
+    baz!(a?a,); //~ ERROR no rules expected the token `?`
+    baz!(a?,); //~ ERROR no rules expected the token `?`
     barplus!(); //~ ERROR unexpected end of macro invocation
-    barstar!(); //~ ERROR unexpected end of macro invocation
-    barplus!(a?); //~ ERROR no rules expected the token `?`
-    barplus!(a); //~ ERROR unexpected end of macro invocation
-    barstar!(a?); //~ ERROR no rules expected the token `?`
-    barstar!(a); //~ ERROR unexpected end of macro invocation
-    barplus!(+); // ok
-    barstar!(*); // ok
-    barplus!(a+); // ok
-    barstar!(a*); // ok
+    barplus!(a?); //~ ERROR unexpected end of macro invocation
+    barstar!(a?); //~ ERROR unexpected end of macro invocation
 }
index cb1e360471cc8671969a0cb274f3dd67b721f64d..d382082a5758562bb4f6163ef74237c8c0fbc3af 100644 (file)
@@ -1,62 +1,80 @@
-error: `?` macro repetition does not allow a separator
-  --> $DIR/macro-at-most-once-rep-ambig.rs:22:10
-   |
-LL |     ($(a),?) => {} //~ ERROR `?` macro repetition does not allow a separator
-   |          ^
-
 error: no rules expected the token `?`
-  --> $DIR/macro-at-most-once-rep-ambig.rs:36:11
+  --> $DIR/macro-at-most-once-rep-ambig.rs:40:11
    |
 LL |     foo!(a?a?a); //~ ERROR no rules expected the token `?`
    |           ^
 
 error: no rules expected the token `?`
-  --> $DIR/macro-at-most-once-rep-ambig.rs:37:11
+  --> $DIR/macro-at-most-once-rep-ambig.rs:41:11
    |
 LL |     foo!(a?a); //~ ERROR no rules expected the token `?`
    |           ^
 
 error: no rules expected the token `?`
-  --> $DIR/macro-at-most-once-rep-ambig.rs:38:11
+  --> $DIR/macro-at-most-once-rep-ambig.rs:42:11
    |
 LL |     foo!(a?); //~ ERROR no rules expected the token `?`
    |           ^
 
-error: unexpected end of macro invocation
-  --> $DIR/macro-at-most-once-rep-ambig.rs:39:5
+error: no rules expected the token `?`
+  --> $DIR/macro-at-most-once-rep-ambig.rs:43:11
    |
-LL |     barplus!(); //~ ERROR unexpected end of macro invocation
-   |     ^^^^^^^^^^^
+LL |     baz!(a?a?a); //~ ERROR no rules expected the token `?`
+   |           ^
 
-error: unexpected end of macro invocation
-  --> $DIR/macro-at-most-once-rep-ambig.rs:40:5
+error: no rules expected the token `?`
+  --> $DIR/macro-at-most-once-rep-ambig.rs:44:11
    |
-LL |     barstar!(); //~ ERROR unexpected end of macro invocation
-   |     ^^^^^^^^^^^
+LL |     baz!(a?a); //~ ERROR no rules expected the token `?`
+   |           ^
 
 error: no rules expected the token `?`
-  --> $DIR/macro-at-most-once-rep-ambig.rs:41:15
+  --> $DIR/macro-at-most-once-rep-ambig.rs:45:11
    |
-LL |     barplus!(a?); //~ ERROR no rules expected the token `?`
-   |               ^
+LL |     baz!(a?); //~ ERROR no rules expected the token `?`
+   |           ^
 
 error: unexpected end of macro invocation
-  --> $DIR/macro-at-most-once-rep-ambig.rs:42:14
+  --> $DIR/macro-at-most-once-rep-ambig.rs:46:11
+   |
+LL |     baz!(a,); //~ ERROR unexpected end of macro invocation
+   |           ^
+
+error: no rules expected the token `?`
+  --> $DIR/macro-at-most-once-rep-ambig.rs:47:11
+   |
+LL |     baz!(a?a?a,); //~ ERROR no rules expected the token `?`
+   |           ^
+
+error: no rules expected the token `?`
+  --> $DIR/macro-at-most-once-rep-ambig.rs:48:11
    |
-LL |     barplus!(a); //~ ERROR unexpected end of macro invocation
-   |              ^
+LL |     baz!(a?a,); //~ ERROR no rules expected the token `?`
+   |           ^
 
 error: no rules expected the token `?`
-  --> $DIR/macro-at-most-once-rep-ambig.rs:43:15
+  --> $DIR/macro-at-most-once-rep-ambig.rs:49:11
+   |
+LL |     baz!(a?,); //~ ERROR no rules expected the token `?`
+   |           ^
+
+error: unexpected end of macro invocation
+  --> $DIR/macro-at-most-once-rep-ambig.rs:50:5
+   |
+LL |     barplus!(); //~ ERROR unexpected end of macro invocation
+   |     ^^^^^^^^^^^
+
+error: unexpected end of macro invocation
+  --> $DIR/macro-at-most-once-rep-ambig.rs:51:15
    |
-LL |     barstar!(a?); //~ ERROR no rules expected the token `?`
+LL |     barplus!(a?); //~ ERROR unexpected end of macro invocation
    |               ^
 
 error: unexpected end of macro invocation
-  --> $DIR/macro-at-most-once-rep-ambig.rs:44:14
+  --> $DIR/macro-at-most-once-rep-ambig.rs:52:15
    |
-LL |     barstar!(a); //~ ERROR unexpected end of macro invocation
-   |              ^
+LL |     barstar!(a?); //~ ERROR unexpected end of macro invocation
+   |               ^
 
-error: aborting due to 10 previous errors
+error: aborting due to 13 previous errors
 
index 284acd20ba5e7835644f074b65c3677a2aada67c..24186d94acce966c087ce5c3d65b41709d55a3de 100644 (file)
@@ -10,11 +10,11 @@ note: unclosed delimiter
 LL |             callback(path.as_ref(); //~ ERROR expected one of
    |                     ^
 
-error: expected one of `,`, `.`, `?`, or an operator, found `;`
+error: expected one of `)`, `,`, `.`, `?`, or an operator, found `;`
   --> $DIR/token-error-correct-3.rs:24:35
    |
 LL |             callback(path.as_ref(); //~ ERROR expected one of
-   |                                   ^ expected one of `,`, `.`, `?`, or an operator here
+   |                                   ^ expected one of `)`, `,`, `.`, `?`, or an operator here
 
 error: expected one of `.`, `;`, `?`, `}`, or an operator, found `)`
   --> $DIR/token-error-correct-3.rs:30:9
index 73a0150c0bb3f0d7e441f7025a2b6abc7c91302c..a0b2784214ae95e0fcbb12523f62fdd53eadf78d 100644 (file)
@@ -10,7 +10,6 @@
 
 // compile-flags: --test
 
-#![feature(termination_trait_test)]
 #![feature(test)]
 
 extern crate test;
index e3dab82df41b9c584fd76ff6b98e4aa9b75899c0..bfdcf01c325f709f0678be458f945313398df750 100644 (file)
@@ -1,5 +1,5 @@
 error: functions using `#[should_panic]` must return `()`
-  --> $DIR/termination-trait-in-test-should-panic.rs:22:1
+  --> $DIR/termination-trait-in-test-should-panic.rs:21:1
    |
 LL | / fn not_a_num() -> Result<(), ParseIntError> {
 LL | |     //~^ ERROR functions using `#[should_panic]` must return `()`
index 2cb4552a4b29e1134ee77eb04361afb2c52b9ebf..0561b12221d1a535149f260261224948b99e64c9 100644 (file)
@@ -11,7 +11,6 @@
 // compile-flags: --test
 // run-pass
 
-#![feature(termination_trait_test)]
 #![feature(test)]
 
 extern crate test;
index 1c00edee770f2d67222f2b6a3aec829a06b4d0ab..6153d840c8a7dc633c4125233cbb5a358c40a602 100644 (file)
@@ -10,8 +10,6 @@
 
 // compile-flags: --test
 
-#![feature(termination_trait_test)]
-
 use std::num::ParseIntError;
 
 #[test]
index 8efd8a216f10f82293c7e060d68a9ea02aa05ec7..0972a0994fc0d38261b8abf776066f5e0f47399f 100644 (file)
@@ -1,5 +1,5 @@
 error[E0277]: `main` has invalid return type `std::result::Result<f32, std::num::ParseIntError>`
-  --> $DIR/termination-trait-test-wrong-type.rs:18:1
+  --> $DIR/termination-trait-test-wrong-type.rs:16:1
    |
 LL | / fn can_parse_zero_as_f32() -> Result<f32, ParseIntError> { //~ ERROR
 LL | |     "0".parse()
index eb7eab9e42dd7a6a86dc802676b91c541152fb4b..350a2262391b5da92dffaf36293e42e46078cde1 100644 (file)
@@ -14,6 +14,6 @@ mod x {
 }
 
 // `.` is similar to `,` so list parsing should continue to closing `}`
-use x::{A. B}; //~ ERROR expected one of `,`, `::`, or `as`, found `.`
+use x::{A. B}; //~ ERROR expected one of `,`, `::`, `as`, or `}`, found `.`
 
 fn main() {}
index fe157b99e65da069cb9bf25a289c5329c77695af..90acc56cbc99964504da56f29db676405d3c41a5 100644 (file)
@@ -1,8 +1,8 @@
-error: expected one of `,`, `::`, or `as`, found `.`
+error: expected one of `,`, `::`, `as`, or `}`, found `.`
   --> $DIR/similar-tokens.rs:17:10
    |
-LL | use x::{A. B}; //~ ERROR expected one of `,`, `::`, or `as`, found `.`
-   |          ^ expected one of `,`, `::`, or `as` here
+LL | use x::{A. B}; //~ ERROR expected one of `,`, `::`, `as`, or `}`, found `.`
+   |          ^ expected one of `,`, `::`, `as`, or `}` here
 
 error: aborting due to previous error
 
index 0edd51ba779ac4eb0009a15ac3f3aa3a58f654fb..ed9bbb60dcd20d773f949f02470b0c7ac23b6303 100644 (file)
@@ -15,6 +15,8 @@
 // ignore-mips
 // ignore-powerpc
 // ignore-s390x
+// ignore-sparc
+// ignore-sparc64
 
 #![feature(target_feature)]
 
index ed86687bb2fccbec23171b60c6a03989041a6a84..39362f74bdd9e7d8ce44adfe76f6ebe3e47777ce 100644 (file)
@@ -1,35 +1,35 @@
 error: #[target_feature] attribute must be of the form #[target_feature(..)]
-  --> $DIR/target-feature-wrong.rs:21:1
+  --> $DIR/target-feature-wrong.rs:23:1
    |
 LL | #[target_feature = "+sse2"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: the feature named `foo` is not valid for this target
-  --> $DIR/target-feature-wrong.rs:23:18
+  --> $DIR/target-feature-wrong.rs:25:18
    |
 LL | #[target_feature(enable = "foo")]
    |                  ^^^^^^^^^^^^^^
 
 error: #[target_feature(..)] only accepts sub-keys of `enable` currently
-  --> $DIR/target-feature-wrong.rs:25:18
+  --> $DIR/target-feature-wrong.rs:27:18
    |
 LL | #[target_feature(bar)]
    |                  ^^^
 
 error: #[target_feature(..)] only accepts sub-keys of `enable` currently
-  --> $DIR/target-feature-wrong.rs:27:18
+  --> $DIR/target-feature-wrong.rs:29:18
    |
 LL | #[target_feature(disable = "baz")]
    |                  ^^^^^^^^^^^^^^^
 
 error: #[target_feature(..)] can only be applied to `unsafe` function
-  --> $DIR/target-feature-wrong.rs:31:1
+  --> $DIR/target-feature-wrong.rs:33:1
    |
 LL | #[target_feature(enable = "sse2")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: attribute should be applied to a function
-  --> $DIR/target-feature-wrong.rs:35:1
+  --> $DIR/target-feature-wrong.rs:37:1
    |
 LL | #[target_feature(enable = "sse2")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -38,7 +38,7 @@ LL | mod another {}
    | -------------- not a function
 
 error: cannot use #[inline(always)] with #[target_feature]
-  --> $DIR/target-feature-wrong.rs:39:1
+  --> $DIR/target-feature-wrong.rs:41:1
    |
 LL | #[inline(always)]
    | ^^^^^^^^^^^^^^^^^
index 56a30423171da52f4ccc49e834eb4afd337b58cc..6c0053f2f8597997489345fb210a66de136321be 100644 (file)
@@ -10,11 +10,11 @@ note: unclosed delimiter
 LL |     option.map(|some| 42;
    |               ^
 
-error: expected one of `,`, `.`, `?`, or an operator, found `;`
+error: expected one of `)`, `,`, `.`, `?`, or an operator, found `;`
   --> $DIR/issue-10636-2.rs:15:25
    |
 LL |     option.map(|some| 42;
-   |                         ^ expected one of `,`, `.`, `?`, or an operator here
+   |                         ^ expected one of `)`, `,`, `.`, `?`, or an operator here
 
 error: expected expression, found `)`
   --> $DIR/issue-10636-2.rs:18:1
diff --git a/src/test/ui/trait-object-auto-dedup-in-impl.rs b/src/test/ui/trait-object-auto-dedup-in-impl.rs
new file mode 100644 (file)
index 0000000..d3e4627
--- /dev/null
@@ -0,0 +1,29 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Checks to make sure that `dyn Trait + Send` and `dyn Trait + Send + Send` are the same type.
+// Issue: #47010
+
+struct Struct;
+impl Trait for Struct {}
+trait Trait {}
+
+type Send1 = Trait + Send;
+type Send2 = Trait + Send + Send;
+
+fn main () {}
+
+impl Trait + Send {
+    fn test(&self) { println!("one"); } //~ ERROR duplicate definitions with name `test`
+}
+
+impl Trait + Send + Send {
+    fn test(&self) { println!("two"); }
+}
diff --git a/src/test/ui/trait-object-auto-dedup-in-impl.stderr b/src/test/ui/trait-object-auto-dedup-in-impl.stderr
new file mode 100644 (file)
index 0000000..9abd81c
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0592]: duplicate definitions with name `test`
+  --> $DIR/trait-object-auto-dedup-in-impl.rs:24:5
+   |
+LL |     fn test(&self) { println!("one"); } //~ ERROR duplicate definitions with name `test`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definitions for `test`
+...
+LL |     fn test(&self) { println!("two"); }
+   |     ----------------------------------- other definition for `test`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0592`.
diff --git a/src/test/ui/tuple-struct-fields/test.rs b/src/test/ui/tuple-struct-fields/test.rs
new file mode 100644 (file)
index 0000000..22d54a3
--- /dev/null
@@ -0,0 +1,17 @@
+// 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.
+
+mod foo {
+    type T = ();
+    struct S1(pub(in foo) (), pub(T), pub(crate) (), pub(((), T)));
+    struct S2(pub((foo)) ());
+    //~^ ERROR expected one of `)` or `,`, found `(`
+    //~| ERROR cannot find type `foo` in this scope
+}
diff --git a/src/test/ui/tuple-struct-fields/test.stderr b/src/test/ui/tuple-struct-fields/test.stderr
new file mode 100644 (file)
index 0000000..59228ea
--- /dev/null
@@ -0,0 +1,20 @@
+error: expected one of `)` or `,`, found `(`
+  --> $DIR/test.rs:14:26
+   |
+LL |     struct S2(pub((foo)) ());
+   |                          ^ expected one of `)` or `,` here
+
+error[E0412]: cannot find type `foo` in this scope
+  --> $DIR/test.rs:14:20
+   |
+LL |     struct S2(pub((foo)) ());
+   |                    ^^^ not found in this scope
+
+error[E0601]: `main` function not found in crate `test`
+   |
+   = note: consider adding a `main` function to `$DIR/test.rs`
+
+error: aborting due to 3 previous errors
+
+Some errors occurred: E0412, E0601.
+For more information about an error, try `rustc --explain E0412`.
diff --git a/src/test/ui/tuple-struct-fields/test2.rs b/src/test/ui/tuple-struct-fields/test2.rs
new file mode 100644 (file)
index 0000000..eead027
--- /dev/null
@@ -0,0 +1,22 @@
+// 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.
+
+macro_rules! define_struct {
+    ($t:ty) => {
+        struct S1(pub $t);
+        struct S2(pub (in foo) ());
+        struct S3(pub $t ());
+        //~^ ERROR expected one of `)` or `,`, found `(`
+    }
+}
+
+mod foo {
+    define_struct! { (foo) }
+}
diff --git a/src/test/ui/tuple-struct-fields/test2.stderr b/src/test/ui/tuple-struct-fields/test2.stderr
new file mode 100644 (file)
index 0000000..983e747
--- /dev/null
@@ -0,0 +1,11 @@
+error: expected one of `)` or `,`, found `(`
+  --> $DIR/test2.rs:15:26
+   |
+LL |         struct S3(pub $t ());
+   |                          ^ expected one of `)` or `,` here
+...
+LL |     define_struct! { (foo) }
+   |     ------------------------ in this macro invocation
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/tuple-struct-fields/test3.rs b/src/test/ui/tuple-struct-fields/test3.rs
new file mode 100644 (file)
index 0000000..d666c8a
--- /dev/null
@@ -0,0 +1,22 @@
+// 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.
+
+macro_rules! define_struct {
+    ($t:ty) => {
+        struct S1(pub($t));
+        struct S2(pub (in foo) ());
+        struct S3(pub($t) ());
+        //~^ ERROR expected one of `)` or `,`, found `(`
+    }
+}
+
+mod foo {
+    define_struct! { foo }
+}
diff --git a/src/test/ui/tuple-struct-fields/test3.stderr b/src/test/ui/tuple-struct-fields/test3.stderr
new file mode 100644 (file)
index 0000000..6738595
--- /dev/null
@@ -0,0 +1,11 @@
+error: expected one of `)` or `,`, found `(`
+  --> $DIR/test3.rs:15:27
+   |
+LL |         struct S3(pub($t) ());
+   |                           ^ expected one of `)` or `,` here
+...
+LL |     define_struct! { foo }
+   |     ---------------------- in this macro invocation
+
+error: aborting due to previous error
+
index 64264999fd2f1c671a175077f0a65f35ae2d17b7..db27ae89e69fdbef0f101fad6c4444b1fc09ebee 100644 (file)
@@ -11,5 +11,5 @@
 fn main() {
     let v = vec![0];
     const l: usize = v.count(); //~ ERROR can't capture dynamic environment in a fn item
-    let s: [u32; l] = v.into_iter().collect(); //~ ERROR constant evaluation error
+    let s: [u32; l] = v.into_iter().collect();
 }
index f00edccae5d50f585ac06ffcd1224ca4adc2ba1f..361d28f274fa30f8faa1481fa59ffa28ad5e90f5 100644 (file)
@@ -6,13 +6,6 @@ LL |     const l: usize = v.count(); //~ ERROR can't capture dynamic environment
    |
    = help: use the `|| { ... }` closure form instead
 
-error[E0080]: constant evaluation error
-  --> $DIR/type-dependent-def-issue-49241.rs:14:18
-   |
-LL |     let s: [u32; l] = v.into_iter().collect(); //~ ERROR constant evaluation error
-   |                  ^ encountered constants with type errors, stopping evaluation
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors occurred: E0080, E0434.
-For more information about an error, try `rustc --explain E0080`.
+For more information about this error, try `rustc --explain E0434`.
index c3b09c9680fce8ab70a49c8531fd8f84c2ccdff2..e2348c2db296ce33428933c3ab8786d5f3c54a2e 160000 (submodule)
@@ -1 +1 @@
-Subproject commit c3b09c9680fce8ab70a49c8531fd8f84c2ccdff2
+Subproject commit e2348c2db296ce33428933c3ab8786d5f3c54a2e
index 453f5e4dec279167aed825b7ad043d06aa17c667..7d0bc550b0899a13a56c81eb2d5064abd0bcf385 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 453f5e4dec279167aed825b7ad043d06aa17c667
+Subproject commit 7d0bc550b0899a13a56c81eb2d5064abd0bcf385
index bc4503903d665589ab3bf1c0beb887bf8eb795ed..a05c8a8ac9133301bcfc5ea0763d03527f49bed5 100644 (file)
@@ -231,7 +231,9 @@ function main(argv) {
     finalJS = "";
 
     var arraysToLoad = ["itemTypes"];
-    var variablesToLoad = ["MAX_LEV_DISTANCE", "MAX_RESULTS", "TY_PRIMITIVE", "levenshtein_row2"];
+    var variablesToLoad = ["MAX_LEV_DISTANCE", "MAX_RESULTS",
+                           "TY_PRIMITIVE", "TY_KEYWORD",
+                           "levenshtein_row2"];
     // execQuery first parameter is built in getQuery (which takes in the search input).
     // execQuery last parameter is built in buildIndex.
     // buildIndex requires the hashmap from search-index.
index 173ae0d7b92227c7fec4bce67c944dce953256dc..08da30d72c9abfff4d41f6f081e31fd2929b820d 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 173ae0d7b92227c7fec4bce67c944dce953256dc
+Subproject commit 08da30d72c9abfff4d41f6f081e31fd2929b820d