]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #53373 - estebank:unclosed, r=petrochenkov
authorkennytm <kennytm@gmail.com>
Thu, 16 Aug 2018 16:13:24 +0000 (00:13 +0800)
committerGitHub <noreply@github.com>
Thu, 16 Aug 2018 16:13:24 +0000 (00:13 +0800)
Tweak unclosed delimiter parser error

175 files changed:
.gitmodules
.travis.yml
config.toml.example
src/Cargo.lock
src/bootstrap/bootstrap.py
src/bootstrap/builder.rs
src/bootstrap/config.rs
src/bootstrap/configure.py
src/bootstrap/dist.rs
src/bootstrap/lib.rs
src/bootstrap/native.rs
src/doc/unstable-book/src/language-features/on-unimplemented.md
src/liballoc/alloc.rs
src/libcore/iter/iterator.rs
src/libcore/iter/mod.rs
src/libcore/macros.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/librustc/lib.rs
src/librustc/middle/dataflow.rs [deleted file]
src/librustc/mir/mod.rs
src/librustc/mir/tcx.rs
src/librustc/traits/error_reporting.rs
src/librustc/traits/mod.rs
src/librustc/traits/on_unimplemented.rs
src/librustc/traits/select.rs
src/librustc/traits/structural_impls.rs
src/librustc_apfloat/ieee.rs
src/librustc_borrowck/borrowck/check_loans.rs
src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
src/librustc_borrowck/borrowck/gather_loans/lifetime.rs
src/librustc_borrowck/borrowck/gather_loans/mod.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_borrowck/borrowck/move_data.rs
src/librustc_borrowck/dataflow.rs [new file with mode: 0644]
src/librustc_borrowck/graphviz.rs
src/librustc_borrowck/lib.rs
src/librustc_codegen_llvm/back/linker.rs
src/librustc_data_structures/transitive_relation.rs
src/librustc_mir/borrow_check/mod.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/move_paths/builder.rs
src/librustc_mir/dataflow/move_paths/mod.rs
src/librustc_mir/lib.rs
src/librustc_mir/util/mod.rs
src/librustc_target/spec/aarch64_pc_windows_msvc.rs [new file with mode: 0644]
src/librustc_target/spec/mod.rs
src/librustc_typeck/check/generator_interior.rs
src/librustc_typeck/check/wfcheck.rs
src/librustdoc/Cargo.toml
src/librustdoc/html/static/themes/dark.css
src/librustdoc/html/static/themes/light.css
src/libserialize/json.rs
src/libstd/sync/mpsc/mod.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/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/libtest/lib.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/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/run-pass-fulldeps/proc-macro/auxiliary/derive-b.rs
src/test/run-pass-fulldeps/proc-macro/derive-b.rs
src/test/run-pass/generator/issue-52398.rs [new file with mode: 0644]
src/test/run-pass/nll/issue-53123-raw-pointer-cast.rs [new file with mode: 0644]
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/access-mode-in-closures.nll.stderr
src/test/ui/attr-eq-token-tree.rs [new file with mode: 0644]
src/test/ui/borrowck/borrowck-for-loop-correct-cmt-for-pattern.nll.stderr
src/test/ui/borrowck/borrowck-in-static.nll.stderr
src/test/ui/borrowck/borrowck-issue-2657-2.nll.stderr
src/test/ui/borrowck/borrowck-move-by-capture.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/borrowck/unboxed-closures-move-upvar-from-non-once-ref-closure.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/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-27060-2.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-4335.nll.stderr
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/moves/moves-based-on-type-move-out-of-closure-env-issue-1965.nll.stderr
src/test/ui/nll/cannot-move-block-spans.nll.stderr
src/test/ui/nll/issue-52663-span-decl-captured-variable.rs [new file with mode: 0644]
src/test/ui/nll/issue-52663-span-decl-captured-variable.stderr [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/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/span/borrowck-call-is-borrow-issue-12224.nll.stderr
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/unboxed-closures/unboxed-closure-illegal-move.nll.stderr
src/test/ui/unrestricted-attribute-tokens.rs [new file with mode: 0644]
src/tools/build-manifest/src/main.rs
src/tools/cargo
src/tools/clang [new submodule]
src/tools/compiletest/src/json.rs
src/tools/lldb [new submodule]
src/tools/rust-installer
src/tools/tidy/src/lib.rs

index f3eb902709ca7167699e2c46eb6092a506774e10..1631daac76c2ce07b0cc807666e4f2287a9bcfa8 100644 (file)
 [submodule "src/libbacktrace"]
        path = src/libbacktrace
        url = https://github.com/rust-lang-nursery/libbacktrace
+[submodule "src/tools/lldb"]
+       path = src/tools/lldb
+       url = https://github.com/rust-lang-nursery/lldb/
+       branch = rust-release-70
+[submodule "src/tools/clang"]
+       path = src/tools/clang
+       url = https://github.com/rust-lang-nursery/clang/
+       branch = release_70
index d010a8370b502b2159ac4ecfe6750d6cda9a9303..7251a46cc5878156caa21f5881d8b1f9314ce4e0 100644 (file)
@@ -30,7 +30,7 @@ matrix:
 
     - env: >
         RUST_CHECK_TARGET=dist
-        RUST_CONFIGURE_ARGS="--enable-extended --enable-profiler"
+        RUST_CONFIGURE_ARGS="--enable-extended --enable-profiler --enable-lldb"
         SRC=.
         DEPLOY_ALT=1
         RUSTC_RETRY_LINKER_ON_SEGFAULT=1
@@ -85,7 +85,7 @@ matrix:
     # OSX 10.7 and `xcode7` is the latest Xcode able to compile LLVM for 10.7.
     - env: >
         RUST_CHECK_TARGET=dist
-        RUST_CONFIGURE_ARGS="--build=i686-apple-darwin --enable-full-tools --enable-profiler"
+        RUST_CONFIGURE_ARGS="--build=i686-apple-darwin --enable-full-tools --enable-profiler --enable-lldb"
         SRC=.
         DEPLOY=1
         RUSTC_RETRY_LINKER_ON_SEGFAULT=1
@@ -99,7 +99,7 @@ matrix:
 
     - env: >
         RUST_CHECK_TARGET=dist
-        RUST_CONFIGURE_ARGS="--target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler"
+        RUST_CONFIGURE_ARGS="--target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --enable-lldb"
         SRC=.
         DEPLOY=1
         RUSTC_RETRY_LINKER_ON_SEGFAULT=1
@@ -233,7 +233,8 @@ install:
         osx)
           if [[ "$RUST_CHECK_TARGET" == dist ]]; then
             travis_retry brew update &&
-            travis_retry brew install xz;
+            travis_retry brew install xz &&
+            travis_retry brew install swig;
           fi &&
           travis_retry curl -fo /usr/local/bin/sccache https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror/2018-04-02-sccache-x86_64-apple-darwin &&
             chmod +x /usr/local/bin/sccache &&
index eb7cd61a1b07e7a936e126db5f9e622421d291a5..107375ac5cc3a3fa0ce254f11adde571d29d6e60 100644 (file)
 # sysroot.
 #llvm-tools = false
 
+# Indicates whether LLDB will be made available in the sysroot.
+# This is only built if LLVM is also being built.
+#lldb = false
+
 # Whether to deny warnings in crates
 #deny-warnings = true
 
