]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #53413 - eddyb:featured-in-the-latest-edition, r=varkor
authorCorey Farwell <coreyf@rwell.org>
Fri, 17 Aug 2018 15:23:44 +0000 (08:23 -0700)
committerGitHub <noreply@github.com>
Fri, 17 Aug 2018 15:23:44 +0000 (08:23 -0700)
Warn that `#![feature(rust_2018_preview)]` is implied when the edition is set to Rust 2018.

cc @varkor @petrochenkov @joshtriplett

222 files changed:
.travis.yml
src/Cargo.lock
src/bootstrap/test.rs
src/ci/docker/run.sh
src/doc/unstable-book/src/language-features/crate-in-paths.md
src/doc/unstable-book/src/language-features/extern-absolute-paths.md
src/doc/unstable-book/src/library-features/future-atomic-orderings.md [deleted file]
src/doc/unstable-book/src/library-features/io-error-internals.md [deleted file]
src/etc/debugger_pretty_printers_common.py
src/etc/gdb_rust_pretty_printing.py
src/libcore/lib.rs
src/libcore/macros.rs
src/libcore/num/mod.rs
src/libcore/sync/atomic.rs
src/libpanic_unwind/dummy.rs [new file with mode: 0644]
src/libpanic_unwind/lib.rs
src/libpanic_unwind/macros.rs [new file with mode: 0644]
src/libpanic_unwind/wasm32.rs [deleted file]
src/libproc_macro/diagnostic.rs
src/libproc_macro/lib.rs
src/libproc_macro/rustc.rs
src/librustc/Cargo.toml
src/librustc/middle/lib_features.rs
src/librustc/mir/mod.rs
src/librustc/traits/on_unimplemented.rs
src/librustc/traits/util.rs
src/librustc_apfloat/ieee.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_data_structures/indexed_set.rs
src/librustc_mir/borrow_check/move_errors.rs
src/librustc_mir/borrow_check/mutability_errors.rs
src/librustc_mir/build/matches/mod.rs
src/librustc_mir/build/mod.rs
src/librustc_mir/dataflow/at_location.rs
src/librustc_mir/dataflow/graphviz.rs
src/librustc_mir/dataflow/mod.rs
src/librustc_mir/lib.rs
src/librustc_mir/transform/rustc_peek.rs
src/librustc_mir/util/mod.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_target/spec/aarch64_pc_windows_msvc.rs [new file with mode: 0644]
src/librustc_target/spec/mod.rs
src/librustc_traits/Cargo.toml
src/librustc_typeck/check/mod.rs
src/librustc_typeck/collect.rs
src/libserialize/json.rs
src/libstd/build.rs
src/libstd/io/error.rs
src/libstd/lib.rs
src/libstd/sys/cloudabi/abi/cloudabi.rs
src/libstd/sys/windows/backtrace/mod.rs
src/libstd/sys/windows/c.rs
src/libstd/sys/windows/mod.rs
src/libsyntax/attr/mod.rs
src/libsyntax/config.rs
src/libsyntax/feature_gate.rs
src/libsyntax/lib.rs
src/libsyntax/parse/attr.rs
src/libsyntax/parse/lexer/comments.rs
src/libsyntax/parse/lexer/mod.rs
src/libsyntax/parse/lexer/tokentrees.rs
src/libsyntax/parse/lexer/unicode_chars.rs
src/libsyntax/parse/parser.rs
src/libsyntax/tokenstream.rs
src/libsyntax/util/rc_vec.rs [new file with mode: 0644]
src/libsyntax_ext/deriving/default.rs
src/libsyntax_ext/deriving/mod.rs
src/test/compile-fail-fulldeps/issue-48941.rs
src/test/compile-fail-fulldeps/proc-macro/proc-macro-attributes.rs
src/test/compile-fail-fulldeps/proc-macro/proc-macro-gates.rs
src/test/debuginfo/pretty-std-collections.rs
src/test/parse-fail/attr-bad-meta-2.rs [new file with mode: 0644]
src/test/parse-fail/attr-bad-meta-3.rs [new file with mode: 0644]
src/test/parse-fail/attr-bad-meta.rs
src/test/parse-fail/issue-10636-1.rs [deleted file]
src/test/run-make/git_clone_sha1.sh [new file with mode: 0644]
src/test/run-make/thumb-none-cortex-m/Makefile [new file with mode: 0644]
src/test/run-pass-fulldeps/proc-macro/auxiliary/derive-b.rs
src/test/run-pass-fulldeps/proc-macro/derive-b.rs
src/test/run-pass/rfc-2126-crate-paths/crate-path-absolute.rs
src/test/run-pass/rfc-2126-crate-paths/crate-path-visibility-ambiguity.rs
src/test/run-pass/uniform-paths/basic-nested.rs
src/test/ui-fulldeps/invalid-punct-ident-4.stderr
src/test/ui-fulldeps/proc-macro/attribute-spans-preserved.rs
src/test/ui-fulldeps/proc-macro/attribute-spans-preserved.stderr
src/test/ui-fulldeps/proc-macro/attribute-spans-preserved.stdout
src/test/ui/E0508-fail.ast.nll.stderr [new file with mode: 0644]
src/test/ui/E0508-fail.mir.stderr
src/test/ui/E0508.nll.stderr [new file with mode: 0644]
src/test/ui/E0660.rs
src/test/ui/E0660.stderr
src/test/ui/E0661.rs
src/test/ui/E0661.stderr
src/test/ui/E0662.rs
src/test/ui/E0662.stderr
src/test/ui/E0663.rs
src/test/ui/E0663.stderr
src/test/ui/E0664.rs
src/test/ui/E0664.stderr
src/test/ui/E0665.rs
src/test/ui/E0665.stderr
src/test/ui/access-mode-in-closures.nll.stderr
src/test/ui/attr-eq-token-tree.rs [new file with mode: 0644]
src/test/ui/borrowck/borrowck-closures-two-mut-fail.nll.stderr [new file with mode: 0644]
src/test/ui/borrowck/borrowck-closures-two-mut-fail.rs
src/test/ui/borrowck/borrowck-closures-two-mut-fail.stderr
src/test/ui/borrowck/borrowck-closures-unique.nll.stderr [new file with mode: 0644]
src/test/ui/borrowck/borrowck-closures-unique.rs
src/test/ui/borrowck/borrowck-closures-unique.stderr
src/test/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.nll.stderr
src/test/ui/borrowck/borrowck-issue-2657-2.nll.stderr
src/test/ui/borrowck/borrowck-move-error-with-note.nll.stderr
src/test/ui/borrowck/borrowck-move-from-unsafe-ptr.nll.stderr
src/test/ui/borrowck/borrowck-move-in-irrefut-pat.ast.nll.stderr
src/test/ui/borrowck/borrowck-move-in-irrefut-pat.mir.stderr
src/test/ui/borrowck/borrowck-move-out-of-overloaded-deref.nll.stderr [new file with mode: 0644]
src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.ast.nll.stderr
src/test/ui/borrowck/borrowck-move-out-of-struct-with-dtor.mir.stderr
src/test/ui/borrowck/borrowck-move-out-of-tuple-struct-with-dtor.nll.stderr
src/test/ui/borrowck/borrowck-move-out-of-vec-tail.nll.stderr
src/test/ui/borrowck/borrowck-overloaded-index-move-from-vec.nll.stderr
src/test/ui/borrowck/borrowck-vec-pattern-nesting.nll.stderr
src/test/ui/borrowck/issue-51415.nll.stderr
src/test/ui/by-move-pattern-binding.nll.stderr
src/test/ui/check-static-values-constraints.nll.stderr
src/test/ui/codemap_tests/overlapping_spans.nll.stderr
src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-let.nll.stderr
src/test/ui/disallowed-deconstructing/disallowed-deconstructing-destructing-struct-match.nll.stderr
src/test/ui/error-codes/E0232.stderr
src/test/ui/error-codes/E0509.nll.stderr [new file with mode: 0644]
src/test/ui/feature-gates/feature-gate-crate_in_paths.rs
src/test/ui/feature-gates/feature-gate-crate_in_paths.stderr
src/test/ui/hashmap-lifetimes.nll.stderr [new file with mode: 0644]
src/test/ui/hashmap-lifetimes.rs
src/test/ui/hashmap-lifetimes.stderr
src/test/ui/issue-10636-1.rs [new file with mode: 0644]
src/test/ui/issue-10636-1.stderr [new file with mode: 0644]
src/test/ui/issue-51602.rs [new file with mode: 0644]
src/test/ui/issue-51602.stderr [new file with mode: 0644]
src/test/ui/issues/issue-12567.nll.stderr
src/test/ui/issues/issue-17718-static-move.nll.stderr [new file with mode: 0644]
src/test/ui/issues/issue-20801.nll.stderr
src/test/ui/issues/issue-40402-ref-hints/issue-40402-1.nll.stderr
src/test/ui/issues/issue-40402-ref-hints/issue-40402-2.nll.stderr
src/test/ui/issues/issue-53348.rs [new file with mode: 0644]
src/test/ui/issues/issue-53348.stderr [new file with mode: 0644]
src/test/ui/macros/issue-30143.rs [new file with mode: 0644]
src/test/ui/macros/issue-30143.stderr [new file with mode: 0644]
src/test/ui/macros/macro-attribute.rs
src/test/ui/macros/macro-attribute.stderr
src/test/ui/macros/macros-nonfatal-errors.rs
src/test/ui/macros/macros-nonfatal-errors.stderr
src/test/ui/moves/move-out-of-slice-1.nll.stderr
src/test/ui/moves/moves-based-on-type-block-bad.nll.stderr
src/test/ui/nll/cannot-move-block-spans.nll.stderr
src/test/ui/nll/issue-27868.rs [new file with mode: 0644]
src/test/ui/nll/issue-27868.stderr [new file with mode: 0644]
src/test/ui/nll/issue-30104.rs [new file with mode: 0644]
src/test/ui/nll/issue-48697.rs [new file with mode: 0644]
src/test/ui/nll/move-errors.stderr
src/test/ui/on-unimplemented/bad-annotation.rs
src/test/ui/on-unimplemented/bad-annotation.stderr
src/test/ui/parser-recovery-2.stderr
src/test/ui/resolve/token-error-correct-2.stderr
src/test/ui/resolve/token-error-correct-3.stderr
src/test/ui/resolve/token-error-correct.rs
src/test/ui/resolve/token-error-correct.stderr
src/test/ui/rfc-2126-crate-paths/crate-path-non-absolute.rs
src/test/ui/rfc-2126-crate-paths/crate-path-non-absolute.stderr
src/test/ui/rfc-2126-crate-paths/keyword-crate-as-identifier.rs
src/test/ui/rfc-2126-crate-paths/keyword-crate-as-identifier.stderr
src/test/ui/rfc1598-generic-associated-types/collections.rs
src/test/ui/rfc1598-generic-associated-types/collections.stderr
src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.rs
src/test/ui/rfc1598-generic-associated-types/construct_with_other_type.stderr
src/test/ui/rfc1598-generic-associated-types/empty_generics.rs
src/test/ui/rfc1598-generic-associated-types/empty_generics.stderr
src/test/ui/rfc1598-generic-associated-types/gat-incomplete-warning.rs [new file with mode: 0644]
src/test/ui/rfc1598-generic-associated-types/gat-incomplete-warning.stderr [new file with mode: 0644]
src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.stderr [new file with mode: 0644]
src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.rs
src/test/ui/rfc1598-generic-associated-types/generic_associated_type_undeclared_lifetimes.stderr
src/test/ui/rfc1598-generic-associated-types/iterable.rs
src/test/ui/rfc1598-generic-associated-types/iterable.stderr
src/test/ui/rfc1598-generic-associated-types/parameter_number_and_kind.rs
src/test/ui/rfc1598-generic-associated-types/parameter_number_and_kind.stderr
src/test/ui/rfc1598-generic-associated-types/pointer_family.rs
src/test/ui/rfc1598-generic-associated-types/pointer_family.stderr
src/test/ui/rfc1598-generic-associated-types/shadowing.stderr [new file with mode: 0644]
src/test/ui/rfc1598-generic-associated-types/streaming_iterator.rs
src/test/ui/rfc1598-generic-associated-types/streaming_iterator.stderr
src/test/ui/rust-2018/edition-lint-paths.fixed
src/test/ui/rust-2018/edition-lint-paths.rs
src/test/ui/rust-2018/uniform-paths/ambiguity-macros-nested.rs
src/test/ui/rust-2018/uniform-paths/ambiguity-macros-nested.stderr
src/test/ui/rust-2018/uniform-paths/ambiguity-macros.rs
src/test/ui/rust-2018/uniform-paths/ambiguity-macros.stderr
src/test/ui/rust-2018/uniform-paths/ambiguity-nested.rs
src/test/ui/rust-2018/uniform-paths/ambiguity-nested.stderr
src/test/ui/rust-2018/uniform-paths/ambiguity.rs
src/test/ui/rust-2018/uniform-paths/ambiguity.stderr
src/test/ui/rust-2018/uniform-paths/block-scoped-shadow.rs
src/test/ui/rust-2018/uniform-paths/block-scoped-shadow.stderr
src/test/ui/rust-2018/uniform-paths/redundant.rs [new file with mode: 0644]
src/test/ui/rust-2018/uniform-paths/redundant.stderr [new file with mode: 0644]
src/test/ui/std-uncopyable-atomics.nll.stderr [new file with mode: 0644]
src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.rs [new file with mode: 0644]
src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.stderr [new file with mode: 0644]
src/test/ui/suggestions/dont-suggest-ref/move-into-closure.rs [new file with mode: 0644]
src/test/ui/suggestions/dont-suggest-ref/move-into-closure.stderr [new file with mode: 0644]
src/test/ui/suggestions/dont-suggest-ref/simple.rs [new file with mode: 0644]
src/test/ui/suggestions/dont-suggest-ref/simple.stderr [new file with mode: 0644]
src/test/ui/token/issue-10636-2.stderr
src/test/ui/unboxed-closures/unboxed-closure-region.nll.stderr [new file with mode: 0644]
src/test/ui/unboxed-closures/unboxed-closure-region.rs
src/test/ui/unboxed-closures/unboxed-closure-region.stderr
src/test/ui/unboxed-closures/unboxed-closures-borrow-conflict.nll.stderr [new file with mode: 0644]
src/test/ui/unboxed-closures/unboxed-closures-borrow-conflict.rs
src/test/ui/unrestricted-attribute-tokens.rs [new file with mode: 0644]
src/tools/compiletest/src/json.rs
src/tools/tidy/src/unstable_book.rs

index 7251a46cc5878156caa21f5881d8b1f9314ce4e0..2a5f755ebff3df3292587cb6ef96e9e0cb60a718 100644 (file)
@@ -218,10 +218,6 @@ before_install:
       echo '{"ipv6":true,"fixed-cidr-v6":"fd9a:8454:6789:13f7::/64"}' | sudo tee /etc/docker/daemon.json;
       sudo service docker restart;
     fi
-  - date
-  - sudo atq || true
-  - sudo grep -rE 'shutdown|poweroff|halt' /var/spool/cron || true
-  - sudo grep -E 'google-clock-skew|ntpd|startup-script' /var/log/syslog || true
 
 install:
   - case "$TRAVIS_OS_NAME" in
@@ -278,8 +274,6 @@ after_success:
       du . | sort -nr | head -n100
 
 after_failure:
-  # Requested by travis to debug "shutting down NOW" errors
-  - sudo tail -n 500 /var/log/syslog
   - >
       echo "#### Build failed; Disk usage after running script:";
       df -h;
index a8308eb403896a277e766c80bef7545d9ea54521..4e16e61aa0d398cb0f21cfd60a67a64af037403c 100644 (file)
@@ -100,7 +100,7 @@ name = "backtrace"
 version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "backtrace-sys 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
+ "backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-demangle 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -109,7 +109,7 @@ dependencies = [
 
 [[package]]
 name = "backtrace-sys"
-version = "0.1.23"
+version = "0.1.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -308,7 +308,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "chalk-engine"
-version = "0.6.0"
+version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "chalk-macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1897,7 +1897,7 @@ dependencies = [
  "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "chalk-engine 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "chalk-engine 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "fmt_macros 0.0.0",
  "graphviz 0.0.0",
@@ -2408,7 +2408,7 @@ name = "rustc_traits"
 version = "0.0.0"
 dependencies = [
  "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "chalk-engine 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "chalk-engine 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "graphviz 0.0.0",
  "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
@@ -3125,7 +3125,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum assert_cli 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "98589b0e465a6c510d95fceebd365bb79bedece7f6e18a480897f2015f85ec51"
 "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
 "checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a"
-"checksum backtrace-sys 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)" = "bff67d0c06556c0b8e6b5f090f0eac52d950d9dfd1d35ba04e4ca3543eaf6a7e"
+"checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0"
 "checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5"
 "checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789"
 "checksum bufstream 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f382711e76b9de6c744cc00d0497baba02fb00a787f088c879f01d09468e32"
@@ -3135,7 +3135,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum cargo_metadata 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d6809b327f87369e6f3651efd2c5a96c49847a3ed2559477ecba79014751ee1"
 "checksum cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "2119ea4867bd2b8ed3aecab467709720b2d55b1bcfe09f772fd68066eaf15275"
 "checksum cfg-if 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "efe5c877e17a9c717a0bf3613b2709f723202c4e4675cc8f12926ded29bcb17e"
-"checksum chalk-engine 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a146c19172c7eea48ea55a7123ac95da786639bc665097f1e14034ee5f1d8699"
+"checksum chalk-engine 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "25ce2f28f55ed544a2a3756b7acf41dd7d6f27acffb2086439950925506af7d0"
 "checksum chalk-macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "295635afd6853aa9f20baeb7f0204862440c0fe994c5a253d5f479dac41d047e"
 "checksum chrono 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6962c635d530328acc53ac6a955e83093fedc91c5809dfac1fa60fa470830a37"
 "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e"
index c86010379f495fe56e89a31ff1eed0106bd5a513..f762d9414cff383d0554c76d3f8f87ad994eb8dd 100644 (file)
@@ -975,9 +975,19 @@ fn run(self, builder: &Builder) {
             builder.ensure(compile::Rustc { compiler, target });
         }
 
-        if builder.no_std(target) != Some(true) {
+        if builder.no_std(target) == Some(true) {
+            // the `test` doesn't compile for no-std targets
+            builder.ensure(compile::Std { compiler, target });
+        } else {
             builder.ensure(compile::Test { compiler, target });
         }
+
+        if builder.no_std(target) == Some(true) {
+            // for no_std run-make (e.g. thumb*),
+            // we need a host compiler which is called by cargo.
+            builder.ensure(compile::Std { compiler, target: compiler.host });
+        }
+
         builder.ensure(native::TestHelpers { target });
         builder.ensure(RemoteCopyLibs { compiler, target });
 
index b1ee636644ec79e76415e4cb2eb76d64fa3c6f84..3a7714d32fa17741dbf0b4f38822a87dd8b776f0 100755 (executable)
@@ -119,10 +119,6 @@ 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 f1656993e87a5f12c159680a43592468b62a56a2..9901dc1ebe307028eea40ffd140608c0a9b49cc1 100644 (file)
@@ -9,10 +9,6 @@ The tracking issue for this feature is: [#44660]
 The `crate_in_paths` feature allows to explicitly refer to the crate root in absolute paths
 using keyword `crate`.
 
-`crate` can be used *only* in absolute paths, i.e. either in `::crate::a::b::c` form or in `use`
-items where the starting `::` is added implicitly.  
-Paths like `crate::a::b::c` are not accepted currently.
-
 This feature is required in `feature(extern_absolute_paths)` mode to refer to any absolute path
 in the local crate (absolute paths refer to extern crates by default in that mode), but can be
 used without `feature(extern_absolute_paths)` as well.
@@ -39,15 +35,14 @@ mod n
     use crate as root;
     pub fn check() {
         assert_eq!(f(), 1);
-        // `::` is required in non-import paths
-        assert_eq!(::crate::m::g(), 2);
+        assert_eq!(crate::m::g(), 2);
         assert_eq!(root::m::h(), 3);
     }
 }
 
 fn main() {
     assert_eq!(f(), 1);
-    assert_eq!(::crate::m::g(), 2);
+    assert_eq!(crate::m::g(), 2);
     assert_eq!(root::m::h(), 3);
     n::check();
 }
index f45c5053e8dbcd84b7a8a215b2f8439b1c1ba5f5..6a22e7eba646b09185260f62d7f43e7114996d2a 100644 (file)
@@ -12,7 +12,7 @@ The `extern_absolute_paths` feature enables mode allowing to refer to names from
 `::my_crate::a::b` will resolve to path `a::b` in crate `my_crate`.
 
 `feature(crate_in_paths)` can be used in `feature(extern_absolute_paths)` mode for referring
-to absolute paths in the local crate (`::crate::a::b`).
+to absolute paths in the local crate (`crate::a::b`).
 
 `feature(extern_in_paths)` provides the same effect by using keyword `extern` to refer to
 paths from other crates (`extern::my_crate::a::b`).
diff --git a/src/doc/unstable-book/src/library-features/future-atomic-orderings.md b/src/doc/unstable-book/src/library-features/future-atomic-orderings.md
deleted file mode 100644 (file)
index 40c2ef2..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-# `future_atomic_orderings`
-
-This feature is internal to the Rust compiler and is not intended for general use.
-
-------------------------
diff --git a/src/doc/unstable-book/src/library-features/io-error-internals.md b/src/doc/unstable-book/src/library-features/io-error-internals.md
deleted file mode 100644 (file)
index 5bee18d..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-# `io_error_internals`
-
-This feature is internal to the Rust compiler and is not intended for general use.
-
-------------------------
index e64d863717da0019773a6eb0c861ebfd15d32aa1..1797f6708ac5b4745fcc2300fc3653b68c1320bc 100644 (file)
@@ -49,6 +49,7 @@ TYPE_KIND_REGULAR_UNION     = 17
 TYPE_KIND_OS_STRING         = 18
 TYPE_KIND_STD_VECDEQUE      = 19
 TYPE_KIND_STD_BTREESET      = 20
+TYPE_KIND_STD_BTREEMAP      = 21
 
 ENCODED_ENUM_PREFIX = "RUST$ENCODED$ENUM$"
 ENUM_DISR_FIELD_NAME = "RUST$ENUM$DISR"
@@ -75,6 +76,9 @@ STD_VECDEQUE_FIELD_NAMES = [STD_VECDEQUE_FIELD_NAME_TAIL,
 # std::collections::BTreeSet<> related constants
 STD_BTREESET_FIELD_NAMES = ["map"]
 
+# std::collections::BTreeMap<> related constants
+STD_BTREEMAP_FIELD_NAMES = ["root", "length"]
+
 # std::String related constants
 STD_STRING_FIELD_NAMES = ["vec"]
 
@@ -184,6 +188,11 @@ class Type(object):
                 self.__conforms_to_field_layout(STD_BTREESET_FIELD_NAMES)):
             return TYPE_KIND_STD_BTREESET
 
+        # STD COLLECTION BTREEMAP
+        if (unqualified_type_name.startswith("BTreeMap<") and
+                self.__conforms_to_field_layout(STD_BTREEMAP_FIELD_NAMES)):
+            return TYPE_KIND_STD_BTREEMAP
+
         # STD STRING
         if (unqualified_type_name.startswith("String") and
             self.__conforms_to_field_layout(STD_STRING_FIELD_NAMES)):
@@ -380,6 +389,18 @@ def extract_length_and_ptr_from_std_btreeset(vec_val):
     return (length, data_ptr)
 
 
+def extract_length_and_ptr_from_std_btreemap(vec_val):
+    assert vec_val.type.get_type_kind() == TYPE_KIND_STD_BTREEMAP
+    root = vec_val.get_child_at_index(0)
+    length = vec_val.get_child_at_index(1).as_integer()
+    node = root.get_child_at_index(0)
+    ptr = node.get_child_at_index(0)
+    unique_ptr_val = ptr.get_child_at_index(0)
+    data_ptr = unique_ptr_val.get_child_at_index(0)
+    assert data_ptr.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_PTR
+    return (length, data_ptr)
+
+
 def extract_length_and_ptr_from_slice(slice_val):
     assert (slice_val.type.get_type_kind() == TYPE_KIND_SLICE or
             slice_val.type.get_type_kind() == TYPE_KIND_STR_SLICE)
index fae1fd0cac30dde40b36f28e31a5b1a9215d340c..216915dba5fe7c03116d1cf2906afd7bbafe392f 100755 (executable)
@@ -130,6 +130,9 @@ def rust_pretty_printer_lookup_function(gdb_val):
     if type_kind == rustpp.TYPE_KIND_STD_BTREESET:
         return RustStdBTreeSetPrinter(val)
 
+    if type_kind == rustpp.TYPE_KIND_STD_BTREEMAP:
+        return RustStdBTreeMapPrinter(val)
+
     if type_kind == rustpp.TYPE_KIND_STD_STRING:
         return RustStdStringPrinter(val)
 
@@ -325,6 +328,32 @@ class RustStdBTreeSetPrinter(object):
             yield (str(index), gdb_ptr[index])
 
 
+class RustStdBTreeMapPrinter(object):
+    def __init__(self, val):
+        self.__val = val
+
+    @staticmethod
+    def display_hint():
+        return "map"
+
+    def to_string(self):
+        (length, data_ptr) = \
+            rustpp.extract_length_and_ptr_from_std_btreemap(self.__val)
+        return (self.__val.type.get_unqualified_type_name() +
+                ("(len: %i)" % length))
+
+    def children(self):
+        (length, data_ptr) = \
+            rustpp.extract_length_and_ptr_from_std_btreemap(self.__val)
+        keys = GdbValue(data_ptr.get_wrapped_value().dereference()).get_child_at_index(3)
+        keys_ptr = keys.get_wrapped_value()
+        vals = GdbValue(data_ptr.get_wrapped_value().dereference()).get_child_at_index(4)
+        vals_ptr = vals.get_wrapped_value()
+        for index in xrange(length):
+            yield (str(index), keys_ptr[index])
+            yield (str(index), vals_ptr[index])
+
+
 class RustStdStringPrinter(object):
     def __init__(self, val):
         self.__val = val
@@ -338,6 +367,7 @@ class RustStdStringPrinter(object):
     def display_hint(self):
         return "string"
 
+
 class RustOsStringPrinter(object):
     def __init__(self, val):
         self.__val = val
index 178ae62dd3dfa88efdd89de7e878d645e9a6bd22..e85bf1dfcad23c99116b2cd20497752a2f9991e2 100644 (file)
 #![feature(const_slice_len)]
 #![feature(const_str_as_bytes)]
 #![feature(const_str_len)]
+#![feature(non_exhaustive)]
 
 #[prelude_import]
 #[allow(unused)]
index 83f9dfea8f2676059c9dc6cf4c0617534ddd6201..5b3b2d1635688e8c04d5d9ee93e97321e2825a50 100644 (file)
@@ -396,6 +396,7 @@ macro_rules! write {
 /// ```
 #[macro_export]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[allow_internal_unstable]
 macro_rules! writeln {
     ($dst:expr) => (
         write!($dst, "\n")
@@ -403,11 +404,8 @@ macro_rules! writeln {
     ($dst:expr,) => (
         writeln!($dst)
     );
-    ($dst:expr, $fmt:expr) => (
-        write!($dst, concat!($fmt, "\n"))
-    );
-    ($dst:expr, $fmt:expr, $($arg:tt)*) => (
-        write!($dst, concat!($fmt, "\n"), $($arg)*)
+    ($dst:expr, $($arg:tt)*) => (
+        $dst.write_fmt(format_args_nl!($($arg)*))
     );
 }
 
index eb63966354b8644f86a8dcc373403b0d566d7d87..37856dc546935d3421153e26db476eba5437a166 100644 (file)
@@ -1891,7 +1891,7 @@ pub fn is_negative(self) -> bool { self < 0 }
         /// ```
         /// #![feature(int_to_from_bytes)]
         ///
-        /// let bytes = 0x12345678i32.to_be_bytes();
+        /// let bytes = 0x12_34_56_78_i32.to_be_bytes();
         /// assert_eq!(bytes, [0x12, 0x34, 0x56, 0x78]);
         /// ```
         #[unstable(feature = "int_to_from_bytes", issue = "52963")]
@@ -1908,7 +1908,7 @@ pub fn is_negative(self) -> bool { self < 0 }
         /// ```
         /// #![feature(int_to_from_bytes)]
         ///
-        /// let bytes = 0x12345678i32.to_le_bytes();
+        /// let bytes =  0x12_34_56_78_i32.to_le_bytes();
         /// assert_eq!(bytes, [0x78, 0x56, 0x34, 0x12]);
         /// ```
         #[unstable(feature = "int_to_from_bytes", issue = "52963")]
@@ -3568,47 +3568,119 @@ pub fn wrapping_next_power_of_two(self) -> Self {
             }
         }
 
-        /// Return the memory representation of this integer as a byte array.
+        /// Return the memory representation of this integer as a byte array in
+        /// big-endian (network) byte order.
+        ///
+        /// # Examples
         ///
-        /// The target platform’s native endianness is used.
-        /// Portable code likely wants to use this after [`to_be`] or [`to_le`].
+        /// ```
+        /// #![feature(int_to_from_bytes)]
         ///
-        /// [`to_be`]: #method.to_be
-        /// [`to_le`]: #method.to_le
+        /// let bytes =  0x12_34_56_78_i32.to_be_bytes();
+        /// assert_eq!(bytes, [0x12, 0x34, 0x56, 0x78]);
+        /// ```
+        #[unstable(feature = "int_to_from_bytes", issue = "52963")]
+        #[inline]
+        pub fn to_be_bytes(self) -> [u8; mem::size_of::<Self>()] {
+            self.to_be().to_ne_bytes()
+        }
+
+        /// Return the memory representation of this integer as a byte array in
+        /// little-endian byte order.
         ///
         /// # Examples
         ///
         /// ```
         /// #![feature(int_to_from_bytes)]
         ///
-        /// let bytes = 0x1234_5678_u32.to_be().to_bytes();
-        /// assert_eq!(bytes, [0x12, 0x34, 0x56, 0x78]);
+        /// let bytes =  0x12_34_56_78_i32.to_le_bytes();
+        /// assert_eq!(bytes, [0x78, 0x56, 0x34, 0x12]);
+        /// ```
+        #[unstable(feature = "int_to_from_bytes", issue = "52963")]
+        #[inline]
+        pub fn to_le_bytes(self) -> [u8; mem::size_of::<Self>()] {
+            self.to_le().to_ne_bytes()
+        }
+
+        /// Return the memory representation of this integer as a byte array in
+        /// native byte order.
+        ///
+        /// As the target platform's native endianness is used, portable code
+        /// should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate,
+        /// instead.
+        ///
+        /// [`to_be_bytes`]: #method.to_be_bytes
+        /// [`to_le_bytes`]: #method.to_le_bytes
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// #![feature(int_to_from_bytes)]
+        ///
+        /// let bytes = i32::min_value().to_be().to_ne_bytes();
+        /// assert_eq!(bytes, [0x80, 0, 0, 0]);
         /// ```
         #[unstable(feature = "int_to_from_bytes", issue = "52963")]
         #[inline]
-        pub fn to_bytes(self) -> [u8; mem::size_of::<Self>()] {
+        pub fn to_ne_bytes(self) -> [u8; mem::size_of::<Self>()] {
             unsafe { mem::transmute(self) }
         }
 
-        /// Create an integer value from its memory representation as a byte array.
+        /// Create an integer value from its representation as a byte array in
+        /// big endian.
+        ///
+        /// # Examples
         ///
-        /// The target platform’s native endianness is used.
-        /// Portable code likely wants to use [`to_be`] or [`to_le`] after this.
+        /// ```
+        /// #![feature(int_to_from_bytes)]
         ///
-        /// [`to_be`]: #method.to_be
-        /// [`to_le`]: #method.to_le
+        /// let int = i32::from_be_bytes([0x12, 0x34, 0x56, 0x78]);
+        /// assert_eq!(int, 0x12_34_56_78);
+        /// ```
+        #[unstable(feature = "int_to_from_bytes", issue = "52963")]
+        #[inline]
+        pub fn from_be_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
+            Self::from_be(Self::from_ne_bytes(bytes))
+        }
+
+        /// Create an integer value from its representation as a byte array in
+        /// little endian.
         ///
         /// # Examples
         ///
         /// ```
         /// #![feature(int_to_from_bytes)]
         ///
-        /// let int = u32::from_be(u32::from_bytes([0x12, 0x34, 0x56, 0x78]));
-        /// assert_eq!(int, 0x1234_5678_u32);
+        /// let int = i32::from_le_bytes([0x12, 0x34, 0x56, 0x78]);
+        /// assert_eq!(int, 0x78_56_34_12);
         /// ```
         #[unstable(feature = "int_to_from_bytes", issue = "52963")]
         #[inline]
-        pub fn from_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
+        pub fn from_le_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
+            Self::from_le(Self::from_ne_bytes(bytes))
+        }
+
+        /// Create an integer value from its memory representation as a byte
+        /// array in native endianness.
+        ///
+        /// As the target platform's native endianness is used, portable code
+        /// likely wants to use [`from_be_bytes`] or [`from_le_bytes`], as
+        /// appropriate instead.
+        ///
+        /// [`from_be_bytes`]: #method.from_be_bytes
+        /// [`from_le_bytes`]: #method.from_le_bytes
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// #![feature(int_to_from_bytes)]
+        ///
+        /// let int = i32::from_be(i32::from_ne_bytes([0x80, 0, 0, 0]));
+        /// assert_eq!(int, i32::min_value());
+        /// ```
+        #[unstable(feature = "int_to_from_bytes", issue = "52963")]
+        #[inline]
+        pub fn from_ne_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
             unsafe { mem::transmute(bytes) }
         }
     }
index 5bb713f5767411022c1c18a4f119512241f34aec..617e067e0787ed128a1e1217bdc9b6ae395bc575 100644 (file)
@@ -185,6 +185,7 @@ unsafe impl<T> Sync for AtomicPtr<T> {}
 /// [nomicon]: ../../../nomicon/atomics.html
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Copy, Clone, Debug)]
+#[non_exhaustive]
 pub enum Ordering {
     /// No ordering constraints, only atomic operations.
     ///
@@ -256,10 +257,6 @@ pub enum Ordering {
     /// [`AcqRel`]: https://llvm.org/docs/Atomics.html#acquirerelease
     #[stable(feature = "rust1", since = "1.0.0")]
     SeqCst,
-    // Prevent exhaustive matching to allow for future extension
-    #[doc(hidden)]
-    #[unstable(feature = "future_atomic_orderings", issue = "0")]
-    __Nonexhaustive,
 }
 
 /// An [`AtomicBool`] initialized to `false`.
@@ -1954,7 +1951,6 @@ fn strongest_failure_ordering(order: Ordering) -> Ordering {
         SeqCst => SeqCst,
         Acquire => Acquire,
         AcqRel => Acquire,
-        __Nonexhaustive => __Nonexhaustive,
     }
 }
 
@@ -1966,7 +1962,6 @@ unsafe fn atomic_store<T>(dst: *mut T, val: T, order: Ordering) {
         SeqCst => intrinsics::atomic_store(dst, val),
         Acquire => panic!("there is no such thing as an acquire store"),
         AcqRel => panic!("there is no such thing as an acquire/release store"),
-        __Nonexhaustive => panic!("invalid memory ordering"),
     }
 }
 
@@ -1978,7 +1973,6 @@ unsafe fn atomic_load<T>(dst: *const T, order: Ordering) -> T {
         SeqCst => intrinsics::atomic_load(dst),
         Release => panic!("there is no such thing as a release load"),
         AcqRel => panic!("there is no such thing as an acquire/release load"),
-        __Nonexhaustive => panic!("invalid memory ordering"),
     }
 }
 
@@ -1991,7 +1985,6 @@ unsafe fn atomic_swap<T>(dst: *mut T, val: T, order: Ordering) -> T {
         AcqRel => intrinsics::atomic_xchg_acqrel(dst, val),
         Relaxed => intrinsics::atomic_xchg_relaxed(dst, val),
         SeqCst => intrinsics::atomic_xchg(dst, val),
-        __Nonexhaustive => panic!("invalid memory ordering"),
     }
 }
 
@@ -2004,7 +1997,6 @@ unsafe fn atomic_add<T>(dst: *mut T, val: T, order: Ordering) -> T {
         AcqRel => intrinsics::atomic_xadd_acqrel(dst, val),
         Relaxed => intrinsics::atomic_xadd_relaxed(dst, val),
         SeqCst => intrinsics::atomic_xadd(dst, val),
-        __Nonexhaustive => panic!("invalid memory ordering"),
     }
 }
 
@@ -2017,7 +2009,6 @@ unsafe fn atomic_sub<T>(dst: *mut T, val: T, order: Ordering) -> T {
         AcqRel => intrinsics::atomic_xsub_acqrel(dst, val),
         Relaxed => intrinsics::atomic_xsub_relaxed(dst, val),
         SeqCst => intrinsics::atomic_xsub(dst, val),
-        __Nonexhaustive => panic!("invalid memory ordering"),
     }
 }
 
@@ -2039,8 +2030,6 @@ unsafe fn atomic_compare_exchange<T>(dst: *mut T,
         (AcqRel, Relaxed) => intrinsics::atomic_cxchg_acqrel_failrelaxed(dst, old, new),
         (SeqCst, Relaxed) => intrinsics::atomic_cxchg_failrelaxed(dst, old, new),
         (SeqCst, Acquire) => intrinsics::atomic_cxchg_failacq(dst, old, new),
-        (__Nonexhaustive, _) => panic!("invalid memory ordering"),
-        (_, __Nonexhaustive) => panic!("invalid memory ordering"),
         (_, AcqRel) => panic!("there is no such thing as an acquire/release failure ordering"),
         (_, Release) => panic!("there is no such thing as a release failure ordering"),
         _ => panic!("a failure ordering can't be stronger than a success ordering"),
@@ -2065,8 +2054,6 @@ unsafe fn atomic_compare_exchange_weak<T>(dst: *mut T,
         (AcqRel, Relaxed) => intrinsics::atomic_cxchgweak_acqrel_failrelaxed(dst, old, new),
         (SeqCst, Relaxed) => intrinsics::atomic_cxchgweak_failrelaxed(dst, old, new),
         (SeqCst, Acquire) => intrinsics::atomic_cxchgweak_failacq(dst, old, new),
-        (__Nonexhaustive, _) => panic!("invalid memory ordering"),
-        (_, __Nonexhaustive) => panic!("invalid memory ordering"),
         (_, AcqRel) => panic!("there is no such thing as an acquire/release failure ordering"),
         (_, Release) => panic!("there is no such thing as a release failure ordering"),
         _ => panic!("a failure ordering can't be stronger than a success ordering"),
@@ -2082,7 +2069,6 @@ unsafe fn atomic_and<T>(dst: *mut T, val: T, order: Ordering) -> T {
         AcqRel => intrinsics::atomic_and_acqrel(dst, val),
         Relaxed => intrinsics::atomic_and_relaxed(dst, val),
         SeqCst => intrinsics::atomic_and(dst, val),
-        __Nonexhaustive => panic!("invalid memory ordering"),
     }
 }
 
@@ -2094,7 +2080,6 @@ unsafe fn atomic_nand<T>(dst: *mut T, val: T, order: Ordering) -> T {
         AcqRel => intrinsics::atomic_nand_acqrel(dst, val),
         Relaxed => intrinsics::atomic_nand_relaxed(dst, val),
         SeqCst => intrinsics::atomic_nand(dst, val),
-        __Nonexhaustive => panic!("invalid memory ordering"),
     }
 }
 
@@ -2106,7 +2091,6 @@ unsafe fn atomic_or<T>(dst: *mut T, val: T, order: Ordering) -> T {
         AcqRel => intrinsics::atomic_or_acqrel(dst, val),
         Relaxed => intrinsics::atomic_or_relaxed(dst, val),
         SeqCst => intrinsics::atomic_or(dst, val),
-        __Nonexhaustive => panic!("invalid memory ordering"),
     }
 }
 
@@ -2118,7 +2102,6 @@ unsafe fn atomic_xor<T>(dst: *mut T, val: T, order: Ordering) -> T {
         AcqRel => intrinsics::atomic_xor_acqrel(dst, val),
         Relaxed => intrinsics::atomic_xor_relaxed(dst, val),
         SeqCst => intrinsics::atomic_xor(dst, val),
-        __Nonexhaustive => panic!("invalid memory ordering"),
     }
 }
 
@@ -2131,7 +2114,6 @@ unsafe fn atomic_max<T>(dst: *mut T, val: T, order: Ordering) -> T {
         AcqRel => intrinsics::atomic_max_acqrel(dst, val),
         Relaxed => intrinsics::atomic_max_relaxed(dst, val),
         SeqCst => intrinsics::atomic_max(dst, val),
-        __Nonexhaustive => panic!("invalid memory ordering"),
     }
 }
 
@@ -2144,7 +2126,6 @@ unsafe fn atomic_min<T>(dst: *mut T, val: T, order: Ordering) -> T {
         AcqRel => intrinsics::atomic_min_acqrel(dst, val),
         Relaxed => intrinsics::atomic_min_relaxed(dst, val),
         SeqCst => intrinsics::atomic_min(dst, val),
-        __Nonexhaustive => panic!("invalid memory ordering"),
     }
 }
 
@@ -2157,7 +2138,6 @@ unsafe fn atomic_umax<T>(dst: *mut T, val: T, order: Ordering) -> T {
         AcqRel => intrinsics::atomic_umax_acqrel(dst, val),
         Relaxed => intrinsics::atomic_umax_relaxed(dst, val),
         SeqCst => intrinsics::atomic_umax(dst, val),
-        __Nonexhaustive => panic!("invalid memory ordering"),
     }
 }
 
@@ -2170,7 +2150,6 @@ unsafe fn atomic_umin<T>(dst: *mut T, val: T, order: Ordering) -> T {
         AcqRel => intrinsics::atomic_umin_acqrel(dst, val),
         Relaxed => intrinsics::atomic_umin_relaxed(dst, val),
         SeqCst => intrinsics::atomic_umin(dst, val),
-        __Nonexhaustive => panic!("invalid memory ordering"),
     }
 }
 
@@ -2260,7 +2239,6 @@ pub fn fence(order: Ordering) {
             AcqRel => intrinsics::atomic_fence_acqrel(),
             SeqCst => intrinsics::atomic_fence(),
             Relaxed => panic!("there is no such thing as a relaxed fence"),
-            __Nonexhaustive => panic!("invalid memory ordering"),
         }
     }
 }
@@ -2350,7 +2328,6 @@ pub fn compiler_fence(order: Ordering) {
             AcqRel => intrinsics::atomic_singlethreadfence_acqrel(),
             SeqCst => intrinsics::atomic_singlethreadfence(),
             Relaxed => panic!("there is no such thing as a relaxed compiler fence"),
-            __Nonexhaustive => panic!("invalid memory ordering"),
         }
     }
 }
diff --git a/src/libpanic_unwind/dummy.rs b/src/libpanic_unwind/dummy.rs
new file mode 100644 (file)
index 0000000..7150560
--- /dev/null
@@ -0,0 +1,29 @@
+// 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.
+
+//! Unwinding for wasm32
+//!
+//! Right now we don't support this, so this is just stubs
+
+use alloc::boxed::Box;
+use core::any::Any;
+use core::intrinsics;
+
+pub fn payload() -> *mut u8 {
+    0 as *mut u8
+}
+
+pub unsafe fn cleanup(_ptr: *mut u8) -> Box<dyn Any + Send> {
+    intrinsics::abort()
+}
+
+pub unsafe fn panic(_data: Box<dyn Any + Send>) -> u32 {
+    intrinsics::abort()
+}
index a61b2c1f06394aaabfb1775b09abe902f99c6d21..9c3fc76c307a6f7696ba4ce2f163c1dea7812602 100644 (file)
 use core::raw;
 use core::panic::BoxMeUp;
 
-// Rust runtime's startup objects depend on these symbols, so make them public.
-#[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))]
-pub use imp::eh_frame_registry::*;
+#[macro_use]
+mod macros;
 
-// *-pc-windows-msvc
-#[cfg(target_env = "msvc")]
-#[path = "seh.rs"]
-mod imp;
-
-// x86_64-pc-windows-gnu
-#[cfg(all(windows, target_arch = "x86_64", target_env = "gnu"))]
-#[path = "seh64_gnu.rs"]
-mod imp;
-
-// i686-pc-windows-gnu and all others
-#[cfg(any(all(unix, not(target_os = "emscripten")),
-          target_os = "cloudabi",
-          target_os = "redox",
-          all(windows, target_arch = "x86", target_env = "gnu")))]
-#[path = "gcc.rs"]
-mod imp;
-
-// emscripten
-#[cfg(target_os = "emscripten")]
-#[path = "emcc.rs"]
-mod imp;
-
-#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
-#[path = "wasm32.rs"]
-mod imp;
+cfg_if! {
+    if #[cfg(target_os = "emscripten")] {
+        #[path = "emcc.rs"]
+        mod imp;
+    } else if #[cfg(target_arch = "wasm32")] {
+        #[path = "dummy.rs"]
+        mod imp;
+    } else if #[cfg(all(target_env = "msvc", target_arch = "aarch64"))] {
+        #[path = "dummy.rs"]
+        mod imp;
+    } else if #[cfg(target_env = "msvc")] {
+        #[path = "seh.rs"]
+        mod imp;
+    } else if #[cfg(all(windows, target_arch = "x86_64", target_env = "gnu"))] {
+        #[path = "seh64_gnu.rs"]
+        mod imp;
+    } else {
+        // Rust runtime's startup objects depend on these symbols, so make them public.
+        #[cfg(all(target_os="windows", target_arch = "x86", target_env="gnu"))]
+        pub use imp::eh_frame_registry::*;
+        #[path = "gcc.rs"]
+        mod imp;
+    }
+}
 
 mod dwarf;
 mod windows;
diff --git a/src/libpanic_unwind/macros.rs b/src/libpanic_unwind/macros.rs
new file mode 100644 (file)
index 0000000..6ea79dc
--- /dev/null
@@ -0,0 +1,45 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/// A macro for defining `#[cfg]` if-else statements.
+///
+/// This is similar to the `if/elif` C preprocessor macro by allowing definition
+/// of a cascade of `#[cfg]` cases, emitting the implementation which matches
+/// first.
+///
+/// This allows you to conveniently provide a long list `#[cfg]`'d blocks of code
+/// without having to rewrite each clause multiple times.
+macro_rules! cfg_if {
+    ($(
+        if #[cfg($($meta:meta),*)] { $($it:item)* }
+    ) else * else {
+        $($it2:item)*
+    }) => {
+        __cfg_if_items! {
+            () ;
+            $( ( ($($meta),*) ($($it)*) ), )*
+            ( () ($($it2)*) ),
+        }
+    }
+}
+
+macro_rules! __cfg_if_items {
+    (($($not:meta,)*) ; ) => {};
+    (($($not:meta,)*) ; ( ($($m:meta),*) ($($it:item)*) ), $($rest:tt)*) => {
+        __cfg_if_apply! { cfg(all(not(any($($not),*)), $($m,)*)), $($it)* }
+        __cfg_if_items! { ($($not,)* $($m,)*) ; $($rest)* }
+    }
+}
+
+macro_rules! __cfg_if_apply {
+    ($m:meta, $($it:item)*) => {
+        $(#[$m] $it)*
+    }
+}
diff --git a/src/libpanic_unwind/wasm32.rs b/src/libpanic_unwind/wasm32.rs
deleted file mode 100644 (file)
index 7150560..0000000
+++ /dev/null
@@ -1,29 +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.
-
-//! Unwinding for wasm32
-//!
-//! Right now we don't support this, so this is just stubs
-
-use alloc::boxed::Box;
-use core::any::Any;
-use core::intrinsics;
-
-pub fn payload() -> *mut u8 {
-    0 as *mut u8
-}
-
-pub unsafe fn cleanup(_ptr: *mut u8) -> Box<dyn Any + Send> {
-    intrinsics::abort()
-}
-
-pub unsafe fn panic(_data: Box<dyn Any + Send>) -> u32 {
-    intrinsics::abort()
-}
index 51e7647f36cc2f9673d49e27a1100182fe995f46..af7790164183c7dbfed11cc9b671173b1876f2ae 100644 (file)
@@ -16,6 +16,7 @@
 /// An enum representing a diagnostic level.
 #[unstable(feature = "proc_macro_diagnostic", issue = "38356")]
 #[derive(Copy, Clone, Debug)]
+#[non_exhaustive]
 pub enum Level {
     /// An error.
     Error,
@@ -25,8 +26,6 @@ pub enum Level {
     Note,
     /// A help message.
     Help,
-    #[doc(hidden)]
-    __Nonexhaustive,
 }
 
 /// A structure representing a diagnostic message and associated children
index fec90008c6701ec2d074091d68c8302cf58ca8fd..b54054752eaf14521ea3405f9bb7c91039d2cd02 100644 (file)
@@ -36,6 +36,7 @@
 #![feature(staged_api)]
 #![feature(lang_items)]
 #![feature(optin_builtin_traits)]
+#![feature(non_exhaustive)]
 
 #![recursion_limit="256"]
 
@@ -180,6 +181,20 @@ fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self {
     }
 }
 
+#[stable(feature = "token_stream_extend", since = "1.30.0")]
+impl Extend<TokenTree> for TokenStream {
+    fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, trees: I) {
+        self.extend(trees.into_iter().map(TokenStream::from));
+    }
+}
+
+#[stable(feature = "token_stream_extend", since = "1.30.0")]
+impl Extend<TokenStream> for TokenStream {
+    fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) {
+        self.0.extend(streams.into_iter().map(|stream| stream.0));
+    }
+}
+
 /// Public implementation details for the `TokenStream` type, such as iterators.
 #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
 pub mod token_stream {
index a54c695f6376fc0e817d42ea2c58fc9c0cb5067b..21229d3299d7e5a7251e7e52252aec82900539eb 100644 (file)
@@ -278,7 +278,6 @@ pub(crate) fn to_internal(self) -> errors::Level {
             Level::Warning => errors::Level::Warning,
             Level::Note => errors::Level::Note,
             Level::Help => errors::Level::Help,
-            Level::__Nonexhaustive => unreachable!("Level::__Nonexhaustive"),
         }
     }
 }
index 088b9436d0fc9c74b70fd09c741637451498b6a1..59b5b58e61eac533f1c3245b28880c1028405c85 100644 (file)
@@ -31,7 +31,7 @@ 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 }
+chalk-engine = { version = "0.7.0", default-features=false }
 rustc_fs_util = { path = "../librustc_fs_util" }
 
 # Note that these dependencies are a lie, they're just here to get linkage to
index 47c6bfbe6945a4b6822ff88e3ff2f3f33b0ed447..c21ac6218031df84f321d082e792494a93c559e3 100644 (file)
@@ -18,8 +18,7 @@
 use syntax::symbol::Symbol;
 use syntax::ast::{Attribute, MetaItem, MetaItemKind};
 use syntax_pos::{Span, DUMMY_SP};
-use hir;
-use hir::itemlikevisit::ItemLikeVisitor;
+use hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc_data_structures::fx::{FxHashSet, FxHashMap};
 use errors::DiagnosticId;
 
@@ -59,47 +58,44 @@ fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LibFeatureCollector<'a, 'tcx> {
         }
     }
 
-    fn extract(&self, attrs: &[Attribute]) -> Vec<(Symbol, Option<Symbol>, Span)> {
+    fn extract(&self, attr: &Attribute) -> Option<(Symbol, Option<Symbol>, Span)> {
         let stab_attrs = vec!["stable", "unstable", "rustc_const_unstable"];
-        let mut features = vec![];
-
-        for attr in attrs {
-            // Find a stability attribute (i.e. `#[stable (..)]`, `#[unstable (..)]`,
-            // `#[rustc_const_unstable (..)]`).
-            if let Some(stab_attr) = stab_attrs.iter().find(|stab_attr| {
-                attr.check_name(stab_attr)
-            }) {
-                let meta_item = attr.meta();
-                if let Some(MetaItem { node: MetaItemKind::List(ref metas), .. }) = meta_item {
-                    let mut feature = None;
-                    let mut since = None;
-                    for meta in metas {
-                        if let Some(mi) = meta.meta_item() {
-                            // Find the `feature = ".."` meta-item.
-                            match (&*mi.name().as_str(), mi.value_str()) {
-                                ("feature", val) => feature = val,
-                                ("since", val) => since = val,
-                                _ => {}
-                            }
+
+        // Find a stability attribute (i.e. `#[stable (..)]`, `#[unstable (..)]`,
+        // `#[rustc_const_unstable (..)]`).
+        if let Some(stab_attr) = stab_attrs.iter().find(|stab_attr| {
+            attr.check_name(stab_attr)
+        }) {
+            let meta_item = attr.meta();
+            if let Some(MetaItem { node: MetaItemKind::List(ref metas), .. }) = meta_item {
+                let mut feature = None;
+                let mut since = None;
+                for meta in metas {
+                    if let Some(mi) = meta.meta_item() {
+                        // Find the `feature = ".."` meta-item.
+                        match (&*mi.name().as_str(), mi.value_str()) {
+                            ("feature", val) => feature = val,
+                            ("since", val) => since = val,
+                            _ => {}
                         }
                     }
-                    if let Some(feature) = feature {
-                        // This additional check for stability is to make sure we
-                        // don't emit additional, irrelevant errors for malformed
-                        // attributes.
-                        if *stab_attr != "stable" || since.is_some() {
-                            features.push((feature, since, attr.span));
-                        }
+                }
+                if let Some(feature) = feature {
+                    // This additional check for stability is to make sure we
+                    // don't emit additional, irrelevant errors for malformed
+                    // attributes.
+                    if *stab_attr != "stable" || since.is_some() {
+                        return Some((feature, since, attr.span));
                     }
-                    // We need to iterate over the other attributes, because
-                    // `rustc_const_unstable` is not mutually exclusive with
-                    // the other stability attributes, so we can't just `break`
-                    // here.
                 }
+                // We need to iterate over the other attributes, because
+                // `rustc_const_unstable` is not mutually exclusive with
+                // the other stability attributes, so we can't just `break`
+                // here.
             }
         }
 
-        features
+        None
     }
 
     fn collect_feature(&mut self, feature: Symbol, since: Option<Symbol>, span: Span) {
@@ -140,25 +136,17 @@ fn collect_feature(&mut self, feature: Symbol, since: Option<Symbol>, span: Span
             }
         }
     }
-
-    fn collect_from_attrs(&mut self, attrs: &[Attribute]) {
-        for (feature, stable, span) in self.extract(attrs) {
-            self.collect_feature(feature, stable, span);
-        }
-    }
 }
 
-impl<'a, 'v, 'tcx> ItemLikeVisitor<'v> for LibFeatureCollector<'a, 'tcx> {
-    fn visit_item(&mut self, item: &hir::Item) {
-        self.collect_from_attrs(&item.attrs);
-    }
-
-    fn visit_trait_item(&mut self, trait_item: &hir::TraitItem) {
-        self.collect_from_attrs(&trait_item.attrs);
+impl<'a, 'tcx> Visitor<'tcx> for LibFeatureCollector<'a, 'tcx> {
+    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+        NestedVisitorMap::All(&self.tcx.hir)
     }
 
-    fn visit_impl_item(&mut self, impl_item: &hir::ImplItem) {
-        self.collect_from_attrs(&impl_item.attrs);
+    fn visit_attribute(&mut self, attr: &'tcx Attribute) {
+        if let Some((feature, stable, span)) = self.extract(attr) {
+            self.collect_feature(feature, stable, span);
+        }
     }
 }
 
@@ -169,10 +157,6 @@ pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LibFeatures {
             collector.collect_feature(feature, since, DUMMY_SP);
         }
     }
-    collector.collect_from_attrs(&tcx.hir.krate().attrs);
-    tcx.hir.krate().visit_all_item_likes(&mut collector);
-    for exported_macro in &tcx.hir.krate().exported_macros {
-        collector.collect_from_attrs(&exported_macro.attrs);
-    }
+    intravisit::walk_crate(&mut collector, tcx.hir.krate());
     collector.lib_features
 }
index dae5709ba114a3721f86bdb41ee2fcb9ae1594e7..8ceff303774b596a265af6a1dfac05a09589914c 100644 (file)
@@ -429,8 +429,8 @@ pub enum BorrowKind {
 
     /// Data must be immutable but not aliasable.  This kind of borrow
     /// cannot currently be expressed by the user and is used only in
-    /// implicit closure bindings. It is needed when you the closure
-    /// is borrowing or mutating a mutable referent, e.g.:
+    /// implicit closure bindings. It is needed when the closure is
+    /// borrowing or mutating a mutable referent, e.g.:
     ///
     ///    let x: &mut isize = ...;
     ///    let y = || *x += 5;
@@ -443,7 +443,7 @@ pub enum BorrowKind {
     ///    let y = (&mut Env { &x }, fn_ptr);  // Closure is pair of env and fn
     ///    fn fn_ptr(env: &mut Env) { **env.x += 5; }
     ///
-    /// This is then illegal because you cannot mutate a `&mut` found
+    /// This is then illegal because you cannot mutate an `&mut` found
     /// in an aliasable location. To solve, you'd have to translate with
     /// an `&mut` borrow:
     ///
@@ -523,6 +523,8 @@ pub struct VarBindingForm<'tcx> {
     /// (b) it gives a way to separate this case from the remaining cases
     ///     for diagnostics.
     pub opt_match_place: Option<(Option<Place<'tcx>>, Span)>,
+    /// Span of the pattern in which this variable was bound.
+    pub pat_span: Span,
 }
 
 #[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
@@ -540,7 +542,8 @@ pub enum BindingForm<'tcx> {
 impl_stable_hash_for!(struct self::VarBindingForm<'tcx> {
     binding_mode,
     opt_ty_info,
-    opt_match_place
+    opt_match_place,
+    pat_span
 });
 
 mod binding_form_impl {
@@ -673,7 +676,7 @@ pub struct LocalDecl<'tcx> {
     /// ROOT SCOPE
     ///  │{ argument x: &str }
     ///  │
-    ///  │ │{ #[allow(unused_mut] } // this is actually split into 2 scopes
+    ///  │ │{ #[allow(unused_mut)] } // this is actually split into 2 scopes
     ///  │ │                        // in practice because I'm lazy.
     ///  │ │
     ///  │ │← x.source_info.scope
@@ -710,6 +713,7 @@ pub fn can_be_made_mutable(&self) -> bool {
                 binding_mode: ty::BindingMode::BindByValue(_),
                 opt_ty_info: _,
                 opt_match_place: _,
+                pat_span: _,
             }))) => true,
 
             // FIXME: might be able to thread the distinction between
@@ -729,6 +733,7 @@ pub fn is_nonref_binding(&self) -> bool {
                 binding_mode: ty::BindingMode::BindByValue(_),
                 opt_ty_info: _,
                 opt_match_place: _,
+                pat_span: _,
             }))) => true,
 
             Some(ClearCrossCrate::Set(BindingForm::ImplicitSelf)) => true,
@@ -906,7 +911,7 @@ pub enum TerminatorKind<'tcx> {
 
     /// Drop the Place and assign the new value over it. This ensures
     /// that the assignment to `P` occurs *even if* the destructor for
-    /// place unwinds. Its semantics are best explained by by the
+    /// place unwinds. Its semantics are best explained by the
     /// elaboration:
     ///
     /// ```
index e1395c3fa442723c2bba781ea5918aee35bd902d..280ce75720bcfef8d309c0caefbc6197b6648102 100644 (file)
@@ -131,7 +131,7 @@ pub fn parse(tcx: TyCtxt<'a, 'gcx, 'tcx>,
             parse_error(tcx, item.span,
                         "this attribute must have a valid value",
                         "expected value here",
-                        Some(r#"eg `#[rustc_on_unimplemented = "foo"]`"#));
+                        Some(r#"eg `#[rustc_on_unimplemented(message="foo")]`"#));
         }
 
         if errored {
@@ -170,7 +170,7 @@ pub fn of_item(tcx: TyCtxt<'a, 'gcx, 'tcx>,
             return Err(parse_error(tcx, attr.span,
                                    "`#[rustc_on_unimplemented]` requires a value",
                                    "value required here",
-                                   Some(r#"eg `#[rustc_on_unimplemented = "foo"]`"#)));
+                                   Some(r#"eg `#[rustc_on_unimplemented(message="foo")]`"#)));
         };
         debug!("of_item({:?}/{:?}) = {:?}", trait_def_id, impl_def_id, result);
         result
@@ -213,10 +213,13 @@ pub fn evaluate(&self,
             }
         }
 
+        let options: FxHashMap<String, String> = options.into_iter()
+            .filter_map(|(k, v)| v.as_ref().map(|v| (k.to_owned(), v.to_owned())))
+            .collect();
         OnUnimplementedNote {
-            label: label.map(|l| l.format(tcx, trait_ref)),
-            message: message.map(|m| m.format(tcx, trait_ref)),
-            note: note.map(|n| n.format(tcx, trait_ref)),
+            label: label.map(|l| l.format(tcx, trait_ref, &options)),
+            message: message.map(|m| m.format(tcx, trait_ref, &options)),
+            note: note.map(|n| n.format(tcx, trait_ref, &options)),
         }
     }
 }
@@ -251,6 +254,10 @@ fn verify(&self,
                     Position::ArgumentNamed(s) if s == "Self" => (),
                     // `{ThisTraitsName}` is allowed
                     Position::ArgumentNamed(s) if s == name => (),
+                    // `{from_method}` is allowed
+                    Position::ArgumentNamed(s) if s == "from_method" => (),
+                    // `{from_desugaring}` is allowed
+                    Position::ArgumentNamed(s) if s == "from_desugaring" => (),
                     // So is `{A}` if A is a type parameter
                     Position::ArgumentNamed(s) => match generics.params.iter().find(|param| {
                         param.name == s
@@ -258,17 +265,14 @@ fn verify(&self,
                         Some(_) => (),
                         None => {
                             span_err!(tcx.sess, span, E0230,
-                                      "there is no parameter \
-                                       {} on trait {}",
-                                      s, name);
+                                      "there is no parameter `{}` on trait `{}`", s, name);
                             result = Err(ErrorReported);
                         }
                     },
                     // `{:1}` and `{}` are not to be used
                     Position::ArgumentIs(_) | Position::ArgumentImplicitlyIs(_) => {
                         span_err!(tcx.sess, span, E0231,
-                                  "only named substitution \
-                                   parameters are allowed");
+                                  "only named substitution parameters are allowed");
                         result = Err(ErrorReported);
                     }
                 }
@@ -280,7 +284,8 @@ fn verify(&self,
 
     pub fn format(&self,
                   tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                  trait_ref: ty::TraitRef<'tcx>)
+                  trait_ref: ty::TraitRef<'tcx>,
+                  options: &FxHashMap<String, String>)
                   -> String
     {
         let name = tcx.item_name(trait_ref.def_id);
@@ -296,6 +301,7 @@ pub fn format(&self,
             let name = param.name.to_string();
             Some((name, value))
         }).collect::<FxHashMap<String, String>>();
+        let empty_string = String::new();
 
         let parser = Parser::new(&self.0, None);
         parser.map(|p| {
@@ -308,14 +314,20 @@ pub fn format(&self,
                             &trait_str
                         }
                         None => {
-                            bug!("broken on_unimplemented {:?} for {:?}: \
-                                  no argument matching {:?}",
-                                 self.0, trait_ref, s)
+                            if let Some(val) = options.get(s) {
+                                val
+                            } else if s == "from_desugaring" || s == "from_method" {
+                                // don't break messages using these two arguments incorrectly
+                                &empty_string
+                            } else {
+                                bug!("broken on_unimplemented {:?} for {:?}: \
+                                      no argument matching {:?}",
+                                     self.0, trait_ref, s)
+                            }
                         }
                     },
                     _ => {
-                        bug!("broken on_unimplemented {:?} - bad \
-                              format arg", self.0)
+                        bug!("broken on_unimplemented {:?} - bad format arg", self.0)
                     }
                 }
             }
index 875c7199f6d11830e1179b19ad5b7afc0db0dced..40f13ac06f56fbed1439d69e2df4f9793004bafc 100644 (file)
@@ -239,6 +239,10 @@ fn push(&mut self, predicate: &ty::Predicate<'tcx>) {
 impl<'cx, 'gcx, 'tcx> Iterator for Elaborator<'cx, 'gcx, 'tcx> {
     type Item = ty::Predicate<'tcx>;
 
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        (self.stack.len(), None)
+    }
+
     fn next(&mut self) -> Option<ty::Predicate<'tcx>> {
         // Extract next item from top-most stack frame, if any.
         let next_predicate = match self.stack.pop() {
index 45279f18117c16329e8c45b4c584e89cd47f607b..87d59d2e763cbe89743452e59379e8888f639f3a 100644 (file)
@@ -2306,24 +2306,14 @@ pub(super) fn is_all_zeros(limbs: &[Limb]) -> bool {
 
     /// One, not zero, based LSB. That is, returns 0 for a zeroed significand.
     pub(super) fn olsb(limbs: &[Limb]) -> usize {
-        for (i, &limb) in limbs.iter().enumerate() {
-            if limb != 0 {
-                return i * LIMB_BITS + limb.trailing_zeros() as usize + 1;
-            }
-        }
-
-        0
+        limbs.iter().enumerate().find(|(_, &limb)| limb != 0).map_or(0,
+            |(i, limb)| i * LIMB_BITS + limb.trailing_zeros() as usize + 1)
     }
 
     /// One, not zero, based MSB. That is, returns 0 for a zeroed significand.
     pub(super) fn omsb(limbs: &[Limb]) -> usize {
-        for (i, &limb) in limbs.iter().enumerate().rev() {
-            if limb != 0 {
-                return (i + 1) * LIMB_BITS - limb.leading_zeros() as usize;
-            }
-        }
-
-        0
+        limbs.iter().enumerate().rfind(|(_, &limb)| limb != 0).map_or(0,
+            |(i, limb)| (i + 1) * LIMB_BITS - limb.leading_zeros() as usize)
     }
 
     /// Comparison (unsigned) of two significands.
index 098149c36ce435f74f6d253a14914552650c6fcd..5b08400eb112d05ddc56fe37aca367d0eb61391c 100644 (file)
@@ -1235,7 +1235,7 @@ fn note_immutability_blame(&self,
                     ty::BindByReference(..) => {
                         let let_span = self.tcx.hir.span(node_id);
                         let suggestion = suggest_ref_mut(self.tcx, let_span);
-                        if let Some((let_span, replace_str)) = suggestion {
+                        if let Some(replace_str) = suggestion {
                             db.span_suggestion(
                                 let_span,
                                 "use a mutable reference instead",
index 404272d69c863e6314efba24865a92971878fac9..a7672d1ffe8911595c9bc19f94fc4abed22c2bbd 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use array_vec::ArrayVec;
 use std::borrow::{Borrow, BorrowMut, ToOwned};
 use std::fmt;
 use std::iter;
@@ -25,6 +26,8 @@
 ///
 /// In other words, `T` is the type used to index into the bitvector
 /// this type uses to represent the set of object it holds.
+///
+/// The representation is dense, using one bit per possible element.
 #[derive(Eq, PartialEq)]
 pub struct IdxSetBuf<T: Idx> {
     _pd: PhantomData<fn(&T)>,
@@ -90,6 +93,8 @@ fn to_owned(&self) -> Self::Owned {
     }
 }
 
+const BITS_PER_WORD: usize = mem::size_of::<Word>() * 8;
+
 impl<T: Idx> fmt::Debug for IdxSetBuf<T> {
     fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
         w.debug_list()
@@ -108,8 +113,7 @@ fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
 
 impl<T: Idx> IdxSetBuf<T> {
     fn new(init: Word, universe_size: usize) -> Self {
-        let bits_per_word = mem::size_of::<Word>() * 8;
-        let num_words = (universe_size + (bits_per_word - 1)) / bits_per_word;
+        let num_words = (universe_size + (BITS_PER_WORD - 1)) / BITS_PER_WORD;
         IdxSetBuf {
             _pd: Default::default(),
             bits: vec![init; num_words],
@@ -160,6 +164,16 @@ pub fn to_owned(&self) -> IdxSetBuf<T> {
         }
     }
 
+    /// Duplicates as a hybrid set.
+    pub fn to_hybrid(&self) -> HybridIdxSetBuf<T> {
+        // This universe_size may be slightly larger than the one specified
+        // upon creation, due to rounding up to a whole word. That's ok.
+        let universe_size = self.bits.len() * BITS_PER_WORD;
+
+        // Note: we currently don't bother trying to make a Sparse set.
+        HybridIdxSetBuf::Dense(self.to_owned(), universe_size)
+    }
+
     /// Removes all elements
     pub fn clear(&mut self) {
         for b in &mut self.bits {
@@ -177,11 +191,9 @@ pub fn set_up_to(&mut self, universe_size: usize) {
 
     /// Clear all elements above `universe_size`.
     fn trim_to(&mut self, universe_size: usize) {
-        let word_bits = mem::size_of::<Word>() * 8;
-
         // `trim_block` is the first block where some bits have
         // to be cleared.
-        let trim_block = universe_size / word_bits;
+        let trim_block = universe_size / BITS_PER_WORD;
 
         // all the blocks above it have to be completely cleared.
         if trim_block < self.bits.len() {
@@ -189,9 +201,9 @@ fn trim_to(&mut self, universe_size: usize) {
                 *b = 0;
             }
 
-            // at that block, the `universe_size % word_bits` lsbs
+            // at that block, the `universe_size % BITS_PER_WORD` lsbs
             // should remain.
-            let remaining_bits = universe_size % word_bits;
+            let remaining_bits = universe_size % BITS_PER_WORD;
             let mask = (1<<remaining_bits)-1;
             self.bits[trim_block] &= mask;
         }
@@ -242,12 +254,46 @@ pub fn union(&mut self, other: &IdxSet<T>) -> bool {
         bitwise(self.words_mut(), other.words(), &Union)
     }
 
+    /// Like `union()`, but takes a `SparseIdxSetBuf` argument.
+    fn union_sparse(&mut self, other: &SparseIdxSetBuf<T>) -> bool {
+        let mut changed = false;
+        for elem in other.iter() {
+            changed |= self.add(&elem);
+        }
+        changed
+    }
+
+    /// Like `union()`, but takes a `HybridIdxSetBuf` argument.
+    pub fn union_hybrid(&mut self, other: &HybridIdxSetBuf<T>) -> bool {
+        match other {
+            HybridIdxSetBuf::Sparse(sparse, _) => self.union_sparse(sparse),
+            HybridIdxSetBuf::Dense(dense, _) => self.union(dense),
+        }
+    }
+
     /// Set `self = self - other` and return true if `self` changed.
     /// (i.e., if any bits were removed).
     pub fn subtract(&mut self, other: &IdxSet<T>) -> bool {
         bitwise(self.words_mut(), other.words(), &Subtract)
     }
 
+    /// Like `subtract()`, but takes a `SparseIdxSetBuf` argument.
+    fn subtract_sparse(&mut self, other: &SparseIdxSetBuf<T>) -> bool {
+        let mut changed = false;
+        for elem in other.iter() {
+            changed |= self.remove(&elem);
+        }
+        changed
+    }
+
+    /// Like `subtract()`, but takes a `HybridIdxSetBuf` argument.
+    pub fn subtract_hybrid(&mut self, other: &HybridIdxSetBuf<T>) -> bool {
+        match other {
+            HybridIdxSetBuf::Sparse(sparse, _) => self.subtract_sparse(sparse),
+            HybridIdxSetBuf::Dense(dense, _) => self.subtract(dense),
+        }
+    }
+
     /// Set `self = self & other` and return true if `self` changed.
     /// (i.e., if any bits were removed).
     pub fn intersect(&mut self, other: &IdxSet<T>) -> bool {
@@ -273,11 +319,10 @@ impl<'a, T: Idx> Iterator for Iter<'a, T> {
     type Item = T;
 
     fn next(&mut self) -> Option<T> {
-        let word_bits = mem::size_of::<Word>() * 8;
         loop {
             if let Some((ref mut word, offset)) = self.cur {
                 let bit_pos = word.trailing_zeros() as usize;
-                if bit_pos != word_bits {
+                if bit_pos != BITS_PER_WORD {
                     let bit = 1 << bit_pos;
                     *word ^= bit;
                     return Some(T::new(bit_pos + offset))
@@ -285,7 +330,189 @@ fn next(&mut self) -> Option<T> {
             }
 
             let (i, word) = self.iter.next()?;
-            self.cur = Some((*word, word_bits * i));
+            self.cur = Some((*word, BITS_PER_WORD * i));
+        }
+    }
+}
+
+const SPARSE_MAX: usize = 8;
+
+/// A sparse index set with a maximum of SPARSE_MAX elements. Used by
+/// HybridIdxSetBuf; do not use directly.
+///
+/// The elements are stored as an unsorted vector with no duplicates.
+#[derive(Clone, Debug)]
+pub struct SparseIdxSetBuf<T: Idx>(ArrayVec<[T; SPARSE_MAX]>);
+
+impl<T: Idx> SparseIdxSetBuf<T> {
+    fn new() -> Self {
+        SparseIdxSetBuf(ArrayVec::new())
+    }
+
+    fn len(&self) -> usize {
+        self.0.len()
+    }
+
+    fn contains(&self, elem: &T) -> bool {
+        self.0.contains(elem)
+    }
+
+    fn add(&mut self, elem: &T) -> bool {
+        // Ensure there are no duplicates.
+        if self.0.contains(elem) {
+            false
+        } else {
+            self.0.push(*elem);
+            true
+        }
+    }
+
+    fn remove(&mut self, elem: &T) -> bool {
+        if let Some(i) = self.0.iter().position(|e| e == elem) {
+            // Swap the found element to the end, then pop it.
+            let len = self.0.len();
+            self.0.swap(i, len - 1);
+            self.0.pop();
+            true
+        } else {
+            false
+        }
+    }
+
+    fn to_dense(&self, universe_size: usize) -> IdxSetBuf<T> {
+        let mut dense = IdxSetBuf::new_empty(universe_size);
+        for elem in self.0.iter() {
+            dense.add(elem);
+        }
+        dense
+    }
+
+    fn iter(&self) -> SparseIter<T> {
+        SparseIter {
+            iter: self.0.iter(),
+        }
+    }
+}
+
+pub struct SparseIter<'a, T: Idx> {
+    iter: slice::Iter<'a, T>,
+}
+
+impl<'a, T: Idx> Iterator for SparseIter<'a, T> {
+    type Item = T;
+
+    fn next(&mut self) -> Option<T> {
+        self.iter.next().map(|e| *e)
+    }
+}
+
+/// Like IdxSetBuf, but with a hybrid representation: sparse when there are few
+/// elements in the set, but dense when there are many. It's especially
+/// efficient for sets that typically have a small number of elements, but a
+/// large `universe_size`, and are cleared frequently.
+#[derive(Clone, Debug)]
+pub enum HybridIdxSetBuf<T: Idx> {
+    Sparse(SparseIdxSetBuf<T>, usize),
+    Dense(IdxSetBuf<T>, usize),
+}
+
+impl<T: Idx> HybridIdxSetBuf<T> {
+    pub fn new_empty(universe_size: usize) -> Self {
+        HybridIdxSetBuf::Sparse(SparseIdxSetBuf::new(), universe_size)
+    }
+
+    fn universe_size(&mut self) -> usize {
+        match *self {
+            HybridIdxSetBuf::Sparse(_, size) => size,
+            HybridIdxSetBuf::Dense(_, size) => size,
+        }
+    }
+
+    pub fn clear(&mut self) {
+        let universe_size = self.universe_size();
+        *self = HybridIdxSetBuf::new_empty(universe_size);
+    }
+
+    /// Returns true iff set `self` contains `elem`.
+    pub fn contains(&self, elem: &T) -> bool {
+        match self {
+            HybridIdxSetBuf::Sparse(sparse, _) => sparse.contains(elem),
+            HybridIdxSetBuf::Dense(dense, _) => dense.contains(elem),
+        }
+    }
+
+    /// Adds `elem` to the set `self`.
+    pub fn add(&mut self, elem: &T) -> bool {
+        match self {
+            HybridIdxSetBuf::Sparse(sparse, _) if sparse.len() < SPARSE_MAX => {
+                // The set is sparse and has space for `elem`.
+                sparse.add(elem)
+            }
+            HybridIdxSetBuf::Sparse(sparse, _) if sparse.contains(elem) => {
+                // The set is sparse and does not have space for `elem`, but
+                // that doesn't matter because `elem` is already present.
+                false
+            }
+            HybridIdxSetBuf::Sparse(_, _) => {
+                // The set is sparse and full. Convert to a dense set.
+                //
+                // FIXME: This code is awful, but I can't work out how else to
+                //        appease the borrow checker.
+                let dummy = HybridIdxSetBuf::Sparse(SparseIdxSetBuf::new(), 0);
+                match mem::replace(self, dummy) {
+                    HybridIdxSetBuf::Sparse(sparse, universe_size) => {
+                        let mut dense = sparse.to_dense(universe_size);
+                        let changed = dense.add(elem);
+                        assert!(changed);
+                        mem::replace(self, HybridIdxSetBuf::Dense(dense, universe_size));
+                        changed
+                    }
+                    _ => panic!("impossible"),
+                }
+            }
+
+            HybridIdxSetBuf::Dense(dense, _) => dense.add(elem),
+        }
+    }
+
+    /// Removes `elem` from the set `self`.
+    pub fn remove(&mut self, elem: &T) -> bool {
+        // Note: we currently don't bother going from Dense back to Sparse.
+        match self {
+            HybridIdxSetBuf::Sparse(sparse, _) => sparse.remove(elem),
+            HybridIdxSetBuf::Dense(dense, _) => dense.remove(elem),
+        }
+    }
+
+    /// Converts to a dense set, consuming itself in the process.
+    pub fn to_dense(self) -> IdxSetBuf<T> {
+        match self {
+            HybridIdxSetBuf::Sparse(sparse, universe_size) => sparse.to_dense(universe_size),
+            HybridIdxSetBuf::Dense(dense, _) => dense,
+        }
+    }
+
+    /// Iteration order is unspecified.
+    pub fn iter(&self) -> HybridIter<T> {
+        match self {
+            HybridIdxSetBuf::Sparse(sparse, _) => HybridIter::Sparse(sparse.iter()),
+            HybridIdxSetBuf::Dense(dense, _) => HybridIter::Dense(dense.iter()),
+        }
+    }
+}
+
+pub enum HybridIter<'a, T: Idx> {
+    Sparse(SparseIter<'a, T>),
+    Dense(Iter<'a, T>),
+}
+
+impl<'a, T: Idx> Iterator for HybridIter<'a, T> {
+    type Item = T;
+
+    fn next(&mut self) -> Option<T> {
+        match self {
+            HybridIter::Sparse(sparse) => sparse.next(),
+            HybridIter::Dense(dense) => dense.next(),
         }
     }
 }
index d3524e841b223d93d3b927a149ce006a84d5efdb..56ca4db098f87217f9534118238e08b1f3956a38 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use rustc::hir;
+use core::unicode::property::Pattern_White_Space;
 use rustc::mir::*;
 use rustc::ty;
 use rustc_errors::DiagnosticBuilder;
 // let (&x, &y) = (&String::new(), &String::new());
 #[derive(Debug)]
 enum GroupedMoveError<'tcx> {
-    // Match place can't be moved from
+    // Place expression can't be moved from,
     // e.g. match x[0] { s => (), } where x: &[String]
-    MovesFromMatchPlace {
+    MovesFromPlace {
         original_path: Place<'tcx>,
         span: Span,
         move_from: Place<'tcx>,
         kind: IllegalMoveOriginKind<'tcx>,
         binds_to: Vec<Local>,
     },
-    // Part of a pattern can't be moved from,
+    // Part of a value expression can't be moved from,
     // e.g. match &String::new() { &x => (), }
-    MovesFromPattern {
+    MovesFromValue {
         original_path: Place<'tcx>,
         span: Span,
         move_from: MovePathIndex,
@@ -119,6 +119,7 @@ fn append_to_grouped_errors(
                         opt_match_place: Some((ref opt_match_place, match_span)),
                         binding_mode: _,
                         opt_ty_info: _,
+                        pat_span: _,
                     }))) = local_decl.is_user_variable
                     {
                         self.append_binding_error(
@@ -155,7 +156,7 @@ fn append_binding_error(
         statement_span: Span,
     ) {
         debug!(
-            "append_to_grouped_errors(match_place={:?}, match_span={:?})",
+            "append_binding_error(match_place={:?}, match_span={:?})",
             match_place, match_span
         );
 
@@ -166,7 +167,7 @@ fn append_binding_error(
             // Error with the match place
             LookupResult::Parent(_) => {
                 for ge in &mut *grouped_errors {
-                    if let GroupedMoveError::MovesFromMatchPlace { span, binds_to, .. } = ge {
+                    if let GroupedMoveError::MovesFromPlace { span, binds_to, .. } = ge {
                         if match_span == *span {
                             debug!("appending local({:?}) to list", bind_to);
                             if !binds_to.is_empty() {
@@ -184,7 +185,7 @@ fn append_binding_error(
                 } else {
                     (vec![bind_to], match_span)
                 };
-                grouped_errors.push(GroupedMoveError::MovesFromMatchPlace {
+                grouped_errors.push(GroupedMoveError::MovesFromPlace {
                     span,
                     move_from: match_place.clone(),
                     original_path,
@@ -200,7 +201,7 @@ fn append_binding_error(
                     _ => unreachable!("Probably not unreachable..."),
                 };
                 for ge in &mut *grouped_errors {
-                    if let GroupedMoveError::MovesFromPattern {
+                    if let GroupedMoveError::MovesFromValue {
                         span,
                         move_from: other_mpi,
                         binds_to,
@@ -215,7 +216,7 @@ fn append_binding_error(
                     }
                 }
                 debug!("found a new move error location");
-                grouped_errors.push(GroupedMoveError::MovesFromPattern {
+                grouped_errors.push(GroupedMoveError::MovesFromValue {
                     span: match_span,
                     move_from: mpi,
                     original_path,
@@ -230,13 +231,13 @@ fn report(&mut self, error: GroupedMoveError<'tcx>) {
         let (mut err, err_span) = {
             let (span, original_path, kind): (Span, &Place<'tcx>, &IllegalMoveOriginKind) =
                 match error {
-                    GroupedMoveError::MovesFromMatchPlace {
+                    GroupedMoveError::MovesFromPlace {
                         span,
                         ref original_path,
                         ref kind,
                         ..
                     } |
-                    GroupedMoveError::MovesFromPattern { span, ref original_path, ref kind, .. } |
+                    GroupedMoveError::MovesFromValue { span, ref original_path, ref kind, .. } |
                     GroupedMoveError::OtherIllegalMove { span, ref original_path, ref kind } => {
                         (span, original_path, kind)
                     },
@@ -331,111 +332,140 @@ fn add_move_hints(
         err: &mut DiagnosticBuilder<'a>,
         span: Span,
     ) {
+        let snippet = self.tcx.sess.codemap().span_to_snippet(span).unwrap();
         match error {
-            GroupedMoveError::MovesFromMatchPlace {
+            GroupedMoveError::MovesFromPlace {
                 mut binds_to,
                 move_from,
                 ..
             } => {
-                // Ok to suggest a borrow, since the target can't be moved from
-                // anyway.
-                if let Ok(snippet) = self.tcx.sess.codemap().span_to_snippet(span) {
-                    match move_from {
-                        Place::Projection(ref proj)
-                            if self.suitable_to_remove_deref(proj, &snippet) =>
-                        {
-                            err.span_suggestion(
-                                span,
-                                "consider removing this dereference operator",
-                                (&snippet[1..]).to_owned(),
-                            );
-                        }
-                        _ => {
-                            err.span_suggestion(
-                                span,
-                                "consider using a reference instead",
-                                format!("&{}", snippet),
-                            );
-                        }
-                    }
-
-                    binds_to.sort();
-                    binds_to.dedup();
-                    for local in binds_to {
-                        let bind_to = &self.mir.local_decls[local];
-                        let binding_span = bind_to.source_info.span;
-                        err.span_label(
-                            binding_span,
-                            format!(
-                                "move occurs because {} has type `{}`, \
-                                 which does not implement the `Copy` trait",
-                                bind_to.name.unwrap(),
-                                bind_to.ty
-                            ),
-                        );
-                    }
+                let try_remove_deref = match move_from {
+                    Place::Projection(box PlaceProjection {
+                        elem: ProjectionElem::Deref,
+                        ..
+                    }) => true,
+                    _ => false,
+                };
+                if try_remove_deref && snippet.starts_with('*') {
+                    // The snippet doesn't start with `*` in (e.g.) index
+                    // expressions `a[b]`, which roughly desugar to
+                    // `*Index::index(&a, b)` or
+                    // `*IndexMut::index_mut(&mut a, b)`.
+                    err.span_suggestion(
+                        span,
+                        "consider removing the `*`",
+                        snippet[1..].to_owned(),
+                    );
+                } else {
+                    err.span_suggestion(
+                        span,
+                        "consider borrowing here",
+                        format!("&{}", snippet),
+                    );
                 }
+
+                binds_to.sort();
+                binds_to.dedup();
+                self.add_move_error_details(err, &binds_to);
             }
-            GroupedMoveError::MovesFromPattern { mut binds_to, .. } => {
-                // Suggest ref, since there might be a move in
-                // another match arm
+            GroupedMoveError::MovesFromValue { mut binds_to, .. } => {
                 binds_to.sort();
                 binds_to.dedup();
-                let mut multipart_suggestion = Vec::with_capacity(binds_to.len());
-                for (j, local) in binds_to.into_iter().enumerate() {
-                    let bind_to = &self.mir.local_decls[local];
-                    let binding_span = bind_to.source_info.span;
+                self.add_move_error_suggestions(err, &binds_to);
+                self.add_move_error_details(err, &binds_to);
+            }
+            // No binding. Nothing to suggest.
+            GroupedMoveError::OtherIllegalMove { .. } => (),
+        }
+    }
 
-                    // Suggest ref mut when the user has already written mut.
-                    let ref_kind = match bind_to.mutability {
-                        Mutability::Not => "ref",
-                        Mutability::Mut => "ref mut",
-                    };
-                    if j == 0 {
-                        err.span_label(binding_span, format!("data moved here"));
+    fn add_move_error_suggestions(
+        &self,
+        err: &mut DiagnosticBuilder<'a>,
+        binds_to: &[Local],
+    ) {
+        let mut suggestions: Vec<(Span, &str, String)> = Vec::new();
+        for local in binds_to {
+            let bind_to = &self.mir.local_decls[*local];
+            if let Some(
+                ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
+                    pat_span,
+                    ..
+                }))
+            ) = bind_to.is_user_variable {
+                let pat_snippet = self
+                    .tcx.sess.codemap()
+                    .span_to_snippet(pat_span)
+                    .unwrap();
+                if pat_snippet.starts_with('&') {
+                    let pat_snippet = pat_snippet[1..].trim_left();
+                    let suggestion;
+                    let to_remove;
+                    if pat_snippet.starts_with("mut")
+                        && pat_snippet["mut".len()..].starts_with(Pattern_White_Space)
+                    {
+                        suggestion = pat_snippet["mut".len()..].trim_left();
+                        to_remove = "&mut";
                     } else {
-                        err.span_label(binding_span, format!("... and here"));
-                    }
-                    match bind_to.name {
-                        Some(name) => {
-                            multipart_suggestion.push((binding_span,
-                                                       format!("{} {}", ref_kind, name)));
-                        }
-                        None => {
-                            err.span_label(
-                                span,
-                                format!("Local {:?} is not suitable for ref", bind_to),
-                            );
-                        }
+                        suggestion = pat_snippet;
+                        to_remove = "&";
                     }
+                    suggestions.push((
+                        pat_span,
+                        to_remove,
+                        suggestion.to_owned(),
+                    ));
                 }
-                err.multipart_suggestion("to prevent move, use ref or ref mut",
-                                         multipart_suggestion);
             }
-            // Nothing to suggest.
-            GroupedMoveError::OtherIllegalMove { .. } => (),
+        }
+        suggestions.sort_unstable_by_key(|&(span, _, _)| span);
+        suggestions.dedup_by_key(|&mut (span, _, _)| span);
+        for (span, to_remove, suggestion) in suggestions {
+            err.span_suggestion(
+                span,
+                &format!("consider removing the `{}`", to_remove),
+                suggestion
+            );
         }
     }
 
-    fn suitable_to_remove_deref(&self, proj: &PlaceProjection<'tcx>, snippet: &str) -> bool {
-        let is_shared_ref = |ty: ty::Ty| match ty.sty {
-            ty::TypeVariants::TyRef(.., hir::Mutability::MutImmutable) => true,
-            _ => false,
-        };
+    fn add_move_error_details(
+        &self,
+        err: &mut DiagnosticBuilder<'a>,
+        binds_to: &[Local],
+    ) {
+        let mut noncopy_var_spans = Vec::new();
+        for (j, local) in binds_to.into_iter().enumerate() {
+            let bind_to = &self.mir.local_decls[*local];
+            let binding_span = bind_to.source_info.span;
 
-        proj.elem == ProjectionElem::Deref && snippet.starts_with('*') && match proj.base {
-            Place::Local(local) => {
-                let local_decl = &self.mir.local_decls[local];
-                // If this is a temporary, then this could be from an
-                // overloaded * operator.
-                local_decl.is_user_variable.is_some() && is_shared_ref(local_decl.ty)
+            if j == 0 {
+                err.span_label(binding_span, format!("data moved here"));
+            } else {
+                err.span_label(binding_span, format!("...and here"));
             }
-            Place::Promoted(_) => true,
-            Place::Static(ref st) => is_shared_ref(st.ty),
-            Place::Projection(ref proj) => match proj.elem {
-                ProjectionElem::Field(_, ty) => is_shared_ref(ty),
-                _ => false,
-            },
+
+            if binds_to.len() == 1 {
+                err.span_note(
+                    binding_span,
+                    &format!(
+                        "move occurs because `{}` has type `{}`, \
+                            which does not implement the `Copy` trait",
+                        bind_to.name.unwrap(),
+                        bind_to.ty
+                    ),
+                );
+            } else {
+                noncopy_var_spans.push(binding_span);
+            }
+        }
+
+        if binds_to.len() > 1 {
+            err.span_note(
+                noncopy_var_spans,
+                "move occurs because these variables have types that \
+                    don't implement the `Copy` trait",
+            );
         }
     }
 }
index 283cccd51174a1bbe81e32f8c8def62fb5f3805f..f11135fc026f53acd940600a43d226a733416c30 100644 (file)
@@ -329,7 +329,11 @@ pub(super) fn report_mutability_error(
                     ClearCrossCrate::Set(mir::BindingForm::Var(mir::VarBindingForm {
                         binding_mode: ty::BindingMode::BindByReference(_),
                         ..
-                    })) => suggest_ref_mut(self.tcx, local_decl.source_info.span),
+                    })) => {
+                        let pattern_span = local_decl.source_info.span;
+                        suggest_ref_mut(self.tcx, pattern_span)
+                            .map(|replacement| (pattern_span, replacement))
+                    }
 
                     //
                     ClearCrossCrate::Set(mir::BindingForm::RefForGuard) => unreachable!(),
index 6b6ec749bcbe6efd1124d6f529264564a4aab661..b317bb7cff0e3c9a6e0b720f0dd0b2a63e1123f9 100644 (file)
@@ -321,9 +321,10 @@ pub fn place_into_pattern(&mut self,
         block.unit()
     }
 
-    /// Declares the bindings of the given pattern and returns the visibility scope
-    /// for the bindings in this patterns, if such a scope had to be created.
-    /// NOTE: Declaring the bindings should always be done in their drop scope.
+    /// Declares the bindings of the given patterns and returns the visibility
+    /// scope for the bindings in these patterns, if such a scope had to be
+    /// created. NOTE: Declaring the bindings should always be done in their
+    /// drop scope.
     pub fn declare_bindings(&mut self,
                             mut visibility_scope: Option<SourceScope>,
                             scope_span: Span,
@@ -356,7 +357,8 @@ pub fn declare_bindings(&mut self,
             let visibility_scope = visibility_scope.unwrap();
             this.declare_binding(source_info, visibility_scope, mutability, name, mode,
                                  num_patterns, var, ty, has_guard,
-                                 opt_match_place.map(|(x, y)| (x.cloned(), y)));
+                                 opt_match_place.map(|(x, y)| (x.cloned(), y)),
+                                 patterns[0].span);
         });
         visibility_scope
     }
@@ -1181,7 +1183,8 @@ fn declare_binding(&mut self,
                        var_id: NodeId,
                        var_ty: Ty<'tcx>,
                        has_guard: ArmHasGuard,
-                       opt_match_place: Option<(Option<Place<'tcx>>, Span)>)
+                       opt_match_place: Option<(Option<Place<'tcx>>, Span)>,
+                       pat_span: Span)
     {
         debug!("declare_binding(var_id={:?}, name={:?}, mode={:?}, var_ty={:?}, \
                 visibility_scope={:?}, source_info={:?})",
@@ -1207,6 +1210,7 @@ fn declare_binding(&mut self,
                 // Instead, just abandon providing diagnostic info.
                 opt_ty_info: None,
                 opt_match_place,
+                pat_span,
             }))),
         };
         let for_arm_body = self.local_decls.push(local.clone());
index 054bd69c361b92115eb6c60dd32e67ec3cccbcd4..c0c431804d8c1ea52fcf1716084e06c761586e55 100644 (file)
@@ -763,6 +763,7 @@ fn args_and_body(&mut self,
                                     binding_mode,
                                     opt_ty_info,
                                     opt_match_place: Some((Some(place.clone()), span)),
+                                    pat_span: span,
                                 })))
                             };
                         self.var_indices.insert(var, LocalsForNode::One(local));
index 05453bd58c43d9015ccacbf024d47def18252d7e..d2a8a9dcf4ba2c987b501a952e80e5a041ef3613 100644 (file)
@@ -12,7 +12,7 @@
 //! locations.
 
 use rustc::mir::{BasicBlock, Location};
-use rustc_data_structures::indexed_set::{IdxSetBuf, Iter};
+use rustc_data_structures::indexed_set::{HybridIdxSetBuf, IdxSetBuf, Iter};
 use rustc_data_structures::indexed_vec::Idx;
 
 use dataflow::{BitDenotation, BlockSets, DataflowResults};
@@ -68,8 +68,8 @@ pub struct FlowAtLocation<BD>
 {
     base_results: DataflowResults<BD>,
     curr_state: IdxSetBuf<BD::Idx>,
-    stmt_gen: IdxSetBuf<BD::Idx>,
-    stmt_kill: IdxSetBuf<BD::Idx>,
+    stmt_gen: HybridIdxSetBuf<BD::Idx>,
+    stmt_kill: HybridIdxSetBuf<BD::Idx>,
 }
 
 impl<BD> FlowAtLocation<BD>
@@ -97,8 +97,8 @@ pub fn each_gen_bit<F>(&self, f: F)
     pub fn new(results: DataflowResults<BD>) -> Self {
         let bits_per_block = results.sets().bits_per_block();
         let curr_state = IdxSetBuf::new_empty(bits_per_block);
-        let stmt_gen = IdxSetBuf::new_empty(bits_per_block);
-        let stmt_kill = IdxSetBuf::new_empty(bits_per_block);
+        let stmt_gen = HybridIdxSetBuf::new_empty(bits_per_block);
+        let stmt_kill = HybridIdxSetBuf::new_empty(bits_per_block);
         FlowAtLocation {
             base_results: results,
             curr_state: curr_state,
@@ -129,8 +129,8 @@ pub fn with_iter_outgoing<F>(&self, f: F)
         F: FnOnce(Iter<BD::Idx>),
     {
         let mut curr_state = self.curr_state.clone();
-        curr_state.union(&self.stmt_gen);
-        curr_state.subtract(&self.stmt_kill);
+        curr_state.union_hybrid(&self.stmt_gen);
+        curr_state.subtract_hybrid(&self.stmt_kill);
         f(curr_state.iter());
     }
 }
@@ -193,8 +193,8 @@ fn reconstruct_terminator_effect(&mut self, loc: Location) {
     }
 
     fn apply_local_effect(&mut self, _loc: Location) {
-        self.curr_state.union(&self.stmt_gen);
-        self.curr_state.subtract(&self.stmt_kill);
+        self.curr_state.union_hybrid(&self.stmt_gen);
+        self.curr_state.subtract_hybrid(&self.stmt_kill);
     }
 }
 
index 7475b4d82f45207b75cc37db8c8f624c1ac36a79..97d549987712bbe32a8051f1a005ae0c12f839aa 100644 (file)
@@ -168,13 +168,13 @@ fn node_label_verbose_row<W: io::Write>(&self,
         let i = n.index();
 
         macro_rules! dump_set_for {
-            ($set:ident) => {
+            ($set:ident, $interpret:ident) => {
                 write!(w, "<td>")?;
 
                 let flow = self.mbcx.flow_state();
-                let entry_interp = flow.interpret_set(&flow.operator,
-                                                      flow.sets.$set(i),
-                                                      &self.render_idx);
+                let entry_interp = flow.$interpret(&flow.operator,
+                                                   flow.sets.$set(i),
+                                                   &self.render_idx);
                 for e in &entry_interp {
                     write!(w, "{:?}<br/>", e)?;
                 }
@@ -184,7 +184,7 @@ macro_rules! dump_set_for {
 
         write!(w, "<tr>")?;
         // Entry
-        dump_set_for!(on_entry_set_for);
+        dump_set_for!(on_entry_set_for, interpret_set);
 
         // MIR statements
         write!(w, "<td>")?;
@@ -198,10 +198,10 @@ macro_rules! dump_set_for {
         write!(w, "</td>")?;
 
         // Gen
-        dump_set_for!(gen_set_for);
+        dump_set_for!(gen_set_for, interpret_hybrid_set);
 
         // Kill
-        dump_set_for!(kill_set_for);
+        dump_set_for!(kill_set_for, interpret_hybrid_set);
 
         write!(w, "</tr>")?;
 
@@ -217,19 +217,14 @@ fn node_label_final_row<W: io::Write>(&self,
                                           -> io::Result<()> {
         let i = n.index();
 
-        macro_rules! dump_set_for {
-            ($set:ident) => {
-                let flow = self.mbcx.flow_state();
-                let bits_per_block = flow.sets.bits_per_block();
-                let set = flow.sets.$set(i);
-                write!(w, "<td>{:?}</td>",
-                       dot::escape_html(&bits_to_string(set.words(), bits_per_block)))?;
-            }
-        }
+        let flow = self.mbcx.flow_state();
+        let bits_per_block = flow.sets.bits_per_block();
 
         write!(w, "<tr>")?;
+
         // Entry
-        dump_set_for!(on_entry_set_for);
+        let set = flow.sets.on_entry_set_for(i);
+        write!(w, "<td>{:?}</td>", dot::escape_html(&bits_to_string(set.words(), bits_per_block)))?;
 
         // Terminator
         write!(w, "<td>")?;
@@ -242,10 +237,12 @@ macro_rules! dump_set_for {
         write!(w, "</td>")?;
 
         // Gen
-        dump_set_for!(gen_set_for);
+        let set = flow.sets.gen_set_for(i);
+        write!(w, "<td>{:?}</td>", dot::escape_html(&format!("{:?}", set)))?;
 
         // Kill
-        dump_set_for!(kill_set_for);
+        let set = flow.sets.kill_set_for(i);
+        write!(w, "<td>{:?}</td>", dot::escape_html(&format!("{:?}", set)))?;
 
         write!(w, "</tr>")?;
 
index 4227f0bcd362dfcd97912f4a2940e17c654e4faa..56c4dac19e5049f64e4dba05fec6d6b8678693f5 100644 (file)
@@ -10,9 +10,9 @@
 
 use syntax::ast::{self, MetaItem};
 
-use rustc_data_structures::indexed_set::{IdxSet, IdxSetBuf};
-use rustc_data_structures::indexed_vec::Idx;
 use rustc_data_structures::bitslice::{bitwise, BitwiseOperator, Word};
+use rustc_data_structures::indexed_set::{HybridIdxSetBuf, IdxSet, IdxSetBuf};
+use rustc_data_structures::indexed_vec::Idx;
 use rustc_data_structures::work_queue::WorkQueue;
 
 use rustc::ty::{self, TyCtxt};
@@ -188,7 +188,6 @@ fn propagate(&mut self) {
             builder: self,
         };
         propcx.walk_cfg(&mut temp);
-
     }
 
     fn build_sets(&mut self) {
@@ -243,8 +242,8 @@ fn walk_cfg(&mut self, in_out: &mut IdxSet<BD::Idx>) {
                 let sets = self.builder.flow_state.sets.for_block(bb.index());
                 debug_assert!(in_out.words().len() == sets.on_entry.words().len());
                 in_out.overwrite(sets.on_entry);
-                in_out.union(sets.gen_set);
-                in_out.subtract(sets.kill_set);
+                in_out.union_hybrid(sets.gen_set);
+                in_out.subtract_hybrid(sets.kill_set);
             }
             self.builder.propagate_bits_into_graph_successors_of(
                 in_out, (bb, bb_data), &mut dirty_queue);
@@ -289,15 +288,11 @@ fn post_dataflow_instrumentation<P>(&self, p: P) -> io::Result<()>
 }
 
 /// Maps each block to a set of bits
-#[derive(Debug)]
+#[derive(Clone, Debug)]
 pub(crate) struct Bits<E:Idx> {
     bits: IdxSetBuf<E>,
 }
 
-impl<E:Idx> Clone for Bits<E> {
-    fn clone(&self) -> Self { Bits { bits: self.bits.clone() } }
-}
-
 impl<E:Idx> Bits<E> {
     fn new(bits: IdxSetBuf<E>) -> Self {
         Bits { bits: bits }
@@ -372,13 +367,15 @@ pub fn state_for_location<'tcx, T: BitDenotation>(loc: Location,
                                                   result: &DataflowResults<T>,
                                                   mir: &Mir<'tcx>)
     -> IdxSetBuf<T::Idx> {
-    let mut entry = result.sets().on_entry_set_for(loc.block.index()).to_owned();
+    let mut on_entry = result.sets().on_entry_set_for(loc.block.index()).to_owned();
+    let mut kill_set = on_entry.to_hybrid();
+    let mut gen_set = kill_set.clone();
 
     {
         let mut sets = BlockSets {
-            on_entry: &mut entry.clone(),
-            kill_set: &mut entry.clone(),
-            gen_set: &mut entry,
+            on_entry: &mut on_entry,
+            kill_set: &mut kill_set,
+            gen_set: &mut gen_set,
         };
 
         for stmt in 0..loc.statement_index {
@@ -396,7 +393,7 @@ pub fn state_for_location<'tcx, T: BitDenotation>(loc: Location,
         }
     }
 
-    entry
+    gen_set.to_dense()
 }
 
 pub struct DataflowAnalysis<'a, 'tcx: 'a, O> where O: BitDenotation
@@ -443,12 +440,22 @@ pub struct DataflowState<O: BitDenotation>
 impl<O: BitDenotation> DataflowState<O> {
     pub(crate) fn interpret_set<'c, P>(&self,
                                        o: &'c O,
-                                       words: &IdxSet<O::Idx>,
+                                       set: &IdxSet<O::Idx>,
                                        render_idx: &P)
                                        -> Vec<DebugFormatted>
         where P: Fn(&O, O::Idx) -> DebugFormatted
     {
-        words.iter().map(|i| render_idx(o, i)).collect()
+        set.iter().map(|i| render_idx(o, i)).collect()
+    }
+
+    pub(crate) fn interpret_hybrid_set<'c, P>(&self,
+                                              o: &'c O,
+                                              set: &HybridIdxSetBuf<O::Idx>,
+                                              render_idx: &P)
+                                              -> Vec<DebugFormatted>
+        where P: Fn(&O, O::Idx) -> DebugFormatted
+    {
+        set.iter().map(|i| render_idx(o, i)).collect()
     }
 }
 
@@ -461,18 +468,18 @@ pub struct AllSets<E: Idx> {
     /// equal to bits_per_block / (mem::size_of::<Word> * 8), rounded up.
     words_per_block: usize,
 
+    /// For each block, bits valid on entry to the block.
+    on_entry_sets: Bits<E>,
+
     /// For each block, bits generated by executing the statements in
     /// the block. (For comparison, the Terminator for each block is
     /// handled in a flow-specific manner during propagation.)
-    gen_sets: Bits<E>,
+    gen_sets: Vec<HybridIdxSetBuf<E>>,
 
     /// For each block, bits killed by executing the statements in the
     /// block. (For comparison, the Terminator for each block is
     /// handled in a flow-specific manner during propagation.)
-    kill_sets: Bits<E>,
-
-    /// For each block, bits valid on entry to the block.
-    on_entry_sets: Bits<E>,
+    kill_sets: Vec<HybridIdxSetBuf<E>>,
 }
 
 /// Triple of sets associated with a given block.
@@ -494,11 +501,13 @@ pub struct BlockSets<'a, E: Idx> {
     /// Dataflow state immediately before control flow enters the given block.
     pub(crate) on_entry: &'a mut IdxSet<E>,
 
-    /// Bits that are set to 1 by the time we exit the given block.
-    pub(crate) gen_set: &'a mut IdxSet<E>,
+    /// Bits that are set to 1 by the time we exit the given block. Hybrid
+    /// because it usually contains only 0 or 1 elements.
+    pub(crate) gen_set: &'a mut HybridIdxSetBuf<E>,
 
-    /// Bits that are set to 0 by the time we exit the given block.
-    pub(crate) kill_set: &'a mut IdxSet<E>,
+    /// Bits that are set to 0 by the time we exit the given block. Hybrid
+    /// because it usually contains only 0 or 1 elements.
+    pub(crate) kill_set: &'a mut HybridIdxSetBuf<E>,
 }
 
 impl<'a, E:Idx> BlockSets<'a, E> {
@@ -542,8 +551,8 @@ fn kill_all<I>(&mut self, i: I)
     }
 
     fn apply_local_effect(&mut self) {
-        self.on_entry.union(&self.gen_set);
-        self.on_entry.subtract(&self.kill_set);
+        self.on_entry.union_hybrid(&self.gen_set);
+        self.on_entry.subtract_hybrid(&self.kill_set);
     }
 }
 
@@ -554,24 +563,21 @@ pub fn for_block(&mut self, block_idx: usize) -> BlockSets<E> {
         let range = E::new(offset)..E::new(offset + self.words_per_block);
         BlockSets {
             on_entry: self.on_entry_sets.bits.range_mut(&range),
-            gen_set: self.gen_sets.bits.range_mut(&range),
-            kill_set: self.kill_sets.bits.range_mut(&range),
+            gen_set: &mut self.gen_sets[block_idx],
+            kill_set: &mut self.kill_sets[block_idx],
         }
     }
 
-    fn lookup_set_for<'a>(&self, sets: &'a Bits<E>, block_idx: usize) -> &'a IdxSet<E> {
+    pub fn on_entry_set_for(&self, block_idx: usize) -> &IdxSet<E> {
         let offset = self.words_per_block * block_idx;
         let range = E::new(offset)..E::new(offset + self.words_per_block);
-        sets.bits.range(&range)
+        self.on_entry_sets.bits.range(&range)
     }
-    pub fn gen_set_for(&self, block_idx: usize) -> &IdxSet<E> {
-        self.lookup_set_for(&self.gen_sets, block_idx)
+    pub fn gen_set_for(&self, block_idx: usize) -> &HybridIdxSetBuf<E> {
+        &self.gen_sets[block_idx]
     }
-    pub fn kill_set_for(&self, block_idx: usize) -> &IdxSet<E> {
-        self.lookup_set_for(&self.kill_sets, block_idx)
-    }
-    pub fn on_entry_set_for(&self, block_idx: usize) -> &IdxSet<E> {
-        self.lookup_set_for(&self.on_entry_sets, block_idx)
+    pub fn kill_set_for(&self, block_idx: usize) -> &HybridIdxSetBuf<E> {
+        &self.kill_sets[block_idx]
     }
 }
 
@@ -731,12 +737,12 @@ pub fn new(mir: &'a Mir<'tcx>,
         let num_blocks = mir.basic_blocks().len();
         let num_overall = num_blocks * bits_per_block_rounded_up;
 
-        let zeroes = Bits::new(IdxSetBuf::new_empty(num_overall));
         let on_entry = Bits::new(if D::bottom_value() {
             IdxSetBuf::new_filled(num_overall)
         } else {
             IdxSetBuf::new_empty(num_overall)
         });
+        let empties = vec![HybridIdxSetBuf::new_empty(bits_per_block); num_blocks];
 
         DataflowAnalysis {
             mir,
@@ -745,9 +751,9 @@ pub fn new(mir: &'a Mir<'tcx>,
                 sets: AllSets {
                     bits_per_block,
                     words_per_block,
-                    gen_sets: zeroes.clone(),
-                    kill_sets: zeroes,
                     on_entry_sets: on_entry,
+                    gen_sets: empties.clone(),
+                    kill_sets: empties,
                 },
                 operator: denotation,
             }
index 42682c34407cab08c713731ac8fc89d4dadbc097..bda80ff562c75ede8ef6cbacc79b5982d36de066 100644 (file)
@@ -35,6 +35,7 @@
 #![feature(try_trait)]
 #![feature(unicode_internals)]
 #![feature(step_trait)]
+#![feature(slice_concat_ext)]
 
 #![recursion_limit="256"]
 
index da149f420644c5cd551dfd04cb013150b334caaa..776d7888459f78a7d862dc0ac151f46ff589dede 100644 (file)
@@ -138,9 +138,9 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         }
     };
 
-    let mut entry = results.0.sets.on_entry_set_for(bb.index()).to_owned();
-    let mut gen = results.0.sets.gen_set_for(bb.index()).to_owned();
-    let mut kill = results.0.sets.kill_set_for(bb.index()).to_owned();
+    let mut on_entry = results.0.sets.on_entry_set_for(bb.index()).to_owned();
+    let mut gen_set = results.0.sets.gen_set_for(bb.index()).clone();
+    let mut kill_set = results.0.sets.kill_set_for(bb.index()).clone();
 
     // Emulate effect of all statements in the block up to (but not
     // including) the borrow within `peek_arg_place`. Do *not* include
@@ -148,9 +148,9 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // of the argument at time immediate preceding Call to
     // `rustc_peek`).
 
-    let mut sets = dataflow::BlockSets { on_entry: &mut entry,
-                                      gen_set: &mut gen,
-                                      kill_set: &mut kill };
+    let mut sets = dataflow::BlockSets { on_entry: &mut on_entry,
+                                         gen_set: &mut gen_set,
+                                         kill_set: &mut kill_set };
 
     for (j, stmt) in statements.iter().enumerate() {
         debug!("rustc_peek: ({:?},{}) {:?}", bb, j, stmt);
@@ -203,14 +203,14 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         debug!("rustc_peek: computing effect on place: {:?} ({:?}) in stmt: {:?}",
                place, lhs_mpi, stmt);
         // reset GEN and KILL sets before emulating their effect.
-        for e in sets.gen_set.words_mut() { *e = 0; }
-        for e in sets.kill_set.words_mut() { *e = 0; }
+        sets.gen_set.clear();
+        sets.kill_set.clear();
         results.0.operator.before_statement_effect(
             &mut sets, Location { block: bb, statement_index: j });
         results.0.operator.statement_effect(
             &mut sets, Location { block: bb, statement_index: j });
-        sets.on_entry.union(sets.gen_set);
-        sets.on_entry.subtract(sets.kill_set);
+        sets.on_entry.union_hybrid(sets.gen_set);
+        sets.on_entry.subtract_hybrid(sets.kill_set);
     }
 
     results.0.operator.before_terminator_effect(
index 78e9dd23e83ae718387a9fa5bd1e47e2a50028e3..fe6fefe89fd66b59cab4e0e5b4887eb165fbc1ce 100644 (file)
 /// If possible, suggest replacing `ref` with `ref mut`.
 pub fn suggest_ref_mut<'cx, 'gcx, 'tcx>(
     tcx: ty::TyCtxt<'cx, 'gcx, 'tcx>,
-    pattern_span: Span,
-) -> Option<(Span, String)> {
-    let hi_src = tcx.sess.codemap().span_to_snippet(pattern_span).unwrap();
+    binding_span: Span,
+) -> Option<(String)> {
+    let hi_src = tcx.sess.codemap().span_to_snippet(binding_span).unwrap();
     if hi_src.starts_with("ref")
         && hi_src["ref".len()..].starts_with(Pattern_White_Space)
     {
         let replacement = format!("ref mut{}", &hi_src["ref".len()..]);
-        Some((pattern_span, replacement))
+        Some(replacement)
     } else {
         None
     }
index 992ea12ffa2b14c44dde94f4fdfc303ac356d791..729689e35c9989b0cbe9b2dc00389d14d5a0808f 100644 (file)
@@ -3459,33 +3459,37 @@ fn resolve_path(
             let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS };
             let name = ident.name;
 
-            if i == 0 && ns == TypeNS && name == keywords::SelfValue.name() {
-                let mut ctxt = ident.span.ctxt().modern();
-                module = Some(ModuleOrUniformRoot::Module(
-                    self.resolve_self(&mut ctxt, self.current_module)));
-                continue
-            } else if allow_super && ns == TypeNS && name == keywords::Super.name() {
-                let mut ctxt = ident.span.ctxt().modern();
-                let self_module_parent = match i {
-                    0 => self.resolve_self(&mut ctxt, self.current_module).parent,
-                    _ => match module {
-                        Some(ModuleOrUniformRoot::Module(module)) => module.parent,
-                        _ => None,
-                    },
-                };
-                if let Some(parent) = self_module_parent {
-                    module = Some(ModuleOrUniformRoot::Module(
-                        self.resolve_self(&mut ctxt, parent)));
-                    continue
-                } else {
+            allow_super &= ns == TypeNS &&
+                (name == keywords::SelfValue.name() ||
+                 name == keywords::Super.name());
+
+            if ns == TypeNS {
+                if allow_super && name == keywords::Super.name() {
+                    let mut ctxt = ident.span.ctxt().modern();
+                    let self_module = match i {
+                        0 => Some(self.resolve_self(&mut ctxt, self.current_module)),
+                        _ => match module {
+                            Some(ModuleOrUniformRoot::Module(module)) => Some(module),
+                            _ => None,
+                        },
+                    };
+                    if let Some(self_module) = self_module {
+                        if let Some(parent) = self_module.parent {
+                            module = Some(ModuleOrUniformRoot::Module(
+                                self.resolve_self(&mut ctxt, parent)));
+                            continue;
+                        }
+                    }
                     let msg = "There are too many initial `super`s.".to_string();
                     return PathResult::Failed(ident.span, msg, false);
                 }
-            }
-            allow_super = false;
-
-            if ns == TypeNS {
                 if i == 0 {
+                    if name == keywords::SelfValue.name() {
+                        let mut ctxt = ident.span.ctxt().modern();
+                        module = Some(ModuleOrUniformRoot::Module(
+                            self.resolve_self(&mut ctxt, self.current_module)));
+                        continue;
+                    }
                     if name == keywords::Extern.name() ||
                        name == keywords::CrateRoot.name() &&
                        self.session.features_untracked().extern_absolute_paths &&
@@ -3493,30 +3497,19 @@ fn resolve_path(
                         module = Some(ModuleOrUniformRoot::UniformRoot(name));
                         continue;
                     }
-                }
-                if (i == 0 && name == keywords::CrateRoot.name()) ||
-                   (i == 0 && name == keywords::Crate.name()) ||
-                   (i == 0 && name == keywords::DollarCrate.name()) ||
-                   (i == 1 && name == keywords::Crate.name() &&
-                              path[0].name == keywords::CrateRoot.name()) {
-                    // `::a::b`, `crate::a::b`, `::crate::a::b` or `$crate::a::b`
-                    module = Some(ModuleOrUniformRoot::Module(
-                        self.resolve_crate_root(ident)));
-                    continue
+                    if name == keywords::CrateRoot.name() ||
+                       name == keywords::Crate.name() ||
+                       name == keywords::DollarCrate.name() {
+                        // `::a::b`, `crate::a::b` or `$crate::a::b`
+                        module = Some(ModuleOrUniformRoot::Module(
+                            self.resolve_crate_root(ident)));
+                        continue;
+                    }
                 }
             }
 
             // Report special messages for path segment keywords in wrong positions.
-            if name == keywords::CrateRoot.name() && i != 0 ||
-               name == keywords::DollarCrate.name() && i != 0 ||
-               name == keywords::SelfValue.name() && i != 0 ||
-               name == keywords::SelfType.name() && i != 0 ||
-               name == keywords::Super.name() && i != 0 ||
-               name == keywords::Extern.name() && i != 0 ||
-               // we allow crate::foo and ::crate::foo but nothing else
-               name == keywords::Crate.name() && i > 1 &&
-                    path[0].name != keywords::CrateRoot.name() ||
-               name == keywords::Crate.name() && path.len() == 1 {
+            if ident.is_path_segment_keyword() && i != 0 {
                 let name_str = if name == keywords::CrateRoot.name() {
                     "crate root".to_string()
                 } else {
index 35e58bc9fee0db6a95f286ebce191c9fc9e8f886..c70f52e91dbb6fe36967de867eeb6de354829789 100644 (file)
@@ -11,7 +11,7 @@
 use self::ImportDirectiveSubclass::*;
 
 use {AmbiguityError, CrateLint, Module, ModuleOrUniformRoot, PerNS};
-use Namespace::{self, TypeNS, MacroNS, ValueNS};
+use Namespace::{self, TypeNS, MacroNS};
 use {NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyError};
 use Resolver;
 use {names_to_string, module_to_string};
@@ -34,6 +34,8 @@
 use syntax_pos::Span;
 
 use std::cell::{Cell, RefCell};
+use std::collections::BTreeMap;
+use std::fmt::Write;
 use std::{mem, ptr};
 
 /// Contains data for specific types of import directives.
@@ -615,6 +617,17 @@ pub fn finalize_imports(&mut self) {
             self.finalize_resolutions_in(module);
         }
 
+        #[derive(Default)]
+        struct UniformPathsCanaryResult {
+            module_scope: Option<Span>,
+            block_scopes: Vec<Span>,
+        }
+        // Collect all tripped `uniform_paths` canaries separately.
+        let mut uniform_paths_canaries: BTreeMap<
+            (Span, NodeId),
+            (Name, PerNS<UniformPathsCanaryResult>),
+        > = BTreeMap::new();
+
         let mut errors = false;
         let mut seen_spans = FxHashSet();
         for i in 0 .. self.determined_imports.len() {
@@ -624,49 +637,37 @@ pub fn finalize_imports(&mut self) {
             // For a `#![feature(uniform_paths)]` `use self::x as _` canary,
             // failure is ignored, while success may cause an ambiguity error.
             if import.is_uniform_paths_canary {
-                let (name, result) = match import.subclass {
-                    SingleImport { source, ref result, .. } => {
-                        let type_ns = result[TypeNS].get().ok();
-                        let value_ns = result[ValueNS].get().ok();
-                        (source.name, type_ns.or(value_ns))
-                    }
-                    _ => bug!(),
-                };
-
                 if error.is_some() {
                     continue;
                 }
 
-                let is_explicit_self =
+                let (name, result) = match import.subclass {
+                    SingleImport { source, ref result, .. } => (source.name, result),
+                    _ => bug!(),
+                };
+
+                let has_explicit_self =
                     import.module_path.len() > 0 &&
                     import.module_path[0].name == keywords::SelfValue.name();
-                let extern_crate_exists = self.extern_prelude.contains(&name);
 
-                // A successful `self::x` is ambiguous with an `x` external crate.
-                if is_explicit_self && !extern_crate_exists {
-                    continue;
-                }
+                let (prev_name, canary_results) =
+                    uniform_paths_canaries.entry((import.span, import.id))
+                        .or_insert((name, PerNS::default()));
 
-                errors = true;
+                // All the canaries with the same `id` should have the same `name`.
+                assert_eq!(*prev_name, name);
 
-                let msg = format!("import from `{}` is ambiguous", name);
-                let mut err = self.session.struct_span_err(import.span, &msg);
-                if extern_crate_exists {
-                    err.span_label(import.span,
-                        format!("could refer to external crate `::{}`", name));
-                }
-                if let Some(result) = result {
-                    if is_explicit_self {
-                        err.span_label(result.span,
-                            format!("could also refer to `self::{}`", name));
-                    } else {
-                        err.span_label(result.span,
-                            format!("shadowed by block-scoped `{}`", name));
+                self.per_ns(|_, ns| {
+                    if let Some(result) = result[ns].get().ok() {
+                        if has_explicit_self {
+                            // There should only be one `self::x` (module-scoped) canary.
+                            assert_eq!(canary_results[ns].module_scope, None);
+                            canary_results[ns].module_scope = Some(result.span);
+                        } else {
+                            canary_results[ns].block_scopes.push(result.span);
+                        }
                     }
-                }
-                err.help(&format!("write `::{0}` or `self::{0}` explicitly instead", name));
-                err.note("relative `use` paths enabled by `#![feature(uniform_paths)]`");
-                err.emit();
+                });
             } else if let Some((span, err)) = error {
                 errors = true;
 
@@ -694,6 +695,66 @@ pub fn finalize_imports(&mut self) {
             }
         }
 
+        for ((span, _), (name, results)) in uniform_paths_canaries {
+            self.per_ns(|this, ns| {
+                let results = &results[ns];
+
+                let has_external_crate =
+                    ns == TypeNS && this.extern_prelude.contains(&name);
+
+                // An ambiguity requires more than one possible resolution.
+                let possible_resultions =
+                    (has_external_crate as usize) +
+                    (results.module_scope.is_some() as usize) +
+                    (!results.block_scopes.is_empty() as usize);
+                if possible_resultions <= 1 {
+                    return;
+                }
+
+                errors = true;
+
+                // Special-case the error when `self::x` finds its own `use x;`.
+                if has_external_crate &&
+                   results.module_scope == Some(span) &&
+                   results.block_scopes.is_empty() {
+                    let msg = format!("`{}` import is redundant", name);
+                    this.session.struct_span_err(span, &msg)
+                        .span_label(span,
+                            format!("refers to external crate `::{}`", name))
+                        .span_label(span,
+                            format!("defines `self::{}`, shadowing itself", name))
+                        .help(&format!("remove or write `::{}` explicitly instead", name))
+                        .note("relative `use` paths enabled by `#![feature(uniform_paths)]`")
+                        .emit();
+                    return;
+                }
+
+                let msg = format!("`{}` import is ambiguous", name);
+                let mut err = this.session.struct_span_err(span, &msg);
+                let mut suggestion_choices = String::new();
+                if has_external_crate {
+                    write!(suggestion_choices, "`::{}`", name);
+                    err.span_label(span,
+                        format!("can refer to external crate `::{}`", name));
+                }
+                if let Some(span) = results.module_scope {
+                    if !suggestion_choices.is_empty() {
+                        suggestion_choices.push_str(" or ");
+                    }
+                    write!(suggestion_choices, "`self::{}`", name);
+                    err.span_label(span,
+                        format!("can refer to `self::{}`", name));
+                }
+                for &span in &results.block_scopes {
+                    err.span_label(span,
+                        format!("shadowed by block-scoped `{}`", name));
+                }
+                err.help(&format!("write {} explicitly instead", suggestion_choices));
+                err.note("relative `use` paths enabled by `#![feature(uniform_paths)]`");
+                err.emit();
+            });
+        }
+
         // Report unresolved imports only if no hard error was already reported
         // to avoid generating multiple errors on the same import.
         if !errors {
diff --git a/src/librustc_target/spec/aarch64_pc_windows_msvc.rs b/src/librustc_target/spec/aarch64_pc_windows_msvc.rs
new file mode 100644 (file)
index 0000000..8747f23
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use spec::{LinkerFlavor, Target, TargetResult, PanicStrategy, LldFlavor};
+
+pub fn target() -> TargetResult {
+    let mut base = super::windows_msvc_base::opts();
+    base.max_atomic_width = Some(64);
+    base.has_elf_tls = true;
+
+    // FIXME: this shouldn't be panic=abort, it should be panic=unwind
+    base.panic_strategy = PanicStrategy::Abort;
+    base.linker = Some("rust-lld".to_owned());
+
+    Ok(Target {
+        llvm_target: "aarch64-pc-windows-msvc".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "64".to_string(),
+        target_c_int_width: "32".to_string(),
+        data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".to_string(),
+        arch: "aarch64".to_string(),
+        target_os: "windows".to_string(),
+        target_env: "msvc".to_string(),
+        target_vendor: "pc".to_string(),
+        linker_flavor: LinkerFlavor::Lld(LldFlavor::Link),
+        options: base,
+    })
+}
index d55762e03eee3d3e3a40a8ded6e9c1f060a6ea2d..3a18c56f4fc5960f1accb22743d6c25fe896869b 100644 (file)
@@ -355,6 +355,7 @@ fn $module() {
     ("x86_64-pc-windows-gnu", x86_64_pc_windows_gnu),
     ("i686-pc-windows-gnu", i686_pc_windows_gnu),
 
+    ("aarch64-pc-windows-msvc", aarch64_pc_windows_msvc),
     ("x86_64-pc-windows-msvc", x86_64_pc_windows_msvc),
     ("i686-pc-windows-msvc", i686_pc_windows_msvc),
     ("i586-pc-windows-msvc", i586_pc_windows_msvc),
index 134983911100ebaebdf4ab3a4b66d36e55467034..3e1a6ca9aff7c33f40db6c5540cc8ee71428749d 100644 (file)
@@ -16,4 +16,4 @@ rustc = { path = "../librustc" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
-chalk-engine = { version = "0.6.0", default-features=false }
+chalk-engine = { version = "0.7.0", default-features=false }
index 43edb23504480f0fe485855a480e5bb4e5f8e46e..4fac11189a40004951629cd2c9e344247a677344 100644 (file)
@@ -4629,8 +4629,14 @@ pub fn suggest_ref_or_into(
             let methods = self.get_conversion_methods(expr.span, expected, found);
             if let Ok(expr_text) = self.sess().codemap().span_to_snippet(expr.span) {
                 let suggestions = iter::repeat(expr_text).zip(methods.iter())
-                    .map(|(receiver, method)| format!("{}.{}()", receiver, method.ident))
-                    .collect::<Vec<_>>();
+                    .filter_map(|(receiver, method)| {
+                        let method_call = format!(".{}()", method.ident);
+                        if receiver.ends_with(&method_call) {
+                            None  // do not suggest code that is already there (#53348)
+                        } else {
+                            Some(format!("{}{}", receiver, method_call))
+                        }
+                    }) .collect::<Vec<_>>();
                 if !suggestions.is_empty() {
                     err.span_suggestions(expr.span, "try using a conversion method", suggestions);
                 }
index 77b02d9ff5bce8e129460a0a34cecc977594acd1..02f431dccca6b4b9882ad657e25f88e40d3243b9 100644 (file)
@@ -1925,6 +1925,7 @@ fn from_target_feature(
                 Some("mmx_target_feature") => rust_features.mmx_target_feature,
                 Some("sse4a_target_feature") => rust_features.sse4a_target_feature,
                 Some("tbm_target_feature") => rust_features.tbm_target_feature,
+                Some("wasm_target_feature") => rust_features.wasm_target_feature,
                 Some(name) => bug!("unknown target feature gate {}", name),
                 None => true,
             };
index 0361718eb7337d9fb9003605b4bdbaa6dc116189..35ef6327de5fd81f73c63b2092cf79fc6da36745 100644 (file)
@@ -365,6 +365,9 @@ fn description(&self) -> &str { "encoder error" }
 }
 
 impl From<fmt::Error> for EncoderError {
+    /// Converts a [`fmt::Error`] into `EncoderError`
+    ///
+    /// This conversion does not allocate memory.
     fn from(err: fmt::Error) -> EncoderError { EncoderError::FmtError(err) }
 }
 
@@ -1387,10 +1390,9 @@ fn pop(&mut self) {
 
     // Used by Parser to test whether the top-most element is an index.
     fn last_is_index(&self) -> bool {
-        if let Some(InternalIndex(_)) = self.stack.last() {
-            true
-        } else {
-            false
+        match self.stack.last() {
+            Some(InternalIndex(_)) => true,
+            _ => false,
         }
     }
 
index 26d93f97e69f381e6e56479e9fe1775ab3af2b19..016e7adb4c914e1445b4db78d9ddc5229c331884 100644 (file)
@@ -104,7 +104,8 @@ fn build_libbacktrace(target: &str) -> Result<(), ()> {
     } else {
         build.file("../libbacktrace/elf.c");
 
-        if target.contains("64") {
+        let pointer_width = env::var("CARGO_CFG_TARGET_POINTER_WIDTH").unwrap();
+        if pointer_width == "64" {
             build.define("BACKTRACE_ELF_SIZE", "64");
         } else {
             build.define("BACKTRACE_ELF_SIZE", "32");
index 02a3ce8b9c4d475a0dcdb366fcdcd44a9344521b..3e50988a68ba2e13fa34e29e17e3f902f6abfbaf 100644 (file)
@@ -97,6 +97,7 @@ struct Custom {
 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[allow(deprecated)]
+#[non_exhaustive]
 pub enum ErrorKind {
     /// An entity was not found, often a file.
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -180,15 +181,6 @@ pub enum ErrorKind {
     /// read.
     #[stable(feature = "read_exact", since = "1.6.0")]
     UnexpectedEof,
-
-    /// A marker variant that tells the compiler that users of this enum cannot
-    /// match it exhaustively.
-    #[unstable(feature = "io_error_internals",
-               reason = "better expressed through extensible enums that this \
-                         enum cannot be exhaustively matched against",
-               issue = "0")]
-    #[doc(hidden)]
-    __Nonexhaustive,
 }
 
 impl ErrorKind {
@@ -212,7 +204,6 @@ fn as_str(&self) -> &'static str {
             ErrorKind::Interrupted => "operation interrupted",
             ErrorKind::Other => "other os error",
             ErrorKind::UnexpectedEof => "unexpected end of file",
-            ErrorKind::__Nonexhaustive => unreachable!()
         }
     }
 }
index 5d463225ae93b646f3ef3e8612806a6870e9f2b5..60ad330bb9b72a280dd9f888de474e6888c916ba 100644 (file)
 #![feature(doc_keyword)]
 #![feature(panic_info_message)]
 #![feature(panic_implementation)]
+#![feature(non_exhaustive)]
 
 #![default_lib_allocator]
 
index 2909db5098e58f58860d1c4ad4f1a6569706112a..cd9a5ad448f58c31b099818351b39f600b4c9f21 100644 (file)
 /// File or memory access pattern advisory information.
 #[repr(u8)]
 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+#[non_exhaustive]
 pub enum advice {
   /// The application expects that it will not access the
   /// specified data in the near future.
@@ -140,12 +141,12 @@ pub enum advice {
   /// The application expects to access the specified data
   /// in the near future.
   WILLNEED   = 6,
-  #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
 }
 
 /// Enumeration describing the kind of value stored in [`auxv`](struct.auxv.html).
 #[repr(u32)]
 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+#[non_exhaustive]
 pub enum auxtype {
   /// Base address of the binary argument data provided to
   /// [`proc_exec()`](fn.proc_exec.html).
@@ -210,12 +211,12 @@ pub enum auxtype {
   SYSINFO_EHDR = 262,
   /// Thread ID of the initial thread of the process.
   TID          = 261,
-  #[doc(hidden)] _NonExhaustive = -1 as isize as u32,
 }
 
 /// Identifiers for clocks.
 #[repr(u32)]
 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+#[non_exhaustive]
 pub enum clockid {
   /// The system-wide monotonic clock, which is defined as a
   /// clock measuring real time, whose value cannot be
@@ -232,7 +233,6 @@ pub enum clockid {
   REALTIME           = 3,
   /// The CPU-time clock associated with the current thread.
   THREAD_CPUTIME_ID  = 4,
-  #[doc(hidden)] _NonExhaustive = -1 as isize as u32,
 }
 
 /// A userspace condition variable.
@@ -267,6 +267,7 @@ pub enum clockid {
 /// exclusively or merely provided for alignment with POSIX.
 #[repr(u16)]
 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+#[non_exhaustive]
 pub enum errno {
   /// No error occurred. System call completed successfully.
   SUCCESS        =  0,
@@ -422,7 +423,6 @@ pub enum errno {
   XDEV           = 75,
   /// Extension: Capabilities insufficient.
   NOTCAPABLE     = 76,
-  #[doc(hidden)] _NonExhaustive = -1 as isize as u16,
 }
 
 bitflags! {
@@ -438,6 +438,7 @@ pub struct eventrwflags: u16 {
 /// Type of a subscription to an event or its occurrence.
 #[repr(u8)]
 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+#[non_exhaustive]
 pub enum eventtype {
   /// The time value of clock [`subscription.union.clock.clock_id`](struct.subscription_clock.html#structfield.clock_id)
   /// has reached timestamp [`subscription.union.clock.timeout`](struct.subscription_clock.html#structfield.timeout).
@@ -463,7 +464,6 @@ pub enum eventtype {
   /// The process associated with process descriptor
   /// [`subscription.union.proc_terminate.fd`](struct.subscription_proc_terminate.html#structfield.fd) has terminated.
   PROC_TERMINATE = 7,
-  #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
 }
 
 /// Exit code generated by a process when exiting.
@@ -530,6 +530,7 @@ pub struct fdsflags: u16 {
 /// The type of a file descriptor or file.
 #[repr(u8)]
 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+#[non_exhaustive]
 pub enum filetype {
   /// The type of the file descriptor or file is unknown or
   /// is different from any of the other types specified.
@@ -558,7 +559,6 @@ pub enum filetype {
   SOCKET_STREAM    = 130,
   /// The file refers to a symbolic link inode.
   SYMBOLIC_LINK    = 144,
-  #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
 }
 
 bitflags! {
@@ -847,12 +847,12 @@ pub struct roflags: u16 {
 /// memory.
 #[repr(u8)]
 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+#[non_exhaustive]
 pub enum scope {
   /// The object is stored in private memory.
   PRIVATE = 4,
   /// The object is stored in shared memory.
   SHARED  = 8,
-  #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
 }
 
 bitflags! {
@@ -878,6 +878,7 @@ pub struct siflags: u16 {
 /// Signal condition.
 #[repr(u8)]
 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+#[non_exhaustive]
 pub enum signal {
   /// Process abort signal.
   ///
@@ -983,7 +984,6 @@ pub enum signal {
   ///
   /// Action: Terminates the process.
   XFSZ   = 26,
-  #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
 }
 
 bitflags! {
@@ -1049,6 +1049,7 @@ pub struct ulflags: u8 {
 /// should be set.
 #[repr(u8)]
 #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+#[non_exhaustive]
 pub enum whence {
   /// Seek relative to current position.
   CUR = 1,
@@ -1056,7 +1057,6 @@ pub enum whence {
   END = 2,
   /// Seek relative to start-of-file.
   SET = 3,
-  #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
 }
 
 /// Auxiliary vector entry.
index 7ef4e203571b28e6624138655fd58252de1bb403..f64cae810b9ac76bf5a54b317e1bf0df1a6b9b1e 100644 (file)
@@ -229,6 +229,7 @@ fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
         self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
         c::IMAGE_FILE_MACHINE_I386
     }
+
     #[cfg(target_arch = "x86_64")]
     fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
         self.AddrPC.Offset = ctx.Rip as u64;
@@ -240,6 +241,17 @@ fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
         c::IMAGE_FILE_MACHINE_AMD64
     }
 
+    #[cfg(target_arch = "aarch64")]
+    fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
+        self.AddrPC.Offset = ctx.Pc as u64;
+        self.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        self.AddrStack.Offset = ctx.Sp as u64;
+        self.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        self.AddrFrame.Offset = ctx.Fp as u64;
+        self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        c::IMAGE_FILE_MACHINE_ARM64
+    }
+
     fn get_addr(&self) -> *const u8 {
         (self.AddrPC.Offset - 1) as *const u8
     }
@@ -260,6 +272,7 @@ fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
         self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
         c::IMAGE_FILE_MACHINE_I386
     }
+
     #[cfg(target_arch = "x86_64")]
     fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
         self.AddrPC.Offset = ctx.Rip as u64;
@@ -271,6 +284,17 @@ fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
         c::IMAGE_FILE_MACHINE_AMD64
     }
 
+    #[cfg(target_arch = "aarch64")]
+    fn init(&mut self, ctx: &c::CONTEXT) -> c::DWORD {
+        self.AddrPC.Offset = ctx.Pc as u64;
+        self.AddrPC.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        self.AddrStack.Offset = ctx.Sp as u64;
+        self.AddrStack.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        self.AddrFrame.Offset = ctx.Fp as u64;
+        self.AddrFrame.Mode = c::ADDRESS_MODE::AddrModeFlat;
+        c::IMAGE_FILE_MACHINE_ARM64
+    }
+
     fn get_addr(&self) -> *const u8 {
         (self.AddrPC.Offset - 1) as *const u8
     }
index 6f81afe66f95b694ae1123d9da74bfd501103a43..e514a56dcc43681dcb3fd8875e0b900402fa3d9f 100644 (file)
@@ -280,6 +280,9 @@ pub struct ipv6_mreq {
 #[cfg(target_arch = "x86_64")]
 #[cfg(feature = "backtrace")]
 pub const IMAGE_FILE_MACHINE_AMD64: DWORD = 0x8664;
+#[cfg(target_arch = "aarch64")]
+#[cfg(feature = "backtrace")]
+pub const IMAGE_FILE_MACHINE_ARM64: DWORD = 0xAA64;
 
 pub const EXCEPTION_CONTINUE_SEARCH: LONG = 0;
 pub const EXCEPTION_STACK_OVERFLOW: DWORD = 0xc00000fd;
@@ -791,9 +794,68 @@ pub struct FLOATING_SAVE_AREA {
 // will not appear in the final documentation. This should be also defined for
 // other architectures supported by Windows such as ARM, and for historical
 // interest, maybe MIPS and PowerPC as well.
-#[cfg(all(dox, not(any(target_arch = "x86_64", target_arch = "x86"))))]
+#[cfg(all(dox, not(any(target_arch = "x86_64", target_arch = "x86", target_arch = "aarch64"))))]
 pub enum CONTEXT {}
 
+#[cfg(target_arch = "aarch64")]
+pub const ARM64_MAX_BREAKPOINTS: usize = 8;
+
+#[cfg(target_arch = "aarch64")]
+pub const ARM64_MAX_WATCHPOINTS: usize = 2;
+
+#[cfg(target_arch = "aarch64")]
+#[repr(C)]
+pub struct ARM64_NT_NEON128 {
+    pub D: [f64; 2],
+}
+
+#[cfg(target_arch = "aarch64")]
+#[repr(C, align(16))]
+pub struct CONTEXT {
+    pub ContextFlags: DWORD,
+    pub Cpsr: DWORD,
+    pub X0: u64,
+    pub X1: u64,
+    pub X2: u64,
+    pub X3: u64,
+    pub X4: u64,
+    pub X5: u64,
+    pub X6: u64,
+    pub X7: u64,
+    pub X8: u64,
+    pub X9: u64,
+    pub X10: u64,
+    pub X11: u64,
+    pub X12: u64,
+    pub X13: u64,
+    pub X14: u64,
+    pub X15: u64,
+    pub X16: u64,
+    pub X17: u64,
+    pub X18: u64,
+    pub X19: u64,
+    pub X20: u64,
+    pub X21: u64,
+    pub X22: u64,
+    pub X23: u64,
+    pub X24: u64,
+    pub X25: u64,
+    pub X26: u64,
+    pub X27: u64,
+    pub X28: u64,
+    pub Fp: u64,
+    pub Lr: u64,
+    pub Sp: u64,
+    pub Pc: u64,
+    pub V: [ARM64_NT_NEON128; 32],
+    pub Fpcr: DWORD,
+    pub Fpsr: DWORD,
+    pub Bcr: [DWORD; ARM64_MAX_BREAKPOINTS],
+    pub Bvr: [DWORD; ARM64_MAX_BREAKPOINTS],
+    pub Wcr: [DWORD; ARM64_MAX_WATCHPOINTS],
+    pub Wvr: [DWORD; ARM64_MAX_WATCHPOINTS],
+}
+
 #[repr(C)]
 pub struct SOCKADDR_STORAGE_LH {
     pub ss_family: ADDRESS_FAMILY,
index 0d12ecf8fe3a1e12024088e54e202da0c2c8bd41..ccf79de909fa9dd4ca6b51ecafa0f53dce4e8918 100644 (file)
@@ -266,8 +266,12 @@ pub fn dur2timeout(dur: Duration) -> c::DWORD {
 // handlers.
 //
 // https://msdn.microsoft.com/en-us/library/dn774154.aspx
-#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+#[allow(unreachable_code)]
 pub unsafe fn abort_internal() -> ! {
-    asm!("int $$0x29" :: "{ecx}"(7) ::: volatile); // 7 is FAST_FAIL_FATAL_APP_EXIT
-    ::intrinsics::unreachable();
+    #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+    {
+        asm!("int $$0x29" :: "{ecx}"(7) ::: volatile); // 7 is FAST_FAIL_FATAL_APP_EXIT
+        ::intrinsics::unreachable();
+    }
+    ::intrinsics::abort();
 }
index 879f555ba03ee958d6961f122b7b1c3e759eac75..5857bd282f0bc6823cb9a2505117b96594eaa089 100644 (file)
@@ -607,7 +607,7 @@ fn from_tokens<I>(tokens: &mut iter::Peekable<I>) -> Option<NestedMetaItemKind>
 }
 
 impl Lit {
-    fn tokens(&self) -> TokenStream {
+    crate fn tokens(&self) -> TokenStream {
         TokenTree::Token(self.span, self.node.token()).into()
     }
 }
@@ -794,7 +794,7 @@ pub fn inject(mut krate: ast::Crate, parse_sess: &ParseSess, attrs: &[String]) -
         );
 
         let start_span = parser.span;
-        let (path, tokens) = panictry!(parser.parse_path_and_tokens());
+        let (path, tokens) = panictry!(parser.parse_meta_item_unrestricted());
         let end_span = parser.span;
         if parser.token != token::Eof {
             parse_sess.span_diagnostic
index 4fe78bf829a1ca732332530dbb2ad64f82e0b1ae..b4e35a9d56496371ed32ccd82ec9ef294f74ac93 100644 (file)
@@ -90,7 +90,7 @@ fn process_cfg_attr(&mut self, attr: ast::Attribute) -> Option<ast::Attribute> {
             let cfg = parser.parse_meta_item()?;
             parser.expect(&token::Comma)?;
             let lo = parser.span.lo();
-            let (path, tokens) = parser.parse_path_and_tokens()?;
+            let (path, tokens) = parser.parse_meta_item_unrestricted()?;
             parser.expect(&token::CloseDelim(token::Paren))?;
             Ok((cfg, path, tokens, parser.prev_span.with_lo(lo)))
         }) {
index dcae9b1e9ca7eabfa494328cb63d7100266b7364..7a8a7b073185a6477dfeb8fdbb73dec1995d1202 100644 (file)
@@ -1526,27 +1526,29 @@ fn visit_attribute(&mut self, attr: &ast::Attribute) {
             }
         }
 
-        match attr.parse_meta(self.context.parse_sess) {
-            Ok(meta) => {
-                // allow attr_literals in #[repr(align(x))] and #[repr(packed(n))]
-                let mut allow_attr_literal = false;
-                if attr.path == "repr" {
-                    if let Some(content) = meta.meta_item_list() {
-                        allow_attr_literal = content.iter().any(
-                            |c| c.check_name("align") || c.check_name("packed"));
+        if !self.context.features.unrestricted_attribute_tokens {
+            // Unfortunately, `parse_meta` cannot be called speculatively because it can report
+            // errors by itself, so we have to call it only if the feature is disabled.
+            match attr.parse_meta(self.context.parse_sess) {
+                Ok(meta) => {
+                    // allow attr_literals in #[repr(align(x))] and #[repr(packed(n))]
+                    let mut allow_attr_literal = false;
+                    if attr.path == "repr" {
+                        if let Some(content) = meta.meta_item_list() {
+                            allow_attr_literal = content.iter().any(
+                                |c| c.check_name("align") || c.check_name("packed"));
+                        }
                     }
-                }
 
-                if !allow_attr_literal && contains_novel_literal(&meta) {
-                    gate_feature_post!(&self, attr_literals, attr.span,
-                                    "non-string literals in attributes, or string \
-                                    literals in top-level positions, are experimental");
+                    if !allow_attr_literal && contains_novel_literal(&meta) {
+                        gate_feature_post!(&self, attr_literals, attr.span,
+                                        "non-string literals in attributes, or string \
+                                        literals in top-level positions, are experimental");
+                    }
+                }
+                Err(mut err) => {
+                    err.help("try enabling `#![feature(unrestricted_attribute_tokens)]`").emit()
                 }
-            }
-            Err(mut err) => {
-                err.cancel();
-                gate_feature_post!(&self, unrestricted_attribute_tokens, attr.span,
-                                    "arbitrary tokens in non-macro attributes are unstable");
             }
         }
     }
@@ -1920,6 +1922,11 @@ fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) {
         err.emit();
     }
 
+    // Some features are known to be incomplete and using them is likely to have
+    // unanticipated results, such as compiler crashes. We warn the user about these
+    // to alert them.
+    let incomplete_features = ["generic_associated_types"];
+
     let mut features = Features::new();
     let mut edition_enabled_features = FxHashMap();
 
@@ -1959,6 +1966,16 @@ fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) {
                 continue
             };
 
+            if incomplete_features.iter().any(|f| *f == name.as_str()) {
+                span_handler.struct_span_warn(
+                    mi.span,
+                    &format!(
+                        "the feature `{}` is incomplete and may cause the compiler to crash",
+                        name
+                    )
+                ).emit();
+            }
+
             if let Some(edition) = ALL_EDITIONS.iter().find(|e| name == e.feature_name()) {
                 if *edition <= crate_edition {
                     continue;
index c48ad0a802cb0470402f99154adea000f12c3e22..0a42325d2b6ff74a595cfbc0fac2d0ec3a66c9e9 100644 (file)
@@ -130,6 +130,9 @@ pub mod util {
 
     mod rc_slice;
     pub use self::rc_slice::RcSlice;
+
+    mod rc_vec;
+    pub use self::rc_vec::RcVec;
 }
 
 pub mod json;
index 4d59f64bb6b57d3572ff704a196383fecb757508..b0136c3e18b468a5f05e835068c99e3f11f5629d 100644 (file)
@@ -12,9 +12,9 @@
 use ast;
 use codemap::respan;
 use parse::{SeqSep, PResult};
-use parse::token::{self, Nonterminal};
+use parse::token::{self, Nonterminal, DelimToken};
 use parse::parser::{Parser, TokenType, PathStyle};
-use tokenstream::TokenStream;
+use tokenstream::{TokenStream, TokenTree};
 
 #[derive(Debug)]
 enum InnerAttributeParsePolicy<'a> {
@@ -116,7 +116,7 @@ fn parse_attribute_with_inner_parse_policy(&mut self,
                 };
 
                 self.expect(&token::OpenDelim(token::Bracket))?;
-                let (path, tokens) = self.parse_path_and_tokens()?;
+                let (path, tokens) = self.parse_meta_item_unrestricted()?;
                 self.expect(&token::CloseDelim(token::Bracket))?;
                 let hi = self.prev_span;
 
@@ -138,7 +138,16 @@ fn parse_attribute_with_inner_parse_policy(&mut self,
         })
     }
 
-    crate fn parse_path_and_tokens(&mut self) -> PResult<'a, (ast::Path, TokenStream)> {
+    /// Parse an inner part of attribute - path and following tokens.
+    /// The tokens must be either a delimited token stream, or empty token stream,
+    /// or the "legacy" key-value form.
+    /// PATH `(` TOKEN_STREAM `)`
+    /// PATH `[` TOKEN_STREAM `]`
+    /// PATH `{` TOKEN_STREAM `}`
+    /// PATH
+    /// PATH `=` TOKEN_TREE
+    /// The delimiters or `=` are still put into the resulting token stream.
+    crate fn parse_meta_item_unrestricted(&mut self) -> PResult<'a, (ast::Path, TokenStream)> {
         let meta = match self.token {
             token::Interpolated(ref nt) => match nt.0 {
                 Nonterminal::NtMeta(ref meta) => Some(meta.clone()),
@@ -150,7 +159,22 @@ fn parse_attribute_with_inner_parse_policy(&mut self,
             self.bump();
             (meta.ident, meta.node.tokens(meta.span))
         } else {
-            (self.parse_path(PathStyle::Mod)?, self.parse_tokens())
+            let path = self.parse_path(PathStyle::Mod)?;
+            let tokens = if self.check(&token::OpenDelim(DelimToken::Paren)) ||
+               self.check(&token::OpenDelim(DelimToken::Bracket)) ||
+               self.check(&token::OpenDelim(DelimToken::Brace)) {
+                   self.parse_token_tree().into()
+            } else if self.eat(&token::Eq) {
+                let eq = TokenTree::Token(self.prev_span, token::Eq);
+                let tree = match self.token {
+                    token::CloseDelim(_) | token::Eof => self.unexpected()?,
+                    _ => self.parse_token_tree(),
+                };
+                TokenStream::concat(vec![eq.into(), tree.into()])
+            } else {
+                TokenStream::empty()
+            };
+            (path, tokens)
         })
     }
 
index 20a585b6601a51da4b3cf4f273991efc37958200..2c53dbdc402a5b2c415919adb12382a10d9efd5e 100644 (file)
@@ -63,6 +63,7 @@ fn vertical_trim(lines: Vec<String>) -> Vec<String> {
         if !lines.is_empty() && lines[0].chars().all(|c| c == '*') {
             i += 1;
         }
+
         while i < j && lines[i].trim().is_empty() {
             i += 1;
         }
@@ -74,9 +75,11 @@ fn vertical_trim(lines: Vec<String>) -> Vec<String> {
                .all(|c| c == '*') {
             j -= 1;
         }
+
         while j > i && lines[j - 1].trim().is_empty() {
             j -= 1;
         }
+
         lines[i..j].to_vec()
     }
 
@@ -85,6 +88,7 @@ fn horizontal_trim(lines: Vec<String>) -> Vec<String> {
         let mut i = usize::MAX;
         let mut can_trim = true;
         let mut first = true;
+
         for line in &lines {
             for (j, c) in line.chars().enumerate() {
                 if j > i || !"* \t".contains(c) {
@@ -119,7 +123,8 @@ fn horizontal_trim(lines: Vec<String>) -> Vec<String> {
     }
 
     // one-line comments lose their prefix
-    const ONELINERS: &'static [&'static str] = &["///!", "///", "//!", "//"];
+    const ONELINERS: &[&str] = &["///!", "///", "//!", "//"];
+
     for prefix in ONELINERS {
         if comment.starts_with(*prefix) {
             return (&comment[prefix.len()..]).to_string();
@@ -205,6 +210,7 @@ fn all_whitespace(s: &str, col: CharPos) -> Option<usize> {
     let len = s.len();
     let mut col = col.to_usize();
     let mut cursor: usize = 0;
+
     while col > 0 && cursor < len {
         let ch = char_at(s, cursor);
         if !ch.is_whitespace() {
@@ -213,7 +219,8 @@ fn all_whitespace(s: &str, col: CharPos) -> Option<usize> {
         cursor += ch.len_utf8();
         col -= 1;
     }
-    return Some(cursor);
+
+    Some(cursor)
 }
 
 fn trim_whitespace_prefix_and_push_line(lines: &mut Vec<String>, s: String, col: CharPos) {
@@ -246,11 +253,13 @@ fn read_block_comment(rdr: &mut StringReader,
         "src_index={}, end_src_index={}, line_begin_pos={}",
         src_index, end_src_index, rdr.filemap.line_begin_pos(rdr.pos).to_u32());
     let mut n = 0;
+
     while src_index < end_src_index {
         let c = char_at(&rdr.src, src_index);
         src_index += c.len_utf8();
         n += 1;
     }
+
     let col = CharPos(n);
 
     rdr.bump();
@@ -358,10 +367,10 @@ pub struct Literal {
 // it appears this function is called only from pprust... that's
 // probably not a good thing.
 pub fn gather_comments_and_literals(sess: &ParseSess, path: FileName, srdr: &mut dyn Read)
-                                    -> (Vec<Comment>, Vec<Literal>) {
-    let mut src = Vec::new();
-    srdr.read_to_end(&mut src).unwrap();
-    let src = String::from_utf8(src).unwrap();
+    -> (Vec<Comment>, Vec<Literal>)
+{
+    let mut src = String::new();
+    srdr.read_to_string(&mut src).unwrap();
     let cm = CodeMap::new(sess.codemap().path_mapping().clone());
     let filemap = cm.new_filemap(path, src);
     let mut rdr = lexer::StringReader::new_raw(sess, filemap, None);
@@ -370,6 +379,7 @@ pub fn gather_comments_and_literals(sess: &ParseSess, path: FileName, srdr: &mut
     let mut literals: Vec<Literal> = Vec::new();
     let mut code_to_the_left = false; // Only code
     let mut anything_to_the_left = false; // Code or comments
+
     while !rdr.is_eof() {
         loop {
             // Eat all the whitespace and count blank lines.
index f9b9e95ead1b6a389e2d488cf9f9530cdd67216e..bdf25618f474eda00f8d2bb87dab4604b86718f0 100644 (file)
@@ -67,29 +67,30 @@ pub struct StringReader<'a> {
     span_src_raw: Span,
     open_braces: Vec<(token::DelimToken, Span)>,
     crate override_span: Option<Span>,
+    last_unclosed_found_span: Option<Span>,
 }
 
 impl<'a> StringReader<'a> {
     fn mk_sp(&self, lo: BytePos, hi: BytePos) -> Span {
         self.mk_sp_and_raw(lo, hi).0
     }
+
     fn mk_sp_and_raw(&self, lo: BytePos, hi: BytePos) -> (Span, Span) {
         let raw = Span::new(lo, hi, NO_EXPANSION);
-        let real = unwrap_or!(self.override_span, raw);
+        let real = self.override_span.unwrap_or(raw);
+
         (real, raw)
     }
+
     fn mk_ident(&self, string: &str) -> Ident {
         let mut ident = Ident::from_str(string);
         if let Some(span) = self.override_span {
             ident.span = span;
         }
+
         ident
     }
 
-    fn next_token(&mut self) -> TokenAndSpan where Self: Sized {
-        let res = self.try_next_token();
-        self.unwrap_or_abort(res)
-    }
     fn unwrap_or_abort(&mut self, res: Result<TokenAndSpan, ()>) -> TokenAndSpan {
         match res {
             Ok(tok) => tok,
@@ -99,6 +100,25 @@ fn unwrap_or_abort(&mut self, res: Result<TokenAndSpan, ()>) -> TokenAndSpan {
             }
         }
     }
+
+    fn next_token(&mut self) -> TokenAndSpan where Self: Sized {
+        let res = self.try_next_token();
+        self.unwrap_or_abort(res)
+    }
+
+    /// Return the next token. EFFECT: advances the string_reader.
+    pub fn try_next_token(&mut self) -> Result<TokenAndSpan, ()> {
+        assert!(self.fatal_errs.is_empty());
+        let ret_val = TokenAndSpan {
+            tok: replace(&mut self.peek_tok, token::Whitespace),
+            sp: self.peek_span,
+        };
+        self.advance_token()?;
+        self.span_src_raw = self.peek_span_src_raw;
+
+        Ok(ret_val)
+    }
+
     fn try_real_token(&mut self) -> Result<TokenAndSpan, ()> {
         let mut t = self.try_next_token()?;
         loop {
@@ -109,36 +129,32 @@ fn try_real_token(&mut self) -> Result<TokenAndSpan, ()> {
                 _ => break,
             }
         }
+
         self.token = t.tok.clone();
         self.span = t.sp;
+
         Ok(t)
     }
+
     pub fn real_token(&mut self) -> TokenAndSpan {
         let res = self.try_real_token();
         self.unwrap_or_abort(res)
     }
+
+    #[inline]
     fn is_eof(&self) -> bool {
         self.ch.is_none()
     }
-    /// Return the next token. EFFECT: advances the string_reader.
-    pub fn try_next_token(&mut self) -> Result<TokenAndSpan, ()> {
-        assert!(self.fatal_errs.is_empty());
-        let ret_val = TokenAndSpan {
-            tok: replace(&mut self.peek_tok, token::Whitespace),
-            sp: self.peek_span,
-        };
-        self.advance_token()?;
-        self.span_src_raw = self.peek_span_src_raw;
-        Ok(ret_val)
-    }
 
     fn fail_unterminated_raw_string(&self, pos: BytePos, hash_count: u16) {
         let mut err = self.struct_span_fatal(pos, pos, "unterminated raw string");
         err.span_label(self.mk_sp(pos, pos), "unterminated raw string");
+
         if hash_count > 0 {
             err.note(&format!("this raw string should be terminated with `\"{}`",
                               "#".repeat(hash_count as usize)));
         }
+
         err.emit();
         FatalError.raise();
     }
@@ -146,12 +162,15 @@ fn fail_unterminated_raw_string(&self, pos: BytePos, hash_count: u16) {
     fn fatal(&self, m: &str) -> FatalError {
         self.fatal_span(self.peek_span, m)
     }
+
     pub fn emit_fatal_errors(&mut self) {
         for err in &mut self.fatal_errs {
             err.emit();
         }
+
         self.fatal_errs.clear();
     }
+
     pub fn peek(&self) -> TokenAndSpan {
         // FIXME(pcwalton): Bad copy!
         TokenAndSpan {
@@ -161,15 +180,18 @@ pub fn peek(&self) -> TokenAndSpan {
     }
 
     /// For comments.rs, which hackily pokes into next_pos and ch
-    fn new_raw(sess: &'a ParseSess, filemap: Lrc<syntax_pos::FileMap>,
-                   override_span: Option<Span>) -> Self {
+    fn new_raw(sess: &'a ParseSess, filemap: Lrc<syntax_pos::FileMap>, override_span: Option<Span>)
+        -> Self
+    {
         let mut sr = StringReader::new_raw_internal(sess, filemap, override_span);
         sr.bump();
+
         sr
     }
 
     fn new_raw_internal(sess: &'a ParseSess, filemap: Lrc<syntax_pos::FileMap>,
-                        override_span: Option<Span>) -> Self {
+        override_span: Option<Span>) -> Self
+    {
         if filemap.src.is_none() {
             sess.span_diagnostic.bug(&format!("Cannot lex filemap without source: {}",
                                               filemap.name));
@@ -195,16 +217,19 @@ fn new_raw_internal(sess: &'a ParseSess, filemap: Lrc<syntax_pos::FileMap>,
             span_src_raw: syntax_pos::DUMMY_SP,
             open_braces: Vec::new(),
             override_span,
+            last_unclosed_found_span: None,
         }
     }
 
     pub fn new(sess: &'a ParseSess, filemap: Lrc<syntax_pos::FileMap>, override_span: Option<Span>)
-               -> Self {
+        -> Self
+    {
         let mut sr = StringReader::new_raw(sess, filemap, override_span);
         if sr.advance_token().is_err() {
             sr.emit_fatal_errors();
             FatalError.raise();
         }
+
         sr
     }
 
@@ -229,9 +254,11 @@ pub fn retokenize(sess: &'a ParseSess, mut span: Span) -> Self {
             sr.emit_fatal_errors();
             FatalError.raise();
         }
+
         sr
     }
 
+    #[inline]
     fn ch_is(&self, c: char) -> bool {
         self.ch == Some(c)
     }
@@ -276,26 +303,23 @@ fn fatal_span_char(&self, from_pos: BytePos, to_pos: BytePos, m: &str, c: char)
         let mut m = m.to_string();
         m.push_str(": ");
         Self::push_escaped_char_for_msg(&mut m, c);
+
         self.fatal_span_(from_pos, to_pos, &m[..])
     }
 
-    fn struct_span_fatal(&self,
-                         from_pos: BytePos,
-                         to_pos: BytePos,
-                         m: &str)
-                         -> DiagnosticBuilder<'a> {
+    fn struct_span_fatal(&self, from_pos: BytePos, to_pos: BytePos, m: &str)
+        -> DiagnosticBuilder<'a>
+    {
         self.sess.span_diagnostic.struct_span_fatal(self.mk_sp(from_pos, to_pos), m)
     }
 
-    fn struct_fatal_span_char(&self,
-                              from_pos: BytePos,
-                              to_pos: BytePos,
-                              m: &str,
-                              c: char)
-                              -> DiagnosticBuilder<'a> {
+    fn struct_fatal_span_char(&self, from_pos: BytePos, to_pos: BytePos, m: &str, c: char)
+        -> DiagnosticBuilder<'a>
+    {
         let mut m = m.to_string();
         m.push_str(": ");
         Self::push_escaped_char_for_msg(&mut m, c);
+
         self.sess.span_diagnostic.struct_span_fatal(self.mk_sp(from_pos, to_pos), &m[..])
     }
 
@@ -307,15 +331,14 @@ fn err_span_char(&self, from_pos: BytePos, to_pos: BytePos, m: &str, c: char) {
         Self::push_escaped_char_for_msg(&mut m, c);
         self.err_span_(from_pos, to_pos, &m[..]);
     }
-    fn struct_err_span_char(&self,
-                            from_pos: BytePos,
-                            to_pos: BytePos,
-                            m: &str,
-                            c: char)
-                            -> DiagnosticBuilder<'a> {
+
+    fn struct_err_span_char(&self, from_pos: BytePos, to_pos: BytePos, m: &str, c: char)
+        -> DiagnosticBuilder<'a>
+    {
         let mut m = m.to_string();
         m.push_str(": ");
         Self::push_escaped_char_for_msg(&mut m, c);
+
         self.sess.span_diagnostic.struct_span_err(self.mk_sp(from_pos, to_pos), &m[..])
     }
 
@@ -324,6 +347,7 @@ fn struct_err_span_char(&self,
     fn fatal_span_verbose(&self, from_pos: BytePos, to_pos: BytePos, mut m: String) -> FatalError {
         m.push_str(": ");
         m.push_str(&self.src[self.src_index(from_pos)..self.src_index(to_pos)]);
+
         self.fatal_span_(from_pos, to_pos, &m[..])
     }
 
@@ -354,6 +378,7 @@ fn advance_token(&mut self) -> Result<(), ()> {
                 };
             }
         }
+
         Ok(())
     }
 
@@ -468,6 +493,7 @@ fn nextch(&self) -> Option<char> {
         }
     }
 
+    #[inline]
     fn nextch_is(&self, c: char) -> bool {
         self.nextch() == Some(c)
     }
@@ -484,6 +510,7 @@ fn nextnextch(&self) -> Option<char> {
         None
     }
 
+    #[inline]
     fn nextnextch_is(&self, c: char) -> bool {
         self.nextnextch() == Some(c)
     }
@@ -493,8 +520,10 @@ fn scan_optional_raw_name(&mut self) -> Option<ast::Name> {
         if !ident_start(self.ch) {
             return None;
         }
+
         let start = self.pos;
         self.bump();
+
         while ident_continue(self.ch) {
             self.bump();
         }
@@ -709,6 +738,7 @@ fn scan_block_comment(&mut self) -> Option<TokenAndSpan> {
     fn scan_digits(&mut self, real_radix: u32, scan_radix: u32) -> usize {
         assert!(real_radix <= scan_radix);
         let mut len = 0;
+
         loop {
             let c = self.ch;
             if c == Some('_') {
@@ -736,31 +766,29 @@ fn scan_digits(&mut self, real_radix: u32, scan_radix: u32) -> usize {
 
     /// Lex a LIT_INTEGER or a LIT_FLOAT
     fn scan_number(&mut self, c: char) -> token::Lit {
-        let num_digits;
         let mut base = 10;
         let start_bpos = self.pos;
-
         self.bump();
 
-        if c == '0' {
+        let num_digits = if c == '0' {
             match self.ch.unwrap_or('\0') {
                 'b' => {
                     self.bump();
                     base = 2;
-                    num_digits = self.scan_digits(2, 10);
+                    self.scan_digits(2, 10)
                 }
                 'o' => {
                     self.bump();
                     base = 8;
-                    num_digits = self.scan_digits(8, 10);
+                    self.scan_digits(8, 10)
                 }
                 'x' => {
                     self.bump();
                     base = 16;
-                    num_digits = self.scan_digits(16, 16);
+                    self.scan_digits(16, 16)
                 }
                 '0'..='9' | '_' | '.' | 'e' | 'E' => {
-                    num_digits = self.scan_digits(10, 10) + 1;
+                    self.scan_digits(10, 10) + 1
                 }
                 _ => {
                     // just a 0
@@ -768,15 +796,14 @@ fn scan_number(&mut self, c: char) -> token::Lit {
                 }
             }
         } else if c.is_digit(10) {
-            num_digits = self.scan_digits(10, 10) + 1;
+            self.scan_digits(10, 10) + 1
         } else {
-            num_digits = 0;
-        }
+            0
+        };
 
         if num_digits == 0 {
-            self.err_span_(start_bpos,
-                           self.pos,
-                           "no valid digits found for number");
+            self.err_span_(start_bpos, self.pos, "no valid digits found for number");
+
             return token::Integer(Symbol::intern("0"));
         }
 
@@ -794,6 +821,7 @@ fn scan_number(&mut self, c: char) -> token::Lit {
             }
             let pos = self.pos;
             self.check_float_base(start_bpos, pos, base);
+
             token::Float(self.name_from(start_bpos))
         } else {
             // it might be a float if it has an exponent
@@ -873,7 +901,8 @@ fn scan_char_or_byte(&mut self,
                          first_source_char: char,
                          ascii_only: bool,
                          delim: char)
-                         -> bool {
+                         -> bool
+    {
         match first_source_char {
             '\\' => {
                 // '\X' for some X must be a character constant:
@@ -1008,6 +1037,7 @@ fn scan_unicode_escape(&mut self, delim: char) -> bool {
                            "overlong unicode escape (must have at most 6 hex digits)");
             valid = false;
         }
+
         loop {
             match self.ch {
                 Some('}') => {
@@ -1043,6 +1073,7 @@ fn scan_unicode_escape(&mut self, delim: char) -> bool {
             }
             self.bump();
         }
+
         valid
     }
 
@@ -1050,9 +1081,11 @@ fn scan_unicode_escape(&mut self, delim: char) -> bool {
     fn scan_float_exponent(&mut self) {
         if self.ch_is('e') || self.ch_is('E') {
             self.bump();
+
             if self.ch_is('-') || self.ch_is('+') {
                 self.bump();
             }
+
             if self.scan_digits(10, 10) == 0 {
                 let mut err = self.struct_span_fatal(
                     self.pos, self.next_pos,
@@ -1125,6 +1158,7 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
                     ('b', Some('r'), Some('#')) => (false, false),
                     _ => (true, false),
                 };
+
             if is_ident_start {
                 let raw_start = self.pos;
                 if is_raw_ident {
@@ -1135,6 +1169,7 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
 
                 let start = self.pos;
                 self.bump();
+
                 while ident_continue(self.ch) {
                     self.bump();
                 }
@@ -1142,16 +1177,19 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
                 return Ok(self.with_str_from(start, |string| {
                     // FIXME: perform NFKC normalization here. (Issue #2253)
                     let ident = self.mk_ident(string);
+
                     if is_raw_ident && (ident.is_path_segment_keyword() ||
                                         ident.name == keywords::Underscore.name()) {
                         self.fatal_span_(raw_start, self.pos,
                             &format!("`r#{}` is not currently supported.", ident.name)
                         ).raise();
                     }
+
                     if is_raw_ident {
                         let span = self.mk_sp(raw_start, self.pos);
                         self.sess.raw_identifier_spans.borrow_mut().push(span);
                     }
+
                     token::Ident(ident, is_raw_ident)
                 }));
             }
@@ -1337,14 +1375,11 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
                     return Ok(token::Lifetime(ident));
                 }
 
-                let valid = self.scan_char_or_byte(start,
-                                                   c2,
-                                                   // ascii_only =
-                                                   false,
-                                                   '\'');
+                let valid = self.scan_char_or_byte(start, c2, /* ascii_only */ false, '\'');
 
                 if !self.ch_is('\'') {
                     let pos = self.pos;
+
                     loop {
                         self.bump();
                         if self.ch_is('\'') {
@@ -1370,6 +1405,7 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
                             break;
                         }
                     }
+
                     self.fatal_span_verbose(start_with_quote, pos,
                         String::from("character literal may only contain one codepoint")).raise();
                 }
@@ -1379,8 +1415,10 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
                 } else {
                     Symbol::intern("0")
                 };
+
                 self.bump(); // advance ch past token
                 let suffix = self.scan_optional_raw_name();
+
                 Ok(token::Literal(token::Char(id), suffix))
             }
             'b' => {
@@ -1392,12 +1430,14 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
                     _ => unreachable!(),  // Should have been a token::Ident above.
                 };
                 let suffix = self.scan_optional_raw_name();
+
                 Ok(token::Literal(lit, suffix))
             }
             '"' => {
                 let start_bpos = self.pos;
                 let mut valid = true;
                 self.bump();
+
                 while !self.ch_is('"') {
                     if self.is_eof() {
                         let last_bpos = self.pos;
@@ -1409,11 +1449,7 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
                     let ch_start = self.pos;
                     let ch = self.ch.unwrap();
                     self.bump();
-                    valid &= self.scan_char_or_byte(ch_start,
-                                                    ch,
-                                                    // ascii_only =
-                                                    false,
-                                                    '"');
+                    valid &= self.scan_char_or_byte(ch_start, ch, /* ascii_only */ false, '"');
                 }
                 // adjust for the ASCII " at the start of the literal
                 let id = if valid {
@@ -1423,6 +1459,7 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
                 };
                 self.bump();
                 let suffix = self.scan_optional_raw_name();
+
                 Ok(token::Literal(token::Str_(id), suffix))
             }
             'r' => {
@@ -1492,6 +1529,7 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
                     }
                     self.bump();
                 }
+
                 self.bump();
                 let id = if valid {
                     self.name_from_to(content_start_bpos, content_end_bpos)
@@ -1499,6 +1537,7 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
                     Symbol::intern("??")
                 };
                 let suffix = self.scan_optional_raw_name();
+
                 Ok(token::Literal(token::StrRaw(id, hash_count), suffix))
             }
             '-' => {
@@ -1555,6 +1594,7 @@ fn next_token_inner(&mut self) -> Result<token::Token, ()> {
                                                           c);
                 unicode_chars::check_for_substitution(self, c, &mut err);
                 self.fatal_errs.push(err);
+
                 Err(())
             }
         }
@@ -1572,9 +1612,11 @@ fn read_to_eol(&mut self) -> String {
             val.push(self.ch.unwrap());
             self.bump();
         }
+
         if self.ch_is('\n') {
             self.bump();
         }
+
         val
     }
 
@@ -1626,9 +1668,11 @@ fn scan_byte(&mut self) -> token::Lit {
             Symbol::intern("?")
         };
         self.bump(); // advance ch past token
+
         token::Byte(id)
     }
 
+    #[inline]
     fn scan_byte_escape(&mut self, delim: char, below_0x7f_only: bool) -> bool {
         self.scan_hex_digits(2, delim, below_0x7f_only)
     }
@@ -1653,12 +1697,14 @@ fn scan_byte_string(&mut self) -> token::Lit {
                                             true,
                                             '"');
         }
+
         let id = if valid {
             self.name_from(start)
         } else {
             Symbol::intern("??")
         };
         self.bump();
+
         token::ByteStr(id)
     }
 
@@ -1716,25 +1762,26 @@ fn scan_raw_byte_string(&mut self) -> token::Lit {
             }
             self.bump();
         }
+
         self.bump();
-        token::ByteStrRaw(self.name_from_to(content_start_bpos, content_end_bpos),
-                                 hash_count)
+
+        token::ByteStrRaw(self.name_from_to(content_start_bpos, content_end_bpos), hash_count)
     }
 }
 
 // This tests the character for the unicode property 'PATTERN_WHITE_SPACE' which
 // is guaranteed to be forward compatible. http://unicode.org/reports/tr31/#R3
+#[inline]
 crate fn is_pattern_whitespace(c: Option<char>) -> bool {
     c.map_or(false, Pattern_White_Space)
 }
 
+#[inline]
 fn in_range(c: Option<char>, lo: char, hi: char) -> bool {
-    match c {
-        Some(c) => lo <= c && c <= hi,
-        _ => false,
-    }
+    c.map_or(false, |c| lo <= c && c <= hi)
 }
 
+#[inline]
 fn is_dec_digit(c: Option<char>) -> bool {
     in_range(c, '0', '9')
 }
index 36c220fa0d943d34f3aa4973c6618008ca4261a8..e2fd7faf90387e856007ccc7fe8368409ff15044 100644 (file)
@@ -17,9 +17,11 @@ impl<'a> StringReader<'a> {
     // Parse a stream of tokens into a list of `TokenTree`s, up to an `Eof`.
     crate fn parse_all_token_trees(&mut self) -> PResult<'a, TokenStream> {
         let mut tts = Vec::new();
+
         while self.token != token::Eof {
             tts.push(self.parse_token_tree()?);
         }
+
         Ok(TokenStream::concat(tts))
     }
 
@@ -30,6 +32,7 @@ fn parse_token_trees_until_close_delim(&mut self) -> TokenStream {
             if let token::CloseDelim(..) = self.token {
                 return TokenStream::concat(tts);
             }
+
             match self.parse_token_tree() {
                 Ok(tree) => tts.push(tree),
                 Err(mut e) => {
@@ -48,6 +51,7 @@ fn parse_token_tree(&mut self) -> PResult<'a, TokenStream> {
                 for &(_, sp) in &self.open_braces {
                     err.span_help(sp, "did you mean to close this delimiter?");
                 }
+
                 Err(err)
             },
             token::OpenDelim(delim) => {
@@ -77,16 +81,23 @@ fn parse_token_tree(&mut self) -> PResult<'a, TokenStream> {
                     // Incorrect delimiter.
                     token::CloseDelim(other) => {
                         let token_str = token_to_string(&self.token);
-                        let msg = format!("incorrect close delimiter: `{}`", token_str);
-                        let mut err = self.sess.span_diagnostic.struct_span_err(self.span, &msg);
-                        // This is a conservative error: only report the last unclosed delimiter.
-                        // The previous unclosed delimiters could actually be closed! The parser
-                        // just hasn't gotten to them yet.
-                        if let Some(&(_, sp)) = self.open_braces.last() {
-                            err.span_note(sp, "unclosed delimiter");
-                        };
-                        err.emit();
-
+                        if self.last_unclosed_found_span != Some(self.span) {
+                            // do not complain about the same unclosed delimiter multiple times
+                            self.last_unclosed_found_span = Some(self.span);
+                            let msg = format!("incorrect close delimiter: `{}`", token_str);
+                            let mut err = self.sess.span_diagnostic.struct_span_err(
+                                self.span,
+                                &msg,
+                            );
+                            err.span_label(self.span, "incorrect close delimiter");
+                            // This is a conservative error: only report the last unclosed
+                            // delimiter. The previous unclosed delimiters could actually be
+                            // closed! The parser just hasn't gotten to them yet.
+                            if let Some(&(_, sp)) = self.open_braces.last() {
+                                err.span_label(sp, "unclosed delimiter");
+                            };
+                            err.emit();
+                        }
                         self.open_braces.pop().unwrap();
 
                         // If the incorrect delimiter matches an earlier opening
@@ -118,7 +129,8 @@ fn parse_token_tree(&mut self) -> PResult<'a, TokenStream> {
                 // matching opening delimiter).
                 let token_str = token_to_string(&self.token);
                 let msg = format!("unexpected close delimiter: `{}`", token_str);
-                let err = self.sess.span_diagnostic.struct_span_err(self.span, &msg);
+                let mut err = self.sess.span_diagnostic.struct_span_err(self.span, &msg);
+                err.span_label(self.span, "unexpected close delimiter");
                 Err(err)
             },
             _ => {
@@ -129,6 +141,7 @@ fn parse_token_tree(&mut self) -> PResult<'a, TokenStream> {
                 let raw = self.span_src_raw;
                 self.real_token();
                 let is_joint = raw.hi() == self.span_src_raw.lo() && token::is_op(&self.token);
+
                 Ok(if is_joint { tt.joint() } else { tt.into() })
             }
         }
index a32b515672ecaba229bc572b095fb18801ee66fa..88ff8582da80194ec0c24936970cf8517f9f350b 100644 (file)
@@ -15,7 +15,7 @@
 use errors::DiagnosticBuilder;
 use super::StringReader;
 
-const UNICODE_ARRAY: &'static [(char, &'static str, char)] = &[
+const UNICODE_ARRAY: &[(char, &str, char)] = &[
     ('
', "Line Separator", ' '),
     ('
', "Paragraph Separator", ' '),
     (' ', "Ogham Space mark", ' '),
index 0e45cacaf38c91727ae3227bb5763898eed3ec13..345464c66642570e2e39a6d22358f54192c5b5f8 100644 (file)
@@ -825,7 +825,7 @@ fn parse_ident_common(&mut self, recover: bool) -> PResult<'a, ast::Ident> {
     ///
     /// This method will automatically add `tok` to `expected_tokens` if `tok` is not
     /// encountered.
-    fn check(&mut self, tok: &token::Token) -> bool {
+    crate fn check(&mut self, tok: &token::Token) -> bool {
         let is_present = self.token == *tok;
         if !is_present { self.expected_tokens.push(TokenType::Token(tok.clone())); }
         is_present
@@ -4719,7 +4719,12 @@ pub fn parse_block(&mut self) -> PResult<'a, P<Block>> {
         if !self.eat(&token::OpenDelim(token::Brace)) {
             let sp = self.span;
             let tok = self.this_token_to_string();
+            let mut do_not_suggest_help = false;
             let mut e = self.span_fatal(sp, &format!("expected `{{`, found `{}`", tok));
+            if self.token.is_keyword(keywords::In) || self.token == token::Colon {
+                do_not_suggest_help = true;
+                e.span_label(sp, "expected `{`");
+            }
 
             // Check to see if the user has written something like
             //
@@ -4729,7 +4734,8 @@ pub fn parse_block(&mut self) -> PResult<'a, P<Block>> {
             // Which is valid in other languages, but not Rust.
             match self.parse_stmt_without_recovery(false) {
                 Ok(Some(stmt)) => {
-                    if self.look_ahead(1, |t| t == &token::OpenDelim(token::Brace)) {
+                    if self.look_ahead(1, |t| t == &token::OpenDelim(token::Brace))
+                        || do_not_suggest_help {
                         // if the next token is an open brace (e.g., `if a b {`), the place-
                         // inside-a-block suggestion would be more likely wrong than right
                         return Err(e);
index fda975e6c456bdd16dbad09bba0d029c4e8f27cb..840ee299bf338dd302d268ad6fb4a1edb9641a3e 100644 (file)
@@ -29,7 +29,7 @@
 use parse::token::{self, Token};
 use print::pprust;
 use serialize::{Decoder, Decodable, Encoder, Encodable};
-use util::RcSlice;
+use util::RcVec;
 
 use std::borrow::Cow;
 use std::{fmt, iter, mem};
@@ -221,7 +221,7 @@ pub(crate) fn add_comma(&self) -> Option<(TokenStream, Span)> {
                 new_slice.extend_from_slice(parts.0);
                 new_slice.push(comma);
                 new_slice.extend_from_slice(parts.1);
-                let slice = RcSlice::new(new_slice);
+                let slice = RcVec::new(new_slice);
                 return Some((TokenStream { kind: TokenStreamKind::Stream(slice) }, sp));
             }
         }
@@ -234,7 +234,7 @@ enum TokenStreamKind {
     Empty,
     Tree(TokenTree),
     JointTree(TokenTree),
-    Stream(RcSlice<TokenStream>),
+    Stream(RcVec<TokenStream>),
 }
 
 impl From<TokenTree> for TokenStream {
@@ -255,6 +255,60 @@ fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
     }
 }
 
+impl Extend<TokenStream> for TokenStream {
+    fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, iter: I) {
+        let iter = iter.into_iter();
+        let kind = mem::replace(&mut self.kind, TokenStreamKind::Empty);
+
+        // Vector of token streams originally in self.
+        let tts: Vec<TokenStream> = match kind {
+            TokenStreamKind::Empty => {
+                let mut vec = Vec::new();
+                vec.reserve(iter.size_hint().0);
+                vec
+            }
+            TokenStreamKind::Tree(_) | TokenStreamKind::JointTree(_) => {
+                let mut vec = Vec::new();
+                vec.reserve(1 + iter.size_hint().0);
+                vec.push(TokenStream { kind });
+                vec
+            }
+            TokenStreamKind::Stream(rc_vec) => match RcVec::try_unwrap(rc_vec) {
+                Ok(mut vec) => {
+                    // Extend in place using the existing capacity if possible.
+                    // This is the fast path for libraries like `quote` that
+                    // build a token stream.
+                    vec.reserve(iter.size_hint().0);
+                    vec
+                }
+                Err(rc_vec) => {
+                    // Self is shared so we need to copy and extend that.
+                    let mut vec = Vec::new();
+                    vec.reserve(rc_vec.len() + iter.size_hint().0);
+                    vec.extend_from_slice(&rc_vec);
+                    vec
+                }
+            }
+        };
+
+        // Perform the extend, joining tokens as needed along the way.
+        let mut builder = TokenStreamBuilder(tts);
+        for stream in iter {
+            builder.push(stream);
+        }
+
+        // Build the resulting token stream. If it contains more than one token,
+        // preserve capacity in the vector in anticipation of the caller
+        // performing additional calls to extend.
+        let mut tts = builder.0;
+        *self = match tts.len() {
+            0 => TokenStream::empty(),
+            1 => tts.pop().unwrap(),
+            _ => TokenStream::concat_rc_vec(RcVec::new_preserving_capacity(tts)),
+        };
+    }
+}
+
 impl Eq for TokenStream {}
 
 impl PartialEq<TokenStream> for TokenStream {
@@ -287,11 +341,11 @@ pub fn concat(mut streams: Vec<TokenStream>) -> TokenStream {
         match streams.len() {
             0 => TokenStream::empty(),
             1 => streams.pop().unwrap(),
-            _ => TokenStream::concat_rc_slice(RcSlice::new(streams)),
+            _ => TokenStream::concat_rc_vec(RcVec::new(streams)),
         }
     }
 
-    fn concat_rc_slice(streams: RcSlice<TokenStream>) -> TokenStream {
+    fn concat_rc_vec(streams: RcVec<TokenStream>) -> TokenStream {
         TokenStream { kind: TokenStreamKind::Stream(streams) }
     }
 
@@ -434,7 +488,7 @@ fn push_all_but_last_tree(&mut self, stream: &TokenStream) {
             match len {
                 1 => {}
                 2 => self.0.push(streams[0].clone().into()),
-                _ => self.0.push(TokenStream::concat_rc_slice(streams.sub_slice(0 .. len - 1))),
+                _ => self.0.push(TokenStream::concat_rc_vec(streams.sub_slice(0 .. len - 1))),
             }
             self.push_all_but_last_tree(&streams[len - 1])
         }
@@ -446,7 +500,7 @@ fn push_all_but_first_tree(&mut self, stream: &TokenStream) {
             match len {
                 1 => {}
                 2 => self.0.push(streams[1].clone().into()),
-                _ => self.0.push(TokenStream::concat_rc_slice(streams.sub_slice(1 .. len))),
+                _ => self.0.push(TokenStream::concat_rc_vec(streams.sub_slice(1 .. len))),
             }
             self.push_all_but_first_tree(&streams[0])
         }
@@ -466,13 +520,13 @@ enum CursorKind {
 
 #[derive(Clone)]
 struct StreamCursor {
-    stream: RcSlice<TokenStream>,
+    stream: RcVec<TokenStream>,
     index: usize,
-    stack: Vec<(RcSlice<TokenStream>, usize)>,
+    stack: Vec<(RcVec<TokenStream>, usize)>,
 }
 
 impl StreamCursor {
-    fn new(stream: RcSlice<TokenStream>) -> Self {
+    fn new(stream: RcVec<TokenStream>) -> Self {
         StreamCursor { stream: stream, index: 0, stack: Vec::new() }
     }
 
@@ -495,7 +549,7 @@ fn next_as_stream(&mut self) -> Option<TokenStream> {
         }
     }
 
-    fn insert(&mut self, stream: RcSlice<TokenStream>) {
+    fn insert(&mut self, stream: RcVec<TokenStream>) {
         self.stack.push((mem::replace(&mut self.stream, stream),
                          mem::replace(&mut self.index, 0)));
     }
@@ -557,7 +611,7 @@ pub fn original_stream(&self) -> TokenStream {
             CursorKind::Empty => TokenStream::empty(),
             CursorKind::Tree(ref tree, _) => tree.clone().into(),
             CursorKind::JointTree(ref tree, _) => tree.clone().joint(),
-            CursorKind::Stream(ref cursor) => TokenStream::concat_rc_slice({
+            CursorKind::Stream(ref cursor) => TokenStream::concat_rc_vec({
                 cursor.stack.get(0).cloned().map(|(stream, _)| stream)
                     .unwrap_or(cursor.stream.clone())
             }),
@@ -607,14 +661,14 @@ fn look_ahead(streams: &[TokenStream], mut n: usize) -> Result<TokenTree, usize>
 /// `ThinTokenStream` is smaller, but needs to allocate to represent a single `TokenTree`.
 /// We must use `ThinTokenStream` in `TokenTree::Delimited` to avoid infinite size due to recursion.
 #[derive(Debug, Clone)]
-pub struct ThinTokenStream(Option<RcSlice<TokenStream>>);
+pub struct ThinTokenStream(Option<RcVec<TokenStream>>);
 
 impl From<TokenStream> for ThinTokenStream {
     fn from(stream: TokenStream) -> ThinTokenStream {
         ThinTokenStream(match stream.kind {
             TokenStreamKind::Empty => None,
-            TokenStreamKind::Tree(tree) => Some(RcSlice::new(vec![tree.into()])),
-            TokenStreamKind::JointTree(tree) => Some(RcSlice::new(vec![tree.joint()])),
+            TokenStreamKind::Tree(tree) => Some(RcVec::new(vec![tree.into()])),
+            TokenStreamKind::JointTree(tree) => Some(RcVec::new(vec![tree.joint()])),
             TokenStreamKind::Stream(stream) => Some(stream),
         })
     }
@@ -622,7 +676,7 @@ fn from(stream: TokenStream) -> ThinTokenStream {
 
 impl From<ThinTokenStream> for TokenStream {
     fn from(stream: ThinTokenStream) -> TokenStream {
-        stream.0.map(TokenStream::concat_rc_slice).unwrap_or_else(TokenStream::empty)
+        stream.0.map(TokenStream::concat_rc_vec).unwrap_or_else(TokenStream::empty)
     }
 }
 
@@ -773,4 +827,106 @@ fn test_dotdotdot() {
         assert_eq!(stream.trees().count(), 1);
     }
 
+    #[test]
+    fn test_extend_empty() {
+        with_globals(|| {
+            // Append a token onto an empty token stream.
+            let mut stream = TokenStream::empty();
+            stream.extend(vec![string_to_ts("t")]);
+
+            let expected = string_to_ts("t");
+            assert!(stream.eq_unspanned(&expected));
+        });
+    }
+
+    #[test]
+    fn test_extend_nothing() {
+        with_globals(|| {
+            // Append nothing onto a token stream containing one token.
+            let mut stream = string_to_ts("t");
+            stream.extend(vec![]);
+
+            let expected = string_to_ts("t");
+            assert!(stream.eq_unspanned(&expected));
+        });
+    }
+
+    #[test]
+    fn test_extend_single() {
+        with_globals(|| {
+            // Append a token onto token stream containing a single token.
+            let mut stream = string_to_ts("t1");
+            stream.extend(vec![string_to_ts("t2")]);
+
+            let expected = string_to_ts("t1 t2");
+            assert!(stream.eq_unspanned(&expected));
+        });
+    }
+
+    #[test]
+    fn test_extend_in_place() {
+        with_globals(|| {
+            // Append a token onto token stream containing a reference counted
+            // vec of tokens. The token stream has a reference count of 1 so
+            // this can happen in place.
+            let mut stream = string_to_ts("t1 t2");
+            stream.extend(vec![string_to_ts("t3")]);
+
+            let expected = string_to_ts("t1 t2 t3");
+            assert!(stream.eq_unspanned(&expected));
+        });
+    }
+
+    #[test]
+    fn test_extend_copy() {
+        with_globals(|| {
+            // Append a token onto token stream containing a reference counted
+            // vec of tokens. The token stream is shared so the extend takes
+            // place on a copy.
+            let mut stream = string_to_ts("t1 t2");
+            let _incref = stream.clone();
+            stream.extend(vec![string_to_ts("t3")]);
+
+            let expected = string_to_ts("t1 t2 t3");
+            assert!(stream.eq_unspanned(&expected));
+        });
+    }
+
+    #[test]
+    fn test_extend_no_join() {
+        with_globals(|| {
+            let first = TokenTree::Token(DUMMY_SP, Token::Dot);
+            let second = TokenTree::Token(DUMMY_SP, Token::Dot);
+
+            // Append a dot onto a token stream containing a dot, but do not
+            // join them.
+            let mut stream = TokenStream::from(first);
+            stream.extend(vec![TokenStream::from(second)]);
+
+            let expected = string_to_ts(". .");
+            assert!(stream.eq_unspanned(&expected));
+
+            let unexpected = string_to_ts("..");
+            assert!(!stream.eq_unspanned(&unexpected));
+        });
+    }
+
+    #[test]
+    fn test_extend_join() {
+        with_globals(|| {
+            let first = TokenTree::Token(DUMMY_SP, Token::Dot).joint();
+            let second = TokenTree::Token(DUMMY_SP, Token::Dot);
+
+            // Append a dot onto a token stream containing a dot, forming a
+            // dotdot.
+            let mut stream = first;
+            stream.extend(vec![TokenStream::from(second)]);
+
+            let expected = string_to_ts("..");
+            assert!(stream.eq_unspanned(&expected));
+
+            let unexpected = string_to_ts(". .");
+            assert!(!stream.eq_unspanned(&unexpected));
+        });
+    }
 }
diff --git a/src/libsyntax/util/rc_vec.rs b/src/libsyntax/util/rc_vec.rs
new file mode 100644 (file)
index 0000000..99fbce1
--- /dev/null
@@ -0,0 +1,90 @@
+// 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.
+
+use std::fmt;
+use std::ops::{Deref, Range};
+
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult};
+use rustc_data_structures::sync::Lrc;
+
+#[derive(Clone)]
+pub struct RcVec<T> {
+    data: Lrc<Vec<T>>,
+    offset: u32,
+    len: u32,
+}
+
+impl<T> RcVec<T> {
+    pub fn new(mut vec: Vec<T>) -> Self {
+        // By default, constructing RcVec from Vec gives it just enough capacity
+        // to hold the initial elements. Callers that anticipate needing to
+        // extend the vector may prefer RcVec::new_preserving_capacity.
+        vec.shrink_to_fit();
+        Self::new_preserving_capacity(vec)
+    }
+
+    pub fn new_preserving_capacity(vec: Vec<T>) -> Self {
+        RcVec {
+            offset: 0,
+            len: vec.len() as u32,
+            data: Lrc::new(vec),
+        }
+    }
+
+    pub fn sub_slice(&self, range: Range<usize>) -> Self {
+        RcVec {
+            data: self.data.clone(),
+            offset: self.offset + range.start as u32,
+            len: (range.end - range.start) as u32,
+        }
+    }
+
+    /// If this RcVec has exactly one strong reference, returns ownership of the
+    /// underlying vector. Otherwise returns self unmodified.
+    pub fn try_unwrap(self) -> Result<Vec<T>, Self> {
+        match Lrc::try_unwrap(self.data) {
+            // If no other RcVec shares ownership of this data.
+            Ok(mut vec) => {
+                // Drop any elements after our view of the data.
+                vec.truncate(self.offset as usize + self.len as usize);
+                // Drop any elements before our view of the data. Do this after
+                // the `truncate` so that elements past the end of our view do
+                // not need to be copied around.
+                vec.drain(..self.offset as usize);
+                Ok(vec)
+            }
+
+            // If the data is shared.
+            Err(data) => Err(RcVec { data, ..self }),
+        }
+    }
+}
+
+impl<T> Deref for RcVec<T> {
+    type Target = [T];
+    fn deref(&self) -> &[T] {
+        &self.data[self.offset as usize..(self.offset + self.len) as usize]
+    }
+}
+
+impl<T: fmt::Debug> fmt::Debug for RcVec<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Debug::fmt(self.deref(), f)
+    }
+}
+
+impl<CTX, T> HashStable<CTX> for RcVec<T>
+where
+    T: HashStable<CTX>,
+{
+    fn hash_stable<W: StableHasherResult>(&self, hcx: &mut CTX, hasher: &mut StableHasher<W>) {
+        (**self).hash_stable(hcx, hasher);
+    }
+}
index 958116f7809bbb3d078455fbc80be8f863763795..adbc5828b8fb88bae1fb7124bf40dc14ac94ec72 100644 (file)
@@ -76,8 +76,8 @@ fn default_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructur
             }
         }
         StaticEnum(..) => {
-            span_err_if_not_stage0!(cx, trait_span, E0665,
-                                    "`Default` cannot be derived for enums, only structs");
+            span_err!(cx, trait_span, E0665,
+                      "`Default` cannot be derived for enums, only structs");
             // let compilation continue
             cx.expr_usize(trait_span, 0)
         }
index 2f5e42d2f7b17f6d70be355adea003a2c34f953d..ae47a028bc3865346485126978e53c7fd0b8f6a4 100644 (file)
 use syntax::symbol::Symbol;
 use syntax_pos::Span;
 
-macro_rules! span_err_if_not_stage0 {
-    ($cx:expr, $sp:expr, $code:ident, $text:tt) => {
-        #[cfg(not(stage0))] {
-            span_err!($cx, $sp, $code, $text)
-        }
-        #[cfg(stage0)] {
-            $cx.span_err($sp, $text)
-        }
-    }
-}
-
 macro path_local($x:ident) {
     generic::ty::Path::new_local(stringify!($x))
 }
index 4be2874ed4ff6e3b5e4aee5559b630ac08ce1ff8..baeb019df1ca0491a0c1c531df5788f8aacbb23d 100644 (file)
 #![feature(plugin)]
 #![plugin(macro_crate_test)]
 
-#[noop_attribute"x"] //~ ERROR expected one of
-fn night() { }
-
-#[noop_attribute("hi"), rank = 2] //~ ERROR unexpected token
+#[noop_attribute("hi", rank = a)] //~ ERROR expected unsuffixed literal or identifier, found a
 fn knight() { }
 
 #[noop_attribute("/user", data= = "<user")] //~ ERROR literal or identifier
index 8d53699c0640e0bb2ce3088491c9329cc8d73ce2..df3f7a239b926b9132e752ebe953f35ab49368fe 100644 (file)
@@ -21,7 +21,7 @@
 #[C] //~ ERROR: The attribute `C` is currently unknown to the compiler
 #[B(D)]
 #[B(E = "foo")]
-#[B arbitrary tokens] //~ ERROR arbitrary tokens in non-macro attributes are unstable
+#[B(arbitrary tokens)] //~ ERROR expected one of `(`, `)`, `,`, `::`, or `=`, found `tokens`
 struct B;
 
 fn main() {}
index 9a0171c2ae5ea205296d129bfae6d8c965c104fc..0798aa549f0b2cd4d2a8ac905551509ad165be54 100644 (file)
@@ -41,12 +41,6 @@ mod _test2_inner {
 #[a = y] //~ ERROR: must only be followed by a delimiter token
 fn _test3() {}
 
-#[a = ] //~ ERROR: must only be followed by a delimiter token
-fn _test4() {}
-
-#[a () = ] //~ ERROR: must only be followed by a delimiter token
-fn _test5() {}
-
 fn attrs() {
     // Statement, item
     #[a] // OK
index 18d73bf5677bce950c35c9dece69f5837e0cc0ce..8e37a884b34bbe24171fee585e1b98f1e8a394c3 100644 (file)
 // gdb-command: print btree_set
 // gdb-check:$1 = BTreeSet<i32>(len: 3) = {3, 5, 7}
 
+// gdb-command: print btree_map
+// gdb-check:$2 = BTreeMap<i32, i32>(len: 3) = {[3] = 3, [5] = 7, [7] = 4}
+
 // gdb-command: print vec_deque
-// gdb-check:$2 = VecDeque<i32>(len: 3, cap: 8) = {5, 3, 7}
+// gdb-check:$3 = VecDeque<i32>(len: 3, cap: 8) = {5, 3, 7}
 
 #![allow(unused_variables)]
 use std::collections::BTreeSet;
+use std::collections::BTreeMap;
 use std::collections::VecDeque;
 
 
@@ -38,6 +42,12 @@ fn main() {
     btree_set.insert(3);
     btree_set.insert(7);
 
+    // BTreeMap
+    let mut btree_map = BTreeMap::new();
+    btree_map.insert(5, 7);
+    btree_map.insert(3, 3);
+    btree_map.insert(7, 4);
+
     // VecDeque
     let mut vec_deque = VecDeque::new();
     vec_deque.push_back(5);
diff --git a/src/test/parse-fail/attr-bad-meta-2.rs b/src/test/parse-fail/attr-bad-meta-2.rs
new file mode 100644 (file)
index 0000000..ce640a3
--- /dev/null
@@ -0,0 +1,12 @@
+// 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.
+
+#[path =] //~ ERROR unexpected token: `]`
+mod m {}
diff --git a/src/test/parse-fail/attr-bad-meta-3.rs b/src/test/parse-fail/attr-bad-meta-3.rs
new file mode 100644 (file)
index 0000000..92e2a59
--- /dev/null
@@ -0,0 +1,12 @@
+// 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.
+
+#[path() token] //~ ERROR expected `]`, found `token`
+mod m {}
index 41db88121cb5292ef9adc410391404a7d7dfcbbc..6f9d794dc2dc302d36eb0f298e1af0652f338344 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// asterisk is bogus
-#[path*] //~ ERROR arbitrary tokens in non-macro attributes are unstable
+#![feature(unrestricted_attribute_tokens)]
+
+#[path*] //~ ERROR expected one of `(`, `::`, `=`, `[`, `]`, or `{`, found `*`
 mod m {}
diff --git a/src/test/parse-fail/issue-10636-1.rs b/src/test/parse-fail/issue-10636-1.rs
deleted file mode 100644 (file)
index 398fe8c..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// compile-flags: -Z parse-only
-
-struct Obj { //~ NOTE: unclosed delimiter
-    member: usize
-) //~ ERROR: incorrect close delimiter
diff --git a/src/test/run-make/git_clone_sha1.sh b/src/test/run-make/git_clone_sha1.sh
new file mode 100644 (file)
index 0000000..efcc93c
--- /dev/null
@@ -0,0 +1,33 @@
+#!/bin/bash -x
+
+# 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.
+
+# Usage: $0 project_name url sha1
+# Get the crate with the specified sha1.
+#
+# all arguments are required.
+#
+# See below link for git usage:
+# https://stackoverflow.com/questions/3489173#14091182
+
+# Mandatory arguments:
+PROJECT_NAME=$1
+URL=$2
+SHA1=$3
+
+function err_exit() {
+    echo "ERROR:" $*
+    exit 1
+}
+
+git clone $URL $PROJECT_NAME || err_exit
+cd $PROJECT_NAME || err_exit
+git reset --hard $SHA1 || err_exit
diff --git a/src/test/run-make/thumb-none-cortex-m/Makefile b/src/test/run-make/thumb-none-cortex-m/Makefile
new file mode 100644 (file)
index 0000000..a267016
--- /dev/null
@@ -0,0 +1,38 @@
+-include ../../run-make-fulldeps/tools.mk
+
+# How to run this
+# $ ./x.py clean
+# $ ./x.py test --target thumbv6m-none-eabi,thumbv7m-none-eabi src/test/run-make
+
+# Supported targets:
+# - thumbv6m-none-eabi (Bare Cortex-M0, M0+, M1)
+# - thumbv7em-none-eabi (Bare Cortex-M4, M7)
+# - thumbv7em-none-eabihf (Bare Cortex-M4F, M7F, FPU, hardfloat)
+# - thumbv7m-none-eabi (Bare Cortex-M3)
+
+# See https://stackoverflow.com/questions/7656425/makefile-ifeq-logical-or
+ifneq (,$(filter $(TARGET),thumbv6m-none-eabi thumbv7em-none-eabi thumbv7em-none-eabihf thumbv7m-none-eabi))
+
+# For cargo setting
+RUSTC := $(RUSTC_ORIGINAL)
+LD_LIBRARY_PATH := $(HOST_RPATH_DIR)
+# We need to be outside of 'src' dir in order to run cargo
+WORK_DIR := $(TMPDIR)
+
+HERE := $(shell pwd)
+
+CRATE := cortex-m
+CRATE_URL := https://github.com/rust-embedded/cortex-m
+CRATE_SHA1 := a448e9156e2cb1e556e5441fd65426952ef4b927 # 0.5.0
+
+all:
+       env
+       mkdir -p $(WORK_DIR)
+       -cd $(WORK_DIR) && rm -rf $(CRATE)
+       cd $(WORK_DIR) && bash -x $(HERE)/../git_clone_sha1.sh $(CRATE) $(CRATE_URL) $(CRATE_SHA1)
+       cd $(WORK_DIR) && cd $(CRATE) && $(CARGO) build --target $(TARGET) -v
+else
+
+all:
+
+endif
index 7b521f2b9138a21bb01c40d2ae9ea1d7ff0ebdb5..e1aabad4142f93cae3f0d00698034e7efe1eb09d 100644 (file)
@@ -19,7 +19,7 @@
 #[proc_macro_derive(B, attributes(B, C))]
 pub fn derive(input: TokenStream) -> TokenStream {
     let input = input.to_string();
-    assert!(input.contains("#[B arbitrary tokens]"));
+    assert!(input.contains("#[B [ arbitrary tokens ]]"));
     assert!(input.contains("struct B {"));
     assert!(input.contains("#[C]"));
     "".parse().unwrap()
index 918d2c17123e88b427106040538b454fd8a6b529..1de6496e29f8b22fc6a6d8d92bfd7dbb7208b84c 100644 (file)
@@ -16,7 +16,7 @@
 extern crate derive_b;
 
 #[derive(Debug, PartialEq, derive_b::B, Eq, Copy, Clone)]
-#[cfg_attr(all(), B arbitrary tokens)]
+#[cfg_attr(all(), B[arbitrary tokens])]
 struct B {
     #[C]
     a: u64
index 7003541e86cd331bd89cca4dc8a8cf4b63029261..31f683a17355066c8e825c30295570bfa9f5ed51 100644 (file)
@@ -28,14 +28,14 @@ mod n
     use crate as root;
     pub fn check() {
         assert_eq!(f(), 1);
-        assert_eq!(::crate::m::g(), 2);
+        assert_eq!(crate::m::g(), 2);
         assert_eq!(root::m::h(), 3);
     }
 }
 
 fn main() {
     assert_eq!(f(), 1);
-    assert_eq!(::crate::m::g(), 2);
+    assert_eq!(crate::m::g(), 2);
     assert_eq!(root::m::h(), 3);
     n::check();
 }
index 1a8d2d80ef4d9e250a73c75f5a82c5821106c42c..4646d81cf518f8b79715ba0a9d99ee40ada5d9d0 100644 (file)
@@ -14,8 +14,9 @@
 mod m {
     pub struct Z;
     pub struct S1(crate (::m::Z)); // OK
-    pub struct S2(::crate ::m::Z); // OK
+    pub struct S2((crate ::m::Z)); // OK
     pub struct S3(crate ::m::Z); // OK
+    pub struct S4(crate crate::m::Z); // OK
 }
 
 fn main() {
index 086fd58cffa9e1d5cb2d9244edd7fd4b933f600c..954736dfd907cf0b09cdae6847334c4cd5980273 100644 (file)
@@ -10,7 +10,7 @@
 
 // edition:2018
 
-#![feature(uniform_paths)]
+#![feature(decl_macro, uniform_paths)]
 
 // This test is similar to `basic.rs`, but nested in modules.
 
@@ -40,6 +40,11 @@ mod bar {
     // item, e.g. the automatically injected `extern crate std;`, which in
     // the Rust 2018 should no longer be visible through `crate::std`.
     pub use std::io;
+
+    // Also test that items named `std` in other namespaces don't
+    // cause ambiguity errors for the import from `std` above.
+    pub fn std() {}
+    pub macro std() {}
 }
 
 
@@ -49,4 +54,6 @@ fn main() {
     foo::local_io(());
     io::stdout();
     bar::io::stdout();
+    bar::std();
+    bar::std!();
 }
index 4493e37eeb2739ed877dd1776b298c3540093dda..669a1eb58392163fcbe97a03d534036331a13806 100644 (file)
@@ -2,7 +2,7 @@ error: unexpected close delimiter: `)`
   --> $DIR/invalid-punct-ident-4.rs:16:1
    |
 LL | lexer_failure!(); //~ ERROR proc macro panicked
-   | ^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^ unexpected close delimiter
 
 error: proc macro panicked
   --> $DIR/invalid-punct-ident-4.rs:16:1
index e1401653ba356a3330bbbcffabd5ab2ae28168ee..18ca34b117db7a943aa2b5543fd3f39af1e8ba8e 100644 (file)
@@ -17,6 +17,6 @@
 use foo::foo;
 
 #[ foo ( let y: u32 = "z"; ) ] //~ ERROR: mismatched types
-#[ bar let x: u32 = "y"; ] //~ ERROR: mismatched types
+#[ bar { let x: u32 = "y"; } ] //~ ERROR: mismatched types
 fn main() {
 }
index fe62bd23b87c9bc4a6e2421bcdd0a7ac0c205881..a6cbf79209e2e0dccd4ce9bbb221439dd7544276 100644 (file)
@@ -8,10 +8,10 @@ LL | #[ foo ( let y: u32 = "z"; ) ] //~ ERROR: mismatched types
               found type `&'static str`
 
 error[E0308]: mismatched types
-  --> $DIR/attribute-spans-preserved.rs:20:21
+  --> $DIR/attribute-spans-preserved.rs:20:23
    |
-LL | #[ bar let x: u32 = "y"; ] //~ ERROR: mismatched types
-   |                     ^^^ expected u32, found reference
+LL | #[ bar { let x: u32 = "y"; } ] //~ ERROR: mismatched types
+   |                       ^^^ expected u32, found reference
    |
    = note: expected type `u32`
               found type `&'static str`
index 33dc064ef680f313d8bedc215f569f4ecf7cb269..b1487fcd5edbdd7b8db1619f214b78db01b78de0 100644 (file)
@@ -1 +1 @@
-fn main (  ) { let y : u32 = "z" ; let x : u32 = "y" ; }
+fn main (  ) { let y : u32 = "z" ; { let x : u32 = "y" ; } }
diff --git a/src/test/ui/E0508-fail.ast.nll.stderr b/src/test/ui/E0508-fail.ast.nll.stderr
new file mode 100644 (file)
index 0000000..fda6c24
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0508]: cannot move out of type `[NonCopy; 1]`, a non-copy array
+  --> $DIR/E0508-fail.rs:18:18
+   |
+LL |     let _value = array[0];  //[ast]~ ERROR [E0508]
+   |                  ^^^^^^^^
+   |                  |
+   |                  cannot move out of here
+   |                  help: consider borrowing here: `&array[0]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0508`.
index faf7411af317b15b2f8faf13cb99ff2a052cd173..fda6c24dc8710a8e5d97bf5bf119d843e95cb793 100644 (file)
@@ -5,7 +5,7 @@ LL |     let _value = array[0];  //[ast]~ ERROR [E0508]
    |                  ^^^^^^^^
    |                  |
    |                  cannot move out of here
-   |                  help: consider using a reference instead: `&array[0]`
+   |                  help: consider borrowing here: `&array[0]`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/E0508.nll.stderr b/src/test/ui/E0508.nll.stderr
new file mode 100644 (file)
index 0000000..025ff87
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0508]: cannot move out of type `[NonCopy; 1]`, a non-copy array
+  --> $DIR/E0508.rs:15:18
+   |
+LL |     let _value = array[0];  //~ ERROR [E0508]
+   |                  ^^^^^^^^
+   |                  |
+   |                  cannot move out of here
+   |                  help: consider borrowing here: `&array[0]`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0508`.
index 82ef38e96cdede4c62c3ceaf5c976d97b687b718..2981e4ea8b3a38e0579116b68f4b307efb4cbf80 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-stage1
-
 #![feature(asm)]
 
 fn main() {
index fcf3e9a255273877ecd284011070ecdb4fb89738..e8acb282be94d370abfa1c6eb6ca5d441636deef 100644 (file)
@@ -1,11 +1,11 @@
 error[E0660]: malformed inline assembly
-  --> $DIR/E0660.rs:17:5
+  --> $DIR/E0660.rs:15:5
    |
 LL |     asm!("nop" "nop");
    |     ^^^^^^^^^^^^^^^^^^
 
 error[E0660]: malformed inline assembly
-  --> $DIR/E0660.rs:19:5
+  --> $DIR/E0660.rs:17:5
    |
 LL |     asm!("nop" "nop" : "=r"(a));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
index 7f8a0d8b5742051f61a0df2be1c7c4a16ee0a6b0..2410eba02451fc6fb08307b72ad138a7796e4003 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-stage1
-
 #![feature(asm)]
 
 fn main() {
index d8b974d4240747cdd1ee5f6608256df0bf1d268b..90aeca5612ae468269b6a60be3924826debc1a3e 100644 (file)
@@ -1,5 +1,5 @@
 error[E0661]: output operand constraint lacks '=' or '+'
-  --> $DIR/E0661.rs:17:18
+  --> $DIR/E0661.rs:15:18
    |
 LL |     asm!("nop" : "r"(a));
    |                  ^^^
index 6adb11c56169c956be8eb69665dad27a0ba15c33..700540fd1e0c07b8544bb0740998c6257ba5aa2b 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-stage1
-
 #![feature(asm)]
 
 fn main() {
index 215e3a6d2f02357e7d1087ad3415cc756361ea11..31655ca198794c4f392755e8dbacfb57aa98ce1a 100644 (file)
@@ -1,5 +1,5 @@
 error[E0662]: input operand constraint contains '='
-  --> $DIR/E0662.rs:18:12
+  --> $DIR/E0662.rs:16:12
    |
 LL |          : "=test"("a") //~ ERROR E0662
    |            ^^^^^^^
index 9eb05ada4a82a0c79d65d29149d1ce6efe198329..dea2b9156b7e9f40b10085322b34ec44adb80f8d 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-stage1
-
 #![feature(asm)]
 
 fn main() {
index 123aa73eccc5e9e0e135c49e432f61bf7a3e9184..0a287620f20e1836d3dc9db93c294dacad6703a6 100644 (file)
@@ -1,5 +1,5 @@
 error[E0663]: input operand constraint contains '+'
-  --> $DIR/E0663.rs:18:12
+  --> $DIR/E0663.rs:16:12
    |
 LL |          : "+test"("a") //~ ERROR E0663
    |            ^^^^^^^
index 738ffc18e38271bd353dfc3063090e331990516a..9773f604c468bc831f3b3ab467eb45333d2395f2 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-stage1
-
 #![feature(asm)]
 
 fn main() {
index 570811729be85a26bdb1142979a10a7cb0bb7807..1e79c84cbc8c460904b9cfe00e8717027f6d6690 100644 (file)
@@ -1,5 +1,5 @@
 error[E0664]: clobber should not be surrounded by braces
-  --> $DIR/E0664.rs:19:12
+  --> $DIR/E0664.rs:17:12
    |
 LL |          : "{eax}" //~ ERROR E0664
    |            ^^^^^^^
index 8888bedf01687840cd1bc71ad251ad813c454773..0a0bd3f59052cf36edba5777d804a85a97a2b206 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-stage1
-
 #[derive(Default)] //~ ERROR E0665
 enum Food {
     Sweet,
index c97e9e5ea89d080b25e57e0d1ab0741f438b56f2..268224cac3826f0841d6020eef36087d49eba68f 100644 (file)
@@ -1,5 +1,5 @@
 error[E0665]: `Default` cannot be derived for enums, only structs
-  --> $DIR/E0665.rs:13:10
+  --> $DIR/E0665.rs:11:10
    |
 LL | #[derive(Default)] //~ ERROR E0665
    |          ^^^^^^^
index 2aa8f1c3813090291fbca72df73f78ee8f2f8785..b9de60f43f703f72c82096ffa92e995bea3c211d 100644 (file)
@@ -2,10 +2,16 @@ error[E0507]: cannot move out of borrowed content
   --> $DIR/access-mode-in-closures.rs:19:15
    |
 LL |         match *s { sty(v) => v } //~ ERROR cannot move out
-   |               ^^       - move occurs because v has type `std::vec::Vec<isize>`, which does not implement the `Copy` trait
+   |               ^^       - data moved here
    |               |
    |               cannot move out of borrowed content
-   |               help: consider removing this dereference operator: `s`
+   |               help: consider removing the `*`: `s`
+   |
+note: move occurs because `v` has type `std::vec::Vec<isize>`, which does not implement the `Copy` trait
+  --> $DIR/access-mode-in-closures.rs:19:24
+   |
+LL |         match *s { sty(v) => v } //~ ERROR cannot move out
+   |                        ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/attr-eq-token-tree.rs b/src/test/ui/attr-eq-token-tree.rs
new file mode 100644 (file)
index 0000000..c759e62
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-pass
+
+#![feature(custom_attribute, unrestricted_attribute_tokens)]
+
+#[my_attr = !] // OK under feature gate
+fn main() {}
diff --git a/src/test/ui/borrowck/borrowck-closures-two-mut-fail.nll.stderr b/src/test/ui/borrowck/borrowck-closures-two-mut-fail.nll.stderr
new file mode 100644 (file)
index 0000000..c96799c
--- /dev/null
@@ -0,0 +1,75 @@
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/borrowck-closures-two-mut-fail.rs:26:24
+   |
+LL |     let c1 = to_fn_mut(|| x = 4);
+   |                        -- - first borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+LL |     let c2 = to_fn_mut(|| x = 5); //~ ERROR cannot borrow `x` as mutable more than once
+   |                        ^^ - second borrow occurs due to use of `x` in closure
+   |                        |
+   |                        second mutable borrow occurs here
+LL |     c1;
+   |     -- borrow later used here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/borrowck-closures-two-mut-fail.rs:37:24
+   |
+LL |     let c1 = to_fn_mut(|| set(&mut x));
+   |                        --          - first borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+LL |     let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once
+   |                        ^^          - second borrow occurs due to use of `x` in closure
+   |                        |
+   |                        second mutable borrow occurs here
+LL |     c1;
+   |     -- borrow later used here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/borrowck-closures-two-mut-fail.rs:44:24
+   |
+LL |     let c1 = to_fn_mut(|| x = 5);
+   |                        -- - first borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+LL |     let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once
+   |                        ^^          - second borrow occurs due to use of `x` in closure
+   |                        |
+   |                        second mutable borrow occurs here
+LL |     c1;
+   |     -- borrow later used here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/borrowck-closures-two-mut-fail.rs:51:24
+   |
+LL |     let c1 = to_fn_mut(|| x = 5);
+   |                        -- - first borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+LL |     let c2 = to_fn_mut(|| { let _y = to_fn_mut(|| set(&mut x)); }); // (nested closure)
+   |                        ^^                                  - second borrow occurs due to use of `x` in closure
+   |                        |
+   |                        second mutable borrow occurs here
+LL |     //~^ ERROR cannot borrow `x` as mutable more than once
+LL |     c1;
+   |     -- borrow later used here
+
+error[E0499]: cannot borrow `x` as mutable more than once at a time
+  --> $DIR/borrowck-closures-two-mut-fail.rs:63:24
+   |
+LL |     let c1 = to_fn_mut(|| set(&mut *x.f));
+   |                        --           - first borrow occurs due to use of `x` in closure
+   |                        |
+   |                        first mutable borrow occurs here
+LL |     let c2 = to_fn_mut(|| set(&mut *x.f));
+   |                        ^^           - second borrow occurs due to use of `x` in closure
+   |                        |
+   |                        second mutable borrow occurs here
+LL |     //~^ ERROR cannot borrow `x` as mutable more than once
+LL |     c1;
+   |     -- borrow later used here
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0499`.
index 6a1b786f52843539c91f924f7185ceb31904c629..66ebd346dab62620e58bd893548db35b30b3980c 100644 (file)
@@ -8,22 +8,23 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-compare-mode-nll
-
 // Tests that two closures cannot simultaneously have mutable
 // access to the variable, whether that mutable access be used
 // for direct assignment or for taking mutable ref. Issue #6801.
 
-// ignore-compare-mode-nll
-
 #![feature(box_syntax)]
 
+
+
+
+
 fn to_fn_mut<F: FnMut()>(f: F) -> F { f }
 
 fn a() {
     let mut x = 3;
     let c1 = to_fn_mut(|| x = 4);
     let c2 = to_fn_mut(|| x = 5); //~ ERROR cannot borrow `x` as mutable more than once
+    c1;
 }
 
 fn set(x: &mut isize) {
@@ -34,12 +35,14 @@ fn b() {
     let mut x = 3;
     let c1 = to_fn_mut(|| set(&mut x));
     let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once
+    c1;
 }
 
 fn c() {
     let mut x = 3;
     let c1 = to_fn_mut(|| x = 5);
     let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once
+    c1;
 }
 
 fn d() {
@@ -47,6 +50,7 @@ fn d() {
     let c1 = to_fn_mut(|| x = 5);
     let c2 = to_fn_mut(|| { let _y = to_fn_mut(|| set(&mut x)); }); // (nested closure)
     //~^ ERROR cannot borrow `x` as mutable more than once
+    c1;
 }
 
 fn g() {
@@ -58,6 +62,7 @@ struct Foo {
     let c1 = to_fn_mut(|| set(&mut *x.f));
     let c2 = to_fn_mut(|| set(&mut *x.f));
     //~^ ERROR cannot borrow `x` as mutable more than once
+    c1;
 }
 
 fn main() {
index bea32f6be9964d75c0fef850fd99dd447e057137..59104cc4be9b9d0921cb0bd67ef7b1e46458e754 100644 (file)
@@ -9,11 +9,12 @@ LL |     let c2 = to_fn_mut(|| x = 5); //~ ERROR cannot borrow `x` as mutable mo
    |                        ^^ - borrow occurs due to use of `x` in closure
    |                        |
    |                        second mutable borrow occurs here
+LL |     c1;
 LL | }
    | - first borrow ends here
 
 error[E0499]: cannot borrow `x` as mutable more than once at a time
-  --> $DIR/borrowck-closures-two-mut-fail.rs:36:24
+  --> $DIR/borrowck-closures-two-mut-fail.rs:37:24
    |
 LL |     let c1 = to_fn_mut(|| set(&mut x));
    |                        --          - previous borrow occurs due to use of `x` in closure
@@ -23,11 +24,12 @@ LL |     let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as muta
    |                        ^^          - borrow occurs due to use of `x` in closure
    |                        |
    |                        second mutable borrow occurs here
+LL |     c1;
 LL | }
    | - first borrow ends here
 
 error[E0499]: cannot borrow `x` as mutable more than once at a time
-  --> $DIR/borrowck-closures-two-mut-fail.rs:42:24
+  --> $DIR/borrowck-closures-two-mut-fail.rs:44:24
    |
 LL |     let c1 = to_fn_mut(|| x = 5);
    |                        -- - previous borrow occurs due to use of `x` in closure
@@ -37,11 +39,12 @@ LL |     let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as muta
    |                        ^^          - borrow occurs due to use of `x` in closure
    |                        |
    |                        second mutable borrow occurs here
+LL |     c1;
 LL | }
    | - first borrow ends here
 
 error[E0499]: cannot borrow `x` as mutable more than once at a time
-  --> $DIR/borrowck-closures-two-mut-fail.rs:48:24
+  --> $DIR/borrowck-closures-two-mut-fail.rs:51:24
    |
 LL |     let c1 = to_fn_mut(|| x = 5);
    |                        -- - previous borrow occurs due to use of `x` in closure
@@ -51,12 +54,12 @@ LL |     let c2 = to_fn_mut(|| { let _y = to_fn_mut(|| set(&mut x)); }); // (nes
    |                        ^^                                  - borrow occurs due to use of `x` in closure
    |                        |
    |                        second mutable borrow occurs here
-LL |     //~^ ERROR cannot borrow `x` as mutable more than once
+...
 LL | }
    | - first borrow ends here
 
 error[E0499]: cannot borrow `x` as mutable more than once at a time
-  --> $DIR/borrowck-closures-two-mut-fail.rs:59:24
+  --> $DIR/borrowck-closures-two-mut-fail.rs:63:24
    |
 LL |     let c1 = to_fn_mut(|| set(&mut *x.f));
    |                        --           - previous borrow occurs due to use of `x` in closure
@@ -66,7 +69,7 @@ LL |     let c2 = to_fn_mut(|| set(&mut *x.f));
    |                        ^^           - borrow occurs due to use of `x` in closure
    |                        |
    |                        second mutable borrow occurs here
-LL |     //~^ ERROR cannot borrow `x` as mutable more than once
+...
 LL | }
    | - first borrow ends here
 
diff --git a/src/test/ui/borrowck/borrowck-closures-unique.nll.stderr b/src/test/ui/borrowck/borrowck-closures-unique.nll.stderr
new file mode 100644 (file)
index 0000000..17519cc
--- /dev/null
@@ -0,0 +1,54 @@
+error[E0500]: closure requires unique access to `x` but it is already borrowed
+  --> $DIR/borrowck-closures-unique.rs:36:14
+   |
+LL |     let c1 = || get(x);
+   |              --     - first borrow occurs due to use of `x` in closure
+   |              |
+   |              borrow occurs here
+LL |     let c2 = || set(x); //~ ERROR closure requires unique access to `x`
+   |              ^^     - second borrow occurs due to use of `x` in closure
+   |              |
+   |              closure construction occurs here
+LL |     c1;
+   |     -- borrow later used here
+
+error[E0500]: closure requires unique access to `x` but it is already borrowed
+  --> $DIR/borrowck-closures-unique.rs:42:14
+   |
+LL |     let c1 = || get(x);
+   |              --     - first borrow occurs due to use of `x` in closure
+   |              |
+   |              borrow occurs here
+LL |     let c2 = || { get(x); set(x); }; //~ ERROR closure requires unique access to `x`
+   |              ^^       - second borrow occurs due to use of `x` in closure
+   |              |
+   |              closure construction occurs here
+LL |     c1;
+   |     -- borrow later used here
+
+error[E0524]: two closures require unique access to `x` at the same time
+  --> $DIR/borrowck-closures-unique.rs:48:14
+   |
+LL |     let c1 = || set(x);
+   |              --     - first borrow occurs due to use of `x` in closure
+   |              |
+   |              first closure is constructed here
+LL |     let c2 = || set(x); //~ ERROR two closures require unique access to `x` at the same time
+   |              ^^     - second borrow occurs due to use of `x` in closure
+   |              |
+   |              second closure is constructed here
+LL |     c1;
+   |     -- borrow later used here
+
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
+  --> $DIR/borrowck-closures-unique.rs:57:38
+   |
+LL | fn e(x: &'static mut isize) {
+   |      - help: consider changing this to be mutable: `mut x`
+LL |     let c1 = |y: &'static mut isize| x = y; //~ ERROR closure cannot assign to immutable argument
+   |                                      ^^^^^ cannot assign
+
+error: aborting due to 4 previous errors
+
+Some errors occurred: E0500, E0524, E0594.
+For more information about an error, try `rustc --explain E0500`.
index 9a74f188a545f825f653bd03e3dc3afb4402a17c..caf5785f481c2bded03c8b17be98998af959d92f 100644 (file)
@@ -8,14 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-compare-mode-nll
-
 // Tests that a closure which requires mutable access to the referent
 // of an `&mut` requires a "unique" borrow -- that is, the variable to
 // be borrowed (here, `x`) will not be borrowed *mutably*, but
 //  may be *immutable*, but we cannot allow
 // multiple borrows.
 
+
+
 fn get(x: &isize) -> isize {
     *x
 }
@@ -27,25 +27,40 @@ fn set(x: &mut isize) -> isize {
 fn a(x: &mut isize) {
     let c1 = || get(x);
     let c2 = || get(x);
+    c1();
+    c2();
 }
 
 fn b(x: &mut isize) {
     let c1 = || get(x);
     let c2 = || set(x); //~ ERROR closure requires unique access to `x`
+    c1;
 }
 
 fn c(x: &mut isize) {
     let c1 = || get(x);
     let c2 = || { get(x); set(x); }; //~ ERROR closure requires unique access to `x`
+    c1;
 }
 
 fn d(x: &mut isize) {
     let c1 = || set(x);
     let c2 = || set(x); //~ ERROR two closures require unique access to `x` at the same time
+    c1;
+}
+
+// This test was originally encoded in the form shown as `fn f` below.
+// However, since MIR-borrowck and thus NLL takes more control-flow information
+// into account, it was necessary to change the test in order to witness the
+// same (expected) error under both AST-borrowck and NLL.
+fn e(x: &'static mut isize) {
+    let c1 = |y: &'static mut isize| x = y; //~ ERROR closure cannot assign to immutable argument
+    c1;
 }
 
-fn e(x: &mut isize) {
+fn f(x: &'static mut isize) {
     let c1 = || x = panic!(); //~ ERROR closure cannot assign to immutable argument
+    c1;
 }
 
 fn main() {
index 27163bde34f6ab0a375a87919256371e8f3f771a..cfcb81b31e700947cc09d72fd0358eaf004a4872 100644 (file)
@@ -1,5 +1,5 @@
 error[E0500]: closure requires unique access to `x` but it is already borrowed
-  --> $DIR/borrowck-closures-unique.rs:34:14
+  --> $DIR/borrowck-closures-unique.rs:36:14
    |
 LL |     let c1 = || get(x);
    |              --     - previous borrow occurs due to use of `x` in closure
@@ -9,11 +9,12 @@ LL |     let c2 = || set(x); //~ ERROR closure requires unique access to `x`
    |              ^^     - borrow occurs due to use of `x` in closure
    |              |
    |              closure construction occurs here
+LL |     c1;
 LL | }
    | - borrow ends here
 
 error[E0500]: closure requires unique access to `x` but it is already borrowed
-  --> $DIR/borrowck-closures-unique.rs:39:14
+  --> $DIR/borrowck-closures-unique.rs:42:14
    |
 LL |     let c1 = || get(x);
    |              --     - previous borrow occurs due to use of `x` in closure
@@ -23,11 +24,12 @@ LL |     let c2 = || { get(x); set(x); }; //~ ERROR closure requires unique acce
    |              ^^       - borrow occurs due to use of `x` in closure
    |              |
    |              closure construction occurs here
+LL |     c1;
 LL | }
    | - borrow ends here
 
 error[E0524]: two closures require unique access to `x` at the same time
-  --> $DIR/borrowck-closures-unique.rs:44:14
+  --> $DIR/borrowck-closures-unique.rs:48:14
    |
 LL |     let c1 = || set(x);
    |              --     - previous borrow occurs due to use of `x` in closure
@@ -37,11 +39,22 @@ LL |     let c2 = || set(x); //~ ERROR two closures require unique access to `x`
    |              ^^     - borrow occurs due to use of `x` in closure
    |              |
    |              second closure is constructed here
+LL |     c1;
 LL | }
    | - borrow from first closure ends here
 
 error[E0595]: closure cannot assign to immutable argument `x`
-  --> $DIR/borrowck-closures-unique.rs:48:14
+  --> $DIR/borrowck-closures-unique.rs:57:14
+   |
+LL |     let c1 = |y: &'static mut isize| x = y; //~ ERROR closure cannot assign to immutable argument
+   |              ^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow mutably
+help: consider removing the `&mut`, as it is an immutable binding to a mutable reference
+   |
+LL |     x //~ ERROR closure cannot assign to immutable argument
+   |     ^
+
+error[E0595]: closure cannot assign to immutable argument `x`
+  --> $DIR/borrowck-closures-unique.rs:62:14
    |
 LL |     let c1 = || x = panic!(); //~ ERROR closure cannot assign to immutable argument
    |              ^^ cannot borrow mutably
@@ -50,7 +63,7 @@ help: consider removing the `&mut`, as it is an immutable binding to a mutable r
 LL |     x //~ ERROR closure cannot assign to immutable argument
    |     ^
 
-error: aborting due to 4 previous errors
+error: aborting due to 5 previous errors
 
 Some errors occurred: E0500, E0524, E0595.
 For more information about an error, try `rustc --explain E0500`.
index f9e517def14060e049e7d8629c1058e35691cc4b..25eb69ad9377dfe21b260a35ad50463847956d75 100644 (file)
@@ -2,28 +2,46 @@ error[E0507]: cannot move out of borrowed content
   --> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:22:15
    |
 LL |     for &a in x.iter() {    //~ ERROR cannot move out
-   |          -    ^^^^^^^^ cannot move out of borrowed content
-   |          |
-   |          data moved here
-   |          help: to prevent move, use ref or ref mut: `ref a`
+   |         --    ^^^^^^^^ cannot move out of borrowed content
+   |         ||
+   |         |data moved here
+   |         help: consider removing the `&`: `a`
+   |
+note: move occurs because `a` has type `&mut i32`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:22:10
+   |
+LL |     for &a in x.iter() {    //~ ERROR cannot move out
+   |          ^
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:28:15
    |
 LL |     for &a in &f.a {  //~ ERROR cannot move out
-   |          -    ^^^^ cannot move out of borrowed content
-   |          |
-   |          data moved here
-   |          help: to prevent move, use ref or ref mut: `ref a`
+   |         --    ^^^^ cannot move out of borrowed content
+   |         ||
+   |         |data moved here
+   |         help: consider removing the `&`: `a`
+   |
+note: move occurs because `a` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:28:10
+   |
+LL |     for &a in &f.a {  //~ ERROR cannot move out
+   |          ^
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:32:15
    |
 LL |     for &a in x.iter() {    //~ ERROR cannot move out
-   |          -    ^^^^^^^^ cannot move out of borrowed content
-   |          |
-   |          data moved here
-   |          help: to prevent move, use ref or ref mut: `ref a`
+   |         --    ^^^^^^^^ cannot move out of borrowed content
+   |         ||
+   |         |data moved here
+   |         help: consider removing the `&`: `a`
+   |
+note: move occurs because `a` has type `std::boxed::Box<i32>`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-for-loop-correct-cmt-for-pattern.rs:32:10
+   |
+LL |     for &a in x.iter() {    //~ ERROR cannot move out
+   |          ^
 
 error: aborting due to 3 previous errors
 
index 55c6a40d281bc0c55dc1c9d02b52de582e9c3364..cdbfab8bd054a1903c2d53ce953bc577d7f9faeb 100644 (file)
@@ -5,7 +5,7 @@ LL |         let _b = *y; //~ ERROR cannot move out
    |                  ^^
    |                  |
    |                  cannot move out of borrowed content
-   |                  help: consider removing this dereference operator: `y`
+   |                  help: consider removing the `*`: `y`
 
 error: aborting due to previous error
 
index 1b913471924b799a19fbcefa11978ce2bef67d0a..2df520a936c9d4a9975563d5eb6221917fda2853 100644 (file)
@@ -5,14 +5,24 @@ LL |     match *f {             //~ ERROR cannot move out of
    |           ^^
    |           |
    |           cannot move out of borrowed content
-   |           help: consider removing this dereference operator: `f`
+   |           help: consider removing the `*`: `f`
 LL |                            //~| cannot move out
 LL |         Foo::Foo1(num1,
-   |                   ---- move occurs because num1 has type `std::boxed::Box<u32>`, which does not implement the `Copy` trait
+   |                   ---- data moved here
 LL |                   num2) => (),
-   |                   ---- move occurs because num2 has type `std::boxed::Box<u32>`, which does not implement the `Copy` trait
+   |                   ---- ...and here
 LL |         Foo::Foo2(num) => (),
-   |                   --- move occurs because num has type `std::boxed::Box<u32>`, which does not implement the `Copy` trait
+   |                   --- ...and here
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/borrowck-move-error-with-note.rs:23:19
+   |
+LL |         Foo::Foo1(num1,
+   |                   ^^^^
+LL |                   num2) => (),
+   |                   ^^^^
+LL |         Foo::Foo2(num) => (),
+   |                   ^^^
 
 error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
   --> $DIR/borrowck-move-error-with-note.rs:39:11
@@ -23,12 +33,15 @@ LL |     match (S {f: "foo".to_string(), g: "bar".to_string()}) {
 LL |             f: _s,
    |                -- data moved here
 LL |             g: _t
-   |                -- ... and here
-help: to prevent move, use ref or ref mut
+   |                -- ...and here
    |
-LL |             f: ref _s,
-LL |             g: ref _t
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/borrowck-move-error-with-note.rs:42:16
    |
+LL |             f: _s,
+   |                ^^
+LL |             g: _t
+   |                ^^
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/borrowck-move-error-with-note.rs:57:11
@@ -37,10 +50,16 @@ LL |     match a.a {           //~ ERROR cannot move out of
    |           ^^^
    |           |
    |           cannot move out of borrowed content
-   |           help: consider using a reference instead: `&a.a`
+   |           help: consider borrowing here: `&a.a`
 LL |                           //~| cannot move out
 LL |         n => {
-   |         - move occurs because n has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+   |         - data moved here
+   |
+note: move occurs because `n` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-error-with-note.rs:59:9
+   |
+LL |         n => {
+   |         ^
 
 error: aborting due to 3 previous errors
 
index 4f692bfc55e427cb92ed903d240d51e4269da96c..f823a6f08d789485e47546b7e9fa34f4ec5f1f34 100644 (file)
@@ -5,7 +5,7 @@ LL |     let y = *x; //~ ERROR cannot move out of dereference of raw pointer
    |             ^^
    |             |
    |             cannot move out of borrowed content
-   |             help: consider using a reference instead: `&*x`
+   |             help: consider removing the `*`: `x`
 
 error: aborting due to previous error
 
index f670936dbac17b7a4bee7dac9c2e38d198641daa..49c2ec0dcf4e7c996e77b3f918f482664288f74f 100644 (file)
@@ -5,8 +5,14 @@ LL | fn arg_item(&_x: &String) {}
    |             ^--
    |             ||
    |             |data moved here
-   |             |help: to prevent move, use ref or ref mut: `ref _x`
    |             cannot move out of borrowed content
+   |             help: consider removing the `&`: `_x`
+   |
+note: move occurs because `_x` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-in-irrefut-pat.rs:16:14
+   |
+LL | fn arg_item(&_x: &String) {}
+   |              ^^
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/borrowck-move-in-irrefut-pat.rs:21:11
@@ -15,17 +21,29 @@ LL |     with(|&_x| ())
    |           ^--
    |           ||
    |           |data moved here
-   |           |help: to prevent move, use ref or ref mut: `ref _x`
    |           cannot move out of borrowed content
+   |           help: consider removing the `&`: `_x`
+   |
+note: move occurs because `_x` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-in-irrefut-pat.rs:21:12
+   |
+LL |     with(|&_x| ())
+   |            ^^
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/borrowck-move-in-irrefut-pat.rs:27:15
    |
 LL |     let &_x = &"hi".to_string();
-   |          --   ^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
-   |          |
-   |          data moved here
-   |          help: to prevent move, use ref or ref mut: `ref _x`
+   |         ---   ^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+   |         ||
+   |         |data moved here
+   |         help: consider removing the `&`: `_x`
+   |
+note: move occurs because `_x` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-in-irrefut-pat.rs:27:10
+   |
+LL |     let &_x = &"hi".to_string();
+   |          ^^
 
 error: aborting due to 3 previous errors
 
index f670936dbac17b7a4bee7dac9c2e38d198641daa..49c2ec0dcf4e7c996e77b3f918f482664288f74f 100644 (file)
@@ -5,8 +5,14 @@ LL | fn arg_item(&_x: &String) {}
    |             ^--
    |             ||
    |             |data moved here
-   |             |help: to prevent move, use ref or ref mut: `ref _x`
    |             cannot move out of borrowed content
+   |             help: consider removing the `&`: `_x`
+   |
+note: move occurs because `_x` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-in-irrefut-pat.rs:16:14
+   |
+LL | fn arg_item(&_x: &String) {}
+   |              ^^
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/borrowck-move-in-irrefut-pat.rs:21:11
@@ -15,17 +21,29 @@ LL |     with(|&_x| ())
    |           ^--
    |           ||
    |           |data moved here
-   |           |help: to prevent move, use ref or ref mut: `ref _x`
    |           cannot move out of borrowed content
+   |           help: consider removing the `&`: `_x`
+   |
+note: move occurs because `_x` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-in-irrefut-pat.rs:21:12
+   |
+LL |     with(|&_x| ())
+   |            ^^
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/borrowck-move-in-irrefut-pat.rs:27:15
    |
 LL |     let &_x = &"hi".to_string();
-   |          --   ^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
-   |          |
-   |          data moved here
-   |          help: to prevent move, use ref or ref mut: `ref _x`
+   |         ---   ^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+   |         ||
+   |         |data moved here
+   |         help: consider removing the `&`: `_x`
+   |
+note: move occurs because `_x` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-in-irrefut-pat.rs:27:10
+   |
+LL |     let &_x = &"hi".to_string();
+   |          ^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-overloaded-deref.nll.stderr b/src/test/ui/borrowck/borrowck-move-out-of-overloaded-deref.nll.stderr
new file mode 100644 (file)
index 0000000..b9c47e6
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/borrowck-move-out-of-overloaded-deref.rs:14:14
+   |
+LL |     let _x = *Rc::new("hi".to_string());
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |              |
+   |              cannot move out of borrowed content
+   |              help: consider removing the `*`: `Rc::new("hi".to_string())`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
index 15c7011d71671c90b0852f028ce47060a1102c0d..34f9f035188b8d4276c21c2f5afc674365cb5f29 100644 (file)
@@ -5,10 +5,13 @@ LL |     match (S {f:"foo".to_string()}) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
 LL |         //[mir]~^ ERROR [E0509]
 LL |         S {f:_s} => {}
-   |              --
-   |              |
-   |              data moved here
-   |              help: to prevent move, use ref or ref mut: `ref _s`
+   |              -- data moved here
+   |
+note: move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:22:14
+   |
+LL |         S {f:_s} => {}
+   |              ^^
 
 error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
   --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:28:20
@@ -17,7 +20,12 @@ LL |     let S {f:_s} = S {f:"foo".to_string()};
    |              --    ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
    |              |
    |              data moved here
-   |              help: to prevent move, use ref or ref mut: `ref _s`
+   |
+note: move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:28:14
+   |
+LL |     let S {f:_s} = S {f:"foo".to_string()};
+   |              ^^
 
 error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
   --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:33:19
@@ -26,8 +34,13 @@ LL | fn move_in_fn_arg(S {f:_s}: S) {
    |                   ^^^^^--^
    |                   |    |
    |                   |    data moved here
-   |                   |    help: to prevent move, use ref or ref mut: `ref _s`
    |                   cannot move out of here
+   |
+note: move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:33:24
+   |
+LL | fn move_in_fn_arg(S {f:_s}: S) {
+   |                        ^^
 
 error: aborting due to 3 previous errors
 
index 15c7011d71671c90b0852f028ce47060a1102c0d..34f9f035188b8d4276c21c2f5afc674365cb5f29 100644 (file)
@@ -5,10 +5,13 @@ LL |     match (S {f:"foo".to_string()}) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
 LL |         //[mir]~^ ERROR [E0509]
 LL |         S {f:_s} => {}
-   |              --
-   |              |
-   |              data moved here
-   |              help: to prevent move, use ref or ref mut: `ref _s`
+   |              -- data moved here
+   |
+note: move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:22:14
+   |
+LL |         S {f:_s} => {}
+   |              ^^
 
 error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
   --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:28:20
@@ -17,7 +20,12 @@ LL |     let S {f:_s} = S {f:"foo".to_string()};
    |              --    ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
    |              |
    |              data moved here
-   |              help: to prevent move, use ref or ref mut: `ref _s`
+   |
+note: move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:28:14
+   |
+LL |     let S {f:_s} = S {f:"foo".to_string()};
+   |              ^^
 
 error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
   --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:33:19
@@ -26,8 +34,13 @@ LL | fn move_in_fn_arg(S {f:_s}: S) {
    |                   ^^^^^--^
    |                   |    |
    |                   |    data moved here
-   |                   |    help: to prevent move, use ref or ref mut: `ref _s`
    |                   cannot move out of here
+   |
+note: move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-out-of-struct-with-dtor.rs:33:24
+   |
+LL | fn move_in_fn_arg(S {f:_s}: S) {
+   |                        ^^
 
 error: aborting due to 3 previous errors
 
index c69ae8755a957dcdebeff4e25172412f6f622cf1..278c33c71e24549f00090137180e5a32f9df8d7d 100644 (file)
@@ -4,10 +4,13 @@ error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
 LL |     match S("foo".to_string()) {
    |           ^^^^^^^^^^^^^^^^^^^^ cannot move out of here
 LL |         S(_s) => {}
-   |           --
-   |           |
-   |           data moved here
-   |           help: to prevent move, use ref or ref mut: `ref _s`
+   |           -- data moved here
+   |
+note: move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:18:11
+   |
+LL |         S(_s) => {}
+   |           ^^
 
 error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
   --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:24:17
@@ -16,7 +19,12 @@ LL |     let S(_s) = S("foo".to_string());
    |           --    ^^^^^^^^^^^^^^^^^^^^ cannot move out of here
    |           |
    |           data moved here
-   |           help: to prevent move, use ref or ref mut: `ref _s`
+   |
+note: move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:24:11
+   |
+LL |     let S(_s) = S("foo".to_string());
+   |           ^^
 
 error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
   --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:28:19
@@ -25,8 +33,13 @@ LL | fn move_in_fn_arg(S(_s): S) {
    |                   ^^--^
    |                   | |
    |                   | data moved here
-   |                   | help: to prevent move, use ref or ref mut: `ref _s`
    |                   cannot move out of here
+   |
+note: move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-move-out-of-tuple-struct-with-dtor.rs:28:21
+   |
+LL | fn move_in_fn_arg(S(_s): S) {
+   |                     ^^
 
 error: aborting due to 3 previous errors
 
index 95a7894d532546e1f8dd942b7c11e536c906eb22..f3430ba4e06c9038310a8f087594447e8b89dbce 100644 (file)
@@ -7,14 +7,23 @@ LL |                 &[Foo { string: a },
    |                                 - data moved here
 ...
 LL |                   Foo { string: b }] => {
-   |                                 - ... and here
-help: to prevent move, use ref or ref mut
+   |                                 - ...and here
    |
-LL |                 &[Foo { string: ref a },
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/borrowck-move-out-of-vec-tail.rs:30:33
+   |
+LL |                 &[Foo { string: a },
+   |                                 ^
+...
+LL |                   Foo { string: b }] => {
+   |                                 ^
+help: consider removing the `&`
+   |
+LL |                 [Foo { string: a },
 LL |                 //~^ ERROR cannot move out of type `[Foo]`
 LL |                 //~| cannot move out
 LL |                 //~| to prevent move
-LL |                   Foo { string: ref b }] => {
+LL |                   Foo { string: b }] => {
    |
 
 error: aborting due to previous error
index 4a72d7f33026652970b485baf7aa76e090aaba8b..92e10c258c269efbd9cca6855d1dcd0e351bf573 100644 (file)
@@ -5,7 +5,7 @@ LL |     let bad = v[0];
    |               ^^^^
    |               |
    |               cannot move out of borrowed content
-   |               help: consider using a reference instead: `&v[0]`
+   |               help: consider borrowing here: `&v[0]`
 
 error: aborting due to previous error
 
index 2779132590e2c00b57e1b06f1a9d372b2af166fd..d5b17119d85f52abeb645cf07b1f5b8c24f2ec8e 100644 (file)
@@ -28,10 +28,21 @@ error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy sli
 LL |     match vec {
    |           ^^^ cannot move out of here
 LL |         &mut [_a, //~ ERROR cannot move out
-   |               --
-   |               |
-   |               data moved here
-   |               help: to prevent move, use ref or ref mut: `ref _a`
+   |               -- data moved here
+   |
+note: move occurs because `_a` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-vec-pattern-nesting.rs:44:15
+   |
+LL |         &mut [_a, //~ ERROR cannot move out
+   |               ^^
+help: consider removing the `&mut`
+   |
+LL |         [_a, //~ ERROR cannot move out
+LL |             //~| cannot move out
+LL |             //~| to prevent move
+LL |             ..
+LL |         ] => {
+   |
 
 error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
   --> $DIR/borrowck-vec-pattern-nesting.rs:57:13
@@ -40,7 +51,7 @@ LL |     let a = vec[0]; //~ ERROR cannot move out
    |             ^^^^^^
    |             |
    |             cannot move out of here
-   |             help: consider using a reference instead: `&vec[0]`
+   |             help: consider borrowing here: `&vec[0]`
 
 error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
   --> $DIR/borrowck-vec-pattern-nesting.rs:64:11
@@ -49,10 +60,19 @@ LL |     match vec {
    |           ^^^ cannot move out of here
 ...
 LL |          _b] => {}
-   |          --
-   |          |
-   |          data moved here
-   |          help: to prevent move, use ref or ref mut: `ref _b`
+   |          -- data moved here
+   |
+note: move occurs because `_b` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+  --> $DIR/borrowck-vec-pattern-nesting.rs:67:10
+   |
+LL |          _b] => {}
+   |          ^^
+help: consider removing the `&mut`
+   |
+LL |         [ //~ ERROR cannot move out
+LL |         //~^ cannot move out
+LL |          _b] => {}
+   |
 
 error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
   --> $DIR/borrowck-vec-pattern-nesting.rs:70:13
@@ -61,7 +81,7 @@ LL |     let a = vec[0]; //~ ERROR cannot move out
    |             ^^^^^^
    |             |
    |             cannot move out of here
-   |             help: consider using a reference instead: `&vec[0]`
+   |             help: consider borrowing here: `&vec[0]`
 
 error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
   --> $DIR/borrowck-vec-pattern-nesting.rs:77:11
@@ -69,14 +89,18 @@ error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy sli
 LL |     match vec {
    |           ^^^ cannot move out of here
 LL |         &mut [_a, _b, _c] => {}  //~ ERROR cannot move out
-   |               --  --  -- ... and here
-   |               |   |
-   |               |   ... and here
-   |               data moved here
-help: to prevent move, use ref or ref mut
-   |
-LL |         &mut [ref _a, ref _b, ref _c] => {}  //~ ERROR cannot move out
-   |               ^^^^^^  ^^^^^^  ^^^^^^
+   |         -----------------
+   |         |     |   |   |
+   |         |     |   |   ...and here
+   |         |     |   ...and here
+   |         |     data moved here
+   |         help: consider removing the `&mut`: `[_a, _b, _c]`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/borrowck-vec-pattern-nesting.rs:78:15
+   |
+LL |         &mut [_a, _b, _c] => {}  //~ ERROR cannot move out
+   |               ^^  ^^  ^^
 
 error[E0508]: cannot move out of type `[std::boxed::Box<isize>]`, a non-copy slice
   --> $DIR/borrowck-vec-pattern-nesting.rs:82:13
@@ -85,7 +109,7 @@ LL |     let a = vec[0]; //~ ERROR cannot move out
    |             ^^^^^^
    |             |
    |             cannot move out of here
-   |             help: consider using a reference instead: `&vec[0]`
+   |             help: consider borrowing here: `&vec[0]`
 
 error: aborting due to 8 previous errors
 
index 20713c3392e8e9c23e0f2cfe66337beee321ede3..d4340938eebc14880e7b4409021344c26f733c86 100644 (file)
@@ -5,8 +5,13 @@ LL |     let opt = a.iter().enumerate().find(|(_, &s)| {
    |                                          ^^^^^-^
    |                                          |    |
    |                                          |    data moved here
-   |                                          |    help: to prevent move, use ref or ref mut: `ref s`
    |                                          cannot move out of borrowed content
+   |
+note: move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/issue-51415.rs:16:47
+   |
+LL |     let opt = a.iter().enumerate().find(|(_, &s)| {
+   |                                               ^
 
 error: aborting due to previous error
 
index 4ba9b3aeb5d5da423591f7b3554db573cdaad917..491b5b5bd74abef53a40f7b6d0e963f9c0683bd5 100644 (file)
@@ -5,10 +5,16 @@ LL |     match &s.x {
    |           ^^^^ cannot move out of borrowed content
 LL |         &E::Foo => {}
 LL |         &E::Bar(identifier) => f(identifier.clone())  //~ ERROR cannot move
-   |                 ----------
-   |                 |
-   |                 data moved here
-   |                 help: to prevent move, use ref or ref mut: `ref identifier`
+   |         -------------------
+   |         |       |
+   |         |       data moved here
+   |         help: consider removing the `&`: `E::Bar(identifier)`
+   |
+note: move occurs because `identifier` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/by-move-pattern-binding.rs:26:17
+   |
+LL |         &E::Bar(identifier) => f(identifier.clone())  //~ ERROR cannot move
+   |                 ^^^^^^^^^^
 
 error: aborting due to previous error
 
index b265ec8bddac689c663c9d8b1d35e527f397e2c6..5522e22fb1fa28089a33a6c8851a39b7b52cf70a 100644 (file)
@@ -56,7 +56,7 @@ LL |     let y = { static x: Box<isize> = box 3; x };
    |                                             ^
    |                                             |
    |                                             cannot move out of static item
-   |                                             help: consider using a reference instead: `&x`
+   |                                             help: consider borrowing here: `&x`
 
 error[E0010]: allocations are not allowed in statics
   --> $DIR/check-static-values-constraints.rs:120:38
index a1fbcf1430db93b2b4a40c3077ee87db39a4cce9..e334472f9d6e1b26cba8b06eb20fe2ccdd999cfe 100644 (file)
@@ -4,10 +4,13 @@ error[E0509]: cannot move out of type `S`, which implements the `Drop` trait
 LL |     match (S {f:"foo".to_string()}) {
    |           ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of here
 LL |         S {f:_s} => {} //~ ERROR cannot move out
-   |              --
-   |              |
-   |              data moved here
-   |              help: to prevent move, use ref or ref mut: `ref _s`
+   |              -- data moved here
+   |
+note: move occurs because `_s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/overlapping_spans.rs:21:14
+   |
+LL |         S {f:_s} => {} //~ ERROR cannot move out
+   |              ^^
 
 error: aborting due to previous error
 
index a8be048d7df6c25c5e0e2c8551704e01d546f7a4..8e0599370287fb886ef239e8b593c5088c94d7dd 100644 (file)
@@ -5,7 +5,12 @@ LL |     let X { x: y } = x; //~ ERROR cannot move out of type
    |                -     ^ cannot move out of here
    |                |
    |                data moved here
-   |                help: to prevent move, use ref or ref mut: `ref y`
+   |
+note: move occurs because `y` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/disallowed-deconstructing-destructing-struct-let.rs:22:16
+   |
+LL |     let X { x: y } = x; //~ ERROR cannot move out of type
+   |                ^
 
 error: aborting due to previous error
 
index 9f0d2d5f0e1891e42d588a51db7c0b663dd22428..dd1a3ef2a2b9835c1403c0796b7475cb4b7de57d 100644 (file)
@@ -4,10 +4,13 @@ error[E0509]: cannot move out of type `X`, which implements the `Drop` trait
 LL |     match x {
    |           ^ cannot move out of here
 LL |         X { x: y } => println!("contents: {}", y)
-   |                -
-   |                |
-   |                data moved here
-   |                help: to prevent move, use ref or ref mut: `ref y`
+   |                - data moved here
+   |
+note: move occurs because `y` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/disallowed-deconstructing-destructing-struct-match.rs:25:16
+   |
+LL |         X { x: y } => println!("contents: {}", y)
+   |                ^
 
 error: aborting due to previous error
 
index cb6cc44a73597686f222eeb76d9fcbc3721f6d35..613b359c299b80238f2a9ab34803032d6147204e 100644 (file)
@@ -4,7 +4,7 @@ error[E0232]: `#[rustc_on_unimplemented]` requires a value
 LL | #[rustc_on_unimplemented]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^ value required here
    |
-   = note: eg `#[rustc_on_unimplemented = "foo"]`
+   = note: eg `#[rustc_on_unimplemented(message="foo")]`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0509.nll.stderr b/src/test/ui/error-codes/E0509.nll.stderr
new file mode 100644 (file)
index 0000000..723b083
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0509]: cannot move out of type `DropStruct`, which implements the `Drop` trait
+  --> $DIR/E0509.rs:26:23
+   |
+LL |     let fancy_field = drop_struct.fancy; //~ ERROR E0509
+   |                       ^^^^^^^^^^^^^^^^^
+   |                       |
+   |                       cannot move out of here
+   |                       help: consider borrowing here: `&drop_struct.fancy`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0509`.
index 830ec5959b7027e18476d98996c551ba8f1bfa7d..e667dab621bda6e1026e0a2c912ba2988bd7c43b 100644 (file)
@@ -11,5 +11,5 @@
 struct S;
 
 fn main() {
-    let _ = ::crate::S; //~ ERROR `crate` in paths is experimental
+    let _ = crate::S; //~ ERROR `crate` in paths is experimental
 }
index 1d0eed5319874ac938b1f88b270d91034bca8bd5..32115ba2111b57368efb15ca6315ac3e91cfa011 100644 (file)
@@ -1,8 +1,8 @@
 error[E0658]: `crate` in paths is experimental (see issue #45477)
-  --> $DIR/feature-gate-crate_in_paths.rs:14:15
+  --> $DIR/feature-gate-crate_in_paths.rs:14:13
    |
-LL |     let _ = ::crate::S; //~ ERROR `crate` in paths is experimental
-   |               ^^^^^
+LL |     let _ = crate::S; //~ ERROR `crate` in paths is experimental
+   |             ^^^^^
    |
    = help: add #![feature(crate_in_paths)] to the crate attributes to enable
 
diff --git a/src/test/ui/hashmap-lifetimes.nll.stderr b/src/test/ui/hashmap-lifetimes.nll.stderr
new file mode 100644 (file)
index 0000000..943b684
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0502]: cannot borrow `my_stuff` as mutable because it is also borrowed as immutable
+  --> $DIR/hashmap-lifetimes.rs:18:5
+   |
+LL |     let mut it = my_stuff.iter();
+   |                  -------- immutable borrow occurs here
+LL |     my_stuff.insert(1, 43); //~ ERROR cannot borrow
+   |     ^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
+LL |     it;
+   |     -- borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0502`.
index 9418c34cbfdaa2dc054683a1c4935930a8dbbda8..eb7404e7b780b9434594c845e515e016d42b5c42 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-compare-mode-nll
+
 
 fn main() {
     let mut my_stuff = std::collections::HashMap::new();
@@ -16,4 +16,5 @@ fn main() {
 
     let mut it = my_stuff.iter();
     my_stuff.insert(1, 43); //~ ERROR cannot borrow
+    it;
 }
index eb129848ed2d650abc8f423c2f58680333d84bca..187c98ab298b67e1513bde0228f05bde1fbd05f9 100644 (file)
@@ -5,6 +5,7 @@ LL |     let mut it = my_stuff.iter();
    |                  -------- immutable borrow occurs here
 LL |     my_stuff.insert(1, 43); //~ ERROR cannot borrow
    |     ^^^^^^^^ mutable borrow occurs here
+LL |     it;
 LL | }
    | - immutable borrow ends here
 
diff --git a/src/test/ui/issue-10636-1.rs b/src/test/ui/issue-10636-1.rs
new file mode 100644 (file)
index 0000000..fdd5077
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -Z parse-only
+
+struct Obj { //~ NOTE: unclosed delimiter
+    member: usize
+)
+//~^ ERROR incorrect close delimiter
+//~| NOTE incorrect close delimiter
+
+fn main() {}
diff --git a/src/test/ui/issue-10636-1.stderr b/src/test/ui/issue-10636-1.stderr
new file mode 100644 (file)
index 0000000..af80e25
--- /dev/null
@@ -0,0 +1,11 @@
+error: incorrect close delimiter: `)`
+  --> $DIR/issue-10636-1.rs:15:1
+   |
+LL | struct Obj { //~ NOTE: unclosed delimiter
+   |            - unclosed delimiter
+LL |     member: usize
+LL | )
+   | ^ incorrect close delimiter
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issue-51602.rs b/src/test/ui/issue-51602.rs
new file mode 100644 (file)
index 0000000..a3edecb
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main(){
+    if i in 1..10 {
+        break;
+    }
+}
diff --git a/src/test/ui/issue-51602.stderr b/src/test/ui/issue-51602.stderr
new file mode 100644 (file)
index 0000000..ac079b4
--- /dev/null
@@ -0,0 +1,10 @@
+error: expected `{`, found `in`
+  --> $DIR/issue-51602.rs:12:10
+   |
+LL |     if i in 1..10 {
+   |     --   ^^ expected `{`
+   |     |
+   |     this `if` statement has a condition, but no block
+
+error: aborting due to previous error
+
index 29bda252b9115f180495870e819928142669be9c..72d21d47d86fa765985da974e0b8b2664837d7fa 100644 (file)
@@ -8,15 +8,16 @@ LL |         (&[], &[hd, ..]) | (&[hd, ..], &[])
    |                 -- data moved here
 ...
 LL |         (&[hd1, ..], &[hd2, ..])
-   |                        --- ... and here
-help: to prevent move, use ref or ref mut
+   |                        --- ...and here
    |
-LL |         (&[], &[ref hd, ..]) | (&[hd, ..], &[])
-LL |             => println!("one empty"),
-LL |         //~^^ ERROR: cannot move out of type `[T]`, a non-copy slice
-LL |         //~^^^ ERROR: cannot move out of type `[T]`, a non-copy slice
-LL |         (&[hd1, ..], &[ref hd2, ..])
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/issue-12567.rs:16:17
    |
+LL |         (&[], &[hd, ..]) | (&[hd, ..], &[])
+   |                 ^^
+...
+LL |         (&[hd1, ..], &[hd2, ..])
+   |                        ^^^
 
 error[E0508]: cannot move out of type `[T]`, a non-copy slice
   --> $DIR/issue-12567.rs:14:11
@@ -28,15 +29,16 @@ LL |         (&[], &[hd, ..]) | (&[hd, ..], &[])
    |                 -- data moved here
 ...
 LL |         (&[hd1, ..], &[hd2, ..])
-   |            --- ... and here
-help: to prevent move, use ref or ref mut
+   |            --- ...and here
    |
-LL |         (&[], &[ref hd, ..]) | (&[hd, ..], &[])
-LL |             => println!("one empty"),
-LL |         //~^^ ERROR: cannot move out of type `[T]`, a non-copy slice
-LL |         //~^^^ ERROR: cannot move out of type `[T]`, a non-copy slice
-LL |         (&[ref hd1, ..], &[hd2, ..])
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/issue-12567.rs:16:17
    |
+LL |         (&[], &[hd, ..]) | (&[hd, ..], &[])
+   |                 ^^
+...
+LL |         (&[hd1, ..], &[hd2, ..])
+   |            ^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-17718-static-move.nll.stderr b/src/test/ui/issues/issue-17718-static-move.nll.stderr
new file mode 100644 (file)
index 0000000..f8da3c3
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0507]: cannot move out of static item
+  --> $DIR/issue-17718-static-move.rs:16:14
+   |
+LL |     let _a = FOO; //~ ERROR: cannot move out of static item
+   |              ^^^
+   |              |
+   |              cannot move out of static item
+   |              help: consider borrowing here: `&FOO`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
index fc94cc423c53138d3c35bcbbdfef22648835772e..3a6784eed67dd35d3adaaadb90b1bcd59d38ebc7 100644 (file)
@@ -5,7 +5,7 @@ LL |     let a = unsafe { *mut_ref() };
    |                      ^^^^^^^^^^
    |                      |
    |                      cannot move out of borrowed content
-   |                      help: consider using a reference instead: `&*mut_ref()`
+   |                      help: consider removing the `*`: `mut_ref()`
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/issue-20801.rs:39:22
@@ -14,7 +14,7 @@ LL |     let b = unsafe { *imm_ref() };
    |                      ^^^^^^^^^^
    |                      |
    |                      cannot move out of borrowed content
-   |                      help: consider using a reference instead: `&*imm_ref()`
+   |                      help: consider removing the `*`: `imm_ref()`
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/issue-20801.rs:42:22
@@ -23,7 +23,7 @@ LL |     let c = unsafe { *mut_ptr() };
    |                      ^^^^^^^^^^
    |                      |
    |                      cannot move out of borrowed content
-   |                      help: consider using a reference instead: `&*mut_ptr()`
+   |                      help: consider removing the `*`: `mut_ptr()`
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/issue-20801.rs:45:22
@@ -32,7 +32,7 @@ LL |     let d = unsafe { *const_ptr() };
    |                      ^^^^^^^^^^^^
    |                      |
    |                      cannot move out of borrowed content
-   |                      help: consider using a reference instead: `&*const_ptr()`
+   |                      help: consider removing the `*`: `const_ptr()`
 
 error: aborting due to 4 previous errors
 
index 162e43abc0ac47a0e915200ff2df12e647227194..9020d3778c3730820347651be4554a9b7d9c1f0b 100644 (file)
@@ -5,7 +5,7 @@ LL |     let e = f.v[0]; //~ ERROR cannot move out of indexed content
    |             ^^^^^^
    |             |
    |             cannot move out of borrowed content
-   |             help: consider using a reference instead: `&f.v[0]`
+   |             help: consider borrowing here: `&f.v[0]`
 
 error: aborting due to previous error
 
index cd75be24589dfbf443bd00671ba8dc3e43056891..a80e9a5fe091f70343247033078fb2881a09d61d 100644 (file)
@@ -5,9 +5,15 @@ LL |     let (a, b) = x[0]; //~ ERROR cannot move out of indexed content
    |          -  -    ^^^^
    |          |  |    |
    |          |  |    cannot move out of borrowed content
-   |          |  |    help: consider using a reference instead: `&x[0]`
-   |          |  move occurs because b has type `std::string::String`, which does not implement the `Copy` trait
-   |          move occurs because a has type `std::string::String`, which does not implement the `Copy` trait
+   |          |  |    help: consider borrowing here: `&x[0]`
+   |          |  ...and here
+   |          data moved here
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/issue-40402-2.rs:15:10
+   |
+LL |     let (a, b) = x[0]; //~ ERROR cannot move out of indexed content
+   |          ^  ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-53348.rs b/src/test/ui/issues/issue-53348.rs
new file mode 100644 (file)
index 0000000..46ab07d
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    let mut v = vec!["hello", "this", "is", "a", "test"];
+
+    let v2 = Vec::new();
+
+    v.into_iter().map(|s|s.to_owned()).collect::<Vec<_>>();
+
+    let mut a = String::new();
+    for i in v {
+        a = *i.to_string();
+        //~^ ERROR mismatched types
+        //~| NOTE expected struct `std::string::String`, found str
+        //~| NOTE expected type
+        v2.push(a);
+    }
+}
diff --git a/src/test/ui/issues/issue-53348.stderr b/src/test/ui/issues/issue-53348.stderr
new file mode 100644 (file)
index 0000000..9aab492
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-53348.rs:20:13
+   |
+LL |         a = *i.to_string();
+   |             ^^^^^^^^^^^^^^ expected struct `std::string::String`, found str
+   |
+   = note: expected type `std::string::String`
+              found type `str`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/macros/issue-30143.rs b/src/test/ui/macros/issue-30143.rs
new file mode 100644 (file)
index 0000000..b7fb5b3
--- /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.
+
+use std::fmt::Write;
+
+fn main() {
+    println!(0);
+    //~^ ERROR format argument must be a string literal
+    eprintln!('a');
+    //~^ ERROR format argument must be a string literal
+    let mut s = String::new();
+    writeln!(s, true).unwrap();
+    //~^ ERROR format argument must be a string literal
+}
diff --git a/src/test/ui/macros/issue-30143.stderr b/src/test/ui/macros/issue-30143.stderr
new file mode 100644 (file)
index 0000000..56834f6
--- /dev/null
@@ -0,0 +1,32 @@
+error: format argument must be a string literal
+  --> $DIR/issue-30143.rs:14:14
+   |
+LL |     println!(0);
+   |              ^
+help: you might be missing a string literal to format with
+   |
+LL |     println!("{}", 0);
+   |              ^^^^^
+
+error: format argument must be a string literal
+  --> $DIR/issue-30143.rs:16:15
+   |
+LL |     eprintln!('a');
+   |               ^^^
+help: you might be missing a string literal to format with
+   |
+LL |     eprintln!("{}", 'a');
+   |               ^^^^^
+
+error: format argument must be a string literal
+  --> $DIR/issue-30143.rs:19:17
+   |
+LL |     writeln!(s, true).unwrap();
+   |                 ^^^^
+help: you might be missing a string literal to format with
+   |
+LL |     writeln!(s, "{}", true).unwrap();
+   |                 ^^^^^
+
+error: aborting due to 3 previous errors
+
index a77b172487600fa30accb038d043a483d2b8fe98..111375b369363e9e2821f961da5e3c4d5dc8dd77 100644 (file)
@@ -8,5 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[doc = $not_there] //~ ERROR arbitrary tokens in non-macro attributes are unstable
+#![feature(unrestricted_attribute_tokens)]
+
+#[doc = $not_there] //~ ERROR expected `]`, found `not_there`
 fn main() { }
index 48132dddf1a42492773aea8a0f6804e41ddd178c..c403872ecb38581bb4c9bc6cf0d533a51997dd92 100644 (file)
@@ -1,11 +1,8 @@
-error[E0658]: arbitrary tokens in non-macro attributes are unstable (see issue #44690)
-  --> $DIR/macro-attribute.rs:11:1
+error: expected `]`, found `not_there`
+  --> $DIR/macro-attribute.rs:13:10
    |
-LL | #[doc = $not_there] //~ ERROR arbitrary tokens in non-macro attributes are unstable
-   | ^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add #![feature(unrestricted_attribute_tokens)] to the crate attributes to enable
+LL | #[doc = $not_there] //~ ERROR expected `]`, found `not_there`
+   |          ^^^^^^^^^ expected `]`
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0658`.
index 7290d18beb74e9388990b29fe87aaa62a6b25570..2815e1be70983377e45eaae934acb59da450eee7 100644 (file)
@@ -10,7 +10,6 @@
 
 // normalize-stderr-test: "The system cannot find the file specified\." -> "No such file or directory"
 // ignore-tidy-linelength
-// ignore-stage1
 
 // test that errors in a (selection) of macros don't kill compilation
 // immediately, so that we get more errors listed at a time.
index efb2c248813d7bd13237b65eaacb8aa43d8d0bbc..084042acc974d698f5655013cec24e281707ce81 100644 (file)
@@ -1,47 +1,47 @@
 error[E0665]: `Default` cannot be derived for enums, only structs
-  --> $DIR/macros-nonfatal-errors.rs:21:10
+  --> $DIR/macros-nonfatal-errors.rs:20:10
    |
 LL | #[derive(Default)] //~ ERROR
    |          ^^^^^^^
 
 error: inline assembly must be a string literal
-  --> $DIR/macros-nonfatal-errors.rs:25:10
+  --> $DIR/macros-nonfatal-errors.rs:24:10
    |
 LL |     asm!(invalid); //~ ERROR
    |          ^^^^^^^
 
 error: concat_idents! requires ident args.
-  --> $DIR/macros-nonfatal-errors.rs:27:5
+  --> $DIR/macros-nonfatal-errors.rs:26:5
    |
 LL |     concat_idents!("not", "idents"); //~ ERROR
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: argument must be a string literal
-  --> $DIR/macros-nonfatal-errors.rs:29:17
+  --> $DIR/macros-nonfatal-errors.rs:28:17
    |
 LL |     option_env!(invalid); //~ ERROR
    |                 ^^^^^^^
 
 error: expected string literal
-  --> $DIR/macros-nonfatal-errors.rs:30:10
+  --> $DIR/macros-nonfatal-errors.rs:29:10
    |
 LL |     env!(invalid); //~ ERROR
    |          ^^^^^^^
 
 error: expected string literal
-  --> $DIR/macros-nonfatal-errors.rs:31:10
+  --> $DIR/macros-nonfatal-errors.rs:30:10
    |
 LL |     env!(foo, abr, baz); //~ ERROR
    |          ^^^
 
 error: environment variable `RUST_HOPEFULLY_THIS_DOESNT_EXIST` not defined
-  --> $DIR/macros-nonfatal-errors.rs:32:5
+  --> $DIR/macros-nonfatal-errors.rs:31:5
    |
 LL |     env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST"); //~ ERROR
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0658]: non-ident macro paths are experimental (see issue #35896)
-  --> $DIR/macros-nonfatal-errors.rs:34:5
+  --> $DIR/macros-nonfatal-errors.rs:33:5
    |
 LL |     foo::blah!(); //~ ERROR
    |     ^^^^^^^^^
@@ -49,7 +49,7 @@ LL |     foo::blah!(); //~ ERROR
    = help: add #![feature(use_extern_macros)] to the crate attributes to enable
 
 error: format argument must be a string literal
-  --> $DIR/macros-nonfatal-errors.rs:36:13
+  --> $DIR/macros-nonfatal-errors.rs:35:13
    |
 LL |     format!(invalid); //~ ERROR
    |             ^^^^^^^
@@ -59,37 +59,37 @@ LL |     format!("{}", invalid); //~ ERROR
    |             ^^^^^
 
 error: argument must be a string literal
-  --> $DIR/macros-nonfatal-errors.rs:38:14
+  --> $DIR/macros-nonfatal-errors.rs:37:14
    |
 LL |     include!(invalid); //~ ERROR
    |              ^^^^^^^
 
 error: argument must be a string literal
-  --> $DIR/macros-nonfatal-errors.rs:40:18
+  --> $DIR/macros-nonfatal-errors.rs:39:18
    |
 LL |     include_str!(invalid); //~ ERROR
    |                  ^^^^^^^
 
 error: couldn't read $DIR/i'd be quite surprised if a file with this name existed: No such file or directory (os error 2)
-  --> $DIR/macros-nonfatal-errors.rs:41:5
+  --> $DIR/macros-nonfatal-errors.rs:40:5
    |
 LL |     include_str!("i'd be quite surprised if a file with this name existed"); //~ ERROR
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: argument must be a string literal
-  --> $DIR/macros-nonfatal-errors.rs:42:20
+  --> $DIR/macros-nonfatal-errors.rs:41:20
    |
 LL |     include_bytes!(invalid); //~ ERROR
    |                    ^^^^^^^
 
 error: couldn't read $DIR/i'd be quite surprised if a file with this name existed: No such file or directory (os error 2)
-  --> $DIR/macros-nonfatal-errors.rs:43:5
+  --> $DIR/macros-nonfatal-errors.rs:42:5
    |
 LL |     include_bytes!("i'd be quite surprised if a file with this name existed"); //~ ERROR
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: trace_macros! accepts only `true` or `false`
-  --> $DIR/macros-nonfatal-errors.rs:45:5
+  --> $DIR/macros-nonfatal-errors.rs:44:5
    |
 LL |     trace_macros!(invalid); //~ ERROR
    |     ^^^^^^^^^^^^^^^^^^^^^^^
index b061b6a7963859daed322b322498da6a7c3dd45c..aa62b457ecdf378cef6c96e4a6256aa36293a886 100644 (file)
@@ -4,10 +4,13 @@ error[E0508]: cannot move out of type `[A]`, a non-copy slice
 LL |     match a {
    |           ^ cannot move out of here
 LL |         box [a] => {}, //~ ERROR cannot move out of type `[A]`, a non-copy slice
-   |              -
-   |              |
-   |              data moved here
-   |              help: to prevent move, use ref or ref mut: `ref a`
+   |              - data moved here
+   |
+note: move occurs because `a` has type `A`, which does not implement the `Copy` trait
+  --> $DIR/move-out-of-slice-1.rs:18:14
+   |
+LL |         box [a] => {}, //~ ERROR cannot move out of type `[A]`, a non-copy slice
+   |              ^
 
 error: aborting due to previous error
 
index 94f2074b45d4c0a444f38b6606876e5eefdb3097..1f22ab148185296bbf3ca71abe0a75ca06630a3d 100644 (file)
@@ -5,10 +5,16 @@ LL |             match hellothere.x { //~ ERROR cannot move out
    |                   ^^^^^^^^^^^^
    |                   |
    |                   cannot move out of borrowed content
-   |                   help: consider using a reference instead: `&hellothere.x`
+   |                   help: consider borrowing here: `&hellothere.x`
 ...
 LL |                 box E::Bar(x) => println!("{}", x.to_string()),
-   |                            - move occurs because x has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+   |                            - data moved here
+   |
+note: move occurs because `x` has type `std::boxed::Box<isize>`, which does not implement the `Copy` trait
+  --> $DIR/moves-based-on-type-block-bad.rs:37:28
+   |
+LL |                 box E::Bar(x) => println!("{}", x.to_string()),
+   |                            ^
 
 error: aborting due to previous error
 
index 814e11b6f0682f5feccb0a49fce9885b48d65dbd..6a4c8f2e8d81570161b7d251523acb9c6483235f 100644 (file)
@@ -5,7 +5,7 @@ LL |     let x = { *r }; //~ ERROR
    |               ^^
    |               |
    |               cannot move out of borrowed content
-   |               help: consider removing this dereference operator: `r`
+   |               help: consider removing the `*`: `r`
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/cannot-move-block-spans.rs:16:22
@@ -14,7 +14,7 @@ LL |     let y = unsafe { *r }; //~ ERROR
    |                      ^^
    |                      |
    |                      cannot move out of borrowed content
-   |                      help: consider removing this dereference operator: `r`
+   |                      help: consider removing the `*`: `r`
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/cannot-move-block-spans.rs:17:26
@@ -23,7 +23,7 @@ LL |     let z = loop { break *r; }; //~ ERROR
    |                          ^^
    |                          |
    |                          cannot move out of borrowed content
-   |                          help: consider removing this dereference operator: `r`
+   |                          help: consider removing the `*`: `r`
 
 error[E0508]: cannot move out of type `[std::string::String; 2]`, a non-copy array
   --> $DIR/cannot-move-block-spans.rs:21:15
@@ -32,7 +32,7 @@ LL |     let x = { arr[0] }; //~ ERROR
    |               ^^^^^^
    |               |
    |               cannot move out of here
-   |               help: consider using a reference instead: `&arr[0]`
+   |               help: consider borrowing here: `&arr[0]`
 
 error[E0508]: cannot move out of type `[std::string::String; 2]`, a non-copy array
   --> $DIR/cannot-move-block-spans.rs:22:22
@@ -41,7 +41,7 @@ LL |     let y = unsafe { arr[0] }; //~ ERROR
    |                      ^^^^^^
    |                      |
    |                      cannot move out of here
-   |                      help: consider using a reference instead: `&arr[0]`
+   |                      help: consider borrowing here: `&arr[0]`
 
 error[E0508]: cannot move out of type `[std::string::String; 2]`, a non-copy array
   --> $DIR/cannot-move-block-spans.rs:23:26
@@ -50,7 +50,7 @@ LL |     let z = loop { break arr[0]; }; //~ ERROR
    |                          ^^^^^^
    |                          |
    |                          cannot move out of here
-   |                          help: consider using a reference instead: `&arr[0]`
+   |                          help: consider borrowing here: `&arr[0]`
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/cannot-move-block-spans.rs:27:38
@@ -59,7 +59,7 @@ LL |     let x = { let mut u = 0; u += 1; *r }; //~ ERROR
    |                                      ^^
    |                                      |
    |                                      cannot move out of borrowed content
-   |                                      help: consider removing this dereference operator: `r`
+   |                                      help: consider removing the `*`: `r`
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/cannot-move-block-spans.rs:28:45
@@ -68,7 +68,7 @@ LL |     let y = unsafe { let mut u = 0; u += 1; *r }; //~ ERROR
    |                                             ^^
    |                                             |
    |                                             cannot move out of borrowed content
-   |                                             help: consider removing this dereference operator: `r`
+   |                                             help: consider removing the `*`: `r`
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/cannot-move-block-spans.rs:29:49
@@ -77,7 +77,7 @@ LL |     let z = loop { let mut u = 0; u += 1; break *r; u += 2; }; //~ ERROR
    |                                                 ^^
    |                                                 |
    |                                                 cannot move out of borrowed content
-   |                                                 help: consider removing this dereference operator: `r`
+   |                                                 help: consider removing the `*`: `r`
 
 error: aborting due to 9 previous errors
 
diff --git a/src/test/ui/nll/issue-27868.rs b/src/test/ui/nll/issue-27868.rs
new file mode 100644 (file)
index 0000000..022917a
--- /dev/null
@@ -0,0 +1,40 @@
+// 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.
+
+// Regression test for issue #27868
+
+#![feature(nll)]
+
+use std::ops::AddAssign;
+
+struct MyVec<T>(Vec<T>);
+
+impl <T> Drop for MyVec<T> {
+    fn drop(&mut self) {
+        println!("Being dropped.");
+    }
+}
+
+impl<T> AddAssign<T> for MyVec<T> {
+    fn add_assign(&mut self, _elem: T) {
+        println!("In add_assign.");
+    }
+}
+
+fn main() {
+    let mut vec = MyVec(vec![0]);
+    let mut vecvec = vec![vec];
+
+    vecvec[0] += {
+        vecvec = vec![];
+        //~^ ERROR cannot assign to `vecvec` because it is borrowed [E0506]
+        0
+    };
+}
diff --git a/src/test/ui/nll/issue-27868.stderr b/src/test/ui/nll/issue-27868.stderr
new file mode 100644 (file)
index 0000000..a376829
--- /dev/null
@@ -0,0 +1,18 @@
+error[E0506]: cannot assign to `vecvec` because it is borrowed
+  --> $DIR/issue-27868.rs:36:9
+   |
+LL |       vecvec[0] += {
+   |       ------
+   |       |
+   |  _____borrow of `vecvec` occurs here
+   | |
+LL | |         vecvec = vec![];
+   | |         ^^^^^^ assignment to borrowed `vecvec` occurs here
+LL | |         //~^ ERROR cannot assign to `vecvec` because it is borrowed [E0506]
+LL | |         0
+LL | |     };
+   | |_____- borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/nll/issue-30104.rs b/src/test/ui/nll/issue-30104.rs
new file mode 100644 (file)
index 0000000..64c32a5
--- /dev/null
@@ -0,0 +1,52 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Regression test for #30104
+
+// compile-pass
+
+#![feature(nll)]
+
+use std::ops::{Deref, DerefMut};
+
+fn box_two_field(v: &mut Box<(i32, i32)>) {
+    let _a = &mut v.0;
+    let _b = &mut v.1;
+}
+
+fn box_destructure(v: &mut Box<(i32, i32)>) {
+    let (ref mut _head, ref mut _tail) = **v;
+}
+
+struct Wrap<T>(T);
+
+impl<T> Deref for Wrap<T> {
+    type Target = T;
+    fn deref(&self) -> &T {
+        &self.0
+    }
+}
+
+impl<T> DerefMut for Wrap<T> {
+    fn deref_mut(&mut self) -> &mut T {
+        &mut self.0
+    }
+}
+
+fn smart_two_field(v: &mut Wrap<(i32, i32)>) {
+    let _a = &mut v.0;
+    let _b = &mut v.1;
+}
+
+fn smart_destructure(v: &mut Wrap<(i32, i32)>) {
+    let (ref mut _head, ref mut _tail) = **v;
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/issue-48697.rs b/src/test/ui/nll/issue-48697.rs
new file mode 100644 (file)
index 0000000..69ff82e
--- /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.
+
+// Regression test for #48697
+
+// compile-pass
+
+#![feature(nll)]
+
+fn foo(x: &i32) -> &i32 {
+    let z = 4;
+    let f = &|y| y;
+    let k = f(&z);
+    f(x)
+}
+
+fn main() {}
index 53d60d3f6d649a4b4ec0b3d9efbc1dc8c14f4ba7..592768363096cae2d0d60a37ee35a0eefb81d24b 100644 (file)
@@ -5,7 +5,7 @@ LL |     let b = *a;
    |             ^^
    |             |
    |             cannot move out of borrowed content
-   |             help: consider removing this dereference operator: `a`
+   |             help: consider removing the `*`: `a`
 
 error[E0508]: cannot move out of type `[A; 1]`, a non-copy array
   --> $DIR/move-errors.rs:25:13
@@ -14,7 +14,7 @@ LL |     let b = a[0];
    |             ^^^^
    |             |
    |             cannot move out of here
-   |             help: consider using a reference instead: `&a[0]`
+   |             help: consider borrowing here: `&a[0]`
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/move-errors.rs:32:13
@@ -23,7 +23,7 @@ LL |     let s = **r;
    |             ^^^
    |             |
    |             cannot move out of borrowed content
-   |             help: consider using a reference instead: `&**r`
+   |             help: consider removing the `*`: `*r`
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/move-errors.rs:40:13
@@ -32,7 +32,7 @@ LL |     let s = *r;
    |             ^^
    |             |
    |             cannot move out of borrowed content
-   |             help: consider using a reference instead: `&*r`
+   |             help: consider removing the `*`: `r`
 
 error[E0508]: cannot move out of type `[A; 1]`, a non-copy array
   --> $DIR/move-errors.rs:45:13
@@ -41,7 +41,7 @@ LL |     let a = [A("".to_string())][0];
    |             ^^^^^^^^^^^^^^^^^^^^^^
    |             |
    |             cannot move out of here
-   |             help: consider using a reference instead: `&[A("".to_string())][0]`
+   |             help: consider borrowing here: `&[A("".to_string())][0]`
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/move-errors.rs:51:16
@@ -50,8 +50,14 @@ LL |     let A(s) = *a;
    |           -    ^^
    |           |    |
    |           |    cannot move out of borrowed content
-   |           |    help: consider removing this dereference operator: `a`
-   |           move occurs because s has type `std::string::String`, which does not implement the `Copy` trait
+   |           |    help: consider removing the `*`: `a`
+   |           data moved here
+   |
+note: move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/move-errors.rs:51:11
+   |
+LL |     let A(s) = *a;
+   |           ^
 
 error[E0509]: cannot move out of type `D`, which implements the `Drop` trait
   --> $DIR/move-errors.rs:57:19
@@ -60,7 +66,12 @@ LL |     let C(D(s)) = c;
    |             -     ^ cannot move out of here
    |             |
    |             data moved here
-   |             help: to prevent move, use ref or ref mut: `ref s`
+   |
+note: move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/move-errors.rs:57:13
+   |
+LL |     let C(D(s)) = c;
+   |             ^
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/move-errors.rs:64:9
@@ -75,12 +86,20 @@ LL |     match x[0] {
    |           ^^^^
    |           |
    |           cannot move out of here
-   |           help: consider using a reference instead: `&x[0]`
+   |           help: consider borrowing here: `&x[0]`
 LL |     //~^ ERROR
 LL |         B::U(d) => (),
-   |              - move occurs because d has type `D`, which does not implement the `Copy` trait
+   |              - data moved here
 LL |         B::V(s) => (),
-   |              - move occurs because s has type `std::string::String`, which does not implement the `Copy` trait
+   |              - ...and here
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/move-errors.rs:89:14
+   |
+LL |         B::U(d) => (),
+   |              ^
+LL |         B::V(s) => (),
+   |              ^
 
 error[E0509]: cannot move out of type `D`, which implements the `Drop` trait
   --> $DIR/move-errors.rs:96:11
@@ -89,10 +108,13 @@ LL |     match x {
    |           ^ cannot move out of here
 ...
 LL |         B::U(D(s)) => (),
-   |                -
-   |                |
-   |                data moved here
-   |                help: to prevent move, use ref or ref mut: `ref s`
+   |                - data moved here
+   |
+note: move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/move-errors.rs:99:16
+   |
+LL |         B::U(D(s)) => (),
+   |                ^
 
 error[E0509]: cannot move out of type `D`, which implements the `Drop` trait
   --> $DIR/move-errors.rs:105:11
@@ -101,10 +123,13 @@ LL |     match x {
    |           ^ cannot move out of here
 ...
 LL |         (D(s), &t) => (),
-   |            -
-   |            |
-   |            data moved here
-   |            help: to prevent move, use ref or ref mut: `ref s`
+   |            - data moved here
+   |
+note: move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/move-errors.rs:108:12
+   |
+LL |         (D(s), &t) => (),
+   |            ^
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/move-errors.rs:105:11
@@ -113,10 +138,13 @@ LL |     match x {
    |           ^ cannot move out of borrowed content
 ...
 LL |         (D(s), &t) => (),
-   |                 -
-   |                 |
-   |                 data moved here
-   |                 help: to prevent move, use ref or ref mut: `ref t`
+   |                 - data moved here
+   |
+note: move occurs because `t` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/move-errors.rs:108:17
+   |
+LL |         (D(s), &t) => (),
+   |                 ^
 
 error[E0509]: cannot move out of type `F`, which implements the `Drop` trait
   --> $DIR/move-errors.rs:115:11
@@ -125,13 +153,15 @@ LL |     match x {
    |           ^ cannot move out of here
 LL |     //~^ ERROR
 LL |         F(s, mut t) => (),
-   |           -  ----- ... and here
+   |           -  ----- ...and here
    |           |
    |           data moved here
-help: to prevent move, use ref or ref mut
    |
-LL |         F(ref s, ref mut t) => (),
-   |           ^^^^^  ^^^^^^^^^
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/move-errors.rs:117:11
+   |
+LL |         F(s, mut t) => (),
+   |           ^  ^^^^^
 
 error[E0507]: cannot move out of borrowed content
   --> $DIR/move-errors.rs:123:11
@@ -140,10 +170,16 @@ LL |     match *x {
    |           ^^
    |           |
    |           cannot move out of borrowed content
-   |           help: consider removing this dereference operator: `x`
+   |           help: consider removing the `*`: `x`
 LL |     //~^ ERROR
 LL |         Ok(s) | Err(s) => (),
-   |            - move occurs because s has type `std::string::String`, which does not implement the `Copy` trait
+   |            - data moved here
+   |
+note: move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait
+  --> $DIR/move-errors.rs:125:12
+   |
+LL |         Ok(s) | Err(s) => (),
+   |            ^
 
 error: aborting due to 14 previous errors
 
index 7ef155e5f2ebece26ddc962389863f4f1bc7d023..286c71bb2990847078ba45170003511a9958ae17 100644 (file)
@@ -28,7 +28,7 @@ trait BadAnnotation1
 {}
 
 #[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{C}>`"]
-//~^ ERROR there is no parameter C on trait BadAnnotation2
+//~^ ERROR there is no parameter `C` on trait `BadAnnotation2`
 trait BadAnnotation2<A,B>
 {}
 
index 1c5d4d603afc662d6cae88914ec8a29104a74eb9..212eb125f85b386e715b6c59c1b31df7b2f131c0 100644 (file)
@@ -4,9 +4,9 @@ error[E0232]: `#[rustc_on_unimplemented]` requires a value
 LL | #[rustc_on_unimplemented] //~ ERROR `#[rustc_on_unimplemented]` requires a value
    | ^^^^^^^^^^^^^^^^^^^^^^^^^ value required here
    |
-   = note: eg `#[rustc_on_unimplemented = "foo"]`
+   = note: eg `#[rustc_on_unimplemented(message="foo")]`
 
-error[E0230]: there is no parameter C on trait BadAnnotation2
+error[E0230]: there is no parameter `C` on trait `BadAnnotation2`
   --> $DIR/bad-annotation.rs:30:1
    |
 LL | #[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{C}>`"]
@@ -24,7 +24,7 @@ error[E0232]: this attribute must have a valid value
 LL | #[rustc_on_unimplemented(lorem="")]
    |                          ^^^^^^^^ expected value here
    |
-   = note: eg `#[rustc_on_unimplemented = "foo"]`
+   = note: eg `#[rustc_on_unimplemented(message="foo")]`
 
 error[E0232]: this attribute must have a valid value
   --> $DIR/bad-annotation.rs:44:26
@@ -32,7 +32,7 @@ error[E0232]: this attribute must have a valid value
 LL | #[rustc_on_unimplemented(lorem(ipsum(dolor)))]
    |                          ^^^^^^^^^^^^^^^^^^^ expected value here
    |
-   = note: eg `#[rustc_on_unimplemented = "foo"]`
+   = note: eg `#[rustc_on_unimplemented(message="foo")]`
 
 error[E0232]: this attribute must have a valid value
   --> $DIR/bad-annotation.rs:48:39
@@ -40,7 +40,7 @@ error[E0232]: this attribute must have a valid value
 LL | #[rustc_on_unimplemented(message="x", message="y")]
    |                                       ^^^^^^^^^^^ expected value here
    |
-   = note: eg `#[rustc_on_unimplemented = "foo"]`
+   = note: eg `#[rustc_on_unimplemented(message="foo")]`
 
 error[E0232]: this attribute must have a valid value
   --> $DIR/bad-annotation.rs:52:39
@@ -48,7 +48,7 @@ error[E0232]: this attribute must have a valid value
 LL | #[rustc_on_unimplemented(message="x", on(desugared, message="y"))]
    |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected value here
    |
-   = note: eg `#[rustc_on_unimplemented = "foo"]`
+   = note: eg `#[rustc_on_unimplemented(message="foo")]`
 
 error[E0232]: empty `on`-clause in `#[rustc_on_unimplemented]`
   --> $DIR/bad-annotation.rs:56:26
@@ -62,7 +62,7 @@ error[E0232]: this attribute must have a valid value
 LL | #[rustc_on_unimplemented(on="x", message="y")]
    |                          ^^^^^^ expected value here
    |
-   = note: eg `#[rustc_on_unimplemented = "foo"]`
+   = note: eg `#[rustc_on_unimplemented(message="foo")]`
 
 error[E0232]: this attribute must have a valid value
   --> $DIR/bad-annotation.rs:67:40
@@ -70,7 +70,7 @@ error[E0232]: this attribute must have a valid value
 LL | #[rustc_on_unimplemented(on(desugared, on(desugared, message="x")), message="y")]
    |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected value here
    |
-   = note: eg `#[rustc_on_unimplemented = "foo"]`
+   = note: eg `#[rustc_on_unimplemented(message="foo")]`
 
 error: aborting due to 10 previous errors
 
index 7b5206073522f8ddb7b7fa3d059c1b7e36e92c08..1025dad3af7738c8675e18374b77baebbe770f8b 100644 (file)
@@ -1,14 +1,11 @@
 error: incorrect close delimiter: `)`
   --> $DIR/parser-recovery-2.rs:18:5
    |
-LL |     ) //~ ERROR incorrect close delimiter: `)`
-   |     ^
-   |
-note: unclosed delimiter
-  --> $DIR/parser-recovery-2.rs:16:14
-   |
 LL |     fn bar() {
-   |              ^
+   |              - unclosed delimiter
+LL |         let x = foo(); //~ ERROR cannot find function `foo` in this scope
+LL |     ) //~ ERROR incorrect close delimiter: `)`
+   |     ^ incorrect close delimiter
 
 error: unexpected token: `;`
   --> $DIR/parser-recovery-2.rs:22:15
index 7abc1ba47810bf5476a2539031ffefc83d569e06..fcd4b4888b0ad66f5863df0041cb92e3f564de0f 100644 (file)
@@ -1,14 +1,11 @@
 error: incorrect close delimiter: `)`
   --> $DIR/token-error-correct-2.rs:16:5
    |
-LL |     ) //~ ERROR: incorrect close delimiter: `)`
-   |     ^
-   |
-note: unclosed delimiter
-  --> $DIR/token-error-correct-2.rs:14:12
-   |
 LL |     if foo {
-   |            ^
+   |            - unclosed delimiter
+LL |     //~^ ERROR: cannot find value `foo`
+LL |     ) //~ ERROR: incorrect close delimiter: `)`
+   |     ^ incorrect close delimiter
 
 error[E0425]: cannot find value `foo` in this scope
   --> $DIR/token-error-correct-2.rs:14:8
index 24186d94acce966c087ce5c3d65b41709d55a3de..a546c2704d9154d80ccae25d44c2f2077cb1d8c5 100644 (file)
@@ -1,14 +1,11 @@
 error: incorrect close delimiter: `}`
   --> $DIR/token-error-correct-3.rs:30:9
    |
-LL |         } else { //~ ERROR: incorrect close delimiter: `}`
-   |         ^
-   |
-note: unclosed delimiter
-  --> $DIR/token-error-correct-3.rs:24:21
-   |
 LL |             callback(path.as_ref(); //~ ERROR expected one of
-   |                     ^
+   |                     - unclosed delimiter
+...
+LL |         } else { //~ ERROR: incorrect close delimiter: `}`
+   |         ^ incorrect close delimiter
 
 error: expected one of `)`, `,`, `.`, `?`, or an operator, found `;`
   --> $DIR/token-error-correct-3.rs:24:35
index c88f823839dad4db40b3290d35645ad8f0b4def0..39c664e270c4515c62d7e5953a917fd46d6932cb 100644 (file)
@@ -15,4 +15,3 @@ fn main() {
     //~^ ERROR: expected expression, found `;`
 }
 //~^ ERROR: incorrect close delimiter: `}`
-//~| ERROR: incorrect close delimiter: `}`
index c6d32c6726ea576e13b881b552f52267adc5b05c..1e246b6f085bd66dbe6b2c40a97df77e169e0bac 100644 (file)
@@ -1,26 +1,11 @@
 error: incorrect close delimiter: `}`
   --> $DIR/token-error-correct.rs:16:1
    |
-LL | }
-   | ^
-   |
-note: unclosed delimiter
-  --> $DIR/token-error-correct.rs:14:12
-   |
 LL |     foo(bar(;
-   |            ^
-
-error: incorrect close delimiter: `}`
-  --> $DIR/token-error-correct.rs:16:1
-   |
+   |            - unclosed delimiter
+LL |     //~^ ERROR: expected expression, found `;`
 LL | }
-   | ^
-   |
-note: unclosed delimiter
-  --> $DIR/token-error-correct.rs:14:8
-   |
-LL |     foo(bar(;
-   |        ^
+   | ^ incorrect close delimiter
 
 error: expected expression, found `;`
   --> $DIR/token-error-correct.rs:14:13
@@ -28,5 +13,5 @@ error: expected expression, found `;`
 LL |     foo(bar(;
    |             ^ expected expression
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
index 65f11c063ed2e3302b04d3c7b0e4c4bee0f96ba4..a44ca9d2d25c986a7acba0e44199878406e6bc38 100644 (file)
@@ -15,6 +15,7 @@
 pub mod m {
     fn f() {
         let s = ::m::crate::S; //~ ERROR failed to resolve
+        let s1 = ::crate::S; //~ ERROR failed to resolve
         let s2 = crate::S; // no error
     }
 }
index f4d33e0b9db2f973e2fe0da61cde91cdda904b37..f16c84960776663322ea5620e8aa699358a0ca4e 100644 (file)
@@ -1,9 +1,15 @@
-error[E0433]: failed to resolve. Could not find `crate` in `m`
+error[E0433]: failed to resolve. `crate` in paths can only be used in start position
   --> $DIR/crate-path-non-absolute.rs:17:22
    |
 LL |         let s = ::m::crate::S; //~ ERROR failed to resolve
-   |                      ^^^^^ Could not find `crate` in `m`
+   |                      ^^^^^ `crate` in paths can only be used in start position
 
-error: aborting due to previous error
+error[E0433]: failed to resolve. global paths cannot start with `crate`
+  --> $DIR/crate-path-non-absolute.rs:18:20
+   |
+LL |         let s1 = ::crate::S; //~ ERROR failed to resolve
+   |                    ^^^^^ global paths cannot start with `crate`
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0433`.
index bdd03be4356c9391d97f4a6f5c7ad58b9c13a447..3ebb3a25d8d3551c46d6591f17157a660e15f7a0 100644 (file)
@@ -11,5 +11,6 @@
 #![feature(crate_in_paths)]
 
 fn main() {
-    let crate = 0; //~ ERROR failed to resolve. `crate` in paths can only be used in start position
+    let crate = 0;
+    //~^ ERROR expected unit struct/variant or constant, found module `crate`
 }
index e4d2db057f272929f9fc5f2da18417e16481dfe4..ec44fb4db0090e99c5e99e5fc36d234b29fcc3f0 100644 (file)
@@ -1,9 +1,9 @@
-error[E0433]: failed to resolve. `crate` in paths can only be used in start position
+error[E0532]: expected unit struct/variant or constant, found module `crate`
   --> $DIR/keyword-crate-as-identifier.rs:14:9
    |
-LL |     let crate = 0; //~ ERROR failed to resolve. `crate` in paths can only be used in start position
-   |         ^^^^^ `crate` in paths can only be used in start position
+LL |     let crate = 0;
+   |         ^^^^^ not a unit struct/variant or constant
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0433`.
+For more information about this error, try `rustc --explain E0532`.
index e71166ed65bba4ec9bbb6030dc8ab481a6a468e6..a6dbb03d379db532db316179d640a98ee089b0ab 100644 (file)
@@ -9,10 +9,11 @@
 // except according to those terms.
 
 #![feature(generic_associated_types)]
+//~^ WARNING the feature `generic_associated_types` is incomplete
 #![feature(associated_type_defaults)]
 
-//FIXME(#44265): "lifetime parameters are not allowed on this type" errors will be addressed in a
-//follow-up PR
+// FIXME(#44265): "lifetime parameters are not allowed on this type" errors will be addressed in a
+// follow-up PR.
 
 // A Collection trait and collection families. Based on
 // http://smallcultfollowing.com/babysteps/blog/2016/11/03/
index 8c31ab2ca88e4d71a88dda2c6d1b759b1c3444d0..0e7d6ace1bb1d0560a1dabffcdc871f87d1748a4 100644 (file)
@@ -1,29 +1,35 @@
+warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
+  --> $DIR/collections.rs:11:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+
 error[E0109]: type parameters are not allowed on this type
-  --> $DIR/collections.rs:65:90
+  --> $DIR/collections.rs:66:90
    |
 LL | fn floatify<C>(ints: &C) -> <<C as Collection<i32>>::Family as CollectionFamily>::Member<f32>
    |                                                                                          ^^^ type parameter not allowed
 
 error[E0109]: type parameters are not allowed on this type
-  --> $DIR/collections.rs:77:69
+  --> $DIR/collections.rs:78:69
    |
 LL | fn floatify_sibling<C>(ints: &C) -> <C as Collection<i32>>::Sibling<f32>
    |                                                                     ^^^ type parameter not allowed
 
 error[E0109]: type parameters are not allowed on this type
-  --> $DIR/collections.rs:26:71
+  --> $DIR/collections.rs:27:71
    |
 LL |         <<Self as Collection<T>>::Family as CollectionFamily>::Member<U>;
    |                                                                       ^ type parameter not allowed
 
 error[E0110]: lifetime parameters are not allowed on this type
-  --> $DIR/collections.rs:33:50
+  --> $DIR/collections.rs:34:50
    |
 LL |     fn iterate<'iter>(&'iter self) -> Self::Iter<'iter>;
    |                                                  ^^^^^ lifetime parameter not allowed
 
 error[E0110]: lifetime parameters are not allowed on this type
-  --> $DIR/collections.rs:59:50
+  --> $DIR/collections.rs:60:50
    |
 LL |     fn iterate<'iter>(&'iter self) -> Self::Iter<'iter> {
    |                                                  ^^^^^ lifetime parameter not allowed
index 04294100315264ec5f1a26bb3a6834da7e86500b..88a660b3a5afe51d16028566a03b1423362a334a 100644 (file)
@@ -9,11 +9,12 @@
 // except according to those terms.
 
 #![feature(generic_associated_types)]
+//~^ WARNING the feature `generic_associated_types` is incomplete
 
 use std::ops::Deref;
 
-//FIXME(#44265): "lifetime parameters are not allowed on this type" errors will be addressed in a
-//follow-up PR
+// FIXME(#44265): "lifetime parameters are not allowed on this type" errors will be addressed in a
+// follow-up PR.
 
 trait Foo {
     type Bar<'a, 'b>;
index 1746122eb49f41d68b726acf25b086e6cda7e555..5c85698fa55c702e796c282b90c61418e26aa151 100644 (file)
@@ -1,17 +1,23 @@
+warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
+  --> $DIR/construct_with_other_type.rs:11:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+
 error[E0110]: lifetime parameters are not allowed on this type
-  --> $DIR/construct_with_other_type.rs:26:46
+  --> $DIR/construct_with_other_type.rs:27:46
    |
 LL |     type Baa<'a>: Deref<Target = <Self::Quux<'a> as Foo>::Bar<'a, 'static>>;
    |                                              ^^ lifetime parameter not allowed
 
 error[E0110]: lifetime parameters are not allowed on this type
-  --> $DIR/construct_with_other_type.rs:26:63
+  --> $DIR/construct_with_other_type.rs:27:63
    |
 LL |     type Baa<'a>: Deref<Target = <Self::Quux<'a> as Foo>::Bar<'a, 'static>>;
    |                                                               ^^ lifetime parameter not allowed
 
 error[E0110]: lifetime parameters are not allowed on this type
-  --> $DIR/construct_with_other_type.rs:34:40
+  --> $DIR/construct_with_other_type.rs:35:40
    |
 LL |     type Baa<'a> = &'a <T as Foo>::Bar<'a, 'static>;
    |                                        ^^ lifetime parameter not allowed
index b12c075d1329178ca5f797339919262b8543ddc4..d8a2a1b73f7ef084078e2728c3467c9a431114c9 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![feature(generic_associated_types)]
+//~^ WARNING the feature `generic_associated_types` is incomplete
 
 trait Foo {
     type Bar<,>;
index aff3044e9a14dc753341557ba1693ef4e876622e..2670c3aa142b204be287aa319e7a778505337c2b 100644 (file)
@@ -1,8 +1,14 @@
 error: expected one of `>`, identifier, or lifetime, found `,`
-  --> $DIR/empty_generics.rs:14:14
+  --> $DIR/empty_generics.rs:15:14
    |
 LL |     type Bar<,>;
    |              ^ expected one of `>`, identifier, or lifetime here
 
+warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
+  --> $DIR/empty_generics.rs:11:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+
 error: aborting due to previous error
 
diff --git a/src/test/ui/rfc1598-generic-associated-types/gat-incomplete-warning.rs b/src/test/ui/rfc1598-generic-associated-types/gat-incomplete-warning.rs
new file mode 100644 (file)
index 0000000..7f48408
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// run-pass
+
+#![feature(generic_associated_types)]
+//~^ WARNING the feature `generic_associated_types` is incomplete
+
+fn main() {}
diff --git a/src/test/ui/rfc1598-generic-associated-types/gat-incomplete-warning.stderr b/src/test/ui/rfc1598-generic-associated-types/gat-incomplete-warning.stderr
new file mode 100644 (file)
index 0000000..67682dc
--- /dev/null
@@ -0,0 +1,6 @@
+warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
+  --> $DIR/gat-incomplete-warning.rs:13:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+
diff --git a/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.stderr b/src/test/ui/rfc1598-generic-associated-types/generic-associated-types-where.stderr
new file mode 100644 (file)
index 0000000..97d5482
--- /dev/null
@@ -0,0 +1,6 @@
+warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
+  --> $DIR/generic-associated-types-where.rs:11:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+
index 263b3cb42eb4f32d465de767687b79ea25f954cf..267272ded8c06876777d8cb4f2ed8181ac1c70aa 100644 (file)
@@ -9,11 +9,12 @@
 // except according to those terms.
 
 #![feature(generic_associated_types)]
+//~^ WARNING the feature `generic_associated_types` is incomplete
 
 use std::ops::Deref;
 
-//FIXME(#44265): "lifetime parameters are not allowed on this type" errors will be addressed in a
-//follow-up PR
+// FIXME(#44265): "lifetime parameters are not allowed on this type" errors will be addressed in a
+// follow-up PR.
 
 trait Iterable {
     type Item<'a>;
index d48c21477b310668bfa620ace9f6314c561a08e0..79b29902ccdf05fb2c6bf9d6025cd4fcd20c47c1 100644 (file)
@@ -1,29 +1,35 @@
+warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
+  --> $DIR/generic_associated_type_undeclared_lifetimes.rs:11:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+
 error[E0261]: use of undeclared lifetime name `'b`
-  --> $DIR/generic_associated_type_undeclared_lifetimes.rs:22:37
+  --> $DIR/generic_associated_type_undeclared_lifetimes.rs:23:37
    |
 LL |         + Deref<Target = Self::Item<'b>>;
    |                                     ^^ undeclared lifetime
 
 error[E0261]: use of undeclared lifetime name `'undeclared`
-  --> $DIR/generic_associated_type_undeclared_lifetimes.rs:26:41
+  --> $DIR/generic_associated_type_undeclared_lifetimes.rs:27:41
    |
 LL |     fn iter<'a>(&'a self) -> Self::Iter<'undeclared>;
    |                                         ^^^^^^^^^^^ undeclared lifetime
 
 error[E0110]: lifetime parameters are not allowed on this type
-  --> $DIR/generic_associated_type_undeclared_lifetimes.rs:20:47
+  --> $DIR/generic_associated_type_undeclared_lifetimes.rs:21:47
    |
 LL |     type Iter<'a>: Iterator<Item = Self::Item<'a>>
    |                                               ^^ lifetime parameter not allowed
 
 error[E0110]: lifetime parameters are not allowed on this type
-  --> $DIR/generic_associated_type_undeclared_lifetimes.rs:22:37
+  --> $DIR/generic_associated_type_undeclared_lifetimes.rs:23:37
    |
 LL |         + Deref<Target = Self::Item<'b>>;
    |                                     ^^ lifetime parameter not allowed
 
 error[E0110]: lifetime parameters are not allowed on this type
-  --> $DIR/generic_associated_type_undeclared_lifetimes.rs:26:41
+  --> $DIR/generic_associated_type_undeclared_lifetimes.rs:27:41
    |
 LL |     fn iter<'a>(&'a self) -> Self::Iter<'undeclared>;
    |                                         ^^^^^^^^^^^ lifetime parameter not allowed
index 38967dbbe4530ea4ab28da1943889f4ef1e8d54f..b52b6e024219a194059a82fafc80a78b594c0d88 100644 (file)
@@ -9,11 +9,12 @@
 // except according to those terms.
 
 #![feature(generic_associated_types)]
+//~^ WARNING the feature `generic_associated_types` is incomplete
 
 use std::ops::Deref;
 
-//FIXME(#44265): "lifetime parameters are not allowed on this type" errors will be addressed in a
-//follow-up PR
+// FIXME(#44265): "lifetime parameters are not allowed on this type" errors will be addressed in a
+// follow-up PR.
 
 trait Iterable {
     type Item<'a>;
index 737a29ec2c8be46ced3f82ad9674b416b6ca9b73..de3563c14eb7c44208e92020c0d3c3a7604cffef 100644 (file)
@@ -1,35 +1,41 @@
+warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
+  --> $DIR/iterable.rs:11:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+
 error[E0110]: lifetime parameters are not allowed on this type
-  --> $DIR/iterable.rs:20:47
+  --> $DIR/iterable.rs:21:47
    |
 LL |     type Iter<'a>: Iterator<Item = Self::Item<'a>>;
    |                                               ^^ lifetime parameter not allowed
 
 error[E0110]: lifetime parameters are not allowed on this type
-  --> $DIR/iterable.rs:49:53
+  --> $DIR/iterable.rs:50:53
    |
 LL | fn make_iter<'a, I: Iterable>(it: &'a I) -> I::Iter<'a> {
    |                                                     ^^ lifetime parameter not allowed
 
 error[E0110]: lifetime parameters are not allowed on this type
-  --> $DIR/iterable.rs:54:60
+  --> $DIR/iterable.rs:55:60
    |
 LL | fn get_first<'a, I: Iterable>(it: &'a I) -> Option<I::Item<'a>> {
    |                                                            ^^ lifetime parameter not allowed
 
 error[E0110]: lifetime parameters are not allowed on this type
-  --> $DIR/iterable.rs:23:41
+  --> $DIR/iterable.rs:24:41
    |
 LL |     fn iter<'a>(&'a self) -> Self::Iter<'a>;
    |                                         ^^ lifetime parameter not allowed
 
 error[E0110]: lifetime parameters are not allowed on this type
-  --> $DIR/iterable.rs:32:41
+  --> $DIR/iterable.rs:33:41
    |
 LL |     fn iter<'a>(&'a self) -> Self::Iter<'a> {
    |                                         ^^ lifetime parameter not allowed
 
 error[E0110]: lifetime parameters are not allowed on this type
-  --> $DIR/iterable.rs:43:41
+  --> $DIR/iterable.rs:44:41
    |
 LL |     fn iter<'a>(&'a self) -> Self::Iter<'a> {
    |                                         ^^ lifetime parameter not allowed
index 51527d4117c2c04c35ec02748bb9a1b0401ffb8e..82e82e6dbccaf3bfd01c9d5a334b46d8fb1ee82b 100644 (file)
@@ -9,12 +9,13 @@
 // except according to those terms.
 
 #![feature(generic_associated_types)]
+//~^ WARNING the feature `generic_associated_types` is incomplete
 #![feature(associated_type_defaults)]
 
-//FIXME(#44265): "lifetime parameters are not allowed on this type" errors will be addressed in a
-//follow-up PR
+// FIXME(#44265): "lifetime parameters are not allowed on this type" errors will be addressed in a
+// follow-up PR.
 
-//FIXME(#44265): Update expected errors once E110 is resolved, now does not get past `trait Foo`
+// FIXME(#44265): Update expected errors once E110 is resolved, now does not get past `trait Foo`.
 
 trait Foo {
     type A<'a>;
index c8d37a51fa96bd5cd73e1c6161a89c453bca1b62..e47daf2ae1bbae0198480b1f05a18199c2e36c9f 100644 (file)
@@ -1,29 +1,35 @@
+warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
+  --> $DIR/parameter_number_and_kind.rs:11:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+
 error[E0110]: lifetime parameters are not allowed on this type
-  --> $DIR/parameter_number_and_kind.rs:26:27
+  --> $DIR/parameter_number_and_kind.rs:27:27
    |
 LL |     type FOk<T> = Self::E<'static, T>;
    |                           ^^^^^^^ lifetime parameter not allowed
 
 error[E0109]: type parameters are not allowed on this type
-  --> $DIR/parameter_number_and_kind.rs:26:36
+  --> $DIR/parameter_number_and_kind.rs:27:36
    |
 LL |     type FOk<T> = Self::E<'static, T>;
    |                                    ^ type parameter not allowed
 
 error[E0110]: lifetime parameters are not allowed on this type
-  --> $DIR/parameter_number_and_kind.rs:29:26
+  --> $DIR/parameter_number_and_kind.rs:30:26
    |
 LL |     type FErr1 = Self::E<'static, 'static>; // Error
    |                          ^^^^^^^ lifetime parameter not allowed
 
 error[E0110]: lifetime parameters are not allowed on this type
-  --> $DIR/parameter_number_and_kind.rs:31:29
+  --> $DIR/parameter_number_and_kind.rs:32:29
    |
 LL |     type FErr2<T> = Self::E<'static, T, u32>; // Error
    |                             ^^^^^^^ lifetime parameter not allowed
 
 error[E0109]: type parameters are not allowed on this type
-  --> $DIR/parameter_number_and_kind.rs:31:38
+  --> $DIR/parameter_number_and_kind.rs:32:38
    |
 LL |     type FErr2<T> = Self::E<'static, T, u32>; // Error
    |                                      ^ type parameter not allowed
index cbeeb1d6ca7b292686f21deaa02e27405e47ace6..0300ad06194e76c726cbcee4574d56e9e7cc14d0 100644 (file)
@@ -9,8 +9,9 @@
 // except according to those terms.
 
 #![feature(generic_associated_types)]
+//~^ WARNING the feature `generic_associated_types` is incomplete
 
-//FIXME(#44265): "type parameter not allowed" errors will be addressed in a follow-up PR
+// FIXME(#44265): "type parameter not allowed" errors will be addressed in a follow-up PR.
 
 use std::rc::Rc;
 use std::sync::Arc;
index 3e772eee4f4920ae0feedd4f6e260458b2b285fc..3be0481dc67e85f0d4cefdcd04455ef254faa209 100644 (file)
@@ -1,23 +1,29 @@
+warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
+  --> $DIR/pointer_family.rs:11:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+
 error[E0109]: type parameters are not allowed on this type
-  --> $DIR/pointer_family.rs:46:21
+  --> $DIR/pointer_family.rs:47:21
    |
 LL |     bar: P::Pointer<String>,
    |                     ^^^^^^ type parameter not allowed
 
 error[E0109]: type parameters are not allowed on this type
-  --> $DIR/pointer_family.rs:21:42
+  --> $DIR/pointer_family.rs:22:42
    |
 LL |     fn new<T>(value: T) -> Self::Pointer<T>;
    |                                          ^ type parameter not allowed
 
 error[E0109]: type parameters are not allowed on this type
-  --> $DIR/pointer_family.rs:29:42
+  --> $DIR/pointer_family.rs:30:42
    |
 LL |     fn new<T>(value: T) -> Self::Pointer<T> {
    |                                          ^ type parameter not allowed
 
 error[E0109]: type parameters are not allowed on this type
-  --> $DIR/pointer_family.rs:39:42
+  --> $DIR/pointer_family.rs:40:42
    |
 LL |     fn new<T>(value: T) -> Self::Pointer<T> {
    |                                          ^ type parameter not allowed
diff --git a/src/test/ui/rfc1598-generic-associated-types/shadowing.stderr b/src/test/ui/rfc1598-generic-associated-types/shadowing.stderr
new file mode 100644 (file)
index 0000000..f2d626f
--- /dev/null
@@ -0,0 +1,6 @@
+warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
+  --> $DIR/shadowing.rs:11:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+
index 522ddb5dc135e36e162d34cc5bfb34e2f27f427b..aa90886fdfd65c6787ffebe7d051c95e1217ad60 100644 (file)
@@ -9,8 +9,9 @@
 // except according to those terms.
 
 #![feature(generic_associated_types)]
+//~^ WARNING the feature `generic_associated_types` is incomplete
 
-//FIXME(#44265): "lifetime parameter not allowed on this type" errors will be addressed in a
+// FIXME(#44265): "lifetime parameter not allowed on this type" errors will be addressed in a
 // follow-up PR
 
 use std::fmt::Display;
index 12e206cbd476af56a70098be716d39a69b699fc8..4aca8d476877b78e53165b448978c41e246ec6c0 100644 (file)
@@ -1,29 +1,35 @@
+warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash
+  --> $DIR/streaming_iterator.rs:11:12
+   |
+LL | #![feature(generic_associated_types)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
+
 error[E0110]: lifetime parameters are not allowed on this type
-  --> $DIR/streaming_iterator.rs:27:41
+  --> $DIR/streaming_iterator.rs:28:41
    |
 LL |     bar: <T as StreamingIterator>::Item<'static>,
    |                                         ^^^^^^^ lifetime parameter not allowed
 
 error[E0110]: lifetime parameters are not allowed on this type
-  --> $DIR/streaming_iterator.rs:35:64
+  --> $DIR/streaming_iterator.rs:36:64
    |
 LL | fn foo<T>(iter: T) where T: StreamingIterator, for<'a> T::Item<'a>: Display { /* ... */ }
    |                                                                ^^ lifetime parameter not allowed
 
 error[E0110]: lifetime parameters are not allowed on this type
-  --> $DIR/streaming_iterator.rs:21:48
+  --> $DIR/streaming_iterator.rs:22:48
    |
 LL |     fn next<'a>(&'a self) -> Option<Self::Item<'a>>;
    |                                                ^^ lifetime parameter not allowed
 
 error[E0110]: lifetime parameters are not allowed on this type
-  --> $DIR/streaming_iterator.rs:47:37
+  --> $DIR/streaming_iterator.rs:48:37
    |
 LL |     type Item<'a> = (usize, I::Item<'a>);
    |                                     ^^ lifetime parameter not allowed
 
 error[E0110]: lifetime parameters are not allowed on this type
-  --> $DIR/streaming_iterator.rs:49:48
+  --> $DIR/streaming_iterator.rs:50:48
    |
 LL |     fn next<'a>(&'a self) -> Option<Self::Item<'a>> {
    |                                                ^^ lifetime parameter not allowed
index ecc71909334091eba1be8814470cf49207d663b1..8a2b9c1f27213c19df0980019af787546c7be6bf 100644 (file)
@@ -68,7 +68,7 @@ fn main() {
     //~^ ERROR absolute
     //~| WARN this was previously accepted
     let x = bar::Bar;
-    let x = ::crate::bar::Bar;
+    let x = crate::bar::Bar;
     let x = self::bar::Bar;
     foo::test();
 
index c08be85531d5ec42244704a1d962df0fd1b604e4..b6e5d5a8afbf1cddc5e3e5f7e41c1db5730583e5 100644 (file)
@@ -68,7 +68,7 @@ fn main() {
     //~^ ERROR absolute
     //~| WARN this was previously accepted
     let x = bar::Bar;
-    let x = ::crate::bar::Bar;
+    let x = crate::bar::Bar;
     let x = self::bar::Bar;
     foo::test();
 
index 5f29e7bc99e94bf472bc7e13448bb47b13543335..e0992c906663248c172273a83d12a542974edd1c 100644 (file)
@@ -16,7 +16,7 @@
 
 mod foo {
     pub use std::io;
-    //~^ ERROR import from `std` is ambiguous
+    //~^ ERROR `std` import is ambiguous
 
     macro_rules! m {
         () => {
index d400987dfee3c8e8522618308dcff8f2107f6a2c..154ee412e72825024a5babb822f9d7c7d5ccc623 100644 (file)
@@ -1,13 +1,13 @@
-error: import from `std` is ambiguous
+error: `std` import is ambiguous
   --> $DIR/ambiguity-macros-nested.rs:18:13
    |
 LL |       pub use std::io;
-   |               ^^^ could refer to external crate `::std`
+   |               ^^^ can refer to external crate `::std`
 ...
 LL | /             mod std {
 LL | |                 pub struct io;
 LL | |             }
-   | |_____________- could also refer to `self::std`
+   | |_____________- can refer to `self::std`
    |
    = help: write `::std` or `self::std` explicitly instead
    = note: relative `use` paths enabled by `#![feature(uniform_paths)]`
index 547b2508b96ab42c453eaa8ab370131aab7a41f4..9439d92aa710be0470b34d6b6a30891389a19f88 100644 (file)
@@ -15,7 +15,7 @@
 // This test is similar to `ambiguity.rs`, but with macros defining local items.
 
 use std::io;
-//~^ ERROR import from `std` is ambiguous
+//~^ ERROR `std` import is ambiguous
 
 macro_rules! m {
     () => {
index 24a2061a3cb2aa63488465079bdb4442073d30d2..3c0d5601f9c8a9e22056d85b0bc6f6beaa0c13c2 100644 (file)
@@ -1,13 +1,13 @@
-error: import from `std` is ambiguous
+error: `std` import is ambiguous
   --> $DIR/ambiguity-macros.rs:17:5
    |
 LL |   use std::io;
-   |       ^^^ could refer to external crate `::std`
+   |       ^^^ can refer to external crate `::std`
 ...
 LL | /         mod std {
 LL | |             pub struct io;
 LL | |         }
-   | |_________- could also refer to `self::std`
+   | |_________- can refer to `self::std`
    |
    = help: write `::std` or `self::std` explicitly instead
    = note: relative `use` paths enabled by `#![feature(uniform_paths)]`
index fe00fd94ee942a69069f1bebe78cf5ff88f8cfc0..1756acc6057f2dac81da6dcf785ea94671ae1d15 100644 (file)
@@ -16,7 +16,7 @@
 
 mod foo {
     pub use std::io;
-    //~^ ERROR import from `std` is ambiguous
+    //~^ ERROR `std` import is ambiguous
 
     mod std {
         pub struct io;
index 5104aba8b44a21b500dc84bd34e2c76a4a3f860d..a607eeb0b43e0afe693f75e6e1266f8fae4e5f5a 100644 (file)
@@ -1,13 +1,13 @@
-error: import from `std` is ambiguous
+error: `std` import is ambiguous
   --> $DIR/ambiguity-nested.rs:18:13
    |
 LL |       pub use std::io;
-   |               ^^^ could refer to external crate `::std`
+   |               ^^^ can refer to external crate `::std`
 ...
 LL | /     mod std {
 LL | |         pub struct io;
 LL | |     }
-   | |_____- could also refer to `self::std`
+   | |_____- can refer to `self::std`
    |
    = help: write `::std` or `self::std` explicitly instead
    = note: relative `use` paths enabled by `#![feature(uniform_paths)]`
index 49ab2f0c19168e0e0071c21273e5869257894ca9..9ae3d79c22cf225e540ead2fe63e0a21d9cdf849 100644 (file)
@@ -13,7 +13,7 @@
 #![feature(uniform_paths)]
 
 use std::io;
-//~^ ERROR import from `std` is ambiguous
+//~^ ERROR `std` import is ambiguous
 
 mod std {
     pub struct io;
index 2e227dce96cb0ce7ffd348fd843fedb519ad0b41..c65db3072f440d8435e06516d43623149b7c9114 100644 (file)
@@ -1,13 +1,13 @@
-error: import from `std` is ambiguous
+error: `std` import is ambiguous
   --> $DIR/ambiguity.rs:15:5
    |
 LL |   use std::io;
-   |       ^^^ could refer to external crate `::std`
+   |       ^^^ can refer to external crate `::std`
 ...
 LL | / mod std {
 LL | |     pub struct io;
 LL | | }
-   | |_- could also refer to `self::std`
+   | |_- can refer to `self::std`
    |
    = help: write `::std` or `self::std` explicitly instead
    = note: relative `use` paths enabled by `#![feature(uniform_paths)]`
index b8489c61dadeeba13bd14c19a4dd7a102e9dfbce..ee141d444b2cf36e5dc08a5cdf4100d5b347564e 100644 (file)
 
 enum Foo { A, B }
 
+struct std;
+
 fn main() {
     enum Foo {}
     use Foo::*;
-    //~^ ERROR import from `Foo` is ambiguous
+    //~^ ERROR `Foo` import is ambiguous
 
     let _ = (A, B);
+
+    fn std() {}
+    enum std {}
+    use std as foo;
+    //~^ ERROR `std` import is ambiguous
+    //~| ERROR `std` import is ambiguous
 }
index 656af91a8c7fef55aa6e4d715ea4ed3605fb996e..86d95f2ac4567234c60af0942dd13be8b4ec5193 100644 (file)
@@ -1,13 +1,45 @@
-error: import from `Foo` is ambiguous
-  --> $DIR/block-scoped-shadow.rs:19:9
+error: `Foo` import is ambiguous
+  --> $DIR/block-scoped-shadow.rs:21:9
    |
+LL | enum Foo { A, B }
+   | ----------------- can refer to `self::Foo`
+...
 LL |     enum Foo {}
    |     ----------- shadowed by block-scoped `Foo`
 LL |     use Foo::*;
    |         ^^^
    |
-   = help: write `::Foo` or `self::Foo` explicitly instead
+   = help: write `self::Foo` explicitly instead
    = note: relative `use` paths enabled by `#![feature(uniform_paths)]`
 
-error: aborting due to previous error
+error: `std` import is ambiguous
+  --> $DIR/block-scoped-shadow.rs:28:9
+   |
+LL | struct std;
+   | ----------- can refer to `self::std`
+...
+LL |     enum std {}
+   |     ----------- shadowed by block-scoped `std`
+LL |     use std as foo;
+   |         ^^^ can refer to external crate `::std`
+   |
+   = help: write `::std` or `self::std` explicitly instead
+   = note: relative `use` paths enabled by `#![feature(uniform_paths)]`
+
+error: `std` import is ambiguous
+  --> $DIR/block-scoped-shadow.rs:28:9
+   |
+LL | struct std;
+   | ----------- can refer to `self::std`
+...
+LL |     fn std() {}
+   |     ----------- shadowed by block-scoped `std`
+LL |     enum std {}
+LL |     use std as foo;
+   |         ^^^
+   |
+   = help: write `self::std` explicitly instead
+   = note: relative `use` paths enabled by `#![feature(uniform_paths)]`
+
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/rust-2018/uniform-paths/redundant.rs b/src/test/ui/rust-2018/uniform-paths/redundant.rs
new file mode 100644 (file)
index 0000000..8f384b7
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// edition:2018
+
+#![feature(uniform_paths)]
+
+use std;
+
+fn main() {}
diff --git a/src/test/ui/rust-2018/uniform-paths/redundant.stderr b/src/test/ui/rust-2018/uniform-paths/redundant.stderr
new file mode 100644 (file)
index 0000000..dd38407
--- /dev/null
@@ -0,0 +1,14 @@
+error: `std` import is redundant
+  --> $DIR/redundant.rs:15:5
+   |
+LL | use std;
+   |     ^^^
+   |     |
+   |     refers to external crate `::std`
+   |     defines `self::std`, shadowing itself
+   |
+   = help: remove or write `::std` explicitly instead
+   = note: relative `use` paths enabled by `#![feature(uniform_paths)]`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/std-uncopyable-atomics.nll.stderr b/src/test/ui/std-uncopyable-atomics.nll.stderr
new file mode 100644 (file)
index 0000000..e6b612f
--- /dev/null
@@ -0,0 +1,39 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/std-uncopyable-atomics.rs:19:13
+   |
+LL |     let x = *&x; //~ ERROR: cannot move out of borrowed content
+   |             ^^^
+   |             |
+   |             cannot move out of borrowed content
+   |             help: consider removing the `*`: `&x`
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/std-uncopyable-atomics.rs:21:13
+   |
+LL |     let x = *&x; //~ ERROR: cannot move out of borrowed content
+   |             ^^^
+   |             |
+   |             cannot move out of borrowed content
+   |             help: consider removing the `*`: `&x`
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/std-uncopyable-atomics.rs:23:13
+   |
+LL |     let x = *&x; //~ ERROR: cannot move out of borrowed content
+   |             ^^^
+   |             |
+   |             cannot move out of borrowed content
+   |             help: consider removing the `*`: `&x`
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/std-uncopyable-atomics.rs:25:13
+   |
+LL |     let x = *&x; //~ ERROR: cannot move out of borrowed content
+   |             ^^^
+   |             |
+   |             cannot move out of borrowed content
+   |             help: consider removing the `*`: `&x`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.rs b/src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.rs
new file mode 100644 (file)
index 0000000..dc0186e
--- /dev/null
@@ -0,0 +1,162 @@
+// 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(nll)]
+
+#[derive(Clone)]
+enum Either {
+    One(X),
+    Two(X),
+}
+
+#[derive(Clone)]
+struct X(Y);
+
+#[derive(Clone)]
+struct Y;
+
+
+pub fn main() {
+    let e = Either::One(X(Y));
+    let mut em = Either::One(X(Y));
+
+    let r = &e;
+    let rm = &mut Either::One(X(Y));
+
+    let x = X(Y);
+    let mut xm = X(Y);
+
+    let s = &x;
+    let sm = &mut X(Y);
+
+    let ve = vec![Either::One(X(Y))];
+
+    let vr = &ve;
+    let vrm = &mut vec![Either::One(X(Y))];
+
+    let vx = vec![X(Y)];
+
+    let vs = &vx;
+    let vsm = &mut vec![X(Y)];
+
+    // -------- test for duplicate suggestions --------
+
+    let &(X(_t), X(_u)) = &(x.clone(), x.clone());
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&`
+    //~| SUGGESTION (X(_t), X(_u))
+    if let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&`
+    //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+    while let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&`
+    //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+    match &(e.clone(), e.clone()) {
+        //~^ ERROR cannot move
+        &(Either::One(_t), Either::Two(_u)) => (),
+        //~^ HELP consider removing the `&`
+        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        &(Either::Two(_t), Either::One(_u)) => (),
+        //~^ HELP consider removing the `&`
+        //~| SUGGESTION (Either::Two(_t), Either::One(_u))
+        _ => (),
+    }
+    match &(e.clone(), e.clone()) {
+        //~^ ERROR cannot move
+        &(Either::One(_t), Either::Two(_u))
+        //~^ HELP consider removing the `&`
+        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        | &(Either::Two(_t), Either::One(_u)) => (),
+        // FIXME: would really like a suggestion here too
+        _ => (),
+    }
+    match &(e.clone(), e.clone()) {
+        //~^ ERROR cannot move
+        &(Either::One(_t), Either::Two(_u)) => (),
+        //~^ HELP consider removing the `&`
+        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        &(Either::Two(ref _t), Either::One(ref _u)) => (),
+        _ => (),
+    }
+    match &(e.clone(), e.clone()) {
+        //~^ ERROR cannot move
+        &(Either::One(_t), Either::Two(_u)) => (),
+        //~^ HELP consider removing the `&`
+        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        (Either::Two(_t), Either::One(_u)) => (),
+        _ => (),
+    }
+    fn f5(&(X(_t), X(_u)): &(X, X)) { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&`
+    //~| SUGGESTION (X(_t), X(_u))
+
+    let &mut (X(_t), X(_u)) = &mut (xm.clone(), xm.clone());
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&mut`
+    //~| SUGGESTION (X(_t), X(_u))
+    if let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&mut`
+    //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+    while let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&mut`
+    //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+    match &mut (em.clone(), em.clone()) {
+        //~^ ERROR cannot move
+        &mut (Either::One(_t), Either::Two(_u)) => (),
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        &mut (Either::Two(_t), Either::One(_u)) => (),
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION (Either::Two(_t), Either::One(_u))
+        _ => (),
+    }
+    match &mut (em.clone(), em.clone()) {
+        //~^ ERROR cannot move
+        &mut (Either::One(_t), Either::Two(_u))
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        | &mut (Either::Two(_t), Either::One(_u)) => (),
+        // FIXME: would really like a suggestion here too
+        _ => (),
+    }
+    match &mut (em.clone(), em.clone()) {
+        //~^ ERROR cannot move
+        &mut (Either::One(_t), Either::Two(_u)) => (),
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        &mut (Either::Two(ref _t), Either::One(ref _u)) => (),
+        _ => (),
+    }
+    match &mut (em.clone(), em.clone()) {
+        //~^ ERROR cannot move
+        &mut (Either::One(_t), Either::Two(_u)) => (),
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        &mut (Either::Two(ref mut _t), Either::One(ref mut _u)) => (),
+        _ => (),
+    }
+    match &mut (em.clone(), em.clone()) {
+        //~^ ERROR cannot move
+        &mut (Either::One(_t), Either::Two(_u)) => (),
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION (Either::One(_t), Either::Two(_u))
+        (Either::Two(_t), Either::One(_u)) => (),
+        _ => (),
+    }
+    fn f6(&mut (X(_t), X(_u)): &mut (X, X)) { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&mut`
+    //~| SUGGESTION (X(_t), X(_u))
+}
diff --git a/src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.stderr b/src/test/ui/suggestions/dont-suggest-ref/duplicate-suggestions.stderr
new file mode 100644 (file)
index 0000000..bb36884
--- /dev/null
@@ -0,0 +1,328 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:51:27
+   |
+LL |     let &(X(_t), X(_u)) = &(x.clone(), x.clone());
+   |         ---------------   ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+   |         |   |      |
+   |         |   |      ...and here
+   |         |   data moved here
+   |         help: consider removing the `&`: `(X(_t), X(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:51:13
+   |
+LL |     let &(X(_t), X(_u)) = &(x.clone(), x.clone());
+   |             ^^     ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:55:50
+   |
+LL |     if let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+   |            -----------------------------------   ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+   |            |             |                |
+   |            |             |                ...and here
+   |            |             data moved here
+   |            help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:55:26
+   |
+LL |     if let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+   |                          ^^               ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:59:53
+   |
+LL |     while let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+   |               -----------------------------------   ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+   |               |             |                |
+   |               |             |                ...and here
+   |               |             data moved here
+   |               help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:59:29
+   |
+LL |     while let &(Either::One(_t), Either::Two(_u)) = &(e.clone(), e.clone()) { }
+   |                             ^^               ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:63:11
+   |
+LL |     match &(e.clone(), e.clone()) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         &(Either::One(_t), Either::Two(_u)) => (),
+   |                       --               -- ...and here
+   |                       |
+   |                       data moved here
+...
+LL |         &(Either::Two(_t), Either::One(_u)) => (),
+   |                       -- ...and here   -- ...and here
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:65:23
+   |
+LL |         &(Either::One(_t), Either::Two(_u)) => (),
+   |                       ^^               ^^
+...
+LL |         &(Either::Two(_t), Either::One(_u)) => (),
+   |                       ^^               ^^
+help: consider removing the `&`
+   |
+LL |         (Either::One(_t), Either::Two(_u)) => (),
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: consider removing the `&`
+   |
+LL |         (Either::Two(_t), Either::One(_u)) => (),
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:73:11
+   |
+LL |     match &(e.clone(), e.clone()) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         &(Either::One(_t), Either::Two(_u))
+   |         -----------------------------------
+   |         |             |                |
+   |         |             |                ...and here
+   |         |             data moved here
+   |         help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:75:23
+   |
+LL |         &(Either::One(_t), Either::Two(_u))
+   |                       ^^               ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:82:11
+   |
+LL |     match &(e.clone(), e.clone()) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         &(Either::One(_t), Either::Two(_u)) => (),
+   |         -----------------------------------
+   |         |             |                |
+   |         |             |                ...and here
+   |         |             data moved here
+   |         help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:84:23
+   |
+LL |         &(Either::One(_t), Either::Two(_u)) => (),
+   |                       ^^               ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:90:11
+   |
+LL |     match &(e.clone(), e.clone()) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         &(Either::One(_t), Either::Two(_u)) => (),
+   |         -----------------------------------
+   |         |             |                |
+   |         |             |                ...and here
+   |         |             data moved here
+   |         help: consider removing the `&`: `(Either::One(_t), Either::Two(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:92:23
+   |
+LL |         &(Either::One(_t), Either::Two(_u)) => (),
+   |                       ^^               ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:103:31
+   |
+LL |     let &mut (X(_t), X(_u)) = &mut (xm.clone(), xm.clone());
+   |         -------------------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+   |         |       |      |
+   |         |       |      ...and here
+   |         |       data moved here
+   |         help: consider removing the `&mut`: `(X(_t), X(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:103:17
+   |
+LL |     let &mut (X(_t), X(_u)) = &mut (xm.clone(), xm.clone());
+   |                 ^^     ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:107:54
+   |
+LL |     if let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+   |            ---------------------------------------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+   |            |                 |                |
+   |            |                 |                ...and here
+   |            |                 data moved here
+   |            help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:107:30
+   |
+LL |     if let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+   |                              ^^               ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:111:57
+   |
+LL |     while let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+   |               ---------------------------------------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+   |               |                 |                |
+   |               |                 |                ...and here
+   |               |                 data moved here
+   |               help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:111:33
+   |
+LL |     while let &mut (Either::One(_t), Either::Two(_u)) = &mut (em.clone(), em.clone()) { }
+   |                                 ^^               ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:115:11
+   |
+LL |     match &mut (em.clone(), em.clone()) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         &mut (Either::One(_t), Either::Two(_u)) => (),
+   |                           --               -- ...and here
+   |                           |
+   |                           data moved here
+...
+LL |         &mut (Either::Two(_t), Either::One(_u)) => (),
+   |                           -- ...and here   -- ...and here
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:117:27
+   |
+LL |         &mut (Either::One(_t), Either::Two(_u)) => (),
+   |                           ^^               ^^
+...
+LL |         &mut (Either::Two(_t), Either::One(_u)) => (),
+   |                           ^^               ^^
+help: consider removing the `&mut`
+   |
+LL |         (Either::One(_t), Either::Two(_u)) => (),
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: consider removing the `&mut`
+   |
+LL |         (Either::Two(_t), Either::One(_u)) => (),
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:125:11
+   |
+LL |     match &mut (em.clone(), em.clone()) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         &mut (Either::One(_t), Either::Two(_u))
+   |         ---------------------------------------
+   |         |                 |                |
+   |         |                 |                ...and here
+   |         |                 data moved here
+   |         help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:127:27
+   |
+LL |         &mut (Either::One(_t), Either::Two(_u))
+   |                           ^^               ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:134:11
+   |
+LL |     match &mut (em.clone(), em.clone()) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         &mut (Either::One(_t), Either::Two(_u)) => (),
+   |         ---------------------------------------
+   |         |                 |                |
+   |         |                 |                ...and here
+   |         |                 data moved here
+   |         help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:136:27
+   |
+LL |         &mut (Either::One(_t), Either::Two(_u)) => (),
+   |                           ^^               ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:142:11
+   |
+LL |     match &mut (em.clone(), em.clone()) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         &mut (Either::One(_t), Either::Two(_u)) => (),
+   |         ---------------------------------------
+   |         |                 |                |
+   |         |                 |                ...and here
+   |         |                 data moved here
+   |         help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:144:27
+   |
+LL |         &mut (Either::One(_t), Either::Two(_u)) => (),
+   |                           ^^               ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:150:11
+   |
+LL |     match &mut (em.clone(), em.clone()) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         &mut (Either::One(_t), Either::Two(_u)) => (),
+   |         ---------------------------------------
+   |         |                 |                |
+   |         |                 |                ...and here
+   |         |                 data moved here
+   |         help: consider removing the `&mut`: `(Either::One(_t), Either::Two(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:152:27
+   |
+LL |         &mut (Either::One(_t), Either::Two(_u)) => (),
+   |                           ^^               ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:98:11
+   |
+LL |     fn f5(&(X(_t), X(_u)): &(X, X)) { }
+   |           ^^^^--^^^^^--^^
+   |           |   |      |
+   |           |   |      ...and here
+   |           |   data moved here
+   |           cannot move out of borrowed content
+   |           help: consider removing the `&`: `(X(_t), X(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:98:15
+   |
+LL |     fn f5(&(X(_t), X(_u)): &(X, X)) { }
+   |               ^^     ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/duplicate-suggestions.rs:158:11
+   |
+LL |     fn f6(&mut (X(_t), X(_u)): &mut (X, X)) { }
+   |           ^^^^^^^^--^^^^^--^^
+   |           |       |      |
+   |           |       |      ...and here
+   |           |       data moved here
+   |           cannot move out of borrowed content
+   |           help: consider removing the `&mut`: `(X(_t), X(_u))`
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/duplicate-suggestions.rs:158:19
+   |
+LL |     fn f6(&mut (X(_t), X(_u)): &mut (X, X)) { }
+   |                   ^^     ^^
+
+error: aborting due to 17 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.rs b/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.rs
new file mode 100644 (file)
index 0000000..8cc847e
--- /dev/null
@@ -0,0 +1,171 @@
+// 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(nll)]
+
+#[derive(Clone)]
+enum Either {
+    One(X),
+    Two(X),
+}
+
+#[derive(Clone)]
+struct X(Y);
+
+#[derive(Clone)]
+struct Y;
+
+fn consume_fn<F: Fn()>(_f: F) { }
+
+fn consume_fnmut<F: FnMut()>(_f: F) { }
+
+pub fn main() { }
+
+fn move_into_fn() {
+    let e = Either::One(X(Y));
+    let mut em = Either::One(X(Y));
+
+    let x = X(Y);
+
+    // -------- move into Fn --------
+
+    consume_fn(|| {
+        let X(_t) = x;
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &x
+        if let Either::One(_t) = e { }
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &e
+        while let Either::One(_t) = e { }
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &e
+        match e {
+            //~^ ERROR cannot move
+            //~| HELP consider borrowing here
+            //~| SUGGESTION &e
+            Either::One(_t)
+            | Either::Two(_t) => (),
+        }
+        match e {
+            //~^ ERROR cannot move
+            //~| HELP consider borrowing here
+            //~| SUGGESTION &e
+            Either::One(_t) => (),
+            Either::Two(ref _t) => (),
+            // FIXME: should suggest removing `ref` too
+        }
+
+        let X(mut _t) = x;
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &x
+        if let Either::One(mut _t) = em { }
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &em
+        while let Either::One(mut _t) = em { }
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &em
+        match em {
+            //~^ ERROR cannot move
+            //~| HELP consider borrowing here
+            //~| SUGGESTION &em
+            Either::One(mut _t)
+            | Either::Two(mut _t) => (),
+        }
+        match em {
+            //~^ ERROR cannot move
+            //~| HELP consider borrowing here
+            //~| SUGGESTION &em
+            Either::One(mut _t) => (),
+            Either::Two(ref _t) => (),
+            // FIXME: should suggest removing `ref` too
+        }
+    });
+}
+
+fn move_into_fnmut() {
+    let e = Either::One(X(Y));
+    let mut em = Either::One(X(Y));
+
+    let x = X(Y);
+
+    // -------- move into FnMut --------
+
+    consume_fnmut(|| {
+        let X(_t) = x;
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &x
+        if let Either::One(_t) = e { }
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &e
+        while let Either::One(_t) = e { }
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &e
+        match e {
+            //~^ ERROR cannot move
+            //~| HELP consider borrowing here
+            //~| SUGGESTION &e
+            Either::One(_t)
+            | Either::Two(_t) => (),
+        }
+        match e {
+            //~^ ERROR cannot move
+            //~| HELP consider borrowing here
+            //~| SUGGESTION &e
+            Either::One(_t) => (),
+            Either::Two(ref _t) => (),
+            // FIXME: should suggest removing `ref` too
+        }
+
+        let X(mut _t) = x;
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &x
+        if let Either::One(mut _t) = em { }
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &em
+        while let Either::One(mut _t) = em { }
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &em
+        match em {
+            //~^ ERROR cannot move
+            //~| HELP consider borrowing here
+            //~| SUGGESTION &em
+            Either::One(mut _t)
+            | Either::Two(mut _t) => (),
+        }
+        match em {
+            //~^ ERROR cannot move
+            //~| HELP consider borrowing here
+            //~| SUGGESTION &em
+            Either::One(mut _t) => (),
+            Either::Two(ref _t) => (),
+            // FIXME: should suggest removing `ref` too
+        }
+        match em {
+            //~^ ERROR cannot move
+            //~| HELP consider borrowing here
+            //~| SUGGESTION &em
+            Either::One(mut _t) => (),
+            Either::Two(ref mut _t) => (),
+            // FIXME: should suggest removing `ref` too
+        }
+    });
+}
diff --git a/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.stderr b/src/test/ui/suggestions/dont-suggest-ref/move-into-closure.stderr
new file mode 100644 (file)
index 0000000..228ec5a
--- /dev/null
@@ -0,0 +1,420 @@
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+  --> $DIR/move-into-closure.rs:40:21
+   |
+LL |     let x = X(Y);
+   |         - captured outer variable
+...
+LL |         let X(_t) = x;
+   |               --    ^
+   |               |     |
+   |               |     cannot move out of captured variable in an `Fn` closure
+   |               |     help: consider borrowing here: `&x`
+   |               data moved here
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:40:15
+   |
+LL |         let X(_t) = x;
+   |               ^^
+
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+  --> $DIR/move-into-closure.rs:44:34
+   |
+LL |     let e = Either::One(X(Y));
+   |         - captured outer variable
+...
+LL |         if let Either::One(_t) = e { }
+   |                            --    ^
+   |                            |     |
+   |                            |     cannot move out of captured variable in an `Fn` closure
+   |                            |     help: consider borrowing here: `&e`
+   |                            data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:44:28
+   |
+LL |         if let Either::One(_t) = e { }
+   |                            ^^
+
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+  --> $DIR/move-into-closure.rs:48:37
+   |
+LL |     let e = Either::One(X(Y));
+   |         - captured outer variable
+...
+LL |         while let Either::One(_t) = e { }
+   |                               --    ^
+   |                               |     |
+   |                               |     cannot move out of captured variable in an `Fn` closure
+   |                               |     help: consider borrowing here: `&e`
+   |                               data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:48:31
+   |
+LL |         while let Either::One(_t) = e { }
+   |                               ^^
+
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+  --> $DIR/move-into-closure.rs:52:15
+   |
+LL |     let e = Either::One(X(Y));
+   |         - captured outer variable
+...
+LL |         match e {
+   |               ^
+   |               |
+   |               cannot move out of captured variable in an `Fn` closure
+   |               help: consider borrowing here: `&e`
+...
+LL |             Either::One(_t)
+   |                         -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:56:25
+   |
+LL |             Either::One(_t)
+   |                         ^^
+
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+  --> $DIR/move-into-closure.rs:59:15
+   |
+LL |     let e = Either::One(X(Y));
+   |         - captured outer variable
+...
+LL |         match e {
+   |               ^
+   |               |
+   |               cannot move out of captured variable in an `Fn` closure
+   |               help: consider borrowing here: `&e`
+...
+LL |             Either::One(_t) => (),
+   |                         -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:63:25
+   |
+LL |             Either::One(_t) => (),
+   |                         ^^
+
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+  --> $DIR/move-into-closure.rs:68:25
+   |
+LL |     let x = X(Y);
+   |         - captured outer variable
+...
+LL |         let X(mut _t) = x;
+   |               ------    ^
+   |               |         |
+   |               |         cannot move out of captured variable in an `Fn` closure
+   |               |         help: consider borrowing here: `&x`
+   |               data moved here
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:68:15
+   |
+LL |         let X(mut _t) = x;
+   |               ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+  --> $DIR/move-into-closure.rs:72:38
+   |
+LL |     let mut em = Either::One(X(Y));
+   |         ------ captured outer variable
+...
+LL |         if let Either::One(mut _t) = em { }
+   |                            ------    ^^
+   |                            |         |
+   |                            |         cannot move out of captured variable in an `Fn` closure
+   |                            |         help: consider borrowing here: `&em`
+   |                            data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:72:28
+   |
+LL |         if let Either::One(mut _t) = em { }
+   |                            ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+  --> $DIR/move-into-closure.rs:76:41
+   |
+LL |     let mut em = Either::One(X(Y));
+   |         ------ captured outer variable
+...
+LL |         while let Either::One(mut _t) = em { }
+   |                               ------    ^^
+   |                               |         |
+   |                               |         cannot move out of captured variable in an `Fn` closure
+   |                               |         help: consider borrowing here: `&em`
+   |                               data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:76:31
+   |
+LL |         while let Either::One(mut _t) = em { }
+   |                               ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+  --> $DIR/move-into-closure.rs:80:15
+   |
+LL |     let mut em = Either::One(X(Y));
+   |         ------ captured outer variable
+...
+LL |         match em {
+   |               ^^
+   |               |
+   |               cannot move out of captured variable in an `Fn` closure
+   |               help: consider borrowing here: `&em`
+...
+LL |             Either::One(mut _t)
+   |                         ------ data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:84:25
+   |
+LL |             Either::One(mut _t)
+   |                         ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+  --> $DIR/move-into-closure.rs:87:15
+   |
+LL |     let mut em = Either::One(X(Y));
+   |         ------ captured outer variable
+...
+LL |         match em {
+   |               ^^
+   |               |
+   |               cannot move out of captured variable in an `Fn` closure
+   |               help: consider borrowing here: `&em`
+...
+LL |             Either::One(mut _t) => (),
+   |                         ------ data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:91:25
+   |
+LL |             Either::One(mut _t) => (),
+   |                         ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+  --> $DIR/move-into-closure.rs:107:21
+   |
+LL |     let x = X(Y);
+   |         - captured outer variable
+...
+LL |         let X(_t) = x;
+   |               --    ^
+   |               |     |
+   |               |     cannot move out of captured variable in an `FnMut` closure
+   |               |     help: consider borrowing here: `&x`
+   |               data moved here
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:107:15
+   |
+LL |         let X(_t) = x;
+   |               ^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+  --> $DIR/move-into-closure.rs:111:34
+   |
+LL |     let e = Either::One(X(Y));
+   |         - captured outer variable
+...
+LL |         if let Either::One(_t) = e { }
+   |                            --    ^
+   |                            |     |
+   |                            |     cannot move out of captured variable in an `FnMut` closure
+   |                            |     help: consider borrowing here: `&e`
+   |                            data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:111:28
+   |
+LL |         if let Either::One(_t) = e { }
+   |                            ^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+  --> $DIR/move-into-closure.rs:115:37
+   |
+LL |     let e = Either::One(X(Y));
+   |         - captured outer variable
+...
+LL |         while let Either::One(_t) = e { }
+   |                               --    ^
+   |                               |     |
+   |                               |     cannot move out of captured variable in an `FnMut` closure
+   |                               |     help: consider borrowing here: `&e`
+   |                               data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:115:31
+   |
+LL |         while let Either::One(_t) = e { }
+   |                               ^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+  --> $DIR/move-into-closure.rs:119:15
+   |
+LL |     let e = Either::One(X(Y));
+   |         - captured outer variable
+...
+LL |         match e {
+   |               ^
+   |               |
+   |               cannot move out of captured variable in an `FnMut` closure
+   |               help: consider borrowing here: `&e`
+...
+LL |             Either::One(_t)
+   |                         -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:123:25
+   |
+LL |             Either::One(_t)
+   |                         ^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+  --> $DIR/move-into-closure.rs:126:15
+   |
+LL |     let e = Either::One(X(Y));
+   |         - captured outer variable
+...
+LL |         match e {
+   |               ^
+   |               |
+   |               cannot move out of captured variable in an `FnMut` closure
+   |               help: consider borrowing here: `&e`
+...
+LL |             Either::One(_t) => (),
+   |                         -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:130:25
+   |
+LL |             Either::One(_t) => (),
+   |                         ^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+  --> $DIR/move-into-closure.rs:135:25
+   |
+LL |     let x = X(Y);
+   |         - captured outer variable
+...
+LL |         let X(mut _t) = x;
+   |               ------    ^
+   |               |         |
+   |               |         cannot move out of captured variable in an `FnMut` closure
+   |               |         help: consider borrowing here: `&x`
+   |               data moved here
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:135:15
+   |
+LL |         let X(mut _t) = x;
+   |               ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+  --> $DIR/move-into-closure.rs:139:38
+   |
+LL |     let mut em = Either::One(X(Y));
+   |         ------ captured outer variable
+...
+LL |         if let Either::One(mut _t) = em { }
+   |                            ------    ^^
+   |                            |         |
+   |                            |         cannot move out of captured variable in an `FnMut` closure
+   |                            |         help: consider borrowing here: `&em`
+   |                            data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:139:28
+   |
+LL |         if let Either::One(mut _t) = em { }
+   |                            ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+  --> $DIR/move-into-closure.rs:143:41
+   |
+LL |     let mut em = Either::One(X(Y));
+   |         ------ captured outer variable
+...
+LL |         while let Either::One(mut _t) = em { }
+   |                               ------    ^^
+   |                               |         |
+   |                               |         cannot move out of captured variable in an `FnMut` closure
+   |                               |         help: consider borrowing here: `&em`
+   |                               data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:143:31
+   |
+LL |         while let Either::One(mut _t) = em { }
+   |                               ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+  --> $DIR/move-into-closure.rs:147:15
+   |
+LL |     let mut em = Either::One(X(Y));
+   |         ------ captured outer variable
+...
+LL |         match em {
+   |               ^^
+   |               |
+   |               cannot move out of captured variable in an `FnMut` closure
+   |               help: consider borrowing here: `&em`
+...
+LL |             Either::One(mut _t)
+   |                         ------ data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:151:25
+   |
+LL |             Either::One(mut _t)
+   |                         ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+  --> $DIR/move-into-closure.rs:154:15
+   |
+LL |     let mut em = Either::One(X(Y));
+   |         ------ captured outer variable
+...
+LL |         match em {
+   |               ^^
+   |               |
+   |               cannot move out of captured variable in an `FnMut` closure
+   |               help: consider borrowing here: `&em`
+...
+LL |             Either::One(mut _t) => (),
+   |                         ------ data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:158:25
+   |
+LL |             Either::One(mut _t) => (),
+   |                         ^^^^^^
+
+error[E0507]: cannot move out of captured variable in an `FnMut` closure
+  --> $DIR/move-into-closure.rs:162:15
+   |
+LL |     let mut em = Either::One(X(Y));
+   |         ------ captured outer variable
+...
+LL |         match em {
+   |               ^^
+   |               |
+   |               cannot move out of captured variable in an `FnMut` closure
+   |               help: consider borrowing here: `&em`
+...
+LL |             Either::One(mut _t) => (),
+   |                         ------ data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/move-into-closure.rs:166:25
+   |
+LL |             Either::One(mut _t) => (),
+   |                         ^^^^^^
+
+error: aborting due to 21 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/suggestions/dont-suggest-ref/simple.rs b/src/test/ui/suggestions/dont-suggest-ref/simple.rs
new file mode 100644 (file)
index 0000000..474e88c
--- /dev/null
@@ -0,0 +1,376 @@
+// 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(nll)]
+
+#[derive(Clone)]
+enum Either {
+    One(X),
+    Two(X),
+}
+
+#[derive(Clone)]
+struct X(Y);
+
+#[derive(Clone)]
+struct Y;
+
+pub fn main() {
+    let e = Either::One(X(Y));
+    let mut em = Either::One(X(Y));
+
+    let r = &e;
+    let rm = &mut Either::One(X(Y));
+
+    let x = X(Y);
+    let mut xm = X(Y);
+
+    let s = &x;
+    let sm = &mut X(Y);
+
+    let ve = vec![Either::One(X(Y))];
+
+    let vr = &ve;
+    let vrm = &mut vec![Either::One(X(Y))];
+
+    let vx = vec![X(Y)];
+
+    let vs = &vx;
+    let vsm = &mut vec![X(Y)];
+
+    // -------- move from Either/X place --------
+
+    let X(_t) = *s;
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `*`
+    //~| SUGGESTION s
+    if let Either::One(_t) = *r { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `*`
+    //~| SUGGESTION r
+    while let Either::One(_t) = *r { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `*`
+    //~| SUGGESTION r
+    match *r {
+        //~^ ERROR cannot move
+        //~| HELP consider removing the `*`
+        //~| SUGGESTION r
+        Either::One(_t)
+        | Either::Two(_t) => (),
+    }
+    match *r {
+        //~^ ERROR cannot move
+        //~| HELP consider removing the `*`
+        //~| SUGGESTION r
+        Either::One(_t) => (),
+        Either::Two(ref _t) => (),
+        // FIXME: should suggest removing `ref` too
+    }
+
+    let X(_t) = *sm;
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `*`
+    //~| SUGGESTION sm
+    if let Either::One(_t) = *rm { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `*`
+    //~| SUGGESTION rm
+    while let Either::One(_t) = *rm { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `*`
+    //~| SUGGESTION rm
+    match *rm {
+        //~^ ERROR cannot move
+        //~| HELP consider removing the `*`
+        //~| SUGGESTION rm
+        Either::One(_t)
+        | Either::Two(_t) => (),
+    }
+    match *rm {
+        //~^ ERROR cannot move
+        //~| HELP consider removing the `*`
+        //~| SUGGESTION rm
+        Either::One(_t) => (),
+        Either::Two(ref _t) => (),
+        // FIXME: should suggest removing `ref` too
+    }
+    match *rm {
+        //~^ ERROR cannot move
+        //~| HELP consider removing the `*`
+        //~| SUGGESTION rm
+        Either::One(_t) => (),
+        Either::Two(ref mut _t) => (),
+        // FIXME: should suggest removing `ref` too
+    }
+
+    let X(_t) = vs[0];
+    //~^ ERROR cannot move
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &vs[0]
+    if let Either::One(_t) = vr[0] { }
+    //~^ ERROR cannot move
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &vr[0]
+    while let Either::One(_t) = vr[0] { }
+    //~^ ERROR cannot move
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &vr[0]
+    match vr[0] {
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &vr[0]
+        Either::One(_t)
+        | Either::Two(_t) => (),
+    }
+    match vr[0] {
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &vr[0]
+        Either::One(_t) => (),
+        Either::Two(ref _t) => (),
+        // FIXME: should suggest removing `ref` too
+    }
+
+    let X(_t) = vsm[0];
+    //~^ ERROR cannot move
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &vsm[0]
+    if let Either::One(_t) = vrm[0] { }
+    //~^ ERROR cannot move
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &vrm[0]
+    while let Either::One(_t) = vrm[0] { }
+    //~^ ERROR cannot move
+    //~| HELP consider borrowing here
+    //~| SUGGESTION &vrm[0]
+    match vrm[0] {
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &vrm[0]
+        Either::One(_t)
+        | Either::Two(_t) => (),
+    }
+    match vrm[0] {
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &vrm[0]
+        Either::One(_t) => (),
+        Either::Two(ref _t) => (),
+        // FIXME: should suggest removing `ref` too
+    }
+    match vrm[0] {
+        //~^ ERROR cannot move
+        //~| HELP consider borrowing here
+        //~| SUGGESTION &vrm[0]
+        Either::One(_t) => (),
+        Either::Two(ref mut _t) => (),
+        // FIXME: should suggest removing `ref` too
+    }
+
+    // -------- move from &Either/&X place --------
+
+    let &X(_t) = s;
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&`
+    //~| SUGGESTION X(_t)
+    if let &Either::One(_t) = r { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&`
+    //~| SUGGESTION Either::One(_t)
+    while let &Either::One(_t) = r { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&`
+    //~| SUGGESTION Either::One(_t)
+    match r {
+        //~^ ERROR cannot move
+        &Either::One(_t)
+        //~^ HELP consider removing the `&`
+        //~| SUGGESTION Either::One(_t)
+        | &Either::Two(_t) => (),
+        // FIXME: would really like a suggestion here too
+    }
+    match r {
+        //~^ ERROR cannot move
+        &Either::One(_t) => (),
+        //~^ HELP consider removing the `&`
+        //~| SUGGESTION Either::One(_t)
+        &Either::Two(ref _t) => (),
+    }
+    match r {
+        //~^ ERROR cannot move
+        &Either::One(_t) => (),
+        //~^ HELP consider removing the `&`
+        //~| SUGGESTION Either::One(_t)
+        Either::Two(_t) => (),
+    }
+    fn f1(&X(_t): &X) { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&`
+    //~| SUGGESTION X(_t)
+
+    let &mut X(_t) = sm;
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&mut`
+    //~| SUGGESTION X(_t)
+    if let &mut Either::One(_t) = rm { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&mut`
+    //~| SUGGESTION Either::One(_t)
+    while let &mut Either::One(_t) = rm { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&mut`
+    //~| SUGGESTION Either::One(_t)
+    match rm {
+        //~^ ERROR cannot move
+        &mut Either::One(_t) => (),
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION Either::One(_t)
+        &mut Either::Two(_t) => (),
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION Either::Two(_t)
+    }
+    match rm {
+        //~^ ERROR cannot move
+        &mut Either::One(_t) => (),
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION Either::One(_t)
+        &mut Either::Two(ref _t) => (),
+    }
+    match rm {
+        //~^ ERROR cannot move
+        &mut Either::One(_t) => (),
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION Either::One(_t)
+        &mut Either::Two(ref mut _t) => (),
+    }
+    match rm {
+        //~^ ERROR cannot move
+        &mut Either::One(_t) => (),
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION Either::One(_t)
+        Either::Two(_t) => (),
+    }
+    fn f2(&mut X(_t): &mut X) { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&mut`
+    //~| SUGGESTION X(_t)
+
+    // -------- move from tuple of &Either/&X --------
+
+    // FIXME: These should have suggestions.
+
+    let (&X(_t),) = (&x.clone(),);
+    //~^ ERROR cannot move
+    if let (&Either::One(_t),) = (&e.clone(),) { }
+    //~^ ERROR cannot move
+    while let (&Either::One(_t),) = (&e.clone(),) { }
+    //~^ ERROR cannot move
+    match (&e.clone(),) {
+        //~^ ERROR cannot move
+        (&Either::One(_t),)
+        | (&Either::Two(_t),) => (),
+    }
+    fn f3((&X(_t),): (&X,)) { }
+    //~^ ERROR cannot move
+
+    let (&mut X(_t),) = (&mut xm.clone(),);
+    //~^ ERROR cannot move
+    if let (&mut Either::One(_t),) = (&mut em.clone(),) { }
+    //~^ ERROR cannot move
+    while let (&mut Either::One(_t),) = (&mut em.clone(),) { }
+    //~^ ERROR cannot move
+    match (&mut em.clone(),) {
+        //~^ ERROR cannot move
+        (&mut Either::One(_t),) => (),
+        (&mut Either::Two(_t),) => (),
+    }
+    fn f4((&mut X(_t),): (&mut X,)) { }
+    //~^ ERROR cannot move
+
+    // -------- move from &Either/&X value --------
+
+    let &X(_t) = &x;
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&`
+    //~| SUGGESTION X(_t)
+    if let &Either::One(_t) = &e { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&`
+    //~| SUGGESTION Either::One(_t)
+    while let &Either::One(_t) = &e { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&`
+    //~| SUGGESTION Either::One(_t)
+    match &e {
+        //~^ ERROR cannot move
+        &Either::One(_t)
+        //~^ HELP consider removing the `&`
+        //~| SUGGESTION Either::One(_t)
+        | &Either::Two(_t) => (),
+        // FIXME: would really like a suggestion here too
+    }
+    match &e {
+        //~^ ERROR cannot move
+        &Either::One(_t) => (),
+        //~^ HELP consider removing the `&`
+        //~| SUGGESTION Either::One(_t)
+        &Either::Two(ref _t) => (),
+    }
+    match &e {
+        //~^ ERROR cannot move
+        &Either::One(_t) => (),
+        //~^ HELP consider removing the `&`
+        //~| SUGGESTION Either::One(_t)
+        Either::Two(_t) => (),
+    }
+
+    let &mut X(_t) = &mut xm;
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&mut`
+    //~| SUGGESTION X(_t)
+    if let &mut Either::One(_t) = &mut em { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&mut`
+    //~| SUGGESTION Either::One(_t)
+    while let &mut Either::One(_t) = &mut em { }
+    //~^ ERROR cannot move
+    //~| HELP consider removing the `&mut`
+    //~| SUGGESTION Either::One(_t)
+    match &mut em {
+        //~^ ERROR cannot move
+        &mut Either::One(_t)
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION Either::One(_t)
+        | &mut Either::Two(_t) => (),
+        // FIXME: would really like a suggestion here too
+    }
+    match &mut em {
+        //~^ ERROR cannot move
+        &mut Either::One(_t) => (),
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION Either::One(_t)
+        &mut Either::Two(ref _t) => (),
+    }
+    match &mut em {
+        //~^ ERROR cannot move
+        &mut Either::One(_t) => (),
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION Either::One(_t)
+        &mut Either::Two(ref mut _t) => (),
+    }
+    match &mut em {
+        //~^ ERROR cannot move
+        &mut Either::One(_t) => (),
+        //~^ HELP consider removing the `&mut`
+        //~| SUGGESTION Either::One(_t)
+        Either::Two(_t) => (),
+    }
+}
diff --git a/src/test/ui/suggestions/dont-suggest-ref/simple.stderr b/src/test/ui/suggestions/dont-suggest-ref/simple.stderr
new file mode 100644 (file)
index 0000000..d7a32db
--- /dev/null
@@ -0,0 +1,998 @@
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:50:17
+   |
+LL |     let X(_t) = *s;
+   |           --    ^^
+   |           |     |
+   |           |     cannot move out of borrowed content
+   |           |     help: consider removing the `*`: `s`
+   |           data moved here
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:50:11
+   |
+LL |     let X(_t) = *s;
+   |           ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:54:30
+   |
+LL |     if let Either::One(_t) = *r { }
+   |                        --    ^^
+   |                        |     |
+   |                        |     cannot move out of borrowed content
+   |                        |     help: consider removing the `*`: `r`
+   |                        data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:54:24
+   |
+LL |     if let Either::One(_t) = *r { }
+   |                        ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:58:33
+   |
+LL |     while let Either::One(_t) = *r { }
+   |                           --    ^^
+   |                           |     |
+   |                           |     cannot move out of borrowed content
+   |                           |     help: consider removing the `*`: `r`
+   |                           data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:58:27
+   |
+LL |     while let Either::One(_t) = *r { }
+   |                           ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:62:11
+   |
+LL |     match *r {
+   |           ^^
+   |           |
+   |           cannot move out of borrowed content
+   |           help: consider removing the `*`: `r`
+...
+LL |         Either::One(_t)
+   |                     -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:66:21
+   |
+LL |         Either::One(_t)
+   |                     ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:69:11
+   |
+LL |     match *r {
+   |           ^^
+   |           |
+   |           cannot move out of borrowed content
+   |           help: consider removing the `*`: `r`
+...
+LL |         Either::One(_t) => (),
+   |                     -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:73:21
+   |
+LL |         Either::One(_t) => (),
+   |                     ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:78:17
+   |
+LL |     let X(_t) = *sm;
+   |           --    ^^^
+   |           |     |
+   |           |     cannot move out of borrowed content
+   |           |     help: consider removing the `*`: `sm`
+   |           data moved here
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:78:11
+   |
+LL |     let X(_t) = *sm;
+   |           ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:82:30
+   |
+LL |     if let Either::One(_t) = *rm { }
+   |                        --    ^^^
+   |                        |     |
+   |                        |     cannot move out of borrowed content
+   |                        |     help: consider removing the `*`: `rm`
+   |                        data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:82:24
+   |
+LL |     if let Either::One(_t) = *rm { }
+   |                        ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:86:33
+   |
+LL |     while let Either::One(_t) = *rm { }
+   |                           --    ^^^
+   |                           |     |
+   |                           |     cannot move out of borrowed content
+   |                           |     help: consider removing the `*`: `rm`
+   |                           data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:86:27
+   |
+LL |     while let Either::One(_t) = *rm { }
+   |                           ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:90:11
+   |
+LL |     match *rm {
+   |           ^^^
+   |           |
+   |           cannot move out of borrowed content
+   |           help: consider removing the `*`: `rm`
+...
+LL |         Either::One(_t)
+   |                     -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:94:21
+   |
+LL |         Either::One(_t)
+   |                     ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:97:11
+   |
+LL |     match *rm {
+   |           ^^^
+   |           |
+   |           cannot move out of borrowed content
+   |           help: consider removing the `*`: `rm`
+...
+LL |         Either::One(_t) => (),
+   |                     -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:101:21
+   |
+LL |         Either::One(_t) => (),
+   |                     ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:105:11
+   |
+LL |     match *rm {
+   |           ^^^
+   |           |
+   |           cannot move out of borrowed content
+   |           help: consider removing the `*`: `rm`
+...
+LL |         Either::One(_t) => (),
+   |                     -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:109:21
+   |
+LL |         Either::One(_t) => (),
+   |                     ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:114:17
+   |
+LL |     let X(_t) = vs[0];
+   |           --    ^^^^^
+   |           |     |
+   |           |     cannot move out of borrowed content
+   |           |     help: consider borrowing here: `&vs[0]`
+   |           data moved here
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:114:11
+   |
+LL |     let X(_t) = vs[0];
+   |           ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:118:30
+   |
+LL |     if let Either::One(_t) = vr[0] { }
+   |                        --    ^^^^^
+   |                        |     |
+   |                        |     cannot move out of borrowed content
+   |                        |     help: consider borrowing here: `&vr[0]`
+   |                        data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:118:24
+   |
+LL |     if let Either::One(_t) = vr[0] { }
+   |                        ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:122:33
+   |
+LL |     while let Either::One(_t) = vr[0] { }
+   |                           --    ^^^^^
+   |                           |     |
+   |                           |     cannot move out of borrowed content
+   |                           |     help: consider borrowing here: `&vr[0]`
+   |                           data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:122:27
+   |
+LL |     while let Either::One(_t) = vr[0] { }
+   |                           ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:126:11
+   |
+LL |     match vr[0] {
+   |           ^^^^^
+   |           |
+   |           cannot move out of borrowed content
+   |           help: consider borrowing here: `&vr[0]`
+...
+LL |         Either::One(_t)
+   |                     -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:130:21
+   |
+LL |         Either::One(_t)
+   |                     ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:133:11
+   |
+LL |     match vr[0] {
+   |           ^^^^^
+   |           |
+   |           cannot move out of borrowed content
+   |           help: consider borrowing here: `&vr[0]`
+...
+LL |         Either::One(_t) => (),
+   |                     -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:137:21
+   |
+LL |         Either::One(_t) => (),
+   |                     ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:142:17
+   |
+LL |     let X(_t) = vsm[0];
+   |           --    ^^^^^^
+   |           |     |
+   |           |     cannot move out of borrowed content
+   |           |     help: consider borrowing here: `&vsm[0]`
+   |           data moved here
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:142:11
+   |
+LL |     let X(_t) = vsm[0];
+   |           ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:146:30
+   |
+LL |     if let Either::One(_t) = vrm[0] { }
+   |                        --    ^^^^^^
+   |                        |     |
+   |                        |     cannot move out of borrowed content
+   |                        |     help: consider borrowing here: `&vrm[0]`
+   |                        data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:146:24
+   |
+LL |     if let Either::One(_t) = vrm[0] { }
+   |                        ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:150:33
+   |
+LL |     while let Either::One(_t) = vrm[0] { }
+   |                           --    ^^^^^^
+   |                           |     |
+   |                           |     cannot move out of borrowed content
+   |                           |     help: consider borrowing here: `&vrm[0]`
+   |                           data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:150:27
+   |
+LL |     while let Either::One(_t) = vrm[0] { }
+   |                           ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:154:11
+   |
+LL |     match vrm[0] {
+   |           ^^^^^^
+   |           |
+   |           cannot move out of borrowed content
+   |           help: consider borrowing here: `&vrm[0]`
+...
+LL |         Either::One(_t)
+   |                     -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:158:21
+   |
+LL |         Either::One(_t)
+   |                     ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:161:11
+   |
+LL |     match vrm[0] {
+   |           ^^^^^^
+   |           |
+   |           cannot move out of borrowed content
+   |           help: consider borrowing here: `&vrm[0]`
+...
+LL |         Either::One(_t) => (),
+   |                     -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:165:21
+   |
+LL |         Either::One(_t) => (),
+   |                     ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:169:11
+   |
+LL |     match vrm[0] {
+   |           ^^^^^^
+   |           |
+   |           cannot move out of borrowed content
+   |           help: consider borrowing here: `&vrm[0]`
+...
+LL |         Either::One(_t) => (),
+   |                     -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:173:21
+   |
+LL |         Either::One(_t) => (),
+   |                     ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:180:18
+   |
+LL |     let &X(_t) = s;
+   |         ------   ^ cannot move out of borrowed content
+   |         |  |
+   |         |  data moved here
+   |         help: consider removing the `&`: `X(_t)`
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:180:12
+   |
+LL |     let &X(_t) = s;
+   |            ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:184:31
+   |
+LL |     if let &Either::One(_t) = r { }
+   |            ----------------   ^ cannot move out of borrowed content
+   |            |            |
+   |            |            data moved here
+   |            help: consider removing the `&`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:184:25
+   |
+LL |     if let &Either::One(_t) = r { }
+   |                         ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:188:34
+   |
+LL |     while let &Either::One(_t) = r { }
+   |               ----------------   ^ cannot move out of borrowed content
+   |               |            |
+   |               |            data moved here
+   |               help: consider removing the `&`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:188:28
+   |
+LL |     while let &Either::One(_t) = r { }
+   |                            ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:192:11
+   |
+LL |     match r {
+   |           ^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         &Either::One(_t)
+   |         ----------------
+   |         |            |
+   |         |            data moved here
+   |         help: consider removing the `&`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:194:22
+   |
+LL |         &Either::One(_t)
+   |                      ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:200:11
+   |
+LL |     match r {
+   |           ^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         &Either::One(_t) => (),
+   |         ----------------
+   |         |            |
+   |         |            data moved here
+   |         help: consider removing the `&`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:202:22
+   |
+LL |         &Either::One(_t) => (),
+   |                      ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:207:11
+   |
+LL |     match r {
+   |           ^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         &Either::One(_t) => (),
+   |         ----------------
+   |         |            |
+   |         |            data moved here
+   |         help: consider removing the `&`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:209:22
+   |
+LL |         &Either::One(_t) => (),
+   |                      ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:219:22
+   |
+LL |     let &mut X(_t) = sm;
+   |         ----------   ^^ cannot move out of borrowed content
+   |         |      |
+   |         |      data moved here
+   |         help: consider removing the `&mut`: `X(_t)`
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:219:16
+   |
+LL |     let &mut X(_t) = sm;
+   |                ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:223:35
+   |
+LL |     if let &mut Either::One(_t) = rm { }
+   |            --------------------   ^^ cannot move out of borrowed content
+   |            |                |
+   |            |                data moved here
+   |            help: consider removing the `&mut`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:223:29
+   |
+LL |     if let &mut Either::One(_t) = rm { }
+   |                             ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:227:38
+   |
+LL |     while let &mut Either::One(_t) = rm { }
+   |               --------------------   ^^ cannot move out of borrowed content
+   |               |                |
+   |               |                data moved here
+   |               help: consider removing the `&mut`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:227:32
+   |
+LL |     while let &mut Either::One(_t) = rm { }
+   |                                ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:231:11
+   |
+LL |     match rm {
+   |           ^^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         &mut Either::One(_t) => (),
+   |                          -- data moved here
+...
+LL |         &mut Either::Two(_t) => (),
+   |                          -- ...and here
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/simple.rs:233:26
+   |
+LL |         &mut Either::One(_t) => (),
+   |                          ^^
+...
+LL |         &mut Either::Two(_t) => (),
+   |                          ^^
+help: consider removing the `&mut`
+   |
+LL |         Either::One(_t) => (),
+   |         ^^^^^^^^^^^^^^^
+help: consider removing the `&mut`
+   |
+LL |         Either::Two(_t) => (),
+   |         ^^^^^^^^^^^^^^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:240:11
+   |
+LL |     match rm {
+   |           ^^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         &mut Either::One(_t) => (),
+   |         --------------------
+   |         |                |
+   |         |                data moved here
+   |         help: consider removing the `&mut`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:242:26
+   |
+LL |         &mut Either::One(_t) => (),
+   |                          ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:247:11
+   |
+LL |     match rm {
+   |           ^^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         &mut Either::One(_t) => (),
+   |         --------------------
+   |         |                |
+   |         |                data moved here
+   |         help: consider removing the `&mut`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:249:26
+   |
+LL |         &mut Either::One(_t) => (),
+   |                          ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:254:11
+   |
+LL |     match rm {
+   |           ^^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         &mut Either::One(_t) => (),
+   |         --------------------
+   |         |                |
+   |         |                data moved here
+   |         help: consider removing the `&mut`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:256:26
+   |
+LL |         &mut Either::One(_t) => (),
+   |                          ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:270:21
+   |
+LL |     let (&X(_t),) = (&x.clone(),);
+   |             --      ^^^^^^^^^^^^^ cannot move out of borrowed content
+   |             |
+   |             data moved here
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:270:13
+   |
+LL |     let (&X(_t),) = (&x.clone(),);
+   |             ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:272:34
+   |
+LL |     if let (&Either::One(_t),) = (&e.clone(),) { }
+   |                          --      ^^^^^^^^^^^^^ cannot move out of borrowed content
+   |                          |
+   |                          data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:272:26
+   |
+LL |     if let (&Either::One(_t),) = (&e.clone(),) { }
+   |                          ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:274:37
+   |
+LL |     while let (&Either::One(_t),) = (&e.clone(),) { }
+   |                             --      ^^^^^^^^^^^^^ cannot move out of borrowed content
+   |                             |
+   |                             data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:274:29
+   |
+LL |     while let (&Either::One(_t),) = (&e.clone(),) { }
+   |                             ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:276:11
+   |
+LL |     match (&e.clone(),) {
+   |           ^^^^^^^^^^^^^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         (&Either::One(_t),)
+   |                       -- data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:278:23
+   |
+LL |         (&Either::One(_t),)
+   |                       ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:284:25
+   |
+LL |     let (&mut X(_t),) = (&mut xm.clone(),);
+   |                 --      ^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+   |                 |
+   |                 data moved here
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:284:17
+   |
+LL |     let (&mut X(_t),) = (&mut xm.clone(),);
+   |                 ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:286:38
+   |
+LL |     if let (&mut Either::One(_t),) = (&mut em.clone(),) { }
+   |                              --      ^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+   |                              |
+   |                              data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:286:30
+   |
+LL |     if let (&mut Either::One(_t),) = (&mut em.clone(),) { }
+   |                              ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:288:41
+   |
+LL |     while let (&mut Either::One(_t),) = (&mut em.clone(),) { }
+   |                                 --      ^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+   |                                 |
+   |                                 data moved here
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:288:33
+   |
+LL |     while let (&mut Either::One(_t),) = (&mut em.clone(),) { }
+   |                                 ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:290:11
+   |
+LL |     match (&mut em.clone(),) {
+   |           ^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         (&mut Either::One(_t),) => (),
+   |                           -- data moved here
+LL |         (&mut Either::Two(_t),) => (),
+   |                           -- ...and here
+   |
+note: move occurs because these variables have types that don't implement the `Copy` trait
+  --> $DIR/simple.rs:292:27
+   |
+LL |         (&mut Either::One(_t),) => (),
+   |                           ^^
+LL |         (&mut Either::Two(_t),) => (),
+   |                           ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:300:18
+   |
+LL |     let &X(_t) = &x;
+   |         ------   ^^ cannot move out of borrowed content
+   |         |  |
+   |         |  data moved here
+   |         help: consider removing the `&`: `X(_t)`
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:300:12
+   |
+LL |     let &X(_t) = &x;
+   |            ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:304:31
+   |
+LL |     if let &Either::One(_t) = &e { }
+   |            ----------------   ^^ cannot move out of borrowed content
+   |            |            |
+   |            |            data moved here
+   |            help: consider removing the `&`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:304:25
+   |
+LL |     if let &Either::One(_t) = &e { }
+   |                         ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:308:34
+   |
+LL |     while let &Either::One(_t) = &e { }
+   |               ----------------   ^^ cannot move out of borrowed content
+   |               |            |
+   |               |            data moved here
+   |               help: consider removing the `&`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:308:28
+   |
+LL |     while let &Either::One(_t) = &e { }
+   |                            ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:312:11
+   |
+LL |     match &e {
+   |           ^^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         &Either::One(_t)
+   |         ----------------
+   |         |            |
+   |         |            data moved here
+   |         help: consider removing the `&`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:314:22
+   |
+LL |         &Either::One(_t)
+   |                      ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:320:11
+   |
+LL |     match &e {
+   |           ^^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         &Either::One(_t) => (),
+   |         ----------------
+   |         |            |
+   |         |            data moved here
+   |         help: consider removing the `&`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:322:22
+   |
+LL |         &Either::One(_t) => (),
+   |                      ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:327:11
+   |
+LL |     match &e {
+   |           ^^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         &Either::One(_t) => (),
+   |         ----------------
+   |         |            |
+   |         |            data moved here
+   |         help: consider removing the `&`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:329:22
+   |
+LL |         &Either::One(_t) => (),
+   |                      ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:335:22
+   |
+LL |     let &mut X(_t) = &mut xm;
+   |         ----------   ^^^^^^^ cannot move out of borrowed content
+   |         |      |
+   |         |      data moved here
+   |         help: consider removing the `&mut`: `X(_t)`
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:335:16
+   |
+LL |     let &mut X(_t) = &mut xm;
+   |                ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:339:35
+   |
+LL |     if let &mut Either::One(_t) = &mut em { }
+   |            --------------------   ^^^^^^^ cannot move out of borrowed content
+   |            |                |
+   |            |                data moved here
+   |            help: consider removing the `&mut`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:339:29
+   |
+LL |     if let &mut Either::One(_t) = &mut em { }
+   |                             ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:343:38
+   |
+LL |     while let &mut Either::One(_t) = &mut em { }
+   |               --------------------   ^^^^^^^ cannot move out of borrowed content
+   |               |                |
+   |               |                data moved here
+   |               help: consider removing the `&mut`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:343:32
+   |
+LL |     while let &mut Either::One(_t) = &mut em { }
+   |                                ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:347:11
+   |
+LL |     match &mut em {
+   |           ^^^^^^^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         &mut Either::One(_t)
+   |         --------------------
+   |         |                |
+   |         |                data moved here
+   |         help: consider removing the `&mut`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:349:26
+   |
+LL |         &mut Either::One(_t)
+   |                          ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:355:11
+   |
+LL |     match &mut em {
+   |           ^^^^^^^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         &mut Either::One(_t) => (),
+   |         --------------------
+   |         |                |
+   |         |                data moved here
+   |         help: consider removing the `&mut`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:357:26
+   |
+LL |         &mut Either::One(_t) => (),
+   |                          ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:362:11
+   |
+LL |     match &mut em {
+   |           ^^^^^^^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         &mut Either::One(_t) => (),
+   |         --------------------
+   |         |                |
+   |         |                data moved here
+   |         help: consider removing the `&mut`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:364:26
+   |
+LL |         &mut Either::One(_t) => (),
+   |                          ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:369:11
+   |
+LL |     match &mut em {
+   |           ^^^^^^^ cannot move out of borrowed content
+LL |         //~^ ERROR cannot move
+LL |         &mut Either::One(_t) => (),
+   |         --------------------
+   |         |                |
+   |         |                data moved here
+   |         help: consider removing the `&mut`: `Either::One(_t)`
+   |
+note: move occurs because `_t` has type `X`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:371:26
+   |
+LL |         &mut Either::One(_t) => (),
+   |                          ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:214:11
+   |
+LL |     fn f1(&X(_t): &X) { }
+   |           ^^^--^
+   |           |  |
+   |           |  data moved here
+   |           cannot move out of borrowed content
+   |           help: consider removing the `&`: `X(_t)`
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:214:14
+   |
+LL |     fn f1(&X(_t): &X) { }
+   |              ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:261:11
+   |
+LL |     fn f2(&mut X(_t): &mut X) { }
+   |           ^^^^^^^--^
+   |           |      |
+   |           |      data moved here
+   |           cannot move out of borrowed content
+   |           help: consider removing the `&mut`: `X(_t)`
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:261:18
+   |
+LL |     fn f2(&mut X(_t): &mut X) { }
+   |                  ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:281:11
+   |
+LL |     fn f3((&X(_t),): (&X,)) { }
+   |           ^^^^--^^^
+   |           |   |
+   |           |   data moved here
+   |           cannot move out of borrowed content
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:281:15
+   |
+LL |     fn f3((&X(_t),): (&X,)) { }
+   |               ^^
+
+error[E0507]: cannot move out of borrowed content
+  --> $DIR/simple.rs:295:11
+   |
+LL |     fn f4((&mut X(_t),): (&mut X,)) { }
+   |           ^^^^^^^^--^^^
+   |           |       |
+   |           |       data moved here
+   |           cannot move out of borrowed content
+   |
+note: move occurs because `_t` has type `Y`, which does not implement the `Copy` trait
+  --> $DIR/simple.rs:295:19
+   |
+LL |     fn f4((&mut X(_t),): (&mut X,)) { }
+   |                   ^^
+
+error: aborting due to 60 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
index 6c0053f2f8597997489345fb210a66de136321be..634191bb5ef4eab9b877783317e7371144f3ce00 100644 (file)
@@ -1,14 +1,11 @@
 error: incorrect close delimiter: `}`
   --> $DIR/issue-10636-2.rs:18:1
    |
-LL | } //~ ERROR: incorrect close delimiter
-   | ^
-   |
-note: unclosed delimiter
-  --> $DIR/issue-10636-2.rs:15:15
-   |
 LL |     option.map(|some| 42;
-   |               ^
+   |               - unclosed delimiter
+...
+LL | } //~ ERROR: incorrect close delimiter
+   | ^ incorrect close delimiter
 
 error: expected one of `)`, `,`, `.`, `?`, or an operator, found `;`
   --> $DIR/issue-10636-2.rs:15:25
diff --git a/src/test/ui/unboxed-closures/unboxed-closure-region.nll.stderr b/src/test/ui/unboxed-closures/unboxed-closure-region.nll.stderr
new file mode 100644 (file)
index 0000000..6ad57a1
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0597]: `x` does not live long enough
+  --> $DIR/unboxed-closure-region.rs:18:12
+   |
+LL |         || x //~ ERROR `x` does not live long enough
+   |         -- ^ borrowed value does not live long enough
+   |         |
+   |         value captured here
+LL |     };
+   |     - `x` dropped here while still borrowed
+LL |     _f;
+   |     -- borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
index cc635296210a03b013d32ee0dcba41ad19cf9a6d..da6dbc6e74f86b7cfe588d05dd3dc0dd082ada34 100644 (file)
@@ -8,13 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-compare-mode-nll
-
 // Test that an unboxed closure that captures a free variable by
 // reference cannot escape the region of that variable.
+
+
 fn main() {
     let _f = {
         let x = 0;
         || x //~ ERROR `x` does not live long enough
     };
+    _f;
 }
index a838c3608b9a9dcacadbfd55ab5f980c2061970f..f85f3afff70e8ff0a63221c2977da7be535299f7 100644 (file)
@@ -7,6 +7,7 @@ LL |         || x //~ ERROR `x` does not live long enough
    |         capture occurs here
 LL |     };
    |     - borrowed value only lives until here
+LL |     _f;
 LL | }
    | - borrowed value needs to live until here
 
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-borrow-conflict.nll.stderr b/src/test/ui/unboxed-closures/unboxed-closures-borrow-conflict.nll.stderr
new file mode 100644 (file)
index 0000000..cadda39
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0503]: cannot use `x` because it was mutably borrowed
+  --> $DIR/unboxed-closures-borrow-conflict.rs:19:14
+   |
+LL |     let f = || x += 1;
+   |             -- - borrow occurs due to use of `x` in closure
+   |             |
+   |             borrow of `x` occurs here
+LL |     let _y = x; //~ ERROR cannot use `x` because it was mutably borrowed
+   |              ^ use of borrowed `x`
+LL |     f;
+   |     - borrow later used here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0503`.
index 734f89e5e0b8ba3fa5105532ca3750d735575afb..aa50fb837733c6ed729ca2254c462489344fd443 100644 (file)
@@ -8,13 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-compare-mode-nll
-
 // Test that an unboxed closure that mutates a free variable will
 // cause borrow conflicts.
 
+
+
 fn main() {
     let mut x = 0;
     let f = || x += 1;
     let _y = x; //~ ERROR cannot use `x` because it was mutably borrowed
+    f;
 }
diff --git a/src/test/ui/unrestricted-attribute-tokens.rs b/src/test/ui/unrestricted-attribute-tokens.rs
new file mode 100644 (file)
index 0000000..2971b50
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-pass
+
+#![feature(custom_attribute, unrestricted_attribute_tokens)]
+
+#[my_attr(a b c d)]
+fn main() {}
index 201a661726e9179940849bc4dca2126aeca410c6..58220ba992c7a28b7e40637c4a0807b10827b5fc 100644 (file)
@@ -82,7 +82,7 @@ pub fn extract_rendered(output: &str, proc_res: &ProcRes) -> String {
                     Err(error) => {
                         proc_res.fatal(Some(&format!(
                             "failed to decode compiler output as json: \
-                             `{}`\noutput: {}\nline: {}",
+                             `{}`\nline: {}\noutput: {}",
                             error, line, output
                         )));
                     }
@@ -114,7 +114,7 @@ fn parse_line(file_name: &str, line: &str, output: &str, proc_res: &ProcRes) ->
             Err(error) => {
                 proc_res.fatal(Some(&format!(
                     "failed to decode compiler output as json: \
-                     `{}`\noutput: {}\nline: {}",
+                     `{}`\nline: {}\noutput: {}",
                     error, line, output
                 )));
             }
index 6b573908de9025b9da5b90d9964145baeb05e22a..62296f73f016b6b89e7cbb1783c6db6880f30ed9 100644 (file)
@@ -60,6 +60,7 @@ pub fn collect_unstable_book_section_file_names(dir: &path::Path) -> BTreeSet<St
         .map(|entry| entry.expect("could not read directory entry"))
         .filter(dir_entry_is_file)
         .map(|entry| entry.file_name().into_string().unwrap())
+        .filter(|n| n.ends_with(".md"))
         .map(|n| n.trim_right_matches(".md").to_owned())
         .collect()
 }