index 9465f45dc19a47edbf2b8dc582d7b96b3571e1f2..a8308eb403896a277e766c80bef7545d9ea54521 100644 (file)
@@ -187,7 +187,7 @@ dependencies = [
  "filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "git2 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "git2 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "git2-curl 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -197,7 +197,7 @@ dependencies = [
  "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "libgit2-sys 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libgit2-sys 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "miow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -234,7 +234,8 @@ dependencies = [
  "filetime 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "git2 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "fwdansi 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "git2 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "git2-curl 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -244,10 +245,11 @@ dependencies = [
  "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazycell 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "libgit2-sys 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libgit2-sys 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "miow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl 0.10.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-workspace-hack 1.0.0",
  "rustfix 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -616,7 +618,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "commoncrypto 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl 0.10.10 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl 0.10.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -629,7 +631,7 @@ dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "schannel 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "socket2 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -643,7 +645,7 @@ dependencies = [
  "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "vcpkg 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -876,6 +878,15 @@ name = "futures"
 version = "0.1.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "fwdansi"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "termcolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "getopts"
 version = "0.2.17"
@@ -883,15 +894,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "git2"
-version = "0.7.3"
+version = "0.7.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "libgit2-sys 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libgit2-sys 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -901,7 +912,7 @@ version = "0.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "curl 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "git2 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "git2 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1015,7 +1026,7 @@ name = "installer"
 version = "0.0.0"
 dependencies = [
  "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "flate2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1134,7 +1145,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "libgit2-sys"
-version = "0.7.6"
+version = "0.7.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1143,7 +1154,7 @@ dependencies = [
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "libssh2-sys 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -1155,7 +1166,7 @@ dependencies = [
  "cmake 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.35 (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "vcpkg 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -1215,6 +1226,11 @@ name = "mac"
 version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "macro-utils"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "maplit"
 version = "1.0.1"
@@ -1292,10 +1308,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "minifier"
-version = "0.0.14"
+version = "0.0.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
+ "macro-utils 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1382,7 +1398,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "openssl"
-version = "0.10.10"
+version = "0.10.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1390,7 +1406,7 @@ dependencies = [
  "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
- "openssl-sys 0.9.33 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-sys 0.9.35 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -1398,13 +1414,22 @@ name = "openssl-probe"
 version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
+[[package]]
+name = "openssl-src"
+version = "110.0.6+1.1.0h"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "openssl-sys"
-version = "0.9.33"
+version = "0.9.35"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "cc 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "openssl-src 110.0.6+1.1.0h (registry+https://github.com/rust-lang/crates.io-index)",
  "pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "vcpkg 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -2431,7 +2456,7 @@ dependencies = [
 name = "rustdoc"
 version = "0.0.0"
 dependencies = [
- "minifier 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "minifier 0.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
  "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "tempfile 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -3163,8 +3188,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
 "checksum futf 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7c9c1ce3fa9336301af935ab852c437817d14cd33690446569392e65170aac3b"
 "checksum futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "1a70b146671de62ec8c8ed572219ca5d594d9b06c0b364d5e67b722fc559b48c"
+"checksum fwdansi 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "34dd4c507af68d37ffef962063dfa1944ce0dd4d5b82043dbab1dabe088610c3"
 "checksum getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "b900c08c1939860ce8b54dc6a89e26e00c04c380fd0e09796799bd7f12861e05"
-"checksum git2 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b87cffac882c99f9654ca5eb4c6c61527b47bc1e113304f8c57333567cd31f2"
+"checksum git2 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "591f8be1674b421644b6c030969520bc3fa12114d2eb467471982ed3e9584e71"
 "checksum git2-curl 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b502f6b1b467957403d168f0039e0c46fa6a1220efa2adaef25d5b267b5fe024"
 "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
 "checksum globset 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "142754da2c9b3722affd909f9e27f2a6700a7a303f362971e0a74c652005a43d"
@@ -3189,7 +3215,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum lazycell 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a6f08839bc70ef4a3fe1d566d5350f519c5912ea86be0df1740a7d247c7fc0ef"
 "checksum lazycell 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d33a48d0365c96081958cc663eef834975cb1e8d8bea3378513fc72bdbf11e50"
 "checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d"
-"checksum libgit2-sys 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c9051a4b288ba6f8728e9e52bb2510816946b8bcb2e20259e4d4cdc93b9ecafd"
+"checksum libgit2-sys 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6ab62b46003ba97701554631fa570d9f7e7947e2480ae3d941e555a54a2c0f05"
 "checksum libssh2-sys 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c628b499e8d1a4f4bd09a95d6cb1f8aeb231b46a9d40959bbd0408f14dd63adf"
 "checksum libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "87f737ad6cc6fd6eefe3d9dc5412f1573865bded441300904d2f42269e140f16"
 "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
@@ -3197,6 +3223,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum log_settings 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19af41f0565d7c19b2058153ad0b42d4d5ce89ec4dbf06ed6741114a8b63e7cd"
 "checksum lzma-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d1eaa027402541975218bb0eec67d6b0412f6233af96e0d096d31dbdfd22e614"
 "checksum mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
+"checksum macro-utils 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2c4deaccc2ead6a28c16c0ba82f07d52b6475397415ce40876e559b0b0ea510"
 "checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43"
 "checksum markup5ever 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfedc97d5a503e96816d10fedcd5b42f760b2e525ce2f7ec71f6a41780548475"
 "checksum matches 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "835511bab37c34c47da5cb44844bea2cfde0236db0b506f90ea4224482c9774a"
@@ -3204,7 +3231,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
 "checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff"
 "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
-"checksum minifier 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "78cb57f9a385530d60f2d67f6e108050b478b7a0ffd0bb9c350803e1356535dd"
+"checksum minifier 0.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "9908ed7c62f990c21ab41fdca53a864a3ada0da69d8729c4de727b397e27bc11"
 "checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4"
 "checksum miow 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9224c91f82b3c47cf53dcf78dfaa20d6888fbcc5d272d5f2fcdf8a697f3c987d"
 "checksum new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0cdc457076c78ab54d5e0d6fa7c47981757f1e34dc39ff92787f217dede586c4"
@@ -3214,9 +3241,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "630de1ef5cc79d0cdd78b7e33b81f083cbfe90de0f4b2b2f07f905867c70e9fe"
 "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30"
 "checksum open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c281318d992e4432cfa799969467003d05921582a7489a8325e37f8a450d5113"
-"checksum openssl 0.10.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ed18a0f40ec4e9a8a81f8865033d823b7195d16a0a5721e10963ee1b0c2980ca"
+"checksum openssl 0.10.11 (registry+https://github.com/rust-lang/crates.io-index)" = "6c24d3508b4fb6da175c10baac54c578b33f09c89ae90c6fe9788b3b4768efdc"
 "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
-"checksum openssl-sys 0.9.33 (registry+https://github.com/rust-lang/crates.io-index)" = "d8abc04833dcedef24221a91852931df2f63e3369ae003134e70aff3645775cc"
+"checksum openssl-src 110.0.6+1.1.0h (registry+https://github.com/rust-lang/crates.io-index)" = "2011250f011d9c0f2e982f36721c9cbf451a9b04f425ea43a6a3f1bfa889a3b4"
+"checksum openssl-sys 0.9.35 (registry+https://github.com/rust-lang/crates.io-index)" = "912f301a749394e1025d9dcddef6106ddee9252620e6d0a0e5f8d0681de9b129"
 "checksum ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063"
 "checksum ordslice 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dd20eec3dbe4376829cb7d80ae6ac45e0a766831dca50202ff2d40db46a8a024"
 "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37"
index 829487163a945ec21f9850c997901520105ec9b4..d9c66ce2d77905614b5f242c68bfafc123bc7d48 100644 (file)
@@ -721,6 +721,10 @@ class RustBuild(object):
                 config = self.get_toml('lld')
                 if config is None or config == 'false':
                     continue
+            if module.endswith("lldb") or module.endswith("clang"):
+                config = self.get_toml('lldb')
+                if config is None or config == 'false':
+                    continue
             check = self.check_submodule(module, slow_submodules)
             filtered_submodules.append((module, check))
             submodules_names.append(module)
index dc0b0aaf0bb3c894802f18be4d2e21e94b11a57c..12c1972c22039aa4b4b8a498b326bfc70823269a 100644 (file)
@@ -461,6 +461,7 @@ macro_rules! describe {
                 dist::Rustfmt,
                 dist::Clippy,
                 dist::LlvmTools,
+                dist::Lldb,
                 dist::Extended,
                 dist::HashSign
             ),
index 1a94d597ef895d6e5ba8b0cdc0ceab073ca1ffec..43650332d3b67c901df7c8783b09953cd175401d 100644 (file)
@@ -87,6 +87,7 @@ pub struct Config {
     pub llvm_link_jobs: Option<u32>,
 
     pub lld_enabled: bool,
+    pub lldb_enabled: bool,
     pub llvm_tools_enabled: bool,
 
     // rust codegen options
@@ -310,6 +311,7 @@ struct Rust {
     codegen_backends_dir: Option<String>,
     wasm_syscall: Option<bool>,
     lld: Option<bool>,
+    lldb: Option<bool>,
     llvm_tools: Option<bool>,
     deny_warnings: Option<bool>,
     backtrace_on_ice: Option<bool>,
@@ -538,6 +540,7 @@ pub fn parse(args: &[String]) -> Config {
             }
             set(&mut config.wasm_syscall, rust.wasm_syscall);
             set(&mut config.lld_enabled, rust.lld);
+            set(&mut config.lldb_enabled, rust.lldb);
             set(&mut config.llvm_tools_enabled, rust.llvm_tools);
             config.rustc_parallel_queries = rust.experimental_parallel_queries.unwrap_or(false);
             config.rustc_default_linker = rust.default_linker.clone();
index 9fdba044f4be3da82b035e5bc110c4a477f9085d..cf7f78eeba04b13b16e3d64de41efd7609c1f8ca 100755 (executable)
@@ -68,6 +68,7 @@ o("cargo-openssl-static", "build.openssl-static", "static openssl in cargo")
 o("profiler", "build.profiler", "build the profiler runtime")
 o("emscripten", None, "compile the emscripten backend as well as LLVM")
 o("full-tools", None, "enable all tools")
+o("lldb", "rust.lldb", "build lldb")
 
 # Optimization and debugging options. These may be overridden by the release
 # channel, etc.
@@ -350,7 +351,7 @@ set('build.configure-args', sys.argv[1:])
 # all the various comments and whatnot.
 #
 # Note that the `target` section is handled separately as we'll duplicate it
-# per configure dtarget, so there's a bit of special handling for that here.
+# per configuretarget, so there's a bit of special handling for that here.
 sections = {}
 cur_section = None
 sections[None] = []
index 188e64cd668ddc6bb2bdc68c34051254656d1a7a..6e473fae3be5c0208279c662f12e0ead34e9bca1 100644 (file)
@@ -47,6 +47,8 @@ pub fn pkgname(builder: &Builder, component: &str) -> String {
         format!("{}-{}", component, builder.rustfmt_package_vers())
     } else if component == "llvm-tools" {
         format!("{}-{}", component, builder.llvm_tools_package_vers())
+    } else if component == "lldb" {
+        format!("{}-{}", component, builder.lldb_package_vers())
     } else {
         assert!(component.starts_with("rust"));
         format!("{}-{}", component, builder.rust_package_vers())
@@ -1396,6 +1398,7 @@ fn run(self, builder: &Builder) {
         let rls_installer = builder.ensure(Rls { stage, target });
         let llvm_tools_installer = builder.ensure(LlvmTools { stage, target });
         let clippy_installer = builder.ensure(Clippy { stage, target });
+        let lldb_installer = builder.ensure(Lldb { target });
         let mingw_installer = builder.ensure(Mingw { host: target });
         let analysis_installer = builder.ensure(Analysis {
             compiler: builder.compiler(stage, self.host),
@@ -1435,6 +1438,7 @@ fn run(self, builder: &Builder) {
         tarballs.extend(clippy_installer.clone());
         tarballs.extend(rustfmt_installer.clone());
         tarballs.extend(llvm_tools_installer.clone());
+        tarballs.extend(lldb_installer.clone());
         tarballs.push(analysis_installer);
         tarballs.push(std_installer);
         if builder.config.docs {
@@ -1869,6 +1873,7 @@ fn run(self, builder: &Builder) {
         cmd.arg(builder.package_vers(&builder.release_num("clippy")));
         cmd.arg(builder.package_vers(&builder.release_num("rustfmt")));
         cmd.arg(builder.llvm_tools_package_vers());
+        cmd.arg(builder.lldb_package_vers());
         cmd.arg(addr);
 
         builder.create_dir(&distdir(builder));
@@ -1963,3 +1968,121 @@ fn run(self, builder: &Builder) -> Option<PathBuf> {
         Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target)))
     }
 }
+
+#[derive(Clone, Debug, Eq, Hash, PartialEq)]
+pub struct Lldb {
+    pub target: Interned<String>,
+}
+
+impl Step for Lldb {
+    type Output = Option<PathBuf>;
+    const ONLY_HOSTS: bool = true;
+    const DEFAULT: bool = true;
+
+    fn should_run(run: ShouldRun) -> ShouldRun {
+        run.path("src/tools/lldb")
+    }
+
+    fn make_run(run: RunConfig) {
+        run.builder.ensure(Lldb {
+            target: run.target,
+        });
+    }
+
+    fn run(self, builder: &Builder) -> Option<PathBuf> {
+        let target = self.target;
+
+        if builder.config.dry_run {
+            return None;
+        }
+
+        let bindir = builder
+            .llvm_out(target)
+            .join("bin");
+        let lldb_exe = bindir.join(exe("lldb", &target));
+        if !lldb_exe.exists() {
+            return None;
+        }
+
+        builder.info(&format!("Dist Lldb ({})", target));
+        let src = builder.src.join("src/tools/lldb");
+        let name = pkgname(builder, "lldb");
+
+        let tmp = tmpdir(builder);
+        let image = tmp.join("lldb-image");
+        drop(fs::remove_dir_all(&image));
+
+        // Prepare the image directory
+        let dst = image.join("bin");
+        t!(fs::create_dir_all(&dst));
+        for program in &["lldb", "lldb-argdumper", "lldb-mi", "lldb-server"] {
+            let exe = bindir.join(exe(program, &target));
+            builder.install(&exe, &dst, 0o755);
+        }
+
+        // The libraries.
+        let libdir = builder.llvm_out(target).join("lib");
+        let dst = image.join("lib");
+        t!(fs::create_dir_all(&dst));
+        for entry in t!(fs::read_dir(&libdir)) {
+            // let entry = t!(entry);
+            let entry = entry.unwrap();
+            if let Ok(name) = entry.file_name().into_string() {
+                if name.starts_with("liblldb.") && !name.ends_with(".a") {
+                    if t!(entry.file_type()).is_symlink() {
+                        builder.copy_to_folder(&entry.path(), &dst);
+                    } else {
+                       builder.install(&entry.path(), &dst, 0o755);
+                    }
+                }
+            }
+        }
+
+        // The lldb scripts might be installed in lib/python$version
+        // or in lib64/python$version.  If lib64 exists, use it;
+        // otherwise lib.
+        let libdir = builder.llvm_out(target).join("lib64");
+        let (libdir, libdir_name) = if libdir.exists() {
+            (libdir, "lib64")
+        } else {
+            (builder.llvm_out(target).join("lib"), "lib")
+        };
+        for entry in t!(fs::read_dir(&libdir)) {
+            let entry = t!(entry);
+            if let Ok(name) = entry.file_name().into_string() {
+                if name.starts_with("python") {
+                    let dst = image.join(libdir_name)
+                        .join(entry.file_name());
+                    t!(fs::create_dir_all(&dst));
+                    builder.cp_r(&entry.path(), &dst);
+                    break;
+                }
+            }
+        }
+
+        // Prepare the overlay
+        let overlay = tmp.join("lldb-overlay");
+        drop(fs::remove_dir_all(&overlay));
+        builder.create_dir(&overlay);
+        builder.install(&src.join("LICENSE.TXT"), &overlay, 0o644);
+        builder.create(&overlay.join("version"), &builder.lldb_vers());
+
+        // Generate the installer tarball
+        let mut cmd = rust_installer(builder);
+        cmd.arg("generate")
+            .arg("--product-name=Rust")
+            .arg("--rel-manifest-dir=rustlib")
+            .arg("--success-message=lldb-installed.")
+            .arg("--image-dir").arg(&image)
+            .arg("--work-dir").arg(&tmpdir(builder))
+            .arg("--output-dir").arg(&distdir(builder))
+            .arg("--non-installed-overlay").arg(&overlay)
+            .arg(format!("--package-name={}-{}", name, target))
+            .arg("--legacy-manifest-dirs=rustlib,cargo")
+            .arg("--component-name=lldb-preview");
+
+
+        builder.run(&mut cmd);
+        Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target)))
+    }
+}
index 38965949bf22f6ce594090aa6c25812c4549f32f..5bb475e07ba8db1fb4ae46b6180b96f1a267b12d 100644 (file)
 use std::slice;
 use std::str;
 
+#[cfg(unix)]
+use std::os::unix::fs::symlink as symlink_file;
+#[cfg(windows)]
+use std::os::windows::fs::symlink_file;
+
 use build_helper::{run_silent, run_suppressed, try_run_silent, try_run_suppressed, output, mtime};
 use filetime::FileTime;
 
@@ -1005,6 +1010,14 @@ fn llvm_tools_vers(&self) -> String {
         self.rust_version()
     }
 
+    fn lldb_package_vers(&self) -> String {
+        self.package_vers(&self.rust_version())
+    }
+
+    fn lldb_vers(&self) -> String {
+        self.rust_version()
+    }
+
     /// Returns the `version` string associated with this compiler for Rust
     /// itself.
     ///
@@ -1123,20 +1136,24 @@ fn read_stamp_file(&self, stamp: &Path) -> Vec<PathBuf> {
     pub fn copy(&self, src: &Path, dst: &Path) {
         if self.config.dry_run { return; }
         let _ = fs::remove_file(&dst);
-        // Attempt to "easy copy" by creating a hard link (symlinks don't work on
-        // windows), but if that fails just fall back to a slow `copy` operation.
-        if let Ok(()) = fs::hard_link(src, dst) {
-            return
-        }
-        if let Err(e) = fs::copy(src, dst) {
-            panic!("failed to copy `{}` to `{}`: {}", src.display(),
-                dst.display(), e)
+        let metadata = t!(src.symlink_metadata());
+        if metadata.file_type().is_symlink() {
+            let link = t!(fs::read_link(src));
+            t!(symlink_file(link, dst));
+        } else if let Ok(()) = fs::hard_link(src, dst) {
+            // Attempt to "easy copy" by creating a hard link
+            // (symlinks don't work on windows), but if that fails
+            // just fall back to a slow `copy` operation.
+        } else {
+            if let Err(e) = fs::copy(src, dst) {
+                panic!("failed to copy `{}` to `{}`: {}", src.display(),
+                       dst.display(), e)
+            }
+            t!(fs::set_permissions(dst, metadata.permissions()));
+            let atime = FileTime::from_last_access_time(&metadata);
+            let mtime = FileTime::from_last_modification_time(&metadata);
+            t!(filetime::set_file_times(dst, atime, mtime));
         }
-        let metadata = t!(src.metadata());
-        t!(fs::set_permissions(dst, metadata.permissions()));
-        let atime = FileTime::from_last_access_time(&metadata);
-        let mtime = FileTime::from_last_modification_time(&metadata);
-        t!(filetime::set_file_times(dst, atime, mtime));
     }
 
     /// Search-and-replaces within a file. (Not maximally efficiently: allocates a
index d5e1ed02b44c173d5e4159b35e92f70a7de0b4b0..c99347aa94e6637548a86f2e49cf15262ad33775 100644 (file)
@@ -149,7 +149,6 @@ fn run(self, builder: &Builder) -> PathBuf {
            .define("WITH_POLLY", "OFF")
            .define("LLVM_ENABLE_TERMINFO", "OFF")
            .define("LLVM_ENABLE_LIBEDIT", "OFF")
-           .define("LLVM_ENABLE_LIBXML2", "OFF")
            .define("LLVM_PARALLEL_COMPILE_JOBS", builder.jobs().to_string())
            .define("LLVM_TARGET_ARCH", target.split('-').next().unwrap())
            .define("LLVM_DEFAULT_TARGET_TRIPLE", target);
@@ -163,6 +162,8 @@ fn run(self, builder: &Builder) -> PathBuf {
         cfg.define("LLVM_OCAML_INSTALL_PATH",
             env::var_os("LLVM_OCAML_INSTALL_PATH").unwrap_or_else(|| "usr/lib/ocaml".into()));
 
+        let want_lldb = builder.config.lldb_enabled && !self.emscripten;
+
         // This setting makes the LLVM tools link to the dynamic LLVM library,
         // which saves both memory during parallel links and overall disk space
         // for the tools.  We don't distribute any of those tools, so this is
@@ -170,12 +171,13 @@ fn run(self, builder: &Builder) -> PathBuf {
         //
         // If we are shipping llvm tools then we statically link them LLVM
         if (target.contains("linux-gnu") || target.contains("apple-darwin")) &&
-            !builder.config.llvm_tools_enabled {
+            !builder.config.llvm_tools_enabled &&
+            !want_lldb {
                 cfg.define("LLVM_LINK_LLVM_DYLIB", "ON");
         }
 
         // For distribution we want the LLVM tools to be *statically* linked to libstdc++
-        if builder.config.llvm_tools_enabled {
+        if builder.config.llvm_tools_enabled || want_lldb {
             if !target.contains("windows") {
                 if target.contains("apple") {
                     cfg.define("CMAKE_EXE_LINKER_FLAGS", "-static-libstdc++");
@@ -196,6 +198,17 @@ fn run(self, builder: &Builder) -> PathBuf {
             cfg.define("LLVM_BUILD_32_BITS", "ON");
         }
 
+        if want_lldb {
+            cfg.define("LLVM_EXTERNAL_CLANG_SOURCE_DIR", builder.src.join("src/tools/clang"));
+            cfg.define("LLVM_EXTERNAL_LLDB_SOURCE_DIR", builder.src.join("src/tools/lldb"));
+            // For the time being, disable code signing.
+            cfg.define("LLDB_CODESIGN_IDENTITY", "");
+        } else {
+            // LLDB requires libxml2; but otherwise we want it to be disabled.
+            // See https://github.com/rust-lang/rust/pull/50104
+            cfg.define("LLVM_ENABLE_LIBXML2", "OFF");
+        }
+
         if let Some(num_linkers) = builder.config.llvm_link_jobs {
             if num_linkers > 0 {
                 cfg.define("LLVM_PARALLEL_LINK_JOBS", num_linkers.to_string());
index 70c7c110b786a9569effe2e359764357b228e527..f787f629756f32b38fc41418eed8540fe5ce9a76 100644 (file)
@@ -8,7 +8,9 @@ The tracking issue for this feature is: [#29628]
 
 The `on_unimplemented` feature provides the `#[rustc_on_unimplemented]`
 attribute, which allows trait definitions to add specialized notes to error
-messages when an implementation was expected but not found.
+messages when an implementation was expected but not found. You can refer
+to the trait's generic arguments by name and to the resolved type using
+`Self`.
 
 For example:
 
@@ -41,7 +43,98 @@ error[E0277]: the trait bound `&[{integer}]: MyIterator<char>` is not satisfied
    |
    = help: the trait `MyIterator<char>` is not implemented for `&[{integer}]`
    = note: required by `iterate_chars`
+```
+
+`on_unimplemented` also supports advanced filtering for better targeting
+of messages, as well as modifying specific parts of the error message. You
+target the text of:
+
+ - the main error message (`message`)
+ - the label (`label`)
+ - an extra note (`note`)
+
+For example, the following attribute
+
+```rust,compile_fail
+#[rustc_on_unimplemented(
+    message="message",
+    label="label",
+    note="note"
+)]
+trait MyIterator<A> {
+    fn next(&mut self) -> A;
+}
+```
+
+Would generate the following output:
+
+```text
+error[E0277]: message
+  --> <anon>:14:5
+   |
+14 |     iterate_chars(&[1, 2, 3][..]);
+   |     ^^^^^^^^^^^^^ label
+   |
+   = note: note
+   = help: the trait `MyIterator<char>` is not implemented for `&[{integer}]`
+   = note: required by `iterate_chars`
+```
+
+To allow more targeted error messages, it is possible to filter the
+application of these fields based on a variety of attributes when using
+`on`:
 
-error: aborting due to previous error
+ - `crate_local`: whether the code causing the trait bound to not be
+   fulfilled is part of the user's crate. This is used to avoid suggesting
+   code changes that would require modifying a dependency.
+ - Any of the generic arguments that can be substituted in the text can be
+   referred by name as well for filtering, like `Rhs="i32"`, except for
+   `Self`.
+ - `_Self`: to filter only on a particular calculated trait resolution, like
+   `Self="std::iter::Iterator<char>"`. This is needed because `Self` is a
+   keyword which cannot appear in attributes.
+ - `direct`: user-specified rather than derived obligation.
+ - `from_method`: usable both as boolean (whether the flag is present, like
+   `crate_local`) or matching against a particular method. Currently used
+   for `try`.
+ - `from_desugaring`: usable both as boolean (whether the flag is present)
+   or matching against a particular desugaring.
+
+For example, the `Iterator` trait can be annotated in the following way:
+
+```rust,compile_fail
+#[rustc_on_unimplemented(
+    on(
+        _Self="&str",
+        note="call `.chars()` or `.as_bytes()` on `{Self}"
+    ),
+    message="`{Self}` is not an iterator",
+    label="`{Self}` is not an iterator",
+    note="maybe try calling `.iter()` or a similar method"
+)]
+pub trait Iterator {}
 ```
 
+Which would produce the following outputs:
+
+```text
+error[E0277]: `Foo` is not an iterator
+ --> src/main.rs:4:16
+  |
+4 |     for foo in Foo {}
+  |                ^^^ `Foo` is not an iterator
+  |
+  = note: maybe try calling `.iter()` or a similar method
+  = help: the trait `std::iter::Iterator` is not implemented for `Foo`
+  = note: required by `std::iter::IntoIterator::into_iter`
+
+error[E0277]: `&str` is not an iterator
+ --> src/main.rs:5:16
+  |
+5 |     for foo in "" {}
+  |                ^^ `&str` is not an iterator
+  |
+  = note: call `.chars()` or `.bytes() on `&str`
+  = help: the trait `std::iter::Iterator` is not implemented for `&str`
+  = note: required by `std::iter::IntoIterator::into_iter`
+```
index 84bd275df347c9c73b376c37e900ff3212be6900..c69b2fb5e1c2a3e27619f5994f767d8f49d036db 100644 (file)
@@ -56,6 +56,22 @@ fn __rust_realloc(ptr: *mut u8,
 /// # Safety
 ///
 /// See [`GlobalAlloc::alloc`].
+///
+/// # Examples
+///
+/// ```
+/// use std::alloc::{alloc, dealloc, Layout};
+///
+/// unsafe {
+///     let layout = Layout::new::<u16>();
+///     let ptr = alloc(layout);
+///
+///     *(ptr as *mut u16) = 42;
+///     assert_eq!(*(ptr as *mut u16), 42);
+///
+///     dealloc(ptr, layout);
+/// }
+/// ```
 #[stable(feature = "global_alloc", since = "1.28.0")]
 #[inline]
 pub unsafe fn alloc(layout: Layout) -> *mut u8 {
@@ -110,6 +126,21 @@ pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8
 /// # Safety
 ///
 /// See [`GlobalAlloc::alloc_zeroed`].
+///
+/// # Examples
+///
+/// ```
+/// use std::alloc::{alloc_zeroed, dealloc, Layout};
+///
+/// unsafe {
+///     let layout = Layout::new::<u16>();
+///     let ptr = alloc_zeroed(layout);
+///
+///     assert_eq!(*(ptr as *mut u16), 0);
+///
+///     dealloc(ptr, layout);
+/// }
+/// ```
 #[stable(feature = "global_alloc", since = "1.28.0")]
 #[inline]
 pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 {
index 5681cfb04f2088c1fece1a7ede7c9d835b3eb0b5..3918529105334b23ff2aa614beb704f37b2106df 100644 (file)
@@ -1110,7 +1110,7 @@ fn flat_map<U, F>(self, f: F) -> FlatMap<Self, U, F>
     ///
     /// [`flat_map()`]: #method.flat_map
     #[inline]
-    #[stable(feature = "iterator_flatten", since = "1.29")]
+    #[stable(feature = "iterator_flatten", since = "1.29.0")]
     fn flatten(self) -> Flatten<Self>
     where Self: Sized, Self::Item: IntoIterator {
         Flatten { inner: flatten_compat(self) }
index 35ae77411069cdf5c9a63fda2fedc313dad341b3..ef3f4ced4f9b2306fbaea947ab63acf690a3c584 100644 (file)
@@ -2577,13 +2577,13 @@ impl<I, U, F> FusedIterator for FlatMap<I, U, F>
 /// [`flatten`]: trait.Iterator.html#method.flatten
 /// [`Iterator`]: trait.Iterator.html
 #[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
-#[stable(feature = "iterator_flatten", since = "1.29")]
+#[stable(feature = "iterator_flatten", since = "1.29.0")]
 pub struct Flatten<I: Iterator>
 where I::Item: IntoIterator {
     inner: FlattenCompat<I, <I::Item as IntoIterator>::IntoIter>,
 }
 
-#[stable(feature = "iterator_flatten", since = "1.29")]
+#[stable(feature = "iterator_flatten", since = "1.29.0")]
 impl<I, U> fmt::Debug for Flatten<I>
     where I: Iterator + fmt::Debug, U: Iterator + fmt::Debug,
           I::Item: IntoIterator<IntoIter = U, Item = U::Item>,
@@ -2593,7 +2593,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-#[stable(feature = "iterator_flatten", since = "1.29")]
+#[stable(feature = "iterator_flatten", since = "1.29.0")]
 impl<I, U> Clone for Flatten<I>
     where I: Iterator + Clone, U: Iterator + Clone,
           I::Item: IntoIterator<IntoIter = U, Item = U::Item>,
@@ -2601,7 +2601,7 @@ impl<I, U> Clone for Flatten<I>
     fn clone(&self) -> Self { Flatten { inner: self.inner.clone() } }
 }
 
-#[stable(feature = "iterator_flatten", since = "1.29")]
+#[stable(feature = "iterator_flatten", since = "1.29.0")]
 impl<I, U> Iterator for Flatten<I>
     where I: Iterator, U: Iterator,
           I::Item: IntoIterator<IntoIter = U, Item = U::Item>
@@ -2629,7 +2629,7 @@ fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
     }
 }
 
-#[stable(feature = "iterator_flatten", since = "1.29")]
+#[stable(feature = "iterator_flatten", since = "1.29.0")]
 impl<I, U> DoubleEndedIterator for Flatten<I>
     where I: DoubleEndedIterator, U: DoubleEndedIterator,
           I::Item: IntoIterator<IntoIter = U, Item = U::Item>
@@ -2652,7 +2652,7 @@ fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
     }
 }
 
-#[stable(feature = "iterator_flatten", since = "1.29")]
+#[stable(feature = "iterator_flatten", since = "1.29.0")]
 impl<I, U> FusedIterator for Flatten<I>
     where I: FusedIterator, U: Iterator,
           I::Item: IntoIterator<IntoIter = U, Item = U::Item> {}
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)*))
     );
 }
 
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 e250b7549a0520484e6ee7e02da32d4ec1f36c5c..b6f4bd6dc408c9ffb4dfa10b2b7a935ad741434c 100644 (file)
@@ -135,7 +135,6 @@ pub mod middle {
     pub mod borrowck;
     pub mod expr_use_visitor;
     pub mod cstore;
-    pub mod dataflow;
     pub mod dead;
     pub mod dependency_format;
     pub mod entry;
diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs
deleted file mode 100644 (file)
index b949fd0..0000000
+++ /dev/null
@@ -1,686 +0,0 @@
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-
-//! A module for propagating forward dataflow information. The analysis
-//! assumes that the items to be propagated can be represented as bits
-//! and thus uses bitvectors. Your job is simply to specify the so-called
-//! GEN and KILL bits for each expression.
-
-use cfg;
-use cfg::CFGIndex;
-use ty::TyCtxt;
-use std::io;
-use std::mem;
-use std::usize;
-use syntax::print::pprust::PrintState;
-
-use rustc_data_structures::graph::implementation::OUTGOING;
-
-use util::nodemap::FxHashMap;
-use hir;
-use hir::intravisit::{self, IdRange};
-use hir::print as pprust;
-
-
-#[derive(Copy, Clone, Debug)]
-pub enum EntryOrExit {
-    Entry,
-    Exit,
-}
-
-#[derive(Clone)]
-pub struct DataFlowContext<'a, 'tcx: 'a, O> {
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-
-    /// a name for the analysis using this dataflow instance
-    analysis_name: &'static str,
-
-    /// the data flow operator
-    oper: O,
-
-    /// number of bits to propagate per id
-    bits_per_id: usize,
-
-    /// number of words we will use to store bits_per_id.
-    /// equal to bits_per_id/usize::BITS rounded up.
-    words_per_id: usize,
-
-    // mapping from node to cfg node index
-    // FIXME (#6298): Shouldn't this go with CFG?
-    local_id_to_index: FxHashMap<hir::ItemLocalId, Vec<CFGIndex>>,
-
-    // Bit sets per cfg node.  The following three fields (`gens`, `kills`,
-    // and `on_entry`) all have the same structure. For each id in
-    // `id_range`, there is a range of words equal to `words_per_id`.
-    // So, to access the bits for any given id, you take a slice of
-    // the full vector (see the method `compute_id_range()`).
-
-    /// bits generated as we exit the cfg node. Updated by `add_gen()`.
-    gens: Vec<usize>,
-
-    /// bits killed as we exit the cfg node, or non-locally jump over
-    /// it. Updated by `add_kill(KillFrom::ScopeEnd)`.
-    scope_kills: Vec<usize>,
-
-    /// bits killed as we exit the cfg node directly; if it is jumped
-    /// over, e.g. via `break`, the kills are not reflected in the
-    /// jump's effects. Updated by `add_kill(KillFrom::Execution)`.
-    action_kills: Vec<usize>,
-
-    /// bits that are valid on entry to the cfg node. Updated by
-    /// `propagate()`.
-    on_entry: Vec<usize>,
-}
-
-pub trait BitwiseOperator {
-    /// Joins two predecessor bits together, typically either `|` or `&`
-    fn join(&self, succ: usize, pred: usize) -> usize;
-}
-
-/// Parameterization for the precise form of data flow that is used.
-pub trait DataFlowOperator : BitwiseOperator {
-    /// Specifies the initial value for each bit in the `on_entry` set
-    fn initial_value(&self) -> bool;
-}
-
-struct PropagationContext<'a, 'b: 'a, 'tcx: 'b, O: 'a> {
-    dfcx: &'a mut DataFlowContext<'b, 'tcx, O>,
-    changed: bool
-}
-
-fn get_cfg_indices<'a>(id: hir::ItemLocalId,
-                       index: &'a FxHashMap<hir::ItemLocalId, Vec<CFGIndex>>)
-                       -> &'a [CFGIndex] {
-    index.get(&id).map_or(&[], |v| &v[..])
-}
-
-impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> {
-    fn has_bitset_for_local_id(&self, n: hir::ItemLocalId) -> bool {
-        assert!(n != hir::DUMMY_ITEM_LOCAL_ID);
-        self.local_id_to_index.contains_key(&n)
-    }
-}
-
-impl<'a, 'tcx, O:DataFlowOperator> pprust::PpAnn for DataFlowContext<'a, 'tcx, O> {
-    fn nested(&self, state: &mut pprust::State, nested: pprust::Nested) -> io::Result<()> {
-        pprust::PpAnn::nested(&self.tcx.hir, state, nested)
-    }
-    fn pre(&self,
-           ps: &mut pprust::State,
-           node: pprust::AnnNode) -> io::Result<()> {
-        let id = match node {
-            pprust::NodeName(_) => return Ok(()),
-            pprust::NodeExpr(expr) => expr.hir_id.local_id,
-            pprust::NodeBlock(blk) => blk.hir_id.local_id,
-            pprust::NodeItem(_) |
-            pprust::NodeSubItem(_) => return Ok(()),
-            pprust::NodePat(pat) => pat.hir_id.local_id
-        };
-
-        if !self.has_bitset_for_local_id(id) {
-            return Ok(());
-        }
-
-        assert!(self.bits_per_id > 0);
-        let indices = get_cfg_indices(id, &self.local_id_to_index);
-        for &cfgidx in indices {
-            let (start, end) = self.compute_id_range(cfgidx);
-            let on_entry = &self.on_entry[start.. end];
-            let entry_str = bits_to_string(on_entry);
-
-            let gens = &self.gens[start.. end];
-            let gens_str = if gens.iter().any(|&u| u != 0) {
-                format!(" gen: {}", bits_to_string(gens))
-            } else {
-                "".to_string()
-            };
-
-            let action_kills = &self.action_kills[start .. end];
-            let action_kills_str = if action_kills.iter().any(|&u| u != 0) {
-                format!(" action_kill: {}", bits_to_string(action_kills))
-            } else {
-                "".to_string()
-            };
-
-            let scope_kills = &self.scope_kills[start .. end];
-            let scope_kills_str = if scope_kills.iter().any(|&u| u != 0) {
-                format!(" scope_kill: {}", bits_to_string(scope_kills))
-            } else {
-                "".to_string()
-            };
-
-            ps.synth_comment(
-                format!("id {}: {}{}{}{}", id.as_usize(), entry_str,
-                        gens_str, action_kills_str, scope_kills_str))?;
-            ps.s.space()?;
-        }
-        Ok(())
-    }
-}
-
-fn build_local_id_to_index(body: Option<&hir::Body>,
-                           cfg: &cfg::CFG)
-                           -> FxHashMap<hir::ItemLocalId, Vec<CFGIndex>> {
-    let mut index = FxHashMap();
-
-    // FIXME(#15020) Would it be better to fold formals from decl
-    // into cfg itself?  i.e. introduce a fn-based flow-graph in
-    // addition to the current block-based flow-graph, rather than
-    // have to put traversals like this here?
-    if let Some(body) = body {
-        add_entries_from_fn_body(&mut index, body, cfg.entry);
-    }
-
-    cfg.graph.each_node(|node_idx, node| {
-        if let cfg::CFGNodeData::AST(id) = node.data {
-            index.entry(id).or_insert(vec![]).push(node_idx);
-        }
-        true
-    });
-
-    return index;
-
-    /// Add mappings from the ast nodes for the formal bindings to
-    /// the entry-node in the graph.
-    fn add_entries_from_fn_body(index: &mut FxHashMap<hir::ItemLocalId, Vec<CFGIndex>>,
-                                body: &hir::Body,
-                                entry: CFGIndex) {
-        use hir::intravisit::Visitor;
-
-        struct Formals<'a> {
-            entry: CFGIndex,
-            index: &'a mut FxHashMap<hir::ItemLocalId, Vec<CFGIndex>>,
-        }
-        let mut formals = Formals { entry: entry, index: index };
-        for arg in &body.arguments {
-            formals.visit_pat(&arg.pat);
-        }
-        impl<'a, 'v> Visitor<'v> for Formals<'a> {
-            fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'v> {
-                intravisit::NestedVisitorMap::None
-            }
-
-            fn visit_pat(&mut self, p: &hir::Pat) {
-                self.index.entry(p.hir_id.local_id).or_insert(vec![]).push(self.entry);
-                intravisit::walk_pat(self, p)
-            }
-        }
-    }
-}
-
-/// Flag used by `add_kill` to indicate whether the provided kill
-/// takes effect only when control flows directly through the node in
-/// question, or if the kill's effect is associated with any
-/// control-flow directly through or indirectly over the node.
-#[derive(Copy, Clone, PartialEq, Debug)]
-pub enum KillFrom {
-    /// A `ScopeEnd` kill is one that takes effect when any control
-    /// flow goes over the node. A kill associated with the end of the
-    /// scope of a variable declaration `let x;` is an example of a
-    /// `ScopeEnd` kill.
-    ScopeEnd,
-
-    /// An `Execution` kill is one that takes effect only when control
-    /// flow goes through the node to completion. A kill associated
-    /// with an assignment statement `x = expr;` is an example of an
-    /// `Execution` kill.
-    Execution,
-}
-
-impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> {
-    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-               analysis_name: &'static str,
-               body: Option<&hir::Body>,
-               cfg: &cfg::CFG,
-               oper: O,
-               id_range: IdRange,
-               bits_per_id: usize) -> DataFlowContext<'a, 'tcx, O> {
-        let usize_bits = mem::size_of::<usize>() * 8;
-        let words_per_id = (bits_per_id + usize_bits - 1) / usize_bits;
-        let num_nodes = cfg.graph.all_nodes().len();
-
-        debug!("DataFlowContext::new(analysis_name: {}, id_range={:?}, \
-                                     bits_per_id={}, words_per_id={}) \
-                                     num_nodes: {}",
-               analysis_name, id_range, bits_per_id, words_per_id,
-               num_nodes);
-
-        let entry = if oper.initial_value() { usize::MAX } else {0};
-
-        let zeroes = vec![0; num_nodes * words_per_id];
-        let gens = zeroes.clone();
-        let kills1 = zeroes.clone();
-        let kills2 = zeroes;
-        let on_entry = vec![entry; num_nodes * words_per_id];
-
-        let local_id_to_index = build_local_id_to_index(body, cfg);
-
-        DataFlowContext {
-            tcx,
-            analysis_name,
-            words_per_id,
-            local_id_to_index,
-            bits_per_id,
-            oper,
-            gens,
-            action_kills: kills1,
-            scope_kills: kills2,
-            on_entry,
-        }
-    }
-
-    pub fn add_gen(&mut self, id: hir::ItemLocalId, bit: usize) {
-        //! Indicates that `id` generates `bit`
-        debug!("{} add_gen(id={:?}, bit={})",
-               self.analysis_name, id, bit);
-        assert!(self.local_id_to_index.contains_key(&id));
-        assert!(self.bits_per_id > 0);
-
-        let indices = get_cfg_indices(id, &self.local_id_to_index);
-        for &cfgidx in indices {
-            let (start, end) = self.compute_id_range(cfgidx);
-            let gens = &mut self.gens[start.. end];
-            set_bit(gens, bit);
-        }
-    }
-
-    pub fn add_kill(&mut self, kind: KillFrom, id: hir::ItemLocalId, bit: usize) {
-        //! Indicates that `id` kills `bit`
-        debug!("{} add_kill(id={:?}, bit={})",
-               self.analysis_name, id, bit);
-        assert!(self.local_id_to_index.contains_key(&id));
-        assert!(self.bits_per_id > 0);
-
-        let indices = get_cfg_indices(id, &self.local_id_to_index);
-        for &cfgidx in indices {
-            let (start, end) = self.compute_id_range(cfgidx);
-            let kills = match kind {
-                KillFrom::Execution => &mut self.action_kills[start.. end],
-                KillFrom::ScopeEnd =>  &mut self.scope_kills[start.. end],
-            };
-            set_bit(kills, bit);
-        }
-    }
-
-    fn apply_gen_kill(&self, cfgidx: CFGIndex, bits: &mut [usize]) {
-        //! Applies the gen and kill sets for `cfgidx` to `bits`
-        debug!("{} apply_gen_kill(cfgidx={:?}, bits={}) [before]",
-               self.analysis_name, cfgidx, mut_bits_to_string(bits));
-        assert!(self.bits_per_id > 0);
-
-        let (start, end) = self.compute_id_range(cfgidx);
-        let gens = &self.gens[start.. end];
-        bitwise(bits, gens, &Union);
-        let kills = &self.action_kills[start.. end];
-        bitwise(bits, kills, &Subtract);
-        let kills = &self.scope_kills[start.. end];
-        bitwise(bits, kills, &Subtract);
-
-        debug!("{} apply_gen_kill(cfgidx={:?}, bits={}) [after]",
-               self.analysis_name, cfgidx, mut_bits_to_string(bits));
-    }
-
-    fn compute_id_range(&self, cfgidx: CFGIndex) -> (usize, usize) {
-        let n = cfgidx.node_id();
-        let start = n * self.words_per_id;
-        let end = start + self.words_per_id;
-
-        assert!(start < self.gens.len());
-        assert!(end <= self.gens.len());
-        assert!(self.gens.len() == self.action_kills.len());
-        assert!(self.gens.len() == self.scope_kills.len());
-        assert!(self.gens.len() == self.on_entry.len());
-
-        (start, end)
-    }
-
-
-    pub fn each_bit_on_entry<F>(&self, id: hir::ItemLocalId, mut f: F) -> bool where
-        F: FnMut(usize) -> bool,
-    {
-        //! Iterates through each bit that is set on entry to `id`.
-        //! Only useful after `propagate()` has been called.
-        if !self.has_bitset_for_local_id(id) {
-            return true;
-        }
-        let indices = get_cfg_indices(id, &self.local_id_to_index);
-        for &cfgidx in indices {
-            if !self.each_bit_for_node(EntryOrExit::Entry, cfgidx, |i| f(i)) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    pub fn each_bit_for_node<F>(&self, e: EntryOrExit, cfgidx: CFGIndex, f: F) -> bool where
-        F: FnMut(usize) -> bool,
-    {
-        //! Iterates through each bit that is set on entry/exit to `cfgidx`.
-        //! Only useful after `propagate()` has been called.
-
-        if self.bits_per_id == 0 {
-            // Skip the surprisingly common degenerate case.  (Note
-            // compute_id_range requires self.words_per_id > 0.)
-            return true;
-        }
-
-        let (start, end) = self.compute_id_range(cfgidx);
-        let on_entry = &self.on_entry[start.. end];
-        let temp_bits;
-        let slice = match e {
-            EntryOrExit::Entry => on_entry,
-            EntryOrExit::Exit => {
-                let mut t = on_entry.to_vec();
-                self.apply_gen_kill(cfgidx, &mut t);
-                temp_bits = t;
-                &temp_bits[..]
-            }
-        };
-        debug!("{} each_bit_for_node({:?}, cfgidx={:?}) bits={}",
-               self.analysis_name, e, cfgidx, bits_to_string(slice));
-        self.each_bit(slice, f)
-    }
-
-    pub fn each_gen_bit<F>(&self, id: hir::ItemLocalId, mut f: F) -> bool where
-        F: FnMut(usize) -> bool,
-    {
-        //! Iterates through each bit in the gen set for `id`.
-        if !self.has_bitset_for_local_id(id) {
-            return true;
-        }
-
-        if self.bits_per_id == 0 {
-            // Skip the surprisingly common degenerate case.  (Note
-            // compute_id_range requires self.words_per_id > 0.)
-            return true;
-        }
-
-        let indices = get_cfg_indices(id, &self.local_id_to_index);
-        for &cfgidx in indices {
-            let (start, end) = self.compute_id_range(cfgidx);
-            let gens = &self.gens[start.. end];
-            debug!("{} each_gen_bit(id={:?}, gens={})",
-                   self.analysis_name, id, bits_to_string(gens));
-            if !self.each_bit(gens, |i| f(i)) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    fn each_bit<F>(&self, words: &[usize], mut f: F) -> bool where
-        F: FnMut(usize) -> bool,
-    {
-        //! Helper for iterating over the bits in a bit set.
-        //! Returns false on the first call to `f` that returns false;
-        //! if all calls to `f` return true, then returns true.
-
-        let usize_bits = mem::size_of::<usize>() * 8;
-        for (word_index, &word) in words.iter().enumerate() {
-            if word != 0 {
-                let base_index = word_index * usize_bits;
-                for offset in 0..usize_bits {
-                    let bit = 1 << offset;
-                    if (word & bit) != 0 {
-                        // NB: we round up the total number of bits
-                        // that we store in any given bit set so that
-                        // it is an even multiple of usize::BITS.  This
-                        // means that there may be some stray bits at
-                        // the end that do not correspond to any
-                        // actual value.  So before we callback, check
-                        // whether the bit_index is greater than the
-                        // actual value the user specified and stop
-                        // iterating if so.
-                        let bit_index = base_index + offset as usize;
-                        if bit_index >= self.bits_per_id {
-                            return true;
-                        } else if !f(bit_index) {
-                            return false;
-                        }
-                    }
-                }
-            }
-        }
-        return true;
-    }
-
-    pub fn add_kills_from_flow_exits(&mut self, cfg: &cfg::CFG) {
-        //! Whenever you have a `break` or `continue` statement, flow
-        //! exits through any number of enclosing scopes on its way to
-        //! the new destination. This function infers the kill bits of
-        //! those control operators based on the kill bits associated
-        //! with those scopes.
-        //!
-        //! This is usually called (if it is called at all), after
-        //! all add_gen and add_kill calls, but before propagate.
-
-        debug!("{} add_kills_from_flow_exits", self.analysis_name);
-        if self.bits_per_id == 0 {
-            // Skip the surprisingly common degenerate case.  (Note
-            // compute_id_range requires self.words_per_id > 0.)
-            return;
-        }
-        cfg.graph.each_edge(|_edge_index, edge| {
-            let flow_exit = edge.source();
-            let (start, end) = self.compute_id_range(flow_exit);
-            let mut orig_kills = self.scope_kills[start.. end].to_vec();
-
-            let mut changed = false;
-            for &id in &edge.data.exiting_scopes {
-                let opt_cfg_idx = self.local_id_to_index.get(&id);
-                match opt_cfg_idx {
-                    Some(indices) => {
-                        for &cfg_idx in indices {
-                            let (start, end) = self.compute_id_range(cfg_idx);
-                            let kills = &self.scope_kills[start.. end];
-                            if bitwise(&mut orig_kills, kills, &Union) {
-                                debug!("scope exits: scope id={:?} \
-                                        (node={:?} of {:?}) added killset: {}",
-                                       id, cfg_idx, indices,
-                                       bits_to_string(kills));
-                                changed = true;
-                            }
-                        }
-                    }
-                    None => {
-                        debug!("{} add_kills_from_flow_exits flow_exit={:?} \
-                                no cfg_idx for exiting_scope={:?}",
-                               self.analysis_name, flow_exit, id);
-                    }
-                }
-            }
-
-            if changed {
-                let bits = &mut self.scope_kills[start.. end];
-                debug!("{} add_kills_from_flow_exits flow_exit={:?} bits={} [before]",
-                       self.analysis_name, flow_exit, mut_bits_to_string(bits));
-                bits.copy_from_slice(&orig_kills[..]);
-                debug!("{} add_kills_from_flow_exits flow_exit={:?} bits={} [after]",
-                       self.analysis_name, flow_exit, mut_bits_to_string(bits));
-            }
-            true
-        });
-    }
-}
-
-impl<'a, 'tcx, O:DataFlowOperator+Clone+'static> DataFlowContext<'a, 'tcx, O> {
-//                                ^^^^^^^^^^^^^ only needed for pretty printing
-    pub fn propagate(&mut self, cfg: &cfg::CFG, body: &hir::Body) {
-        //! Performs the data flow analysis.
-
-        if self.bits_per_id == 0 {
-            // Optimize the surprisingly common degenerate case.
-            return;
-        }
-
-        {
-            let words_per_id = self.words_per_id;
-            let mut propcx = PropagationContext {
-                dfcx: &mut *self,
-                changed: true
-            };
-
-            let nodes_po = cfg.graph.nodes_in_postorder(OUTGOING, cfg.entry);
-            let mut temp = vec![0; words_per_id];
-            let mut num_passes = 0;
-            while propcx.changed {
-                num_passes += 1;
-                propcx.changed = false;
-                propcx.reset(&mut temp);
-                propcx.walk_cfg(cfg, &nodes_po, &mut temp);
-            }
-            debug!("finished in {} iterations", num_passes);
-        }
-
-        debug!("Dataflow result for {}:", self.analysis_name);
-        debug!("{}", pprust::to_string(self, |s| {
-            s.cbox(pprust::indent_unit)?;
-            s.ibox(0)?;
-            s.print_expr(&body.value)
-        }));
-    }
-}
-
-impl<'a, 'b, 'tcx, O:DataFlowOperator> PropagationContext<'a, 'b, 'tcx, O> {
-    fn walk_cfg(&mut self,
-                cfg: &cfg::CFG,
-                nodes_po: &[CFGIndex],
-                in_out: &mut [usize]) {
-        debug!("DataFlowContext::walk_cfg(in_out={}) {}",
-               bits_to_string(in_out), self.dfcx.analysis_name);
-        assert!(self.dfcx.bits_per_id > 0);
-
-        // Iterate over nodes in reverse postorder
-        for &node_index in nodes_po.iter().rev() {
-            let node = cfg.graph.node(node_index);
-            debug!("DataFlowContext::walk_cfg idx={:?} id={:?} begin in_out={}",
-                   node_index, node.data.id(), bits_to_string(in_out));
-
-            let (start, end) = self.dfcx.compute_id_range(node_index);
-
-            // Initialize local bitvector with state on-entry.
-            in_out.copy_from_slice(&self.dfcx.on_entry[start.. end]);
-
-            // Compute state on-exit by applying transfer function to
-            // state on-entry.
-            self.dfcx.apply_gen_kill(node_index, in_out);
-
-            // Propagate state on-exit from node into its successors.
-            self.propagate_bits_into_graph_successors_of(in_out, cfg, node_index);
-        }
-    }
-
-    fn reset(&mut self, bits: &mut [usize]) {
-        let e = if self.dfcx.oper.initial_value() {usize::MAX} else {0};
-        for b in bits {
-            *b = e;
-        }
-    }
-
-    fn propagate_bits_into_graph_successors_of(&mut self,
-                                               pred_bits: &[usize],
-                                               cfg: &cfg::CFG,
-                                               cfgidx: CFGIndex) {
-        for (_, edge) in cfg.graph.outgoing_edges(cfgidx) {
-            self.propagate_bits_into_entry_set_for(pred_bits, edge);
-        }
-    }
-
-    fn propagate_bits_into_entry_set_for(&mut self,
-                                         pred_bits: &[usize],
-                                         edge: &cfg::CFGEdge) {
-        let source = edge.source();
-        let cfgidx = edge.target();
-        debug!("{} propagate_bits_into_entry_set_for(pred_bits={}, {:?} to {:?})",
-               self.dfcx.analysis_name, bits_to_string(pred_bits), source, cfgidx);
-        assert!(self.dfcx.bits_per_id > 0);
-
-        let (start, end) = self.dfcx.compute_id_range(cfgidx);
-        let changed = {
-            // (scoping mutable borrow of self.dfcx.on_entry)
-            let on_entry = &mut self.dfcx.on_entry[start.. end];
-            bitwise(on_entry, pred_bits, &self.dfcx.oper)
-        };
-        if changed {
-            debug!("{} changed entry set for {:?} to {}",
-                   self.dfcx.analysis_name, cfgidx,
-                   bits_to_string(&self.dfcx.on_entry[start.. end]));
-            self.changed = true;
-        }
-    }
-}
-
-fn mut_bits_to_string(words: &mut [usize]) -> String {
-    bits_to_string(words)
-}
-
-fn bits_to_string(words: &[usize]) -> String {
-    let mut result = String::new();
-    let mut sep = '[';
-
-    // Note: this is a little endian printout of bytes.
-
-    for &word in words {
-        let mut v = word;
-        for _ in 0..mem::size_of::<usize>() {
-            result.push(sep);
-            result.push_str(&format!("{:02x}", v & 0xFF));
-            v >>= 8;
-            sep = '-';
-        }
-    }
-    result.push(']');
-    return result
-}
-
-#[inline]
-fn bitwise<Op:BitwiseOperator>(out_vec: &mut [usize],
-                               in_vec: &[usize],
-                               op: &Op) -> bool {
-    assert_eq!(out_vec.len(), in_vec.len());
-    let mut changed = false;
-    for (out_elt, in_elt) in out_vec.iter_mut().zip(in_vec) {
-        let old_val = *out_elt;
-        let new_val = op.join(old_val, *in_elt);
-        *out_elt = new_val;
-        changed |= old_val != new_val;
-    }
-    changed
-}
-
-fn set_bit(words: &mut [usize], bit: usize) -> bool {
-    debug!("set_bit: words={} bit={}",
-           mut_bits_to_string(words), bit_str(bit));
-    let usize_bits = mem::size_of::<usize>() * 8;
-    let word = bit / usize_bits;
-    let bit_in_word = bit % usize_bits;
-    let bit_mask = 1 << bit_in_word;
-    debug!("word={} bit_in_word={} bit_mask={}", word, bit_in_word, bit_mask);
-    let oldv = words[word];
-    let newv = oldv | bit_mask;
-    words[word] = newv;
-    oldv != newv
-}
-
-fn bit_str(bit: usize) -> String {
-    let byte = bit >> 3;
-    let lobits = 1 << (bit & 0b111);
-    format!("[{}:{}-{:02x}]", bit, byte, lobits)
-}
-
-struct Union;
-impl BitwiseOperator for Union {
-    fn join(&self, a: usize, b: usize) -> usize { a | b }
-}
-struct Subtract;
-impl BitwiseOperator for Subtract {
-    fn join(&self, a: usize, b: usize) -> usize { a & !b }
-}
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 b55843ac527dfd9a90907a602bd492c48360dcb2..5991845d265b24a8ce86842d5f10d6d0e34a7dab 100644 (file)
@@ -127,14 +127,14 @@ pub fn ty<'a, 'gcx, D>(&self, local_decls: &D, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> P
     /// of a closure type.
     pub fn is_upvar_field_projection<'cx, 'gcx>(&self, mir: &'cx Mir<'tcx>,
                                                 tcx: &TyCtxt<'cx, 'gcx, 'tcx>) -> Option<Field> {
-        let place = if let Place::Projection(ref proj) = self {
+        let (place, by_ref) = if let Place::Projection(ref proj) = self {
             if let ProjectionElem::Deref = proj.elem {
-                &proj.base
+                (&proj.base, true)
             } else {
-                self
+                (self, false)
             }
         } else {
-            self
+            (self, false)
         };
 
         match place {
@@ -142,14 +142,16 @@ pub fn is_upvar_field_projection<'cx, 'gcx>(&self, mir: &'cx Mir<'tcx>,
                 ProjectionElem::Field(field, _ty) => {
                     let base_ty = proj.base.ty(mir, *tcx).to_ty(*tcx);
 
-                    if  base_ty.is_closure() || base_ty.is_generator() {
+                    if (base_ty.is_closure() || base_ty.is_generator()) &&
+                        (!by_ref || mir.upvar_decls[field.index()].by_ref)
+                    {
                         Some(field)
                     } else {
                         None
                     }
                 },
                 _ => None,
-            },
+            }\f
             _ => None,
         }
     }
index 7349c520c240778f09e433cbbc4aff66d58ff523..99b2f3e59feb66253d2f4bbffe67a5a6fc2af0bc 100644 (file)
@@ -1472,11 +1472,16 @@ fn note_obligation_cause_code<T>(&self,
             ObligationCauseCode::StructInitializerSized => {
                 err.note("structs must have a statically known size to be initialized");
             }
-            ObligationCauseCode::FieldSized(ref item) => {
+            ObligationCauseCode::FieldSized { adt_kind: ref item, last } => {
                 match *item {
                     AdtKind::Struct => {
-                        err.note("only the last field of a struct may have a dynamically \
-                                  sized type");
+                        if last {
+                            err.note("the last field of a packed struct may only have a \
+                                      dynamically sized type if it does not need drop to be run");
+                        } else {
+                            err.note("only the last field of a struct may have a dynamically \
+                                      sized type");
+                        }
                     }
                     AdtKind::Union => {
                         err.note("no field of a union may have a dynamically sized type");
index 0290f2e3b13f08e335a1319ca22b64108e9d9517..08434b5f24ef9d2e19503a06fb4ae76bb5a89f78 100644 (file)
@@ -192,8 +192,8 @@ pub enum ObligationCauseCode<'tcx> {
     /// [T,..n] --> T must be Copy
     RepeatVec,
 
-    /// Types of fields (other than the last) in a struct must be sized.
-    FieldSized(AdtKind),
+    /// Types of fields (other than the last, except for packed structs) in a struct must be sized.
+    FieldSized { adt_kind: AdtKind, last: bool },
 
     /// Constant expressions must be sized.
     ConstSized,
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 fbd12c9fe8ecaf796a8f2be66c3c5944fa69d979..ea96c30502680362db489f3af847504fd2a8cede 100644 (file)
@@ -226,6 +226,7 @@ pub struct SelectionCache<'tcx> {
 /// parameter environment.
 #[derive(PartialEq,Eq,Debug,Clone)]
 enum SelectionCandidate<'tcx> {
+    /// If has_nested is false, there are no *further* obligations
     BuiltinCandidate { has_nested: bool },
     ParamCandidate(ty::PolyTraitRef<'tcx>),
     ImplCandidate(DefId),
@@ -2039,12 +2040,20 @@ fn candidate_should_be_dropped_in_favor_of<'o>(
         }
 
         match other.candidate {
+            // Prefer BuiltinCandidate { has_nested: false } to anything else.
+            // This is a fix for #53123 and prevents winnowing from accidentally extending the
+            // lifetime of a variable.
+            BuiltinCandidate { has_nested: false } => true,
             ParamCandidate(ref cand) => match victim.candidate {
                 AutoImplCandidate(..) => {
                     bug!(
                         "default implementations shouldn't be recorded \
                          when there are other valid candidates");
                 }
+                // Prefer BuiltinCandidate { has_nested: false } to anything else.
+                // This is a fix for #53123 and prevents winnowing from accidentally extending the
+                // lifetime of a variable.
+                BuiltinCandidate { has_nested: false } => false,
                 ImplCandidate(..) |
                 ClosureCandidate |
                 GeneratorCandidate |
@@ -2072,6 +2081,10 @@ fn candidate_should_be_dropped_in_favor_of<'o>(
                         "default implementations shouldn't be recorded \
                          when there are other valid candidates");
                 }
+                // Prefer BuiltinCandidate { has_nested: false } to anything else.
+                // This is a fix for #53123 and prevents winnowing from accidentally extending the
+                // lifetime of a variable.
+                BuiltinCandidate { has_nested: false } => false,
                 ImplCandidate(..) |
                 ClosureCandidate |
                 GeneratorCandidate |
@@ -2115,7 +2128,7 @@ fn candidate_should_be_dropped_in_favor_of<'o>(
             FnPointerCandidate |
             BuiltinObjectCandidate |
             BuiltinUnsizeCandidate |
-            BuiltinCandidate { .. } => {
+            BuiltinCandidate { has_nested: true } => {
                 match victim.candidate {
                     ParamCandidate(ref cand) => {
                         // Prefer these to a global where-clause bound
index 39e358803cbe84f7a148de58137875b746ba8af8..544e3f03c03b1c3d936999c31b0ffc8a4b5d5c39 100644 (file)
@@ -206,7 +206,7 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
             super::SizedReturnType => Some(super::SizedReturnType),
             super::SizedYieldType => Some(super::SizedYieldType),
             super::RepeatVec => Some(super::RepeatVec),
-            super::FieldSized(item) => Some(super::FieldSized(item)),
+            super::FieldSized { adt_kind, last } => Some(super::FieldSized { adt_kind, last }),
             super::ConstSized => Some(super::ConstSized),
             super::SharedStatic => Some(super::SharedStatic),
             super::BuiltinDerivedObligation(ref cause) => {
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 49bd69f8262169ad18bb2a85daa9cb487bbdf9ca..709590f649b92cab52d4e65f73867d7b98b69638 100644 (file)
@@ -91,7 +91,6 @@ struct CheckLoanCtxt<'a, 'tcx: 'a> {
     dfcx_loans: &'a LoanDataFlow<'a, 'tcx>,
     move_data: &'a move_data::FlowedMoveData<'a, 'tcx>,
     all_loans: &'a [Loan<'tcx>],
-    param_env: ty::ParamEnv<'tcx>,
     movable_generator: bool,
 }
 
@@ -215,7 +214,6 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
         dfcx_loans,
         move_data,
         all_loans,
-        param_env,
         movable_generator,
     };
     let rvalue_promotable_map = bccx.tcx.rvalue_promotable_map(def_id);
@@ -801,8 +799,7 @@ fn check_if_path_is_moved(&self,
                 use_kind,
                 &lp,
                 the_move,
-                moved_lp,
-                self.param_env);
+                moved_lp);
             false
         });
     }
index 7ce6863a7c986402d1abcd4eede1ef7bc253e931..b76931c301748c44cc995473755bb1547833c017 100644 (file)
@@ -163,15 +163,11 @@ pub fn gather_assignment<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
                                    move_data: &MoveData<'tcx>,
                                    assignment_id: hir::ItemLocalId,
                                    assignment_span: Span,
-                                   assignee_loan_path: Rc<LoanPath<'tcx>>,
-                                   assignee_id: hir::ItemLocalId,
-                                   mode: euv::MutateMode) {
+                                   assignee_loan_path: Rc<LoanPath<'tcx>>) {
     move_data.add_assignment(bccx.tcx,
                              assignee_loan_path,
                              assignment_id,
-                             assignment_span,
-                             assignee_id,
-                             mode);
+                             assignment_span);
 }
 
 // (keep in sync with move_error::report_cannot_move_out_of )
index 323e0997e3e4732c2d81ffafce9d8033effcb6b4..c9dcc0d9fa266beb190653e31c7526d7309f267a 100644 (file)
@@ -28,8 +28,7 @@ pub fn guarantee_lifetime<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
                                     span: Span,
                                     cause: euv::LoanCause,
                                     cmt: &'a mc::cmt_<'tcx>,
-                                    loan_region: ty::Region<'tcx>,
-                                    _: ty::BorrowKind)
+                                    loan_region: ty::Region<'tcx>)
                                     -> Result<(),()> {
     //! Reports error if `loan_region` is larger than S
     //! where S is `item_scope` if `cmt` is an upvar,
index d08814138719a370e1c97e1faf74751db12d69ae..6c83e2dd1c206608915927e42e141bd1dcd743c8 100644 (file)
@@ -145,12 +145,11 @@ fn mutate(&mut self,
               assignment_id: ast::NodeId,
               assignment_span: Span,
               assignee_cmt: &mc::cmt_<'tcx>,
-              mode: euv::MutateMode)
+              _: euv::MutateMode)
     {
         self.guarantee_assignment_valid(assignment_id,
                                         assignment_span,
-                                        assignee_cmt,
-                                        mode);
+                                        assignee_cmt);
     }
 
     fn decl_without_init(&mut self, id: ast::NodeId, _span: Span) {
@@ -246,8 +245,7 @@ pub fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { self.bccx.tcx }
     fn guarantee_assignment_valid(&mut self,
                                   assignment_id: ast::NodeId,
                                   assignment_span: Span,
-                                  cmt: &mc::cmt_<'tcx>,
-                                  mode: euv::MutateMode) {
+                                  cmt: &mc::cmt_<'tcx>) {
 
         let opt_lp = opt_loan_path(cmt);
         debug!("guarantee_assignment_valid(assignment_id={}, cmt={:?}) opt_lp={:?}",
@@ -282,9 +280,7 @@ fn guarantee_assignment_valid(&mut self,
                                                 self.bccx.tcx.hir.node_to_hir_id(assignment_id)
                                                     .local_id,
                                                 assignment_span,
-                                                lp,
-                                                cmt.hir_id.local_id,
-                                                mode);
+                                                lp);
             }
             None => {
                 // This can occur with e.g. `*foo() = 5`.  In such
@@ -320,7 +316,7 @@ fn guarantee_valid(&mut self,
         // Check that the lifetime of the borrow does not exceed
         // the lifetime of the data being borrowed.
         if lifetime::guarantee_lifetime(self.bccx, self.item_ub,
-                                        borrow_span, cause, cmt, loan_region, req_kind).is_err() {
+                                        borrow_span, cause, cmt, loan_region).is_err() {
             return; // reported an error, no sense in reporting more.
         }
 
index a97fc666e25a66bb797dea8dcf0291ba67d28051..5b08400eb112d05ddc56fe37aca367d0eb61391c 100644 (file)
 use rustc::hir::map as hir_map;
 use rustc::hir::map::blocks::FnLikeNode;
 use rustc::cfg;
-use rustc::middle::dataflow::DataFlowContext;
-use rustc::middle::dataflow::BitwiseOperator;
-use rustc::middle::dataflow::DataFlowOperator;
-use rustc::middle::dataflow::KillFrom;
 use rustc::middle::borrowck::{BorrowCheckResult, SignalledError};
 use rustc::hir::def_id::{DefId, LocalDefId};
 use rustc::middle::expr_use_visitor as euv;
@@ -54,6 +50,8 @@
 use rustc::hir;
 use rustc::hir::intravisit::{self, Visitor};
 
+use dataflow::{DataFlowContext, BitwiseOperator, DataFlowOperator, KillFrom};
+
 pub mod check_loans;
 
 pub mod gather_loans;
@@ -640,8 +638,7 @@ pub fn report_use_of_moved_value(&self,
                                      use_kind: MovedValueUseKind,
                                      lp: &LoanPath<'tcx>,
                                      the_move: &move_data::Move,
-                                     moved_lp: &LoanPath<'tcx>,
-                                     _param_env: ty::ParamEnv<'tcx>) {
+                                     moved_lp: &LoanPath<'tcx>) {
         let (verb, verb_participle) = match use_kind {
             MovedInUse => ("use", "used"),
             MovedInCapture => ("capture", "captured"),
@@ -806,23 +803,6 @@ pub fn report_reassigned_immutable_variable(&self,
         self.signal_error();
     }
 
-    pub fn struct_span_err_with_code<S: Into<MultiSpan>>(&self,
-                                                         s: S,
-                                                         msg: &str,
-                                                         code: DiagnosticId)
-                                                         -> DiagnosticBuilder<'a> {
-        self.tcx.sess.struct_span_err_with_code(s, msg, code)
-    }
-
-    pub fn span_err_with_code<S: Into<MultiSpan>>(
-        &self,
-        s: S,
-        msg: &str,
-        code: DiagnosticId,
-    ) {
-        self.tcx.sess.span_err_with_code(s, msg, code);
-    }
-
     fn report_bckerr(&self, err: &BckError<'a, 'tcx>) {
         let error_span = err.span.clone();
 
@@ -1255,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 4091ca046f44dc7f6a6ec5956d9641433711988d..979d71a0923c40ea4f468f04e80b07716bf13cb4 100644 (file)
 
 pub use self::MoveKind::*;
 
+use dataflow::{DataFlowContext, BitwiseOperator, DataFlowOperator, KillFrom};
+
 use borrowck::*;
 use rustc::cfg;
-use rustc::middle::dataflow::DataFlowContext;
-use rustc::middle::dataflow::BitwiseOperator;
-use rustc::middle::dataflow::DataFlowOperator;
-use rustc::middle::dataflow::KillFrom;
-use rustc::middle::expr_use_visitor as euv;
-use rustc::middle::expr_use_visitor::MutateMode;
 use rustc::ty::{self, TyCtxt};
-use rustc::util::nodemap::{FxHashMap, FxHashSet};
+use rustc::util::nodemap::FxHashMap;
 
 use std::cell::RefCell;
 use std::rc::Rc;
@@ -51,9 +47,6 @@ pub struct MoveData<'tcx> {
     /// assigned dataflow bits, but we track them because they still
     /// kill move bits.
     pub path_assignments: RefCell<Vec<Assignment>>,
-
-    /// Assignments to a variable or path, like `x = foo`, but not `x += foo`.
-    pub assignee_ids: RefCell<FxHashSet<hir::ItemLocalId>>,
 }
 
 pub struct FlowedMoveData<'a, 'tcx: 'a> {
@@ -151,9 +144,6 @@ pub struct Assignment {
 
     /// span of node where assignment occurs
     pub span: Span,
-
-    /// id for place expression on lhs of assignment
-    pub assignee_id: hir::ItemLocalId,
 }
 
 #[derive(Clone, Copy)]
@@ -388,9 +378,7 @@ fn add_move_helper(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
     pub fn add_assignment(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           lp: Rc<LoanPath<'tcx>>,
                           assign_id: hir::ItemLocalId,
-                          span: Span,
-                          assignee_id: hir::ItemLocalId,
-                          mode: euv::MutateMode) {
+                          span: Span) {
         // Assigning to one union field automatically assigns to all its fields.
         if let LpExtend(ref base_lp, mutbl, LpInterior(opt_variant_id, interior)) = lp.kind {
             if let ty::TyAdt(adt_def, _) = base_lp.ty.sty {
@@ -407,39 +395,28 @@ pub fn add_assignment(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                     LpInterior(opt_variant_id, field));
                         let sibling_lp = Rc::new(LoanPath::new(sibling_lp_kind, field_ty));
                         self.add_assignment_helper(tcx, sibling_lp, assign_id,
-                                                   span, assignee_id, mode);
+                                                   span);
                     }
                     return;
                 }
             }
         }
 
-        self.add_assignment_helper(tcx, lp.clone(), assign_id, span, assignee_id, mode);
+        self.add_assignment_helper(tcx, lp.clone(), assign_id, span);
     }
 
     fn add_assignment_helper(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                              lp: Rc<LoanPath<'tcx>>,
                              assign_id: hir::ItemLocalId,
-                             span: Span,
-                             assignee_id: hir::ItemLocalId,
-                             mode: euv::MutateMode) {
-        debug!("add_assignment(lp={:?}, assign_id={:?}, assignee_id={:?}",
-               lp, assign_id, assignee_id);
+                             span: Span) {
+        debug!("add_assignment(lp={:?}, assign_id={:?}", lp, assign_id);
 
         let path_index = self.move_path(tcx, lp.clone());
 
-        match mode {
-            MutateMode::Init | MutateMode::JustWrite => {
-                self.assignee_ids.borrow_mut().insert(assignee_id);
-            }
-            MutateMode::WriteAndRead => { }
-        }
-
         let assignment = Assignment {
             path: path_index,
             id: assign_id,
             span,
-            assignee_id,
         };
 
         if self.is_var_path(path_index) {
diff --git a/src/librustc_borrowck/dataflow.rs b/src/librustc_borrowck/dataflow.rs
new file mode 100644 (file)
index 0000000..d5f30c1
--- /dev/null
@@ -0,0 +1,686 @@
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+//! A module for propagating forward dataflow information. The analysis
+//! assumes that the items to be propagated can be represented as bits
+//! and thus uses bitvectors. Your job is simply to specify the so-called
+//! GEN and KILL bits for each expression.
+
+use rustc::cfg;
+use rustc::cfg::CFGIndex;
+use rustc::ty::TyCtxt;
+use std::io;
+use std::mem;
+use std::usize;
+use syntax::print::pprust::PrintState;
+
+use rustc_data_structures::graph::implementation::OUTGOING;
+
+use rustc::util::nodemap::FxHashMap;
+use rustc::hir;
+use rustc::hir::intravisit::{self, IdRange};
+use rustc::hir::print as pprust;
+
+
+#[derive(Copy, Clone, Debug)]
+pub enum EntryOrExit {
+    Entry,
+    Exit,
+}
+
+#[derive(Clone)]
+pub struct DataFlowContext<'a, 'tcx: 'a, O> {
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+
+    /// a name for the analysis using this dataflow instance
+    analysis_name: &'static str,
+
+    /// the data flow operator
+    oper: O,
+
+    /// number of bits to propagate per id
+    bits_per_id: usize,
+
+    /// number of words we will use to store bits_per_id.
+    /// equal to bits_per_id/usize::BITS rounded up.
+    words_per_id: usize,
+
+    // mapping from node to cfg node index
+    // FIXME (#6298): Shouldn't this go with CFG?
+    local_id_to_index: FxHashMap<hir::ItemLocalId, Vec<CFGIndex>>,
+
+    // Bit sets per cfg node.  The following three fields (`gens`, `kills`,
+    // and `on_entry`) all have the same structure. For each id in
+    // `id_range`, there is a range of words equal to `words_per_id`.
+    // So, to access the bits for any given id, you take a slice of
+    // the full vector (see the method `compute_id_range()`).
+
+    /// bits generated as we exit the cfg node. Updated by `add_gen()`.
+    gens: Vec<usize>,
+
+    /// bits killed as we exit the cfg node, or non-locally jump over
+    /// it. Updated by `add_kill(KillFrom::ScopeEnd)`.
+    scope_kills: Vec<usize>,
+
+    /// bits killed as we exit the cfg node directly; if it is jumped
+    /// over, e.g. via `break`, the kills are not reflected in the
+    /// jump's effects. Updated by `add_kill(KillFrom::Execution)`.
+    action_kills: Vec<usize>,
+
+    /// bits that are valid on entry to the cfg node. Updated by
+    /// `propagate()`.
+    on_entry: Vec<usize>,
+}
+
+pub trait BitwiseOperator {
+    /// Joins two predecessor bits together, typically either `|` or `&`
+    fn join(&self, succ: usize, pred: usize) -> usize;
+}
+
+/// Parameterization for the precise form of data flow that is used.
+pub trait DataFlowOperator : BitwiseOperator {
+    /// Specifies the initial value for each bit in the `on_entry` set
+    fn initial_value(&self) -> bool;
+}
+
+struct PropagationContext<'a, 'b: 'a, 'tcx: 'b, O: 'a> {
+    dfcx: &'a mut DataFlowContext<'b, 'tcx, O>,
+    changed: bool
+}
+
+fn get_cfg_indices<'a>(id: hir::ItemLocalId,
+                       index: &'a FxHashMap<hir::ItemLocalId, Vec<CFGIndex>>)
+                       -> &'a [CFGIndex] {
+    index.get(&id).map_or(&[], |v| &v[..])
+}
+
+impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> {
+    fn has_bitset_for_local_id(&self, n: hir::ItemLocalId) -> bool {
+        assert!(n != hir::DUMMY_ITEM_LOCAL_ID);
+        self.local_id_to_index.contains_key(&n)
+    }
+}
+
+impl<'a, 'tcx, O:DataFlowOperator> pprust::PpAnn for DataFlowContext<'a, 'tcx, O> {
+    fn nested(&self, state: &mut pprust::State, nested: pprust::Nested) -> io::Result<()> {
+        pprust::PpAnn::nested(&self.tcx.hir, state, nested)
+    }
+    fn pre(&self,
+           ps: &mut pprust::State,
+           node: pprust::AnnNode) -> io::Result<()> {
+        let id = match node {
+            pprust::NodeName(_) => return Ok(()),
+            pprust::NodeExpr(expr) => expr.hir_id.local_id,
+            pprust::NodeBlock(blk) => blk.hir_id.local_id,
+            pprust::NodeItem(_) |
+            pprust::NodeSubItem(_) => return Ok(()),
+            pprust::NodePat(pat) => pat.hir_id.local_id
+        };
+
+        if !self.has_bitset_for_local_id(id) {
+            return Ok(());
+        }
+
+        assert!(self.bits_per_id > 0);
+        let indices = get_cfg_indices(id, &self.local_id_to_index);
+        for &cfgidx in indices {
+            let (start, end) = self.compute_id_range(cfgidx);
+            let on_entry = &self.on_entry[start.. end];
+            let entry_str = bits_to_string(on_entry);
+
+            let gens = &self.gens[start.. end];
+            let gens_str = if gens.iter().any(|&u| u != 0) {
+                format!(" gen: {}", bits_to_string(gens))
+            } else {
+                "".to_string()
+            };
+
+            let action_kills = &self.action_kills[start .. end];
+            let action_kills_str = if action_kills.iter().any(|&u| u != 0) {
+                format!(" action_kill: {}", bits_to_string(action_kills))
+            } else {
+                "".to_string()
+            };
+
+            let scope_kills = &self.scope_kills[start .. end];
+            let scope_kills_str = if scope_kills.iter().any(|&u| u != 0) {
+                format!(" scope_kill: {}", bits_to_string(scope_kills))
+            } else {
+                "".to_string()
+            };
+
+            ps.synth_comment(
+                format!("id {}: {}{}{}{}", id.as_usize(), entry_str,
+                        gens_str, action_kills_str, scope_kills_str))?;
+            ps.s.space()?;
+        }
+        Ok(())
+    }
+}
+
+fn build_local_id_to_index(body: Option<&hir::Body>,
+                           cfg: &cfg::CFG)
+                           -> FxHashMap<hir::ItemLocalId, Vec<CFGIndex>> {
+    let mut index = FxHashMap();
+
+    // FIXME(#15020) Would it be better to fold formals from decl
+    // into cfg itself?  i.e. introduce a fn-based flow-graph in
+    // addition to the current block-based flow-graph, rather than
+    // have to put traversals like this here?
+    if let Some(body) = body {
+        add_entries_from_fn_body(&mut index, body, cfg.entry);
+    }
+
+    cfg.graph.each_node(|node_idx, node| {
+        if let cfg::CFGNodeData::AST(id) = node.data {
+            index.entry(id).or_insert(vec![]).push(node_idx);
+        }
+        true
+    });
+
+    return index;
+
+    /// Add mappings from the ast nodes for the formal bindings to
+    /// the entry-node in the graph.
+    fn add_entries_from_fn_body(index: &mut FxHashMap<hir::ItemLocalId, Vec<CFGIndex>>,
+                                body: &hir::Body,
+                                entry: CFGIndex) {
+        use rustc::hir::intravisit::Visitor;
+
+        struct Formals<'a> {
+            entry: CFGIndex,
+            index: &'a mut FxHashMap<hir::ItemLocalId, Vec<CFGIndex>>,
+        }
+        let mut formals = Formals { entry: entry, index: index };
+        for arg in &body.arguments {
+            formals.visit_pat(&arg.pat);
+        }
+        impl<'a, 'v> Visitor<'v> for Formals<'a> {
+            fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'v> {
+                intravisit::NestedVisitorMap::None
+            }
+
+            fn visit_pat(&mut self, p: &hir::Pat) {
+                self.index.entry(p.hir_id.local_id).or_insert(vec![]).push(self.entry);
+                intravisit::walk_pat(self, p)
+            }
+        }
+    }
+}
+
+/// Flag used by `add_kill` to indicate whether the provided kill
+/// takes effect only when control flows directly through the node in
+/// question, or if the kill's effect is associated with any
+/// control-flow directly through or indirectly over the node.
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub enum KillFrom {
+    /// A `ScopeEnd` kill is one that takes effect when any control
+    /// flow goes over the node. A kill associated with the end of the
+    /// scope of a variable declaration `let x;` is an example of a
+    /// `ScopeEnd` kill.
+    ScopeEnd,
+
+    /// An `Execution` kill is one that takes effect only when control
+    /// flow goes through the node to completion. A kill associated
+    /// with an assignment statement `x = expr;` is an example of an
+    /// `Execution` kill.
+    Execution,
+}
+
+impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> {
+    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+               analysis_name: &'static str,
+               body: Option<&hir::Body>,
+               cfg: &cfg::CFG,
+               oper: O,
+               id_range: IdRange,
+               bits_per_id: usize) -> DataFlowContext<'a, 'tcx, O> {
+        let usize_bits = mem::size_of::<usize>() * 8;
+        let words_per_id = (bits_per_id + usize_bits - 1) / usize_bits;
+        let num_nodes = cfg.graph.all_nodes().len();
+
+        debug!("DataFlowContext::new(analysis_name: {}, id_range={:?}, \
+                                     bits_per_id={}, words_per_id={}) \
+                                     num_nodes: {}",
+               analysis_name, id_range, bits_per_id, words_per_id,
+               num_nodes);
+
+        let entry = if oper.initial_value() { usize::MAX } else {0};
+
+        let zeroes = vec![0; num_nodes * words_per_id];
+        let gens = zeroes.clone();
+        let kills1 = zeroes.clone();
+        let kills2 = zeroes;
+        let on_entry = vec![entry; num_nodes * words_per_id];
+
+        let local_id_to_index = build_local_id_to_index(body, cfg);
+
+        DataFlowContext {
+            tcx,
+            analysis_name,
+            words_per_id,
+            local_id_to_index,
+            bits_per_id,
+            oper,
+            gens,
+            action_kills: kills1,
+            scope_kills: kills2,
+            on_entry,
+        }
+    }
+
+    pub fn add_gen(&mut self, id: hir::ItemLocalId, bit: usize) {
+        //! Indicates that `id` generates `bit`
+        debug!("{} add_gen(id={:?}, bit={})",
+               self.analysis_name, id, bit);
+        assert!(self.local_id_to_index.contains_key(&id));
+        assert!(self.bits_per_id > 0);
+
+        let indices = get_cfg_indices(id, &self.local_id_to_index);
+        for &cfgidx in indices {
+            let (start, end) = self.compute_id_range(cfgidx);
+            let gens = &mut self.gens[start.. end];
+            set_bit(gens, bit);
+        }
+    }
+
+    pub fn add_kill(&mut self, kind: KillFrom, id: hir::ItemLocalId, bit: usize) {
+        //! Indicates that `id` kills `bit`
+        debug!("{} add_kill(id={:?}, bit={})",
+               self.analysis_name, id, bit);
+        assert!(self.local_id_to_index.contains_key(&id));
+        assert!(self.bits_per_id > 0);
+
+        let indices = get_cfg_indices(id, &self.local_id_to_index);
+        for &cfgidx in indices {
+            let (start, end) = self.compute_id_range(cfgidx);
+            let kills = match kind {
+                KillFrom::Execution => &mut self.action_kills[start.. end],
+                KillFrom::ScopeEnd =>  &mut self.scope_kills[start.. end],
+            };
+            set_bit(kills, bit);
+        }
+    }
+
+    fn apply_gen_kill(&self, cfgidx: CFGIndex, bits: &mut [usize]) {
+        //! Applies the gen and kill sets for `cfgidx` to `bits`
+        debug!("{} apply_gen_kill(cfgidx={:?}, bits={}) [before]",
+               self.analysis_name, cfgidx, mut_bits_to_string(bits));
+        assert!(self.bits_per_id > 0);
+
+        let (start, end) = self.compute_id_range(cfgidx);
+        let gens = &self.gens[start.. end];
+        bitwise(bits, gens, &Union);
+        let kills = &self.action_kills[start.. end];
+        bitwise(bits, kills, &Subtract);
+        let kills = &self.scope_kills[start.. end];
+        bitwise(bits, kills, &Subtract);
+
+        debug!("{} apply_gen_kill(cfgidx={:?}, bits={}) [after]",
+               self.analysis_name, cfgidx, mut_bits_to_string(bits));
+    }
+
+    fn compute_id_range(&self, cfgidx: CFGIndex) -> (usize, usize) {
+        let n = cfgidx.node_id();
+        let start = n * self.words_per_id;
+        let end = start + self.words_per_id;
+
+        assert!(start < self.gens.len());
+        assert!(end <= self.gens.len());
+        assert!(self.gens.len() == self.action_kills.len());
+        assert!(self.gens.len() == self.scope_kills.len());
+        assert!(self.gens.len() == self.on_entry.len());
+
+        (start, end)
+    }
+
+
+    pub fn each_bit_on_entry<F>(&self, id: hir::ItemLocalId, mut f: F) -> bool where
+        F: FnMut(usize) -> bool,
+    {
+        //! Iterates through each bit that is set on entry to `id`.
+        //! Only useful after `propagate()` has been called.
+        if !self.has_bitset_for_local_id(id) {
+            return true;
+        }
+        let indices = get_cfg_indices(id, &self.local_id_to_index);
+        for &cfgidx in indices {
+            if !self.each_bit_for_node(EntryOrExit::Entry, cfgidx, |i| f(i)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    pub fn each_bit_for_node<F>(&self, e: EntryOrExit, cfgidx: CFGIndex, f: F) -> bool where
+        F: FnMut(usize) -> bool,
+    {
+        //! Iterates through each bit that is set on entry/exit to `cfgidx`.
+        //! Only useful after `propagate()` has been called.
+
+        if self.bits_per_id == 0 {
+            // Skip the surprisingly common degenerate case.  (Note
+            // compute_id_range requires self.words_per_id > 0.)
+            return true;
+        }
+
+        let (start, end) = self.compute_id_range(cfgidx);
+        let on_entry = &self.on_entry[start.. end];
+        let temp_bits;
+        let slice = match e {
+            EntryOrExit::Entry => on_entry,
+            EntryOrExit::Exit => {
+                let mut t = on_entry.to_vec();
+                self.apply_gen_kill(cfgidx, &mut t);
+                temp_bits = t;
+                &temp_bits[..]
+            }
+        };
+        debug!("{} each_bit_for_node({:?}, cfgidx={:?}) bits={}",
+               self.analysis_name, e, cfgidx, bits_to_string(slice));
+        self.each_bit(slice, f)
+    }
+
+    pub fn each_gen_bit<F>(&self, id: hir::ItemLocalId, mut f: F) -> bool where
+        F: FnMut(usize) -> bool,
+    {
+        //! Iterates through each bit in the gen set for `id`.
+        if !self.has_bitset_for_local_id(id) {
+            return true;
+        }
+
+        if self.bits_per_id == 0 {
+            // Skip the surprisingly common degenerate case.  (Note
+            // compute_id_range requires self.words_per_id > 0.)
+            return true;
+        }
+
+        let indices = get_cfg_indices(id, &self.local_id_to_index);
+        for &cfgidx in indices {
+            let (start, end) = self.compute_id_range(cfgidx);
+            let gens = &self.gens[start.. end];
+            debug!("{} each_gen_bit(id={:?}, gens={})",
+                   self.analysis_name, id, bits_to_string(gens));
+            if !self.each_bit(gens, |i| f(i)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    fn each_bit<F>(&self, words: &[usize], mut f: F) -> bool where
+        F: FnMut(usize) -> bool,
+    {
+        //! Helper for iterating over the bits in a bit set.
+        //! Returns false on the first call to `f` that returns false;
+        //! if all calls to `f` return true, then returns true.
+
+        let usize_bits = mem::size_of::<usize>() * 8;
+        for (word_index, &word) in words.iter().enumerate() {
+            if word != 0 {
+                let base_index = word_index * usize_bits;
+                for offset in 0..usize_bits {
+                    let bit = 1 << offset;
+                    if (word & bit) != 0 {
+                        // NB: we round up the total number of bits
+                        // that we store in any given bit set so that
+                        // it is an even multiple of usize::BITS.  This
+                        // means that there may be some stray bits at
+                        // the end that do not correspond to any
+                        // actual value.  So before we callback, check
+                        // whether the bit_index is greater than the
+                        // actual value the user specified and stop
+                        // iterating if so.
+                        let bit_index = base_index + offset as usize;
+                        if bit_index >= self.bits_per_id {
+                            return true;
+                        } else if !f(bit_index) {
+                            return false;
+                        }
+                    }
+                }
+            }
+        }
+        return true;
+    }
+
+    pub fn add_kills_from_flow_exits(&mut self, cfg: &cfg::CFG) {
+        //! Whenever you have a `break` or `continue` statement, flow
+        //! exits through any number of enclosing scopes on its way to
+        //! the new destination. This function infers the kill bits of
+        //! those control operators based on the kill bits associated
+        //! with those scopes.
+        //!
+        //! This is usually called (if it is called at all), after
+        //! all add_gen and add_kill calls, but before propagate.
+
+        debug!("{} add_kills_from_flow_exits", self.analysis_name);
+        if self.bits_per_id == 0 {
+            // Skip the surprisingly common degenerate case.  (Note
+            // compute_id_range requires self.words_per_id > 0.)
+            return;
+        }
+        cfg.graph.each_edge(|_edge_index, edge| {
+            let flow_exit = edge.source();
+            let (start, end) = self.compute_id_range(flow_exit);
+            let mut orig_kills = self.scope_kills[start.. end].to_vec();
+
+            let mut changed = false;
+            for &id in &edge.data.exiting_scopes {
+                let opt_cfg_idx = self.local_id_to_index.get(&id);
+                match opt_cfg_idx {
+                    Some(indices) => {
+                        for &cfg_idx in indices {
+                            let (start, end) = self.compute_id_range(cfg_idx);
+                            let kills = &self.scope_kills[start.. end];
+                            if bitwise(&mut orig_kills, kills, &Union) {
+                                debug!("scope exits: scope id={:?} \
+                                        (node={:?} of {:?}) added killset: {}",
+                                       id, cfg_idx, indices,
+                                       bits_to_string(kills));
+                                changed = true;
+                            }
+                        }
+                    }
+                    None => {
+                        debug!("{} add_kills_from_flow_exits flow_exit={:?} \
+                                no cfg_idx for exiting_scope={:?}",
+                               self.analysis_name, flow_exit, id);
+                    }
+                }
+            }
+
+            if changed {
+                let bits = &mut self.scope_kills[start.. end];
+                debug!("{} add_kills_from_flow_exits flow_exit={:?} bits={} [before]",
+                       self.analysis_name, flow_exit, mut_bits_to_string(bits));
+                bits.copy_from_slice(&orig_kills[..]);
+                debug!("{} add_kills_from_flow_exits flow_exit={:?} bits={} [after]",
+                       self.analysis_name, flow_exit, mut_bits_to_string(bits));
+            }
+            true
+        });
+    }
+}
+
+impl<'a, 'tcx, O:DataFlowOperator+Clone+'static> DataFlowContext<'a, 'tcx, O> {
+//                                ^^^^^^^^^^^^^ only needed for pretty printing
+    pub fn propagate(&mut self, cfg: &cfg::CFG, body: &hir::Body) {
+        //! Performs the data flow analysis.
+
+        if self.bits_per_id == 0 {
+            // Optimize the surprisingly common degenerate case.
+            return;
+        }
+
+        {
+            let words_per_id = self.words_per_id;
+            let mut propcx = PropagationContext {
+                dfcx: &mut *self,
+                changed: true
+            };
+
+            let nodes_po = cfg.graph.nodes_in_postorder(OUTGOING, cfg.entry);
+            let mut temp = vec![0; words_per_id];
+            let mut num_passes = 0;
+            while propcx.changed {
+                num_passes += 1;
+                propcx.changed = false;
+                propcx.reset(&mut temp);
+                propcx.walk_cfg(cfg, &nodes_po, &mut temp);
+            }
+            debug!("finished in {} iterations", num_passes);
+        }
+
+        debug!("Dataflow result for {}:", self.analysis_name);
+        debug!("{}", pprust::to_string(self, |s| {
+            s.cbox(pprust::indent_unit)?;
+            s.ibox(0)?;
+            s.print_expr(&body.value)
+        }));
+    }
+}
+
+impl<'a, 'b, 'tcx, O:DataFlowOperator> PropagationContext<'a, 'b, 'tcx, O> {
+    fn walk_cfg(&mut self,
+                cfg: &cfg::CFG,
+                nodes_po: &[CFGIndex],
+                in_out: &mut [usize]) {
+        debug!("DataFlowContext::walk_cfg(in_out={}) {}",
+               bits_to_string(in_out), self.dfcx.analysis_name);
+        assert!(self.dfcx.bits_per_id > 0);
+
+        // Iterate over nodes in reverse postorder
+        for &node_index in nodes_po.iter().rev() {
+            let node = cfg.graph.node(node_index);
+            debug!("DataFlowContext::walk_cfg idx={:?} id={:?} begin in_out={}",
+                   node_index, node.data.id(), bits_to_string(in_out));
+
+            let (start, end) = self.dfcx.compute_id_range(node_index);
+
+            // Initialize local bitvector with state on-entry.
+            in_out.copy_from_slice(&self.dfcx.on_entry[start.. end]);
+
+            // Compute state on-exit by applying transfer function to
+            // state on-entry.
+            self.dfcx.apply_gen_kill(node_index, in_out);
+
+            // Propagate state on-exit from node into its successors.
+            self.propagate_bits_into_graph_successors_of(in_out, cfg, node_index);
+        }
+    }
+
+    fn reset(&mut self, bits: &mut [usize]) {
+        let e = if self.dfcx.oper.initial_value() {usize::MAX} else {0};
+        for b in bits {
+            *b = e;
+        }
+    }
+
+    fn propagate_bits_into_graph_successors_of(&mut self,
+                                               pred_bits: &[usize],
+                                               cfg: &cfg::CFG,
+                                               cfgidx: CFGIndex) {
+        for (_, edge) in cfg.graph.outgoing_edges(cfgidx) {
+            self.propagate_bits_into_entry_set_for(pred_bits, edge);
+        }
+    }
+
+    fn propagate_bits_into_entry_set_for(&mut self,
+                                         pred_bits: &[usize],
+                                         edge: &cfg::CFGEdge) {
+        let source = edge.source();
+        let cfgidx = edge.target();
+        debug!("{} propagate_bits_into_entry_set_for(pred_bits={}, {:?} to {:?})",
+               self.dfcx.analysis_name, bits_to_string(pred_bits), source, cfgidx);
+        assert!(self.dfcx.bits_per_id > 0);
+
+        let (start, end) = self.dfcx.compute_id_range(cfgidx);
+        let changed = {
+            // (scoping mutable borrow of self.dfcx.on_entry)
+            let on_entry = &mut self.dfcx.on_entry[start.. end];
+            bitwise(on_entry, pred_bits, &self.dfcx.oper)
+        };
+        if changed {
+            debug!("{} changed entry set for {:?} to {}",
+                   self.dfcx.analysis_name, cfgidx,
+                   bits_to_string(&self.dfcx.on_entry[start.. end]));
+            self.changed = true;
+        }
+    }
+}
+
+fn mut_bits_to_string(words: &mut [usize]) -> String {
+    bits_to_string(words)
+}
+
+fn bits_to_string(words: &[usize]) -> String {
+    let mut result = String::new();
+    let mut sep = '[';
+
+    // Note: this is a little endian printout of bytes.
+
+    for &word in words {
+        let mut v = word;
+        for _ in 0..mem::size_of::<usize>() {
+            result.push(sep);
+            result.push_str(&format!("{:02x}", v & 0xFF));
+            v >>= 8;
+            sep = '-';
+        }
+    }
+    result.push(']');
+    return result
+}
+
+#[inline]
+fn bitwise<Op:BitwiseOperator>(out_vec: &mut [usize],
+                               in_vec: &[usize],
+                               op: &Op) -> bool {
+    assert_eq!(out_vec.len(), in_vec.len());
+    let mut changed = false;
+    for (out_elt, in_elt) in out_vec.iter_mut().zip(in_vec) {
+        let old_val = *out_elt;
+        let new_val = op.join(old_val, *in_elt);
+        *out_elt = new_val;
+        changed |= old_val != new_val;
+    }
+    changed
+}
+
+fn set_bit(words: &mut [usize], bit: usize) -> bool {
+    debug!("set_bit: words={} bit={}",
+           mut_bits_to_string(words), bit_str(bit));
+    let usize_bits = mem::size_of::<usize>() * 8;
+    let word = bit / usize_bits;
+    let bit_in_word = bit % usize_bits;
+    let bit_mask = 1 << bit_in_word;
+    debug!("word={} bit_in_word={} bit_mask={}", word, bit_in_word, bit_mask);
+    let oldv = words[word];
+    let newv = oldv | bit_mask;
+    words[word] = newv;
+    oldv != newv
+}
+
+fn bit_str(bit: usize) -> String {
+    let byte = bit >> 3;
+    let lobits = 1 << (bit & 0b111);
+    format!("[{}:{}-{:02x}]", bit, byte, lobits)
+}
+
+struct Union;
+impl BitwiseOperator for Union {
+    fn join(&self, a: usize, b: usize) -> usize { a | b }
+}
+struct Subtract;
+impl BitwiseOperator for Subtract {
+    fn join(&self, a: usize, b: usize) -> usize { a & !b }
+}
index 22867ba5b55a4ae779ebef38fa6469abc5e90ed0..dddd6a354c115bd6f95c24c62f68a8720cfc8294 100644 (file)
@@ -21,7 +21,7 @@
 use borrowck::{BorrowckCtxt, LoanPath};
 use dot;
 use rustc::cfg::CFGIndex;
-use rustc::middle::dataflow::{DataFlowOperator, DataFlowContext, EntryOrExit};
+use dataflow::{DataFlowOperator, DataFlowContext, EntryOrExit};
 use std::rc::Rc;
 use dot::IntoCow;
 
index aa85582432b75f5e12b1a6557377a8eeede61667..16da8c8a3b8bf6651dc41d8b70ef0f9b7cc8341d 100644 (file)
@@ -39,4 +39,6 @@
 
 pub mod graphviz;
 
+mod dataflow;
+
 pub use borrowck::provide;
index e0a30ef5dbc9abe10befecbda24285ef84a394fd..ef98fae9cc7ee46af16dc668a0b2cecf9954a7ee 100644 (file)
@@ -1079,6 +1079,9 @@ fn finalize(&mut self) -> Command {
         // For now we just never have an entry symbol
         self.cmd.arg("--no-entry");
 
+        // Make the default table accessible
+        self.cmd.arg("--export-table");
+
         let mut cmd = Command::new("");
         ::std::mem::swap(&mut cmd, &mut self.cmd);
         cmd
index 18a1e9129b34284bd6949794742d7b83bedba6ef..2acc29acb0caafd0325520d054fd1c18969d3127 100644 (file)
@@ -97,12 +97,7 @@ pub fn maybe_map<F, U>(&self, mut f: F) -> Option<TransitiveRelation<U>>
     {
         let mut result = TransitiveRelation::new();
         for edge in &self.edges {
-            f(&self.elements[edge.source.0]).and_then(|source| {
-                f(&self.elements[edge.target.0]).and_then(|target| {
-                    result.add(source, target);
-                    Some(())
-                })
-            })?;
+            result.add(f(&self.elements[edge.source.0])?, f(&self.elements[edge.target.0])?);
         }
         Some(result)
     }
index 967a8d90330968acdeb4106eb0931aa6b4a88a4f..f96b9b8082fa799d2aee174bd92565d7b2cf0c1b 100644 (file)
@@ -151,7 +151,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
     let location_table = &LocationTable::new(mir);
 
     let mut errors_buffer = Vec::new();
-    let (move_data, move_errors): (MoveData<'tcx>, Option<Vec<MoveError<'tcx>>>) =
+    let (move_data, move_errors): (MoveData<'tcx>, Option<Vec<(Place<'tcx>, MoveError<'tcx>)>>) =
         match MoveData::gather_moves(mir, tcx) {
             Ok(move_data) => (move_data, None),
             Err((move_data, move_errors)) => (move_data, Some(move_errors)),
index 4d988fef450b8a527f5a5e341dca51b9a62e779d..56ca4db098f87217f9534118238e08b1f3956a38 100644 (file)
@@ -8,14 +8,15 @@
 // 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_data_structures::indexed_vec::Idx;
 use rustc_errors::DiagnosticBuilder;
+use rustc_data_structures::indexed_vec::Idx;
 use syntax_pos::Span;
 
 use borrow_check::MirBorrowckCtxt;
+use borrow_check::prefixes::PrefixSet;
 use dataflow::move_paths::{IllegalMoveOrigin, IllegalMoveOriginKind};
 use dataflow::move_paths::{LookupResult, MoveError, MovePathIndex};
 use util::borrowck_errors::{BorrowckErrors, Origin};
 // 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,
         kind: IllegalMoveOriginKind<'tcx>,
@@ -53,23 +56,27 @@ enum GroupedMoveError<'tcx> {
     },
     // Everything that isn't from pattern matching.
     OtherIllegalMove {
+        original_path: Place<'tcx>,
         span: Span,
         kind: IllegalMoveOriginKind<'tcx>,
     },
 }
 
 impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
-    pub(crate) fn report_move_errors(&mut self, move_errors: Vec<MoveError<'tcx>>) {
+    pub(crate) fn report_move_errors(&mut self, move_errors: Vec<(Place<'tcx>, MoveError<'tcx>)>) {
         let grouped_errors = self.group_move_errors(move_errors);
         for error in grouped_errors {
             self.report(error);
         }
     }
 
-    fn group_move_errors(&self, errors: Vec<MoveError<'tcx>>) -> Vec<GroupedMoveError<'tcx>> {
+    fn group_move_errors(
+        &self,
+        errors: Vec<(Place<'tcx>, MoveError<'tcx>)>
+    ) -> Vec<GroupedMoveError<'tcx>> {
         let mut grouped_errors = Vec::new();
-        for error in errors {
-            self.append_to_grouped_errors(&mut grouped_errors, error);
+        for (original_path, error) in errors {
+            self.append_to_grouped_errors(&mut grouped_errors, original_path, error);
         }
         grouped_errors
     }
@@ -77,6 +84,7 @@ fn group_move_errors(&self, errors: Vec<MoveError<'tcx>>) -> Vec<GroupedMoveErro
     fn append_to_grouped_errors(
         &self,
         grouped_errors: &mut Vec<GroupedMoveError<'tcx>>,
+        original_path: Place<'tcx>,
         error: MoveError<'tcx>,
     ) {
         match error {
@@ -111,11 +119,13 @@ 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(
                             grouped_errors,
                             kind,
+                            original_path,
                             move_from,
                             *local,
                             opt_match_place,
@@ -127,6 +137,7 @@ fn append_to_grouped_errors(
                 }
                 grouped_errors.push(GroupedMoveError::OtherIllegalMove {
                     span: stmt_source_info.span,
+                    original_path,
                     kind,
                 });
             }
@@ -137,6 +148,7 @@ fn append_binding_error(
         &self,
         grouped_errors: &mut Vec<GroupedMoveError<'tcx>>,
         kind: IllegalMoveOriginKind<'tcx>,
+        original_path: Place<'tcx>,
         move_from: &Place<'tcx>,
         bind_to: Local,
         match_place: &Option<Place<'tcx>>,
@@ -144,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
         );
 
@@ -155,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() {
@@ -173,9 +185,10 @@ 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,
                     kind,
                     binds_to,
                 });
@@ -188,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,
@@ -203,9 +216,10 @@ 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,
                     kind,
                     binds_to: vec![bind_to],
                 });
@@ -215,12 +229,23 @@ fn append_binding_error(
 
     fn report(&mut self, error: GroupedMoveError<'tcx>) {
         let (mut err, err_span) = {
-            let (span, kind): (Span, &IllegalMoveOriginKind) = match error {
-                GroupedMoveError::MovesFromMatchPlace { span, ref kind, .. }
-                | GroupedMoveError::MovesFromPattern { span, ref kind, .. }
-                | GroupedMoveError::OtherIllegalMove { span, ref kind } => (span, kind),
-            };
+            let (span, original_path, kind): (Span, &Place<'tcx>, &IllegalMoveOriginKind) =
+                match error {
+                    GroupedMoveError::MovesFromPlace {
+                        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)
+                    },
+                };
             let origin = Origin::Mir;
+            debug!("report: original_path={:?} span={:?}, kind={:?} \
+                   original_path.is_upvar_field_projection={:?}", original_path, span, kind,
+                   original_path.is_upvar_field_projection(self.mir, &self.tcx));
             (
                 match kind {
                     IllegalMoveOriginKind::Static => {
@@ -231,22 +256,17 @@ fn report(&mut self, error: GroupedMoveError<'tcx>) {
                         // borrow to provide feedback about why this
                         // was a move rather than a copy.
                         let ty = place.ty(self.mir, self.tcx).to_ty(self.tcx);
+                        let is_upvar_field_projection =
+                            self.prefixes(&original_path, PrefixSet::All)
+                            .any(|p| p.is_upvar_field_projection(self.mir, &self.tcx)
+                                 .is_some());
                         match ty.sty {
                             ty::TyArray(..) | ty::TySlice(..) => self
                                 .tcx
                                 .cannot_move_out_of_interior_noncopy(span, ty, None, origin),
                             ty::TyClosure(def_id, closure_substs)
-                                if !self.mir.upvar_decls.is_empty()
-                                    && {
-                                        match place {
-                                            Place::Projection(ref proj) => {
-                                                proj.base == Place::Local(Local::new(1))
-                                            }
-                                            Place::Promoted(_) |
-                                            Place::Local(_) | Place::Static(_) => unreachable!(),
-                                        }
-                                    } =>
-                            {
+                                if !self.mir.upvar_decls.is_empty() && is_upvar_field_projection
+                            => {
                                 let closure_kind_ty =
                                     closure_substs.closure_kind_ty(def_id, self.tcx);
                                 let closure_kind = closure_kind_ty.to_opt_closure_kind();
@@ -262,7 +282,28 @@ fn report(&mut self, error: GroupedMoveError<'tcx>) {
                                     }
                                     None => bug!("closure kind not inferred by borrowck"),
                                 };
-                                self.tcx.cannot_move_out_of(span, place_description, origin)
+                                debug!("report: closure_kind_ty={:?} closure_kind={:?} \
+                                       place_description={:?}", closure_kind_ty, closure_kind,
+                                       place_description);
+
+                                let mut diag = self.tcx.cannot_move_out_of(
+                                    span, place_description, origin);
+
+                                for prefix in self.prefixes(&original_path, PrefixSet::All) {
+                                    if let Some(field) = prefix.is_upvar_field_projection(
+                                            self.mir, &self.tcx) {
+                                        let upvar_decl = &self.mir.upvar_decls[field.index()];
+                                        let upvar_hir_id =
+                                            upvar_decl.var_hir_id.assert_crate_local();
+                                        let upvar_node_id =
+                                            self.tcx.hir.hir_to_node_id(upvar_hir_id);
+                                        let upvar_span = self.tcx.hir.span(upvar_node_id);
+                                        diag.span_label(upvar_span, "captured outer variable");
+                                        break;
+                                    }
+                                }
+
+                                diag
                             }
                             _ => self
                                 .tcx
@@ -291,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;
+
+            if j == 0 {
+                err.span_label(binding_span, format!("data moved here"));
+            } else {
+                err.span_label(binding_span, format!("...and here"));
+            }
 
-        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 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);
             }
-            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(
+                noncopy_var_spans,
+                "move occurs because these variables have types that \
+                    don't implement the `Copy` trait",
+            );
         }
     }
 }
index e8862320ddf3fcc83ce454ad0b92cae14743edd7..f11135fc026f53acd940600a43d226a733416c30 100644 (file)
@@ -36,10 +36,18 @@ pub(super) fn report_mutability_error(
         error_access: AccessKind,
         location: Location,
     ) {
+        debug!(
+            "report_mutability_error(\
+                access_place={:?}, span={:?}, the_place_err={:?}, error_access={:?}, location={:?},\
+            )",
+            access_place, span, the_place_err, error_access, location,
+        );
+
         let mut err;
         let item_msg;
         let reason;
         let access_place_desc = self.describe_place(access_place);
+        debug!("report_mutability_error: access_place_desc={:?}", access_place_desc);
 
         match the_place_err {
             Place::Local(local) => {
@@ -63,7 +71,7 @@ pub(super) fn report_mutability_error(
                 ));
 
                 item_msg = format!("`{}`", access_place_desc.unwrap());
-                if self.is_upvar(access_place) {
+                if access_place.is_upvar_field_projection(self.mir, &self.tcx).is_some() {
                     reason = ", as it is not declared as mutable".to_string();
                 } else {
                     let name = self.mir.upvar_decls[upvar_index.index()].debug_name;
@@ -82,7 +90,8 @@ pub(super) fn report_mutability_error(
                         the_place_err.ty(self.mir, self.tcx).to_ty(self.tcx)
                     ));
 
-                    reason = if self.is_upvar(access_place) {
+                    reason = if access_place.is_upvar_field_projection(self.mir,
+                                                                       &self.tcx).is_some() {
                         ", as it is a captured variable in a `Fn` closure".to_string()
                     } else {
                         ", as `Fn` closures cannot mutate their captured variables".to_string()
@@ -155,6 +164,8 @@ pub(super) fn report_mutability_error(
             }) => bug!("Unexpected immutable place."),
         }
 
+        debug!("report_mutability_error: item_msg={:?}, reason={:?}", item_msg, reason);
+
         // `act` and `acted_on` are strings that let us abstract over
         // the verbs used in some diagnostic messages.
         let act;
@@ -199,6 +210,8 @@ pub(super) fn report_mutability_error(
             }
         };
 
+        debug!("report_mutability_error: act={:?}, acted_on={:?}", act, acted_on);
+
         match the_place_err {
             // We want to suggest users use `let mut` for local (user
             // variable) mutations...
@@ -316,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!(),
@@ -382,31 +399,6 @@ pub(super) fn report_mutability_error(
 
         err.buffer(&mut self.errors_buffer);
     }
-
-    // Does this place refer to what the user sees as an upvar
-    fn is_upvar(&self, place: &Place<'tcx>) -> bool {
-        match *place {
-            Place::Projection(box Projection {
-                ref base,
-                elem: ProjectionElem::Field(_, _),
-            }) => {
-                let base_ty = base.ty(self.mir, self.tcx).to_ty(self.tcx);
-                is_closure_or_generator(base_ty)
-            }
-            Place::Projection(box Projection {
-                base:
-                    Place::Projection(box Projection {
-                        ref base,
-                        elem: ProjectionElem::Field(upvar_index, _),
-                    }),
-                elem: ProjectionElem::Deref,
-            }) => {
-                let base_ty = base.ty(self.mir, self.tcx).to_ty(self.tcx);
-                is_closure_or_generator(base_ty) && self.mir.upvar_decls[upvar_index.index()].by_ref
-            }
-            _ => false,
-        }
-    }
 }
 
 fn suggest_ampmut_self<'cx, 'gcx, 'tcx>(
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 44e46e90549a706950d97da0750bd124f62035df..60030f270205523937958bbb7f78ab341002015c 100644 (file)
@@ -27,7 +27,7 @@ struct MoveDataBuilder<'a, 'gcx: 'tcx, 'tcx: 'a> {
     mir: &'a Mir<'tcx>,
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
     data: MoveData<'tcx>,
-    errors: Vec<MoveError<'tcx>>,
+    errors: Vec<(Place<'tcx>, MoveError<'tcx>)>,
 }
 
 impl<'a, 'gcx, 'tcx> MoveDataBuilder<'a, 'gcx, 'tcx> {
@@ -186,7 +186,9 @@ fn move_path_for_projection(&mut self,
 }
 
 impl<'a, 'gcx, 'tcx> MoveDataBuilder<'a, 'gcx, 'tcx> {
-    fn finalize(self) -> Result<MoveData<'tcx>, (MoveData<'tcx>, Vec<MoveError<'tcx>>)> {
+    fn finalize(
+        self
+    ) -> Result<MoveData<'tcx>, (MoveData<'tcx>, Vec<(Place<'tcx>, MoveError<'tcx>)>)> {
         debug!("{}", {
             debug!("moves for {:?}:", self.mir.span);
             for (j, mo) in self.data.moves.iter_enumerated() {
@@ -207,9 +209,10 @@ fn finalize(self) -> Result<MoveData<'tcx>, (MoveData<'tcx>, Vec<MoveError<'tcx>
     }
 }
 
-pub(super) fn gather_moves<'a, 'gcx, 'tcx>(mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>)
-                                           -> Result<MoveData<'tcx>,
-                                                     (MoveData<'tcx>, Vec<MoveError<'tcx>>)> {
+pub(super) fn gather_moves<'a, 'gcx, 'tcx>(
+    mir: &Mir<'tcx>,
+    tcx: TyCtxt<'a, 'gcx, 'tcx>
+) -> Result<MoveData<'tcx>, (MoveData<'tcx>, Vec<(Place<'tcx>, MoveError<'tcx>)>)> {
     let mut builder = MoveDataBuilder::new(mir, tcx);
 
     builder.gather_args();
@@ -407,7 +410,7 @@ fn gather_move(&mut self, place: &Place<'tcx>) {
         let path = match self.move_path_for(place) {
             Ok(path) | Err(MoveError::UnionMove { path }) => path,
             Err(error @ MoveError::IllegalMove { .. }) => {
-                self.builder.errors.push(error);
+                self.builder.errors.push((place.clone(), error));
                 return;
             }
         };
index 64bfd36b7eeb6d92faaeb0a19b77c1dcf5c46fb6..7b4cbdf7131b0e67b2c3b78b5c2a3a29210be39a 100644 (file)
@@ -313,7 +313,7 @@ fn cannot_move_out_of(location: Location, kind: IllegalMoveOriginKind<'tcx>) ->
 
 impl<'a, 'gcx, 'tcx> MoveData<'tcx> {
     pub fn gather_moves(mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>)
-                        -> Result<Self, (Self, Vec<MoveError<'tcx>>)> {
+                        -> Result<Self, (Self, Vec<(Place<'tcx>, MoveError<'tcx>)>)> {
         builder::gather_moves(mir, tcx)
     }
 }
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 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
     }
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 e20904930792e76b00297969de45a8b43d7dc273..6e0c0bac186f4a652fddfb7c78851ea5d805006b 100644 (file)
@@ -167,7 +167,13 @@ fn visit_expr(&mut self, expr: &'tcx Expr) {
 
         let scope = self.region_scope_tree.temporary_scope(expr.hir_id.local_id);
 
-        let ty = self.fcx.tables.borrow().expr_ty_adjusted(expr);
+        // Record the unadjusted type
+        let ty = self.fcx.tables.borrow().expr_ty(expr);
         self.record(ty, scope, Some(expr), expr.span);
+
+        // Also include the adjusted types, since these can result in MIR locals
+        for adjustment in self.fcx.tables.borrow().expr_adjustments(expr) {
+            self.record(adjustment.target, scope, Some(expr), expr.span);
+        }
     }
 }
index 38743cc9cf65f4d8bfdbaa529567a3a0cae4d02c..4b609779540f02f674e9645dab463195e7e4874e 100644 (file)
@@ -258,25 +258,35 @@ fn check_type_defn<'a, 'tcx, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     ty.needs_drop(fcx_tcx, fcx_tcx.param_env(def_id))
                 }
             };
-            let unsized_len = if
+            let all_sized =
                 all_sized ||
                 variant.fields.is_empty() ||
-                needs_drop_copy()
-            {
+                needs_drop_copy();
+            let unsized_len = if all_sized {
                 0
             } else {
                 1
             };
-            for field in &variant.fields[..variant.fields.len() - unsized_len] {
+            for (idx, field) in variant.fields[..variant.fields.len() - unsized_len]
+                .iter()
+                .enumerate()
+            {
+                let last = idx == variant.fields.len() - 1;
                 fcx.register_bound(
                     field.ty,
                     fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem),
-                    traits::ObligationCause::new(field.span,
-                                                    fcx.body_id,
-                                                    traits::FieldSized(match item.node.adt_kind() {
-                                                    Some(i) => i,
-                                                    None => bug!(),
-                                                    })));
+                    traits::ObligationCause::new(
+                        field.span,
+                        fcx.body_id,
+                        traits::FieldSized {
+                            adt_kind: match item.node.adt_kind() {
+                                Some(i) => i,
+                                None => bug!(),
+                            },
+                            last
+                        }
+                    )
+                );
             }
 
             // All field types must be well-formed.
index f0c40d1d491e21835828b5ecf4a671d91c729de1..e163fc68cbda73b4d20917f0fb9086be1eb4554d 100644 (file)
@@ -9,5 +9,5 @@ path = "lib.rs"
 
 [dependencies]
 pulldown-cmark = { version = "0.1.2", default-features = false }
-minifier = "0.0.14"
+minifier = "0.0.19"
 tempfile = "3"
index a2cb79582a14c94cd6aa5da7335ce5a4ee054dc5..2ed7f7a926a4808a02843d7bbc87d6cff5073f7c 100644 (file)
@@ -165,8 +165,8 @@ a {
        color: #ddd;
 }
 
-.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow), .docblock-short
-a:not(.srclink):not(.test-arrow), .stability a {
+.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),
+.docblock-short a:not(.srclink):not(.test-arrow), .stability a {
        color: #D2991D;
 }
 
index 6a3c1988977e7a66c87705316fec21eda58a16c6..f7cb51163ecfc2153f861b1e61aa3e1ad0ef8369 100644 (file)
@@ -165,8 +165,8 @@ a {
        color: #000;
 }
 
-.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow), .docblock-short
-a:not(.srclink):not(.test-arrow), .stability a {
+.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),
+.docblock-short a:not(.srclink):not(.test-arrow), .stability a {
        color: #3873AD;
 }
 
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 02a96b01cca28e82ba75d962d6922baa44b3dfca..59cf741487e443710cdd1e32222abe4cf8a7c92b 100644 (file)
@@ -1247,6 +1247,34 @@ pub fn recv(&self) -> Result<T, RecvError> {
     /// [`SyncSender`]: struct.SyncSender.html
     /// [`Err`]: ../../../std/result/enum.Result.html#variant.Err
     ///
+    /// # Known Issues
+    ///
+    /// There is currently a known issue (see [`#39364`]) that causes `recv_timeout`
+    /// to panic unexpectedly with the following example:
+    ///
+    /// ```no_run
+    /// use std::sync::mpsc::channel;
+    /// use std::thread;
+    /// use std::time::Duration;
+    ///
+    /// let (tx, rx) = channel::<String>();
+    ///
+    /// thread::spawn(move || {
+    ///     let d = Duration::from_millis(10);
+    ///     loop {
+    ///         println!("recv");
+    ///         let _r = rx.recv_timeout(d);
+    ///     }
+    /// });
+    ///
+    /// thread::sleep(Duration::from_millis(100));
+    /// let _c1 = tx.clone();
+    ///
+    /// thread::sleep(Duration::from_secs(1));
+    /// ```
+    ///
+    /// [`#39364`]: https://github.com/rust-lang/rust/issues/39364
+    ///
     /// # Examples
     ///
     /// Successfully receiving value before encountering timeout:
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 56e69b9df9e0407c1d68715b420b1590da17c71b..395e5c98652326091ed5ce6f79d573698426722c 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();
 
@@ -1955,6 +1962,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 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 ffa6f65dc027a03132a6b3956a5b9b827526d687..bdf25618f474eda00f8d2bb87dab4604b86718f0 100644 (file)
@@ -74,23 +74,23 @@ 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,
@@ -100,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 {
@@ -110,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();
     }
@@ -147,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 {
@@ -162,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));
@@ -201,12 +222,14 @@ fn new_raw_internal(sess: &'a ParseSess, filemap: Lrc<syntax_pos::FileMap>,
     }
 
     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
     }
 
@@ -231,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)
     }
@@ -278,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[..])
     }
 
@@ -309,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[..])
     }
 
@@ -326,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[..])
     }
 
@@ -356,6 +378,7 @@ fn advance_token(&mut self) -> Result<(), ()> {
                 };
             }
         }
+
         Ok(())
     }
 
@@ -470,6 +493,7 @@ fn nextch(&self) -> Option<char> {
         }
     }
 
+    #[inline]
     fn nextch_is(&self, c: char) -> bool {
         self.nextch() == Some(c)
     }
@@ -486,6 +510,7 @@ fn nextnextch(&self) -> Option<char> {
         None
     }
 
+    #[inline]
     fn nextnextch_is(&self, c: char) -> bool {
         self.nextnextch() == Some(c)
     }
@@ -495,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();
         }
@@ -711,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('_') {
@@ -738,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
@@ -770,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"));
         }
 
@@ -796,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
@@ -875,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:
@@ -1010,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('}') => {
@@ -1045,6 +1073,7 @@ fn scan_unicode_escape(&mut self, delim: char) -> bool {
             }
             self.bump();
         }
+
         valid
     }
 
@@ -1052,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,
@@ -1127,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 {
@@ -1137,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();
                 }
@@ -1144,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)
                 }));
             }
@@ -1339,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('\'') {
@@ -1372,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();
                 }
@@ -1381,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' => {
@@ -1394,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;
@@ -1411,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 {
@@ -1425,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' => {
@@ -1494,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)
@@ -1501,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))
             }
             '-' => {
@@ -1557,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(())
             }
         }
@@ -1574,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
     }
 
@@ -1628,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)
     }
@@ -1655,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)
     }
 
@@ -1718,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 af8ac3895c2736b285a810b06c221ab56c350dbf..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) => {
@@ -137,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 30094223d08585c81e7beb4d0d0044acdeb4a615..060ea1ea9b1329634d2ab6281b467c302563a1d9 100644 (file)
@@ -324,7 +324,14 @@ pub fn test_main_static(tests: &[TestDescAndFn]) {
 /// test is considered a failure. By default, invokes `report()`
 /// and checks for a `0` result.
 pub fn assert_test_result<T: Termination>(result: T) {
-    assert_eq!(result.report(), 0);
+    let code = result.report();
+    assert_eq!(
+        code,
+        0,
+        "the test returned a termination value with a non-zero status code ({}) \
+         which indicates a failure",
+        code
+    );
 }
 
 #[derive(Copy, Clone, Debug)]
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
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 {}
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
diff --git a/src/test/run-pass/generator/issue-52398.rs b/src/test/run-pass/generator/issue-52398.rs
new file mode 100644 (file)
index 0000000..0fb8f27
--- /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.
+
+#![feature(generators)]
+
+use std::cell::RefCell;
+
+struct A;
+
+impl A {
+    fn test(&self, a: ()) {}
+}
+
+fn main() {
+    // Test that the MIR local with type &A created for the auto-borrow adjustment
+    // is caught by typeck
+    move || {
+        A.test(yield);
+    };
+
+    // Test that the std::cell::Ref temporary returned from the `borrow` call
+    // is caught by typeck
+    let y = RefCell::new(true);
+    static move || {
+        yield *y.borrow();
+        return "Done";
+    };
+}
diff --git a/src/test/run-pass/nll/issue-53123-raw-pointer-cast.rs b/src/test/run-pass/nll/issue-53123-raw-pointer-cast.rs
new file mode 100644 (file)
index 0000000..7959f17
--- /dev/null
@@ -0,0 +1,35 @@
+// 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.
+
+#![feature(nll)]
+#![allow(unused_variables)]
+
+pub trait TryTransform {
+    fn try_transform<F>(self, f: F)
+    where
+        Self: Sized,
+        F: FnOnce(Self);
+}
+
+impl<'a, T> TryTransform for &'a mut T {
+    fn try_transform<F>(self, f: F)
+    where
+        // The bug was that `Self: Sized` caused the lifetime of `this` to "extend" for all
+        // of 'a instead of only lasting as long as the binding is used (for just that line).
+        Self: Sized,
+        F: FnOnce(Self),
+    {
+        let this: *mut T = self as *mut T;
+        f(self);
+    }
+}
+
+fn main() {
+}
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 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() {}
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 05a022a726cd977b8013c8bfb45b07db329944cd..45fa1764f7027230af918979f7648d00e8a418cb 100644 (file)
@@ -1,6 +1,8 @@
 error[E0507]: cannot move out of captured variable in an `Fn` closure
   --> $DIR/borrowck-in-static.rs:15:17
    |
+LL |     let x = Box::new(0);
+   |         - captured outer variable
 LL |     Box::new(|| x) //~ ERROR cannot move out of captured outer variable
    |                 ^ cannot move out of captured variable in an `Fn` closure
 
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 f5b7ca22278e43444d39349423d0e7f91b5c7092..9f56b26648b2ac9de625c77df93d3b03f0610ff5 100644 (file)
@@ -1,6 +1,9 @@
 error[E0507]: cannot move out of captured variable in an `FnMut` closure
   --> $DIR/borrowck-move-by-capture.rs:19:29
    |
+LL |     let bar: Box<_> = box 3;
+   |         --- captured outer variable
+LL |     let _g = to_fn_mut(|| {
 LL |         let _h = to_fn_once(move || -> isize { *bar }); //~ ERROR cannot move out of
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of captured variable in an `FnMut` closure
 
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 07a9f374b2c3935fd2368bd4bdee6ab7c960082d..0eb5fc8c324356ad358fa2438ac9bb1c992834a0 100644 (file)
@@ -1,6 +1,9 @@
 error[E0507]: cannot move out of captured variable in an `Fn` closure
   --> $DIR/unboxed-closures-move-upvar-from-non-once-ref-closure.rs:21:9
    |
+LL |     let y = vec![format!("World")];
+   |         - captured outer variable
+LL |     call(|| {
 LL |         y.into_iter();
    |         ^ cannot move out of captured variable in an `Fn` closure
 
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`.
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 ed9db2ea55ed93f809d92ad75e9e64000f8c8dba..c9a29ac2199c0a4ecc773a4b02adca17281d2ba6 100644 (file)
@@ -7,7 +7,7 @@ LL |     data: T, //~ ERROR the size for values of type
    = help: the trait `std::marker::Sized` is not implemented for `T`
    = note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
    = help: consider adding a `where T: std::marker::Sized` bound
-   = note: only the last field of a struct may have a dynamically sized type
+   = note: the last field of a packed struct may only have a dynamically sized type if it does not need drop to be run
 
 error: aborting due to previous error
 
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
 
index 4ccd24fa4592141da4799057f4c26a3cc9978ccd..a9345e86f724817652892986419e26b313268195 100644 (file)
@@ -1,6 +1,8 @@
 error[E0507]: cannot move out of captured variable in an `FnMut` closure
   --> $DIR/issue-4335.rs:16:20
    |
+LL | fn f<'r, T>(v: &'r T) -> Box<FnMut() -> T + 'r> {
+   |             - captured outer variable
 LL |     id(Box::new(|| *v))
    |                    ^^ cannot move out of captured variable in an `FnMut` closure
 
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 2815e1be70983377e45eaae934acb59da450eee7..7290d18beb74e9388990b29fe87aaa62a6b25570 100644 (file)
@@ -10,6 +10,7 @@
 
 // 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 084042acc974d698f5655013cec24e281707ce81..efb2c248813d7bd13237b65eaacb8aa43d8d0bbc 100644 (file)
@@ -1,47 +1,47 @@
 error[E0665]: `Default` cannot be derived for enums, only structs
-  --> $DIR/macros-nonfatal-errors.rs:20:10
+  --> $DIR/macros-nonfatal-errors.rs:21:10
    |
 LL | #[derive(Default)] //~ ERROR
    |          ^^^^^^^
 
 error: inline assembly must be a string literal
-  --> $DIR/macros-nonfatal-errors.rs:24:10
+  --> $DIR/macros-nonfatal-errors.rs:25:10
    |
 LL |     asm!(invalid); //~ ERROR
    |          ^^^^^^^
 
 error: concat_idents! requires ident args.
-  --> $DIR/macros-nonfatal-errors.rs:26:5
+  --> $DIR/macros-nonfatal-errors.rs:27:5
    |
 LL |     concat_idents!("not", "idents"); //~ ERROR
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: argument must be a string literal
-  --> $DIR/macros-nonfatal-errors.rs:28:17
+  --> $DIR/macros-nonfatal-errors.rs:29:17
    |
 LL |     option_env!(invalid); //~ ERROR
    |                 ^^^^^^^
 
 error: expected string literal
-  --> $DIR/macros-nonfatal-errors.rs:29:10
+  --> $DIR/macros-nonfatal-errors.rs:30:10
    |
 LL |     env!(invalid); //~ ERROR
    |          ^^^^^^^
 
 error: expected string literal
-  --> $DIR/macros-nonfatal-errors.rs:30:10
+  --> $DIR/macros-nonfatal-errors.rs:31:10
    |
 LL |     env!(foo, abr, baz); //~ ERROR
    |          ^^^
 
 error: environment variable `RUST_HOPEFULLY_THIS_DOESNT_EXIST` not defined
-  --> $DIR/macros-nonfatal-errors.rs:31:5
+  --> $DIR/macros-nonfatal-errors.rs:32: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:33:5
+  --> $DIR/macros-nonfatal-errors.rs:34: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:35:13
+  --> $DIR/macros-nonfatal-errors.rs:36: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:37:14
+  --> $DIR/macros-nonfatal-errors.rs:38:14
    |
 LL |     include!(invalid); //~ ERROR
    |              ^^^^^^^
 
 error: argument must be a string literal
-  --> $DIR/macros-nonfatal-errors.rs:39:18
+  --> $DIR/macros-nonfatal-errors.rs:40: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:40:5
+  --> $DIR/macros-nonfatal-errors.rs:41: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:41:20
+  --> $DIR/macros-nonfatal-errors.rs:42: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:42:5
+  --> $DIR/macros-nonfatal-errors.rs:43: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:44:5
+  --> $DIR/macros-nonfatal-errors.rs:45: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 4f2220b0de34107df84154575b4c1e0d6df41df8..13a6fc15ce3185b7ebbbd5093d018c515fad9293 100644 (file)
@@ -1,6 +1,8 @@
 error[E0507]: cannot move out of captured variable in an `Fn` closure
   --> $DIR/moves-based-on-type-move-out-of-closure-env-issue-1965.rs:21:28
    |
+LL |     let i = box 3;
+   |         - captured outer variable
 LL |     let _f = to_fn(|| test(i)); //~ ERROR cannot move out
    |                            ^ cannot move out of captured variable in an `Fn` closure
 
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-52663-span-decl-captured-variable.rs b/src/test/ui/nll/issue-52663-span-decl-captured-variable.rs
new file mode 100644 (file)
index 0000000..dc40b0c
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(nll)]
+
+fn expect_fn<F>(f: F) where F : Fn() {
+    f();
+}
+
+fn main() {
+   {
+       let x = (vec![22], vec![44]);
+       expect_fn(|| drop(x.0));
+       //~^ ERROR cannot move out of captured variable in an `Fn` closure [E0507]
+   }
+}
diff --git a/src/test/ui/nll/issue-52663-span-decl-captured-variable.stderr b/src/test/ui/nll/issue-52663-span-decl-captured-variable.stderr
new file mode 100644 (file)
index 0000000..51f1956
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0507]: cannot move out of captured variable in an `Fn` closure
+  --> $DIR/issue-52663-span-decl-captured-variable.rs:20:26
+   |
+LL |        let x = (vec![22], vec![44]);
+   |            - captured outer variable
+LL |        expect_fn(|| drop(x.0));
+   |                          ^^^ cannot move out of captured variable in an `Fn` closure
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
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 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 c7dbc043cdaee3fa78e23f7525645f50516e5a44..a05a3911aa771144eb177e4b291e274e5b49bc29 100644 (file)
@@ -31,6 +31,9 @@ LL |     f.f.call_mut(())
 error[E0507]: cannot move out of captured variable in an `FnMut` closure
   --> $DIR/borrowck-call-is-borrow-issue-12224.rs:66:13
    |
+LL |     let mut f = move |g: Box<FnMut(isize)>, b: isize| {
+   |         ----- captured outer variable
+...
 LL |         foo(f);
    |             ^ cannot move out of captured variable in an `FnMut` closure
 
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 e74c66c27b13671dcc9a79116d4101462daad565..4baa54e34c75532750ffba07c939ae627e9639c8 100644 (file)
@@ -1,24 +1,32 @@
 error[E0507]: cannot move out of captured variable in an `Fn` closure
   --> $DIR/unboxed-closure-illegal-move.rs:25:31
    |
+LL |         let x = Box::new(0);
+   |             - captured outer variable
 LL |         let f = to_fn(|| drop(x)); //~ ERROR cannot move
    |                               ^ cannot move out of captured variable in an `Fn` closure
 
 error[E0507]: cannot move out of captured variable in an `FnMut` closure
   --> $DIR/unboxed-closure-illegal-move.rs:29:35
    |
+LL |         let x = Box::new(0);
+   |             - captured outer variable
 LL |         let f = to_fn_mut(|| drop(x)); //~ ERROR cannot move
    |                                   ^ cannot move out of captured variable in an `FnMut` closure
 
 error[E0507]: cannot move out of captured variable in an `Fn` closure
   --> $DIR/unboxed-closure-illegal-move.rs:38:36
    |
+LL |         let x = Box::new(0);
+   |             - captured outer variable
 LL |         let f = to_fn(move || drop(x)); //~ ERROR cannot move
    |                                    ^ cannot move out of captured variable in an `Fn` closure
 
 error[E0507]: cannot move out of captured variable in an `FnMut` closure
   --> $DIR/unboxed-closure-illegal-move.rs:42:40
    |
+LL |         let x = Box::new(0);
+   |             - captured outer variable
 LL |         let f = to_fn_mut(move || drop(x)); //~ ERROR cannot move
    |                                        ^ cannot move out of captured variable in an `FnMut` closure
 
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 fd8fb54503a6ff85fde21499942d040608360f02..ee1345c7f9411caf31d14c0cd2577d721a2c75a5 100644 (file)
@@ -189,6 +189,7 @@ struct Builder {
     clippy_release: String,
     rustfmt_release: String,
     llvm_tools_release: String,
+    lldb_release: String,
 
     input: PathBuf,
     output: PathBuf,
@@ -203,6 +204,7 @@ struct Builder {
     clippy_version: Option<String>,
     rustfmt_version: Option<String>,
     llvm_tools_version: Option<String>,
+    lldb_version: Option<String>,
 
     rust_git_commit_hash: Option<String>,
     cargo_git_commit_hash: Option<String>,
@@ -210,6 +212,7 @@ struct Builder {
     clippy_git_commit_hash: Option<String>,
     rustfmt_git_commit_hash: Option<String>,
     llvm_tools_git_commit_hash: Option<String>,
+    lldb_git_commit_hash: Option<String>,
 }
 
 fn main() {
@@ -223,6 +226,7 @@ fn main() {
     let clippy_release = args.next().unwrap();
     let rustfmt_release = args.next().unwrap();
     let llvm_tools_release = args.next().unwrap();
+    let lldb_release = args.next().unwrap();
     let s3_address = args.next().unwrap();
     let mut passphrase = String::new();
     t!(io::stdin().read_to_string(&mut passphrase));
@@ -234,6 +238,7 @@ fn main() {
         clippy_release,
         rustfmt_release,
         llvm_tools_release,
+        lldb_release,
 
         input,
         output,
@@ -248,6 +253,7 @@ fn main() {
         clippy_version: None,
         rustfmt_version: None,
         llvm_tools_version: None,
+        lldb_version: None,
 
         rust_git_commit_hash: None,
         cargo_git_commit_hash: None,
@@ -255,6 +261,7 @@ fn main() {
         clippy_git_commit_hash: None,
         rustfmt_git_commit_hash: None,
         llvm_tools_git_commit_hash: None,
+        lldb_git_commit_hash: None,
     }.build();
 }
 
@@ -266,6 +273,7 @@ fn build(&mut self) {
         self.clippy_version = self.version("clippy", "x86_64-unknown-linux-gnu");
         self.rustfmt_version = self.version("rustfmt", "x86_64-unknown-linux-gnu");
         self.llvm_tools_version = self.version("llvm-tools", "x86_64-unknown-linux-gnu");
+        self.lldb_version = self.version("lldb", "x86_64-unknown-linux-gnu");
 
         self.rust_git_commit_hash = self.git_commit_hash("rust", "x86_64-unknown-linux-gnu");
         self.cargo_git_commit_hash = self.git_commit_hash("cargo", "x86_64-unknown-linux-gnu");
@@ -274,6 +282,7 @@ fn build(&mut self) {
         self.rustfmt_git_commit_hash = self.git_commit_hash("rustfmt", "x86_64-unknown-linux-gnu");
         self.llvm_tools_git_commit_hash = self.git_commit_hash("llvm-tools",
                                                                "x86_64-unknown-linux-gnu");
+        self.lldb_git_commit_hash = self.git_commit_hash("lldb", "x86_64-unknown-linux-gnu");
 
         self.digest_and_sign();
         let manifest = self.build_manifest();
@@ -312,11 +321,13 @@ fn build_manifest(&mut self) -> Manifest {
         self.package("rustfmt-preview", &mut manifest.pkg, HOSTS);
         self.package("rust-analysis", &mut manifest.pkg, TARGETS);
         self.package("llvm-tools-preview", &mut manifest.pkg, TARGETS);
+        self.package("lldb-preview", &mut manifest.pkg, TARGETS);
 
         let clippy_present = manifest.pkg.contains_key("clippy-preview");
         let rls_present = manifest.pkg.contains_key("rls-preview");
         let rustfmt_present = manifest.pkg.contains_key("rustfmt-preview");
         let llvm_tools_present = manifest.pkg.contains_key("llvm-tools-preview");
+        let lldb_present = manifest.pkg.contains_key("lldb-preview");
 
         if rls_present {
             manifest.renames.insert("rls".to_owned(), Rename { to: "rls-preview".to_owned() });
@@ -383,6 +394,12 @@ fn build_manifest(&mut self) -> Manifest {
                     target: host.to_string(),
                 });
             }
+            if lldb_present {
+                extensions.push(Component {
+                    pkg: "lldb-preview".to_string(),
+                    target: host.to_string(),
+                });
+            }
             extensions.push(Component {
                 pkg: "rust-analysis".to_string(),
                 target: host.to_string(),
@@ -496,6 +513,8 @@ fn filename(&self, component: &str, target: &str) -> String {
             format!("rustfmt-{}-{}.tar.gz", self.rustfmt_release, target)
         } else if component == "llvm-tools" || component == "llvm-tools-preview" {
             format!("llvm-tools-{}-{}.tar.gz", self.llvm_tools_release, target)
+        } else if component == "lldb" || component == "lldb-preview" {
+            format!("lldb-{}-{}.tar.gz", self.lldb_release, target)
         } else {
             format!("{}-{}-{}.tar.gz", component, self.rust_release, target)
         }
@@ -512,6 +531,8 @@ fn cached_version(&self, component: &str) -> &Option<String> {
             &self.rustfmt_version
         } else if component == "llvm-tools" || component == "llvm-tools-preview" {
             &self.llvm_tools_version
+        } else if component == "lldb" || component == "lldb-preview" {
+            &self.lldb_version
         } else {
             &self.rust_version
         }
@@ -528,6 +549,8 @@ fn cached_git_commit_hash(&self, component: &str) -> &Option<String> {
             &self.rustfmt_git_commit_hash
         } else if component == "llvm-tools" || component == "llvm-tools-preview" {
             &self.llvm_tools_git_commit_hash
+        } else if component == "lldb" || component == "lldb-preview" {
+            &self.lldb_git_commit_hash
         } else {
             &self.rust_git_commit_hash
         }
index b42488270ed29d73445d6c81d303b6a7476f6bb1..6a7672ef5344c1bb570610f2574250fbee932355 160000 (submodule)
@@ -1 +1 @@
-Subproject commit b42488270ed29d73445d6c81d303b6a7476f6bb1
+Subproject commit 6a7672ef5344c1bb570610f2574250fbee932355
diff --git a/src/tools/clang b/src/tools/clang
new file mode 160000 (submodule)
index 0000000..2a284a7
--- /dev/null
@@ -0,0 +1 @@
+Subproject commit 2a284a70e26997273c296afe06586ffdf3a142fd
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
                 )));
             }
diff --git a/src/tools/lldb b/src/tools/lldb
new file mode 160000 (submodule)
index 0000000..3dbe998
--- /dev/null
@@ -0,0 +1 @@
+Subproject commit 3dbe998969d457c5cef245f61b48bdaed0f5c059
index 89414e44dc94844888e59c08bc31dcccb1792800..27dec6cae3a8132d8a073aad6775425c85095c99 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 89414e44dc94844888e59c08bc31dcccb1792800
+Subproject commit 27dec6cae3a8132d8a073aad6775425c85095c99
index 85254c6abb599f5de090e35608ebb3dfddf5813d..f2107f92debd2d915bcc01779f698bb3d9996d02 100644 (file)
@@ -68,12 +68,14 @@ fn filter_dirs(path: &Path) -> bool {
         "src/vendor",
         "src/rt/hoedown",
         "src/tools/cargo",
+        "src/tools/clang",
         "src/tools/rls",
         "src/tools/clippy",
         "src/tools/rust-installer",
         "src/tools/rustfmt",
         "src/tools/miri",
         "src/tools/lld",
+        "src/tools/lldb",
         "src/librustc/mir/interpret",
         "src/librustc_mir/interpret",
         "src/target",