]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #61361 - estebank:infer-type, r=varkor
authorbors <bors@rust-lang.org>
Mon, 3 Jun 2019 02:45:35 +0000 (02:45 +0000)
committerbors <bors@rust-lang.org>
Mon, 3 Jun 2019 02:45:35 +0000 (02:45 +0000)
Add more detail to type inference error

When encountering code where type inference fails, add more actionable
information:

```
fn main() {
    let foo = Vec::new();
}
```

```
error[E0282]: type annotations needed in `std::vec::Vec<T>`
  --> $DIR/vector-no-ann.rs:2:16
   |
LL |     let foo = Vec::new();
   |         ---   ^^^^^^^^ cannot infer type for `T` in `std::vec::Vec<T>`
   |         |
   |         consider giving `foo` a type
```

Fix #25633.

244 files changed:
.azure-pipelines/steps/install-clang.yml
.azure-pipelines/steps/install-sccache.yml
.azure-pipelines/steps/install-windows-build-deps.yml
Cargo.lock
src/bootstrap/doc.rs
src/ci/docker/scripts/musl-toolchain.sh
src/doc/rustdoc/src/command-line-arguments.md
src/doc/rustdoc/src/passes.md
src/doc/unstable-book/src/language-features/asm.md
src/doc/unstable-book/src/language-features/box-patterns.md
src/doc/unstable-book/src/language-features/box-syntax.md
src/doc/unstable-book/src/language-features/global-asm.md
src/doc/unstable-book/src/language-features/lang-items.md
src/doc/unstable-book/src/language-features/non-ascii-idents.md
src/doc/unstable-book/src/language-features/plugin-registrar.md
src/doc/unstable-book/src/language-features/plugin.md
src/doc/unstable-book/src/language-features/unboxed-closures.md
src/doc/unstable-book/src/library-features/fn-traits.md
src/doc/unstable-book/src/library-features/fnbox.md
src/doc/unstable-book/src/the-unstable-book.md
src/liballoc/lib.rs
src/libcore/convert.rs
src/libcore/iter/traits/double_ended.rs
src/libcore/lib.rs
src/libcore/num/mod.rs
src/libcore/num/wrapping.rs
src/libcore/ops/deref.rs
src/libcore/tests/lib.rs
src/librustc/arena.rs
src/librustc/hir/def.rs
src/librustc/hir/map/mod.rs
src/librustc/hir/mod.rs
src/librustc/hir/upvars.rs [new file with mode: 0644]
src/librustc/ich/impls_ty.rs
src/librustc/infer/error_reporting/mod.rs
src/librustc/infer/region_constraints/mod.rs
src/librustc/middle/dead.rs
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/liveness.rs
src/librustc/middle/mem_categorization.rs
src/librustc/middle/reachable.rs
src/librustc/mir/interpret/allocation.rs
src/librustc/mir/interpret/mod.rs
src/librustc/mir/interpret/pointer.rs
src/librustc/mir/interpret/value.rs
src/librustc/mir/mod.rs
src/librustc/query/mod.rs
src/librustc/traits/error_reporting.rs
src/librustc/ty/context.rs
src/librustc/ty/layout.rs
src/librustc/ty/mod.rs
src/librustc/ty/print/pretty.rs
src/librustc/ty/query/mod.rs
src/librustc/ty/structural_impls.rs
src/librustc/ty/sty.rs
src/librustc_borrowck/borrowck/check_loans.rs
src/librustc_borrowck/borrowck/gather_loans/mod.rs
src/librustc_codegen_llvm/builder.rs
src/librustc_codegen_llvm/common.rs
src/librustc_codegen_llvm/debuginfo/metadata.rs
src/librustc_codegen_llvm/lib.rs
src/librustc_codegen_ssa/README.md
src/librustc_codegen_ssa/mir/operand.rs
src/librustc_codegen_utils/symbol_names/legacy.rs
src/librustc_data_structures/Cargo.toml
src/librustc_data_structures/fx.rs
src/librustc_data_structures/stable_hasher.rs
src/librustc_interface/passes.rs
src/librustc_lint/builtin.rs
src/librustc_metadata/cstore_impl.rs
src/librustc_mir/borrow_check/error_reporting.rs
src/librustc_mir/borrow_check/mod.rs
src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
src/librustc_mir/borrow_check/places_conflict.rs
src/librustc_mir/build/mod.rs
src/librustc_mir/const_eval.rs
src/librustc_mir/hair/constant.rs
src/librustc_mir/hair/cx/expr.rs
src/librustc_mir/hair/cx/mod.rs
src/librustc_mir/hair/pattern/check_match.rs
src/librustc_mir/interpret/cast.rs
src/librustc_mir/interpret/eval_context.rs
src/librustc_mir/interpret/intrinsics/type_name.rs
src/librustc_mir/interpret/machine.rs
src/librustc_mir/interpret/memory.rs
src/librustc_mir/interpret/operand.rs
src/librustc_mir/interpret/place.rs
src/librustc_mir/interpret/traits.rs
src/librustc_mir/interpret/validity.rs
src/librustc_mir/lib.rs
src/librustc_mir/monomorphize/collector.rs
src/librustc_mir/shim.rs
src/librustc_mir/transform/mod.rs
src/librustc_mir/transform/qualify_consts.rs
src/librustc_passes/rvalue_promotion.rs
src/librustc_resolve/Cargo.toml
src/librustc_resolve/lib.rs
src/librustc_save_analysis/lib.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/callee.rs
src/librustc_typeck/check/compare_method.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/regionck.rs
src/librustc_typeck/check/upvar.rs
src/librustc_typeck/check/writeback.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/error_codes.rs
src/librustdoc/html/render.rs
src/librustdoc/html/static/main.js
src/libserialize/Cargo.toml
src/libserialize/collection_impls.rs
src/libstd/Cargo.toml
src/libstd/error.rs
src/libstd/macros.rs
src/libstd/net/ip.rs
src/libsyntax/attr/builtin.rs
src/libsyntax/parse/diagnostics.rs
src/libsyntax/parse/parser.rs
src/libtest/lib.rs
src/llvm-project
src/test/run-pass/associated-consts/associated-const-range-match-patterns.rs
src/test/run-pass/binding/pat-ranges.rs
src/test/run-pass/const-int-conversion.rs
src/test/run-pass/drop/dynamic-drop.rs
src/test/run-pass/inc-range-pat.rs
src/test/run-pass/issues/issue-15881-model-lexer-dotdotdot.rs
src/test/run-pass/mir/mir_build_match_comparisons.rs
src/test/rustdoc/trait-attributes.rs
src/test/ui/async-await/async-await.rs
src/test/ui/async-await/await-macro.rs
src/test/ui/borrowck/borrowck-closures-use-after-free.stderr
src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr
src/test/ui/const-generics/const-generic-array-wrapper.rs [new file with mode: 0644]
src/test/ui/const-generics/const-generic-array-wrapper.stderr [new file with mode: 0644]
src/test/ui/const-generics/issue-61422.rs [new file with mode: 0644]
src/test/ui/const-generics/issue-61422.stderr [new file with mode: 0644]
src/test/ui/const-generics/mut-ref-const-param-array.rs [new file with mode: 0644]
src/test/ui/const-generics/mut-ref-const-param-array.stderr [new file with mode: 0644]
src/test/ui/const-generics/transparent-maybeunit-array-wrapper.rs [new file with mode: 0644]
src/test/ui/const-generics/transparent-maybeunit-array-wrapper.stderr [new file with mode: 0644]
src/test/ui/consts/const-int-conversion.rs
src/test/ui/consts/const-int-conversion.stderr
src/test/ui/error-codes/E0049.rs
src/test/ui/error-codes/E0049.stderr
src/test/ui/error-codes/E0730.rs [new file with mode: 0644]
src/test/ui/error-codes/E0730.stderr [new file with mode: 0644]
src/test/ui/extern/extern-const.fixed
src/test/ui/extern/extern-const.rs
src/test/ui/fmt/format-string-error-2.rs
src/test/ui/fmt/format-string-error-2.stderr
src/test/ui/fn-in-pat.stderr
src/test/ui/impl-trait/impl-trait-plus-priority.rs
src/test/ui/issues/issue-11192.stderr
src/test/ui/issues/issue-22644.stderr
src/test/ui/issues/issue-28433.rs
src/test/ui/issues/issue-28433.stderr
src/test/ui/issues/issue-34255-1.stderr
src/test/ui/issues/issue-36638.rs
src/test/ui/issues/issue-36638.stderr
src/test/ui/issues/issue-36708.stderr
src/test/ui/issues/issue-55587.stderr
src/test/ui/issues/type-arg-mismatch-due-to-impl-trait.rs
src/test/ui/issues/type-arg-mismatch-due-to-impl-trait.stderr
src/test/ui/lifetime_starts_expressions.stderr
src/test/ui/lint/issue-54538-unused-parens-lint.rs
src/test/ui/lint/issue-54538-unused-parens-lint.stderr
src/test/ui/match/match-fn-call.stderr
src/test/ui/match/match-range-fail-dominate.rs
src/test/ui/match/match-range-fail-dominate.stderr
src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr
src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr
src/test/ui/nll/issue-57960.rs
src/test/ui/parser/associated-types-project-from-hrtb-explicit.rs
src/test/ui/parser/associated-types-project-from-hrtb-explicit.stderr
src/test/ui/parser/bad-lit-suffixes.rs
src/test/ui/parser/bad-lit-suffixes.stderr
src/test/ui/parser/bounds-type.rs
src/test/ui/parser/doc-after-struct-field.rs
src/test/ui/parser/doc-after-struct-field.stderr
src/test/ui/parser/doc-before-fn-rbrace.rs
src/test/ui/parser/doc-before-fn-rbrace.stderr
src/test/ui/parser/doc-before-identifier.rs
src/test/ui/parser/doc-before-identifier.stderr
src/test/ui/parser/doc-before-mod-rbrace.rs
src/test/ui/parser/doc-before-mod-rbrace.stderr
src/test/ui/parser/doc-before-struct-rbrace-1.rs
src/test/ui/parser/doc-before-struct-rbrace-1.stderr
src/test/ui/parser/doc-before-struct-rbrace-2.rs
src/test/ui/parser/doc-before-struct-rbrace-2.stderr
src/test/ui/parser/issue-17904-2.rs
src/test/ui/parser/issue-17904-2.stderr
src/test/ui/parser/issue-17904.rs
src/test/ui/parser/issue-17904.stderr
src/test/ui/parser/issue-32214.rs
src/test/ui/parser/issue-32214.stderr
src/test/ui/parser/issue-32505.rs
src/test/ui/parser/issue-32505.stderr
src/test/ui/parser/lex-bad-binary-literal.rs
src/test/ui/parser/lex-bad-binary-literal.stderr
src/test/ui/parser/lex-bad-numeric-literals.rs
src/test/ui/parser/lex-bad-numeric-literals.stderr
src/test/ui/parser/lex-bad-octal-literal.rs
src/test/ui/parser/lex-bad-octal-literal.stderr
src/test/ui/parser/macro/macro-incomplete-parse.rs
src/test/ui/parser/macro/macro-incomplete-parse.stderr
src/test/ui/parser/new-unicode-escapes-4.rs
src/test/ui/parser/new-unicode-escapes-4.stderr
src/test/ui/parser/no-unsafe-self.rs
src/test/ui/parser/no-unsafe-self.stderr
src/test/ui/parser/range_inclusive_dotdotdot.rs
src/test/ui/parser/range_inclusive_dotdotdot.stderr
src/test/ui/parser/raw-byte-string-literals.rs
src/test/ui/parser/raw-byte-string-literals.stderr
src/test/ui/parser/recover-enum.rs
src/test/ui/parser/recover-enum.stderr
src/test/ui/parser/recover-enum2.rs
src/test/ui/parser/recover-enum2.stderr
src/test/ui/parser/recover-from-bad-variant.stderr
src/test/ui/parser/recover-struct.rs
src/test/ui/parser/recover-struct.stderr
src/test/ui/parser/removed-syntax-field-let.rs
src/test/ui/parser/removed-syntax-field-let.stderr
src/test/ui/parser/trailing-plus-in-bounds.rs
src/test/ui/parser/trait-bounds-not-on-impl.rs
src/test/ui/parser/trait-bounds-not-on-impl.stderr
src/test/ui/parser/trait-object-bad-parens.rs
src/test/ui/parser/trait-object-bad-parens.stderr
src/test/ui/parser/trait-object-lifetime-parens.rs
src/test/ui/parser/trait-object-lifetime-parens.stderr
src/test/ui/parser/use-as-where-use-ends-with-mod-sep.rs
src/test/ui/parser/use-as-where-use-ends-with-mod-sep.stderr
src/test/ui/parser/where-clauses-no-bounds-or-predicates.rs
src/test/ui/parser/where-clauses-no-bounds-or-predicates.stderr
src/test/ui/self/self_type_keyword.rs
src/test/ui/self/self_type_keyword.stderr
src/test/ui/symbol-names/issue-60925.legacy.stderr
src/test/ui/symbol-names/issue-60925.rs
src/test/ui/traits/trait-object-vs-lifetime-2.rs
src/test/ui/traits/trait-object-vs-lifetime-2.stderr
src/test/ui/type/type-ascription-instead-of-statement-end.stderr
src/tools/clippy
src/tools/miri
src/tools/tidy/src/deps.rs

index e1a6ea510d087550d787a6c3bdd96bb3d6f2c482..0cd6f24e32c7cf186416366fa415724f1306100e 100644 (file)
@@ -27,7 +27,7 @@ steps:
 # Original downloaded here came from
 # http://releases.llvm.org/7.0.0/LLVM-7.0.0-win64.exe
 - script: |
-    powershell -Command "iwr -outf %TEMP%\LLVM-7.0.0-win64.exe https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/LLVM-7.0.0-win64.exe"
+    powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf %TEMP%\LLVM-7.0.0-win64.exe https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/LLVM-7.0.0-win64.exe"
     set CLANG_DIR=%CD%\citools\clang-rust
     %TEMP%\LLVM-7.0.0-win64.exe /S /NCRC /D=%CLANG_DIR%
     set RUST_CONFIGURE_ARGS=%RUST_CONFIGURE_ARGS% --set llvm.clang-cl=%CLANG_DIR%\bin\clang-cl.exe
index 7622f716cc801e6c6dc8042b0c66d576f6c469f8..427e50f571f764197cfca484c0e93fd6da670808 100644 (file)
@@ -9,7 +9,7 @@ steps:
 
 - script: |
     md sccache
-    powershell -Command "iwr -outf sccache\sccache.exe https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2018-04-26-sccache-x86_64-pc-windows-msvc"
+    powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf sccache\sccache.exe https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2018-04-26-sccache-x86_64-pc-windows-msvc"
     echo ##vso[task.prependpath]%CD%\sccache
   displayName: Install sccache (Windows)
   condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'))
index d79ebe973bafbd623791ac22a0cd74797e211fd3..04662a69c87477a16d807449512e62d3daba6ab0 100644 (file)
@@ -54,9 +54,9 @@ steps:
 # Note that we don't literally overwrite the gdb.exe binary because it appears
 # to just use gdborig.exe, so that's the binary we deal with instead.
 - script: |
-    powershell -Command "iwr -outf %MINGW_ARCHIVE% %MINGW_URL%/%MINGW_ARCHIVE%"
+    powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf %MINGW_ARCHIVE% %MINGW_URL%/%MINGW_ARCHIVE%"
     7z x -y %MINGW_ARCHIVE% > nul
-    powershell -Command "iwr -outf 2017-04-20-%MSYS_BITS%bit-gdborig.exe %MINGW_URL%/2017-04-20-%MSYS_BITS%bit-gdborig.exe"
+    powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf 2017-04-20-%MSYS_BITS%bit-gdborig.exe %MINGW_URL%/2017-04-20-%MSYS_BITS%bit-gdborig.exe"
     mv 2017-04-20-%MSYS_BITS%bit-gdborig.exe %MINGW_DIR%\bin\gdborig.exe
     echo ##vso[task.prependpath]%CD%\%MINGW_DIR%\bin
   condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'), ne(variables['MINGW_URL'],''))
@@ -81,7 +81,7 @@ steps:
 # Note that this is originally from the github releases patch of Ninja
 - script: |
     md ninja
-    powershell -Command "iwr -outf 2017-03-15-ninja-win.zip https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2017-03-15-ninja-win.zip"
+    powershell -Command "$ProgressPreference = 'SilentlyContinue'; iwr -outf 2017-03-15-ninja-win.zip https://rust-lang-ci2.s3.amazonaws.com/rust-ci-mirror/2017-03-15-ninja-win.zip"
     7z x -oninja 2017-03-15-ninja-win.zip
     del 2017-03-15-ninja-win.zip
     set RUST_CONFIGURE_ARGS=%RUST_CONFIGURE_ARGS% --enable-ninja
index a13bc0e74760ad30eb4a111677b77c8a525e05fd..ea0087de839af218bf3c6665f32b05124504f0ac 100644 (file)
@@ -1080,7 +1080,7 @@ dependencies = [
 
 [[package]]
 name = "hashbrown"
-version = "0.3.0"
+version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "compiler_builtins 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1183,6 +1183,11 @@ dependencies = [
  "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "indexmap"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
 [[package]]
 name = "installer"
 version = "0.0.0"
@@ -1641,6 +1646,7 @@ dependencies = [
  "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+ "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-workspace-hack 1.0.0",
  "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2719,6 +2725,7 @@ dependencies = [
  "cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "ena 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "graphviz 0.0.0",
+ "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "jobserver 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2970,6 +2977,7 @@ version = "0.0.0"
 dependencies = [
  "arena 0.0.0",
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
+ "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_data_structures 0.0.0",
@@ -3236,6 +3244,7 @@ dependencies = [
 name = "serialize"
 version = "0.0.0"
 dependencies = [
+ "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -3322,7 +3331,7 @@ dependencies = [
  "core 0.0.0",
  "dlmalloc 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "fortanix-sgx-abi 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "hashbrown 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "hashbrown 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)",
  "panic_abort 0.0.0",
  "panic_unwind 0.0.0",
@@ -4188,7 +4197,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum globset 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef4feaabe24a0a658fd9cf4a9acf6ed284f045c77df0f49020ba3245cfb7b454"
 "checksum handlebars 0.32.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d89ec99d1594f285d4590fc32bac5f75cdab383f1123d504d27862c644a807dd"
 "checksum handlebars 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d82e5750d8027a97b9640e3fefa66bbaf852a35228e1c90790efd13c4b09c166"
-"checksum hashbrown 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "570178d5e4952010d138b0f1d581271ff3a02406d990f887d1e87e3d6e43b0ac"
+"checksum hashbrown 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9529213c67695ca2d146e6f263b7b72df8fa973368beadf767e8ed80c03f2f36"
 "checksum heck 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea04fa3ead4e05e51a7c806fc07271fdbde4e246a6c6d1efd52e72230b771b82"
 "checksum hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77"
 "checksum home 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "80dff82fb58cfbbc617fb9a9184b010be0529201553cda50ad04372bc2333aff"
@@ -4199,6 +4208,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum if_chain 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c3360c7b59e5ffa2653671fb74b4741a5d343c03f331c0a4aeda42b5c2b0ec7d"
 "checksum ignore 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8dc57fa12805f367736a38541ac1a9fc6a52812a0ca959b1d4d4b640a89eb002"
 "checksum im-rc 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0a0197597d095c0d11107975d3175173f810ee572c2501ff4de64f4f3f119806"
+"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d"
 "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08"
 "checksum is-match 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7e5b386aef33a1c677be65237cb9d32c3f3ef56bd035949710c4bb13083eb053"
 "checksum itertools 0.7.8 (registry+https://github.com/rust-lang/crates.io-index)" = "f58856976b776fedd95533137617a02fb25719f40e7d9b01c7043cd65474f450"
index 12bdfa5691dc744a7479a6074d6d546ccb3965b0..2a3577a3d20446b0593ec1ba1f916125cdbea3ca 100644 (file)
@@ -62,11 +62,11 @@ fn run(self, builder: &Builder<'_>) {
 book!(
     EditionGuide, "src/doc/edition-guide", "edition-guide", RustbookVersion::MdBook2;
     EmbeddedBook, "src/doc/embedded-book", "embedded-book", RustbookVersion::MdBook2;
-    Nomicon, "src/doc/nomicon", "nomicon", RustbookVersion::MdBook1;
+    Nomicon, "src/doc/nomicon", "nomicon", RustbookVersion::MdBook2;
     Reference, "src/doc/reference", "reference", RustbookVersion::MdBook1;
     RustByExample, "src/doc/rust-by-example", "rust-by-example", RustbookVersion::MdBook1;
     RustcBook, "src/doc/rustc", "rustc", RustbookVersion::MdBook1;
-    RustdocBook, "src/doc/rustdoc", "rustdoc", RustbookVersion::MdBook1;
+    RustdocBook, "src/doc/rustdoc", "rustdoc", RustbookVersion::MdBook2;
 );
 
 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
@@ -134,7 +134,7 @@ fn run(self, builder: &Builder<'_>) {
             target: self.target,
             name: INTERNER.intern_str("unstable-book"),
             src: builder.md_doc_out(self.target),
-            version: RustbookVersion::MdBook1,
+            version: RustbookVersion::MdBook2,
         })
     }
 }
index d5988a25671a2d3109a923b7ea1de1d98968e385..55899fa6c3e695f655971730bf17d77f0fa5196c 100644 (file)
@@ -3,7 +3,7 @@
 #
 # Versions of the toolchain components are configurable in `musl-cross-make/Makefile` and
 # musl unlike GLIBC is forward compatible so upgrading it shouldn't break old distributions.
-# Right now we have: Binutils 2.27, GCC 6.3.0, musl 1.1.18
+# Right now we have: Binutils 2.27, GCC 6.4.0, musl 1.1.22.
 set -ex
 
 hide_output() {
@@ -33,7 +33,7 @@ shift
 # Apparently applying `-fPIC` everywhere allows them to link successfully.
 export CFLAGS="-fPIC $CFLAGS"
 
-git clone https://github.com/richfelker/musl-cross-make -b v0.9.7
+git clone https://github.com/richfelker/musl-cross-make -b v0.9.8
 cd musl-cross-make
 
 hide_output make -j$(nproc) TARGET=$TARGET
index aba485f752ab2bd9b706a1a9739d32bfd2ae1d5c..b21defaedc31312147423bd3c051d9a34b472973 100644 (file)
@@ -178,7 +178,7 @@ $ rustdoc src/lib.rs --passes strip-priv-imports
 An argument of "list" will print a list of possible "rustdoc passes", and other
 arguments will be the name of which passes to run in addition to the defaults.
 
-For more details on passes, see [the chapter on them](passes.html).
+For more details on passes, see [the chapter on them](passes.md).
 
 See also `--no-defaults`.
 
@@ -194,7 +194,7 @@ By default, `rustdoc` will run several passes over your code. This
 removes those defaults, allowing you to use `--passes` to specify
 exactly which passes you want.
 
-For more details on passes, see [the chapter on them](passes.html).
+For more details on passes, see [the chapter on them](passes.md).
 
 See also `--passes`.
 
@@ -207,7 +207,7 @@ $ rustdoc src/lib.rs --test
 ```
 
 This flag will run your code examples as tests. For more, see [the chapter
-on documentation tests](documentation-tests.html).
+on documentation tests](documentation-tests.md).
 
 See also `--test-args`.
 
@@ -220,7 +220,7 @@ $ rustdoc src/lib.rs --test --test-args ignored
 ```
 
 This flag will pass options to the test runner when running documentation tests.
-For more, see [the chapter on documentation tests](documentation-tests.html).
+For more, see [the chapter on documentation tests](documentation-tests.md).
 
 See also `--test`.
 
index 615b3dca199f1cc218a426b49b1bfd2e74d40435..12d4ea205b31e64308106741522b85a910300d99 100644 (file)
@@ -5,8 +5,8 @@ Rustdoc has a concept called "passes". These are transformations that
 
 In addition to the passes below, check out the docs for these flags:
 
-* [`--passes`](command-line-arguments.html#a--passes-add-more-rustdoc-passes)
-* [`--no-defaults`](command-line-arguments.html#a--no-defaults-dont-run-default-passes)
+* [`--passes`](command-line-arguments.md#--passes-add-more-rustdoc-passes)
+* [`--no-defaults`](command-line-arguments.md#--no-defaults-dont-run-default-passes)
 
 ## Default passes
 
index f22095fe5de2e632bdcaae4142b204b744815748..2a1b6397781f95fc9a98fbb620c6e5b2dd29aae8 100644 (file)
@@ -190,4 +190,4 @@ constraints, etc.
 [llvm-docs]: http://llvm.org/docs/LangRef.html#inline-assembler-expressions
 
 If you need more power and don't mind losing some of the niceties of
-`asm!`, check out [global_asm](language-features/global-asm.html).
+`asm!`, check out [global_asm](global-asm.md).
index 0896627acae1b3203a39d1463bcae4d6e470fa19..bf0819ec920b7f0462ad912fa87ad80124e1c34c 100644 (file)
@@ -4,7 +4,7 @@ The tracking issue for this feature is: [#29641]
 
 [#29641]: https://github.com/rust-lang/rust/issues/29641
 
-See also [`box_syntax`](language-features/box-syntax.html)
+See also [`box_syntax`](box-syntax.md)
 
 ------------------------
 
index 414dc48e557d3ec3f391fbb7bd288c19a88a33e4..9569974d22ca28124cd888e78c56a9a81d15aedf 100644 (file)
@@ -4,7 +4,7 @@ The tracking issue for this feature is: [#49733]
 
 [#49733]: https://github.com/rust-lang/rust/issues/49733
 
-See also [`box_patterns`](language-features/box-patterns.html)
+See also [`box_patterns`](box-patterns.md)
 
 ------------------------
 
index f1ef74a63b513acedd4ff96396812640b451ac9b..bc55fe80fa64c599f954ebdedd613ebba60465e1 100644 (file)
@@ -75,4 +75,4 @@ usages and placed the larger, single usage in the crate root.
 If you don't need quite as much power and flexibility as
 `global_asm!` provides, and you don't mind restricting your inline
 assembly to `fn` bodies only, you might try the
-[asm](language-features/asm.html) feature instead.
+[asm](asm.md) feature instead.
index b16739b4743a9ebb0070527216419f6388da4fb3..3ee024c6b588361e8f10a3f593aebf1f60b6333d 100644 (file)
@@ -192,7 +192,7 @@ such as "```undefined reference to `__rust_probestack'```". Using this crate
 also requires enabling the library feature `compiler_builtins_lib`. You can read
 more about this [here][compiler-builtins-lib].
 
-[compiler-builtins-lib]: library-features/compiler-builtins-lib.html
+[compiler-builtins-lib]: ../library-features/compiler-builtins-lib.md
 
 ## More about the language items
 
index 46957c00bf95c749961c44af34d0e455871c5967..22dae0c89a6ff5a460ef4c04679f2b29c24ca0c6 100644 (file)
@@ -45,4 +45,4 @@ that does _not_ occur in the set of [strict keywords].
 
 [`XID_start`]:  http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3AXID_Start%3A%5D&abb=on&g=&i=
 [`XID_continue`]: http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5B%3AXID_Continue%3A%5D&abb=on&g=&i=
-[strict keywords]: ../reference/keywords.html#strict-keywords
+[strict keywords]: ../../reference/keywords.md#strict-keywords
index b16e2ac2d221c97941e4f4ba0c01b31781335bed..bf5dd81d735af768be0994f50fa6fb6193be9569 100644 (file)
@@ -8,6 +8,6 @@ This feature is part of "compiler plugins." It will often be used with the
 [`plugin`] and `rustc_private` features as well. For more details, see
 their docs.
 
-[`plugin`]: language-features/plugin.html
+[`plugin`]: plugin.md
 
 ------------------------
index 49fe7c9e994fe15b7f1df0ddebd4806f1af429d0..43fffd680372fb1330454972561e42abd40a434d 100644 (file)
@@ -8,7 +8,7 @@ The tracking issue for this feature is: [#29597]
 This feature is part of "compiler plugins." It will often be used with the
 [`plugin_registrar`] and `rustc_private` features.
 
-[`plugin_registrar`]: language-features/plugin-registrar.html
+[`plugin_registrar`]: plugin-registrar.md
 
 ------------------------
 
@@ -39,7 +39,7 @@ of a library.
 
 Plugins can extend Rust's syntax in various ways. One kind of syntax extension
 is the procedural macro. These are invoked the same way as [ordinary
-macros](../book/macros.html), but the expansion is performed by arbitrary Rust
+macros](../../book/macros.md), but the expansion is performed by arbitrary Rust
 code that manipulates syntax trees at
 compile time.
 
@@ -130,7 +130,7 @@ The advantages over a simple `fn(&str) -> u32` are:
   a way to define new literal syntax for any data type.
 
 In addition to procedural macros, you can define new
-[`derive`](../reference/attributes/derive.html)-like attributes and other kinds
+[`derive`](../../reference/attributes/derive.md)-like attributes and other kinds
 of extensions.  See `Registry::register_syntax_extension` and the
 `SyntaxExtension` enum.  For a more involved macro example, see
 [`regex_macros`](https://github.com/rust-lang/regex/blob/master/regex_macros/src/lib.rs).
@@ -174,7 +174,7 @@ quasiquote as an ordinary plugin library.
 # Lint plugins
 
 Plugins can extend [Rust's lint
-infrastructure](../reference/attributes/diagnostics.html#lint-check-attributes) with
+infrastructure](../../reference/attributes/diagnostics.md#lint-check-attributes) with
 additional checks for code style, safety, etc. Now let's write a plugin
 [`lint_plugin_test.rs`](https://github.com/rust-lang/rust/blob/master/src/test/ui-fulldeps/auxiliary/lint_plugin_test.rs)
 that warns about any item named `lintme`.
@@ -253,7 +253,7 @@ mostly use the same infrastructure as lint plugins, and provide examples of how
 to access type information.
 
 Lints defined by plugins are controlled by the usual [attributes and compiler
-flags](../reference/attributes/diagnostics.html#lint-check-attributes), e.g.
+flags](../../reference/attributes/diagnostics.md#lint-check-attributes), e.g.
 `#[allow(test_lint)]` or `-A test-lint`. These identifiers are derived from the
 first argument to `declare_lint!`, with appropriate case and punctuation
 conversion.
index d845c99a88a691946d439861d7df4acec850a998..71003fba00ba237e9fed3601258d7aa18c502165 100644 (file)
@@ -2,7 +2,7 @@
 
 The tracking issue for this feature is [#29625]
 
-See Also: [`fn_traits`](library-features/fn-traits.html)
+See Also: [`fn_traits`](../library-features/fn-traits.md)
 
 [#29625]: https://github.com/rust-lang/rust/issues/29625
 
index 72a3f36c10b69ed1d6acc28e9577c085d71e9cd1..29a8aecee6c2fd26e5420a2c06640823e01b99fa 100644 (file)
@@ -2,7 +2,7 @@
 
 The tracking issue for this feature is [#29625]
 
-See Also: [`unboxed_closures`](language-features/unboxed-closures.html)
+See Also: [`unboxed_closures`](../language-features/unboxed-closures.md)
 
 [#29625]: https://github.com/rust-lang/rust/issues/29625
 
index cb3386b7152112a5953d457b12c36c181f061618..97e32cc0acb121ef319d51fa79275dbd5e2073ba 100644 (file)
@@ -27,6 +27,6 @@ impl<A, F> Fn for &F where F: Fn<A> + ?Sized {}
 
 Before the introduction of [`unsized_locals`][unsized_locals], we had been unable to provide the former impls. That means, unlike `&dyn Fn()` or `&mut dyn FnMut()` we could not use `Box<dyn FnOnce()>` at that time.
 
-[unsized_locals]: language-features/unsized-locals.html
+[unsized_locals]: ../language-features/unsized-locals.md
 
 `FnBox()` is an alternative approach to `Box<dyn FnBox()>` is delegated to `FnBox::call_box` which doesn't need unsized locals. As we now have `Box<dyn FnOnce()>` working, the `fnbox` feature is going to be removed.
index 604b449f16379956897e2965c600ad86d80917e3..554c52c3c9c2761c7f6768a51923c7b36fdbf2c5 100644 (file)
@@ -14,7 +14,7 @@ fn main() {
 
 The `box_syntax` feature [has a chapter][box] describing how to use it.
 
-[box]: language-features/box-syntax.html
+[box]: language-features/box-syntax.md
 
 Because this documentation relates to unstable features, we make no guarantees
 that what is contained here is accurate or up to date. It's developed on a
index d90036eaf49b8f3da6389d23e8f978f69fe5984e..bfc008e14a486f870edffde929bdaca1f939d989 100644 (file)
 #![feature(maybe_uninit_extra, maybe_uninit_slice, maybe_uninit_array)]
 #![feature(alloc_layout_extra)]
 #![feature(try_trait)]
-#![feature(iter_nth_back)]
 
 // Allow testing this library
 
index b3ff447be5ee4802f110e4c601b38007b9a30bef..6215bf5cd65723495fdc76d07808f55cd2b906bc 100644 (file)
@@ -129,7 +129,7 @@ pub const fn identity<T>(x: T) -> T { x }
 /// # Examples
 ///
 /// By using trait bounds we can accept arguments of different types as long as they can be
-/// converted a the specified type `T`.
+/// converted to the specified type `T`.
 ///
 /// For example: By creating a generic function that takes an `AsRef<str>` we express that we
 /// want to accept all references that can be converted to `&str` as an argument.
@@ -177,8 +177,8 @@ pub trait AsRef<T: ?Sized> {
 ///
 /// Using `AsMut` as trait bound for a generic function we can accept all mutable references
 /// that can be converted to type `&mut T`. Because [`Box<T>`] implements `AsMut<T>` we can
-/// write a function `add_one`that takes all arguments that can be converted to `&mut u64`.
-/// Because [`Box<T>`] implements `AsMut<T>` `add_one` accepts arguments of type
+/// write a function `add_one` that takes all arguments that can be converted to `&mut u64`.
+/// Because [`Box<T>`] implements `AsMut<T>`, `add_one` accepts arguments of type
 /// `&mut Box<u64>` as well:
 ///
 /// ```
index 06de95c082724bdfcefa15e972374ee46aed10ae..2c1aeb5690a585d0e254bc4b274b9828597a5b8d 100644 (file)
@@ -88,7 +88,6 @@ pub trait DoubleEndedIterator: Iterator {
     /// Basic usage:
     ///
     /// ```
-    /// #![feature(iter_nth_back)]
     /// let a = [1, 2, 3];
     /// assert_eq!(a.iter().nth_back(2), Some(&1));
     /// ```
@@ -96,7 +95,6 @@ pub trait DoubleEndedIterator: Iterator {
     /// Calling `nth_back()` multiple times doesn't rewind the iterator:
     ///
     /// ```
-    /// #![feature(iter_nth_back)]
     /// let a = [1, 2, 3];
     ///
     /// let mut iter = a.iter();
@@ -108,12 +106,11 @@ pub trait DoubleEndedIterator: Iterator {
     /// Returning `None` if there are less than `n + 1` elements:
     ///
     /// ```
-    /// #![feature(iter_nth_back)]
     /// let a = [1, 2, 3];
     /// assert_eq!(a.iter().nth_back(10), None);
     /// ```
     #[inline]
-    #[unstable(feature = "iter_nth_back", issue = "56995")]
+    #[stable(feature = "iter_nth_back", since = "1.37.0")]
     fn nth_back(&mut self, mut n: usize) -> Option<Self::Item> {
         for x in self.rev() {
             if n == 0 { return Some(x) }
index 4a70329b64bc983a7d43b0b4214be77d892c8447..ad35204804755cb6cbcb0c29e07470a00662422f 100644 (file)
 #![feature(const_str_len)]
 #![feature(const_int_conversion)]
 #![feature(const_transmute)]
-#![feature(reverse_bits)]
 #![feature(non_exhaustive)]
 #![feature(structural_match)]
 #![feature(abi_unadjusted)]
index 7ec75ed0114889adb302a009fe71c8e6bb4628a9..7145bf1fbc0ee07a8e4e4bb76bf06bea6e71d257 100644 (file)
@@ -463,15 +463,12 @@ pub const fn swap_bytes(self) -> Self {
 Basic usage:
 
 ```
-#![feature(reverse_bits)]
-
 let n = ", $swap_op, stringify!($SelfT), ";
 let m = n.reverse_bits();
 
 assert_eq!(m, ", $reversed, ");
 ```"),
-            #[unstable(feature = "reverse_bits", issue = "48763")]
-            #[rustc_const_unstable(feature = "const_int_conversion")]
+            #[stable(feature = "reverse_bits", since = "1.37.0")]
             #[inline]
             #[must_use]
             pub const fn reverse_bits(self) -> Self {
@@ -2514,14 +2511,12 @@ pub const fn swap_bytes(self) -> Self {
 Basic usage:
 
 ```
-#![feature(reverse_bits)]
-
 let n = ", $swap_op, stringify!($SelfT), ";
 let m = n.reverse_bits();
 
 assert_eq!(m, ", $reversed, ");
 ```"),
-            #[unstable(feature = "reverse_bits", issue = "48763")]
+            #[stable(feature = "reverse_bits", since = "1.37.0")]
             #[inline]
             #[must_use]
             pub const fn reverse_bits(self) -> Self {
index 5eb5ec558f8c132a847e0ba3680c2360d99e5e16..fd129a306d1c57024d788dc72dfdeea9069616d1 100644 (file)
@@ -511,7 +511,6 @@ pub const fn swap_bytes(self) -> Self {
             /// Basic usage:
             ///
             /// ```
-            /// #![feature(reverse_bits)]
             /// use std::num::Wrapping;
             ///
             /// let n = Wrapping(0b0000000_01010101i16);
@@ -522,7 +521,7 @@ pub const fn swap_bytes(self) -> Self {
             /// assert_eq!(m.0 as u16, 0b10101010_00000000);
             /// assert_eq!(m, Wrapping(-22016));
             /// ```
-            #[unstable(feature = "reverse_bits", issue = "48763")]
+            #[stable(feature = "reverse_bits", since = "1.37.0")]
             #[inline]
             #[must_use]
             pub const fn reverse_bits(self) -> Self {
index e44a6c4d2a0e92a13d35ccc978d56ba5030df1b8..ce0d3fd01f78fefc030dbe2d2a3b67afbfc7561c 100644 (file)
@@ -23,9 +23,9 @@
 /// * Values of type `&T` are coerced to values of type `&U`
 /// * `T` implicitly implements all the (immutable) methods of the type `U`.
 ///
-/// For more details, visit [the chapter in *The Rust Programming Language*]
-/// [book] as well as the reference sections on [the dereference operator]
-/// [ref-deref-op], [method resolution] and [type coercions].
+/// For more details, visit [the chapter in *The Rust Programming Language*][book]
+/// as well as the reference sections on [the dereference operator][ref-deref-op],
+/// [method resolution] and [type coercions].
 ///
 /// [book]: ../../book/ch15-02-deref.html
 /// [`DerefMut`]: trait.DerefMut.html
@@ -113,9 +113,9 @@ fn deref(&self) -> &T { *self }
 /// * Values of type `&mut T` are coerced to values of type `&mut U`
 /// * `T` implicitly implements all the (mutable) methods of the type `U`.
 ///
-/// For more details, visit [the chapter in *The Rust Programming Language*]
-/// [book] as well as the reference sections on [the dereference operator]
-/// [ref-deref-op], [method resolution] and [type coercions].
+/// For more details, visit [the chapter in *The Rust Programming Language*][book]
+/// as well as the reference sections on [the dereference operator][ref-deref-op],
+/// [method resolution] and [type coercions].
 ///
 /// [book]: ../../book/ch15-02-deref.html
 /// [`Deref`]: trait.Deref.html
index c617596aba80159af2ecb5f3c4967bc099897f8f..5050842e409711488fd92462356593674494c40e 100644 (file)
@@ -10,7 +10,6 @@
 #![feature(fmt_internals)]
 #![feature(hashmap_internals)]
 #![feature(is_sorted)]
-#![feature(iter_nth_back)]
 #![feature(iter_once_with)]
 #![feature(pattern)]
 #![feature(range_is_empty)]
@@ -25,7 +24,6 @@
 #![feature(test)]
 #![feature(trusted_len)]
 #![feature(try_trait)]
-#![feature(reverse_bits)]
 #![feature(inner_deref)]
 #![feature(slice_internals)]
 #![feature(slice_partition_dedup)]
index c179b05683d1c91258bf53b335f9cc94d8e305c5..e8c3914e695ad1c71c214cbf240625e758382fbf 100644 (file)
 macro_rules! arena_types {
     ($macro:path, $args:tt, $tcx:lifetime) => (
         $macro!($args, [
+            [] layouts: rustc::ty::layout::LayoutDetails,
+            [] generics: rustc::ty::Generics,
+            [] trait_def: rustc::ty::TraitDef,
+            [] adt_def: rustc::ty::AdtDef,
+            [] steal_mir: rustc::ty::steal::Steal<rustc::mir::Body<$tcx>>,
+            [] mir: rustc::mir::Body<$tcx>,
+            [] tables: rustc::ty::TypeckTables<$tcx>,
+            [] const_allocs: rustc::mir::interpret::Allocation,
             [] vtable_method: Option<(
                 rustc::hir::def_id::DefId,
                 rustc::ty::subst::SubstsRef<$tcx>
@@ -101,6 +109,7 @@ macro_rules! arena_types {
             >,
             [few] crate_variances: rustc::ty::CrateVariancesMap<'tcx>,
             [few] inferred_outlives_crate: rustc::ty::CratePredicatesMap<'tcx>,
+            [] upvars: rustc_data_structures::fx::FxIndexMap<rustc::hir::HirId, rustc::hir::Upvar>,
         ], $tcx);
     )
 }
index 03f24dbb29025f70ef8004cdab5c80275a6e45fc..131a910bebb1aac2832ceb02cda38540e6c85225 100644 (file)
@@ -139,9 +139,6 @@ pub enum Res<Id = hir::HirId> {
     // Value namespace
     SelfCtor(DefId /* impl */),  // `DefId` refers to the impl
     Local(Id),
-    Upvar(Id,           // `HirId` of closed over local
-          usize,        // index in the `upvars` list of the closure
-          ast::NodeId), // expr node that creates the closure
 
     // Macro namespace
     NonMacroAttr(NonMacroAttrKind), // e.g., `#[inline]` or `#[rustfmt::skip]`
@@ -347,7 +344,6 @@ pub fn opt_def_id(&self) -> Option<DefId> {
             Res::Def(_, id) => Some(id),
 
             Res::Local(..) |
-            Res::Upvar(..) |
             Res::PrimTy(..) |
             Res::SelfTy(..) |
             Res::SelfCtor(..) |
@@ -374,7 +370,6 @@ pub fn descr(&self) -> &'static str {
             Res::SelfCtor(..) => "self constructor",
             Res::PrimTy(..) => "builtin type",
             Res::Local(..) => "local variable",
-            Res::Upvar(..) => "closure capture",
             Res::SelfTy(..) => "self type",
             Res::ToolMod => "tool module",
             Res::NonMacroAttr(attr_kind) => attr_kind.descr(),
@@ -397,11 +392,6 @@ pub fn map_id<R>(self, mut map: impl FnMut(Id) -> R) -> Res<R> {
             Res::SelfCtor(id) => Res::SelfCtor(id),
             Res::PrimTy(id) => Res::PrimTy(id),
             Res::Local(id) => Res::Local(map(id)),
-            Res::Upvar(id, index, closure) => Res::Upvar(
-                map(id),
-                index,
-                closure
-            ),
             Res::SelfTy(a, b) => Res::SelfTy(a, b),
             Res::ToolMod => Res::ToolMod,
             Res::NonMacroAttr(attr_kind) => Res::NonMacroAttr(attr_kind),
index fd42c6f469e1eec2bb91f70e64f6b8dc1d6be44e..75799a1903174270912f5babb8616412a8f7710f 100644 (file)
@@ -26,7 +26,7 @@
 
 use std::io;
 use std::result::Result::Err;
-use crate::ty::TyCtxt;
+use crate::ty::query::Providers;
 
 pub mod blocks;
 mod collector;
@@ -628,10 +628,6 @@ pub fn get_generics(&self, id: DefId) -> Option<&'hir Generics> {
         })
     }
 
-    pub fn get_generics_span(&self, id: DefId) -> Option<Span> {
-        self.get_generics(id).map(|generics| generics.span).filter(|sp| *sp != DUMMY_SP)
-    }
-
     /// Retrieves the `Node` corresponding to `id`, returning `None` if cannot be found.
     pub fn find(&self, id: NodeId) -> Option<Node<'hir>> {
         let hir_id = self.node_to_hir_id(id);
@@ -1450,11 +1446,13 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String {
     }
 }
 
-pub fn def_kind(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Option<DefKind> {
-    if let Some(node_id) = tcx.hir().as_local_node_id(def_id) {
-        tcx.hir().def_kind(node_id)
-    } else {
-        bug!("Calling local def_kind query provider for upstream DefId: {:?}",
-             def_id)
-    }
+pub fn provide(providers: &mut Providers<'_>) {
+    providers.def_kind = |tcx, def_id| {
+        if let Some(node_id) = tcx.hir().as_local_node_id(def_id) {
+            tcx.hir().def_kind(node_id)
+        } else {
+            bug!("Calling local def_kind query provider for upstream DefId: {:?}",
+                def_id)
+        }
+    };
 }
index f03a8ddc90825a7a23086878d2150da9d2bb744d..210c0c9225a3d9bb3afb74564c59d21b11595e6f 100644 (file)
@@ -16,7 +16,7 @@
 use crate::mir::mono::Linkage;
 
 use errors::FatalError;
-use syntax_pos::{Span, DUMMY_SP, symbol::InternedString};
+use syntax_pos::{Span, DUMMY_SP, symbol::InternedString, MultiSpan};
 use syntax::source_map::Spanned;
 use rustc_target::spec::abi::Abi;
 use syntax::ast::{self, CrateSugar, Ident, Name, NodeId, AsmDialect};
@@ -63,6 +63,7 @@ macro_rules! hir_vec {
 pub mod map;
 pub mod pat_util;
 pub mod print;
+pub mod upvars;
 
 /// Uniquely identifies a node in the HIR of the current crate. It is
 /// composed of the `owner`, which is the `DefIndex` of the directly enclosing
@@ -624,6 +625,14 @@ pub fn get_named(&self, name: InternedString) -> Option<&GenericParam> {
         }
         None
     }
+
+    pub fn spans(&self) -> MultiSpan {
+        if self.params.is_empty() {
+            self.span.into()
+        } else {
+            self.params.iter().map(|p| p.span).collect::<Vec<Span>>().into()
+        }
+    }
 }
 
 /// Synthetic type parameters are converted to another form during lowering; this allows
@@ -1408,7 +1417,6 @@ pub fn is_place_expr(&self) -> bool {
             ExprKind::Path(QPath::Resolved(_, ref path)) => {
                 match path.res {
                     Res::Local(..)
-                    | Res::Upvar(..)
                     | Res::Def(DefKind::Static, _)
                     | Res::Err => true,
                     _ => false,
@@ -2493,32 +2501,11 @@ pub fn descriptive_variant(&self) -> &str {
 
 /// A variable captured by a closure.
 #[derive(Debug, Copy, Clone, RustcEncodable, RustcDecodable, HashStable)]
-pub struct Upvar<Id = HirId> {
-    /// The variable being captured.
-    pub res: Res<Id>,
-
+pub struct Upvar {
     // First span where it is accessed (there can be multiple).
     pub span: Span
 }
 
-impl<Id: fmt::Debug + Copy> Upvar<Id> {
-    pub fn map_id<R>(self, map: impl FnMut(Id) -> R) -> Upvar<R> {
-        Upvar {
-            res: self.res.map_id(map),
-            span: self.span,
-        }
-    }
-
-    pub fn var_id(&self) -> Id {
-        match self.res {
-            Res::Local(id) | Res::Upvar(id, ..) => id,
-            _ => bug!("Upvar::var_id: bad res ({:?})", self.res)
-        }
-    }
-}
-
-pub type UpvarMap = NodeMap<Vec<Upvar<ast::NodeId>>>;
-
 pub type CaptureModeMap = NodeMap<CaptureClause>;
 
  // The TraitCandidate's import_ids is empty if the trait is defined in the same module, and
@@ -2537,10 +2524,10 @@ pub struct TraitCandidate {
 // imported.
 pub type GlobMap = NodeMap<FxHashSet<Name>>;
 
-
 pub fn provide(providers: &mut Providers<'_>) {
     check_attr::provide(providers);
-    providers.def_kind = map::def_kind;
+    map::provide(providers);
+    upvars::provide(providers);
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
diff --git a/src/librustc/hir/upvars.rs b/src/librustc/hir/upvars.rs
new file mode 100644 (file)
index 0000000..a053deb
--- /dev/null
@@ -0,0 +1,104 @@
+//! Upvar (closure capture) collection from cross-body HIR uses of `Res::Local`s.
+
+use crate::hir::{self, HirId};
+use crate::hir::def::Res;
+use crate::hir::intravisit::{self, Visitor, NestedVisitorMap};
+use crate::ty::TyCtxt;
+use crate::ty::query::Providers;
+use syntax_pos::Span;
+use rustc_data_structures::fx::{FxIndexMap, FxHashSet};
+
+pub fn provide(providers: &mut Providers<'_>) {
+    providers.upvars = |tcx, def_id| {
+        if !tcx.is_closure(def_id) {
+            return None;
+        }
+
+        let node_id = tcx.hir().as_local_node_id(def_id).unwrap();
+        let body = tcx.hir().body(tcx.hir().maybe_body_owned_by(node_id)?);
+
+        let mut local_collector = LocalCollector::default();
+        local_collector.visit_body(body);
+
+        let mut capture_collector = CaptureCollector {
+            tcx,
+            locals: &local_collector.locals,
+            upvars: FxIndexMap::default(),
+        };
+        capture_collector.visit_body(body);
+
+        if !capture_collector.upvars.is_empty() {
+            Some(tcx.arena.alloc(capture_collector.upvars))
+        } else {
+            None
+        }
+    };
+}
+
+#[derive(Default)]
+struct LocalCollector {
+    // FIXME(eddyb) perhaps use `ItemLocalId` instead?
+    locals: FxHashSet<HirId>,
+}
+
+impl Visitor<'tcx> for LocalCollector {
+    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+        NestedVisitorMap::None
+    }
+
+    fn visit_pat(&mut self, pat: &'tcx hir::Pat) {
+        if let hir::PatKind::Binding(_, hir_id, ..) = pat.node {
+            self.locals.insert(hir_id);
+        }
+        intravisit::walk_pat(self, pat);
+    }
+}
+
+struct CaptureCollector<'a, 'tcx> {
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    locals: &'a FxHashSet<HirId>,
+    upvars: FxIndexMap<HirId, hir::Upvar>,
+}
+
+impl CaptureCollector<'_, '_> {
+    fn visit_local_use(&mut self, var_id: HirId, span: Span) {
+        if !self.locals.contains(&var_id) {
+            self.upvars.entry(var_id).or_insert(hir::Upvar { span });
+        }
+    }
+}
+
+impl Visitor<'tcx> for CaptureCollector<'a, 'tcx> {
+    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+        NestedVisitorMap::None
+    }
+
+    fn visit_path(&mut self, path: &'tcx hir::Path, _: hir::HirId) {
+        if let Res::Local(var_id) = path.res {
+            self.visit_local_use(var_id, path.span);
+        }
+
+        intravisit::walk_path(self, path);
+    }
+
+    fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
+        if let hir::ExprKind::Closure(..) = expr.node {
+            let closure_def_id = self.tcx.hir().local_def_id_from_hir_id(expr.hir_id);
+            if let Some(upvars) = self.tcx.upvars(closure_def_id) {
+                // Every capture of a closure expression is a local in scope,
+                // that is moved/copied/borrowed into the closure value, and
+                // for this analysis they are like any other access to a local.
+                //
+                // E.g. in `|b| |c| (a, b, c)`, the upvars of the inner closure
+                // are `a` and `b`, and while `a` is not directly used in the
+                // outer closure, it needs to be an upvar there too, so that
+                // the inner closure can take it (from the outer closure's env).
+                for (&var_id, upvar) in upvars {
+                    self.visit_local_use(var_id, upvar.span);
+                }
+            }
+        }
+
+        intravisit::walk_expr(self, expr);
+    }
+}
index ec1b0da68107439f0b436c1280ad35854edc4963..563948a63514b300eb4c01a23398aa988ffb452c 100644 (file)
@@ -100,7 +100,6 @@ fn hash_stable<W: StableHasherResult>(&self,
             ty::ReClosureBound(vid) => {
                 vid.hash_stable(hcx, hasher);
             }
-            ty::ReLateBound(..) |
             ty::ReVar(..) |
             ty::RePlaceholder(..) => {
                 bug!("StableHasher: unexpected region {:?}", *self)
index f87c6977f33d0261ea99cd3339b5184aa5c4a1ad..b1eba7d5934f91fed1f45662b46200870ac28307 100644 (file)
@@ -218,10 +218,6 @@ fn msg_span_from_early_bound_and_free_regions(
                     format!("the anonymous lifetime #{} defined on", idx + 1),
                     self.hir().span_by_hir_id(node),
                 ),
-                ty::BrFresh(_) => (
-                    "an anonymous lifetime defined on".to_owned(),
-                    self.hir().span_by_hir_id(node),
-                ),
                 _ => (
                     format!("the lifetime {} as defined on", region),
                     cm.def_span(self.hir().span_by_hir_id(node)),
index 6a20d95cc3ad349bb687d73f4a57ebf316fc6507..ca766ea724f3db02379a4a398aeccf8c3496157d 100644 (file)
 use rustc_data_structures::unify as ut;
 use crate::ty::ReStatic;
 use crate::ty::{self, Ty, TyCtxt};
-use crate::ty::{BrFresh, ReLateBound, ReVar};
+use crate::ty::{ReLateBound, ReVar};
 use crate::ty::{Region, RegionVid};
 
 use std::collections::BTreeMap;
-use std::{cmp, fmt, mem, u32};
+use std::{cmp, fmt, mem};
 use std::ops::Range;
 
 mod leak_check;
@@ -37,10 +37,6 @@ pub struct RegionConstraintCollector<'tcx> {
     /// exist). This prevents us from making many such regions.
     glbs: CombineMap<'tcx>,
 
-    /// Global counter used during the GLB algorithm to create unique
-    /// names for fresh bound regions
-    bound_count: u32,
-
     /// The undo log records actions that might later be undone.
     ///
     /// Note: `num_open_snapshots` is used to track if we are actively
@@ -392,7 +388,6 @@ pub fn take_and_reset_data(&mut self) -> RegionConstraintData<'tcx> {
             data,
             lubs,
             glbs,
-            bound_count: _,
             undo_log: _,
             num_open_snapshots: _,
             unification_table,
@@ -579,39 +574,6 @@ fn kill_constraint<'tcx>(
         }
     }
 
-    pub fn new_bound(
-        &mut self,
-        tcx: TyCtxt<'_, '_, 'tcx>,
-        debruijn: ty::DebruijnIndex,
-    ) -> Region<'tcx> {
-        // Creates a fresh bound variable for use in GLB computations.
-        // See discussion of GLB computation in the large comment at
-        // the top of this file for more details.
-        //
-        // This computation is potentially wrong in the face of
-        // rollover.  It's conceivable, if unlikely, that one might
-        // wind up with accidental capture for nested functions in
-        // that case, if the outer function had bound regions created
-        // a very long time before and the inner function somehow
-        // wound up rolling over such that supposedly fresh
-        // identifiers were in fact shadowed. For now, we just assert
-        // that there is no rollover -- eventually we should try to be
-        // robust against this possibility, either by checking the set
-        // of bound identifiers that appear in a given expression and
-        // ensure that we generate one that is distinct, or by
-        // changing the representation of bound regions in a fn
-        // declaration
-
-        let sc = self.bound_count;
-        self.bound_count = sc + 1;
-
-        if sc >= self.bound_count {
-            bug!("rollover in RegionInference new_bound()");
-        }
-
-        tcx.mk_region(ReLateBound(debruijn, BrFresh(sc)))
-    }
-
     fn add_constraint(&mut self, constraint: Constraint<'tcx>, origin: SubregionOrigin<'tcx>) {
         // cannot add constraints once regions are resolved
         debug!(
index 14553a972b704923e8bc26ba6cf076bcb568e339..04f5b35a0061aa4141ca4dca059fe84ce205cec4 100644 (file)
@@ -78,7 +78,7 @@ fn handle_res(&mut self, res: Res) {
             }
             _ if self.in_pat => {},
             Res::PrimTy(..) | Res::SelfTy(..) | Res::SelfCtor(..) |
-            Res::Local(..) | Res::Upvar(..) => {}
+            Res::Local(..) => {}
             Res::Def(DefKind::Ctor(CtorOf::Variant, ..), ctor_def_id) => {
                 let variant_id = self.tcx.parent(ctor_def_id).unwrap();
                 let enum_id = self.tcx.parent(variant_id).unwrap();
index 35b6b76a395679f88165804f7ac0f89c9cebbcb0..34cea2d75eaa81e556725834d5931aa8820f166a 100644 (file)
@@ -268,6 +268,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx, 'tcx> {
     /// See also `with_infer`, which is used *during* typeck.
     pub fn new(delegate: &'a mut (dyn Delegate<'tcx>+'a),
                tcx: TyCtxt<'a, 'tcx, 'tcx>,
+               body_owner: DefId,
                param_env: ty::ParamEnv<'tcx>,
                region_scope_tree: &'a region::ScopeTree,
                tables: &'a ty::TypeckTables<'tcx>,
@@ -276,6 +277,7 @@ pub fn new(delegate: &'a mut (dyn Delegate<'tcx>+'a),
     {
         ExprUseVisitor {
             mc: mc::MemCategorizationContext::new(tcx,
+                                                  body_owner,
                                                   region_scope_tree,
                                                   tables,
                                                   rvalue_promotable_map),
@@ -288,13 +290,19 @@ pub fn new(delegate: &'a mut (dyn Delegate<'tcx>+'a),
 impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
     pub fn with_infer(delegate: &'a mut (dyn Delegate<'tcx>+'a),
                       infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
+                      body_owner: DefId,
                       param_env: ty::ParamEnv<'tcx>,
                       region_scope_tree: &'a region::ScopeTree,
                       tables: &'a ty::TypeckTables<'tcx>)
                       -> Self
     {
         ExprUseVisitor {
-            mc: mc::MemCategorizationContext::with_infer(infcx, region_scope_tree, tables),
+            mc: mc::MemCategorizationContext::with_infer(
+                infcx,
+                body_owner,
+                region_scope_tree,
+                tables,
+            ),
             delegate,
             param_env,
         }
@@ -924,16 +932,15 @@ fn walk_captures(&mut self, closure_expr: &hir::Expr, fn_decl_span: Span) {
 
         let closure_def_id = self.tcx().hir().local_def_id_from_hir_id(closure_expr.hir_id);
         if let Some(upvars) = self.tcx().upvars(closure_def_id) {
-            for upvar in upvars.iter() {
-                let var_hir_id = upvar.var_id();
+            for (&var_id, upvar) in upvars.iter() {
                 let upvar_id = ty::UpvarId {
-                    var_path: ty::UpvarPath { hir_id: var_hir_id },
+                    var_path: ty::UpvarPath { hir_id: var_id },
                     closure_expr_id: closure_def_id.to_local(),
                 };
                 let upvar_capture = self.mc.tables.upvar_capture(upvar_id);
                 let cmt_var = return_if_err!(self.cat_captured_var(closure_expr.hir_id,
                                                                    fn_decl_span,
-                                                                   upvar));
+                                                                   var_id));
                 match upvar_capture {
                     ty::UpvarCapture::ByValue => {
                         let mode = copy_or_move(&self.mc,
@@ -958,13 +965,12 @@ fn walk_captures(&mut self, closure_expr: &hir::Expr, fn_decl_span: Span) {
     fn cat_captured_var(&mut self,
                         closure_hir_id: hir::HirId,
                         closure_span: Span,
-                        upvar: &hir::Upvar)
+                        var_id: hir::HirId)
                         -> mc::McResult<mc::cmt_<'tcx>> {
         // Create the cmt for the variable being borrowed, from the
-        // caller's perspective
-        let var_hir_id = upvar.var_id();
-        let var_ty = self.mc.node_ty(var_hir_id)?;
-        self.mc.cat_res(closure_hir_id, closure_span, var_ty, upvar.res)
+        // perspective of the creator (parent) of the closure.
+        let var_ty = self.mc.node_ty(var_id)?;
+        self.mc.cat_res(closure_hir_id, closure_span, var_ty, Res::Local(var_id))
     }
 }
 
index 91a19852c6c0e06b290a48c98e8713f8aa52501c..45b4fb56056954ca1fc4fe790ab72f0a074c7882 100644 (file)
@@ -182,7 +182,10 @@ fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl,
 }
 
 fn check_mod_liveness<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
-    tcx.hir().visit_item_likes_in_module(module_def_id, &mut IrMaps::new(tcx).as_deep_visitor());
+    tcx.hir().visit_item_likes_in_module(
+        module_def_id,
+        &mut IrMaps::new(tcx, module_def_id).as_deep_visitor(),
+    );
 }
 
 pub fn provide(providers: &mut Providers<'_>) {
@@ -255,6 +258,7 @@ enum VarKind {
 
 struct IrMaps<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    body_owner: DefId,
     num_live_nodes: usize,
     num_vars: usize,
     live_node_map: HirIdMap<LiveNode>,
@@ -265,9 +269,10 @@ struct IrMaps<'a, 'tcx: 'a> {
 }
 
 impl<'a, 'tcx> IrMaps<'a, 'tcx> {
-    fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> IrMaps<'a, 'tcx> {
+    fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, body_owner: DefId) -> IrMaps<'a, 'tcx> {
         IrMaps {
             tcx,
+            body_owner,
             num_live_nodes: 0,
             num_vars: 0,
             live_node_map: HirIdMap::default(),
@@ -356,7 +361,8 @@ fn visit_fn<'a, 'tcx: 'a>(ir: &mut IrMaps<'a, 'tcx>,
     debug!("visit_fn");
 
     // swap in a new set of IR maps for this function body:
-    let mut fn_maps = IrMaps::new(ir.tcx);
+    let def_id = ir.tcx.hir().local_def_id_from_hir_id(id);
+    let mut fn_maps = IrMaps::new(ir.tcx, def_id);
 
     // Don't run unused pass for #[derive()]
     if let FnKind::Method(..) = fk {
@@ -468,8 +474,11 @@ fn visit_expr<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, expr: &'tcx Expr) {
       // live nodes required for uses or definitions of variables:
       hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) => {
         debug!("expr {}: path that leads to {:?}", expr.hir_id, path.res);
-        if let Res::Local(..) = path.res {
-            ir.add_live_node_for_node(expr.hir_id, ExprNode(expr.span));
+        if let Res::Local(var_hir_id) = path.res {
+            let upvars = ir.tcx.upvars(ir.body_owner);
+            if !upvars.map_or(false, |upvars| upvars.contains_key(&var_hir_id)) {
+                ir.add_live_node_for_node(expr.hir_id, ExprNode(expr.span));
+            }
         }
         intravisit::walk_expr(ir, expr);
       }
@@ -485,18 +494,23 @@ fn visit_expr<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, expr: &'tcx Expr) {
         let mut call_caps = Vec::new();
         let closure_def_id = ir.tcx.hir().local_def_id_from_hir_id(expr.hir_id);
         if let Some(upvars) = ir.tcx.upvars(closure_def_id) {
-            call_caps.extend(upvars.iter().filter_map(|upvar| {
-                if let Res::Local(rv) = upvar.res {
+            let parent_upvars = ir.tcx.upvars(ir.body_owner);
+            call_caps.extend(upvars.iter().filter_map(|(&var_id, upvar)| {
+                let has_parent = parent_upvars
+                    .map_or(false, |upvars| upvars.contains_key(&var_id));
+                if !has_parent {
                     let upvar_ln = ir.add_live_node(UpvarNode(upvar.span));
-                    Some(CaptureInfo { ln: upvar_ln, var_hid: rv })
+                    Some(CaptureInfo { ln: upvar_ln, var_hid: var_id })
                 } else {
                     None
                 }
             }));
         }
         ir.set_captures(expr.hir_id, call_caps);
-
+        let old_body_owner = ir.body_owner;
+        ir.body_owner = closure_def_id;
         intravisit::walk_expr(ir, expr);
+        ir.body_owner = old_body_owner;
       }
 
       // live nodes required for interesting control flow:
@@ -1327,8 +1341,13 @@ fn access_path(&mut self, hir_id: HirId, path: &hir::Path, succ: LiveNode, acc:
                    -> LiveNode {
         match path.res {
             Res::Local(hid) => {
-              let nid = self.ir.tcx.hir().hir_to_node_id(hid);
-              self.access_var(hir_id, nid, succ, acc, path.span)
+                let upvars = self.ir.tcx.upvars(self.ir.body_owner);
+                if !upvars.map_or(false, |upvars| upvars.contains_key(&hid)) {
+                    let nid = self.ir.tcx.hir().hir_to_node_id(hid);
+                    self.access_var(hir_id, nid, succ, acc, path.span)
+                } else {
+                    succ
+                }
             }
             _ => succ
         }
@@ -1520,13 +1539,16 @@ fn check_place(&mut self, expr: &'tcx Expr) {
         match expr.node {
             hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) => {
                 if let Res::Local(var_hid) = path.res {
-                    // Assignment to an immutable variable or argument: only legal
-                    // if there is no later assignment. If this local is actually
-                    // mutable, then check for a reassignment to flag the mutability
-                    // as being used.
-                    let ln = self.live_node(expr.hir_id, expr.span);
-                    let var = self.variable(var_hid, expr.span);
-                    self.warn_about_dead_assign(expr.span, expr.hir_id, ln, var);
+                    let upvars = self.ir.tcx.upvars(self.ir.body_owner);
+                    if !upvars.map_or(false, |upvars| upvars.contains_key(&var_hid)) {
+                        // Assignment to an immutable variable or argument: only legal
+                        // if there is no later assignment. If this local is actually
+                        // mutable, then check for a reassignment to flag the mutability
+                        // as being used.
+                        let ln = self.live_node(expr.hir_id, expr.span);
+                        let var = self.variable(var_hid, expr.span);
+                        self.warn_about_dead_assign(expr.span, expr.hir_id, ln, var);
+                    }
                 }
             }
             _ => {
index 8d7c6f18a854f23913db941643cdeabcdd977a70..7011948148d84789a03d58ea8ba7f3f21f508a13 100644 (file)
@@ -78,6 +78,7 @@
 use std::borrow::Cow;
 use std::fmt;
 use std::hash::{Hash, Hasher};
+use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::indexed_vec::Idx;
 use std::rc::Rc;
 use crate::util::nodemap::ItemLocalSet;
@@ -288,6 +289,8 @@ fn span(&self) -> Span { self.span }
 #[derive(Clone)]
 pub struct MemCategorizationContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     pub tcx: TyCtxt<'a, 'gcx, 'tcx>,
+    pub body_owner: DefId,
+    pub upvars: Option<&'tcx FxIndexMap<hir::HirId, hir::Upvar>>,
     pub region_scope_tree: &'a region::ScopeTree,
     pub tables: &'a ty::TypeckTables<'tcx>,
     rvalue_promotable_map: Option<&'tcx ItemLocalSet>,
@@ -398,12 +401,15 @@ pub fn to_user_str(&self) -> &'static str {
 
 impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx, 'tcx> {
     pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+               body_owner: DefId,
                region_scope_tree: &'a region::ScopeTree,
                tables: &'a ty::TypeckTables<'tcx>,
                rvalue_promotable_map: Option<&'tcx ItemLocalSet>)
                -> MemCategorizationContext<'a, 'tcx, 'tcx> {
         MemCategorizationContext {
             tcx,
+            body_owner,
+            upvars: tcx.upvars(body_owner),
             region_scope_tree,
             tables,
             rvalue_promotable_map,
@@ -423,6 +429,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
     /// - similarly, as the results of upvar analysis are not yet
     ///   known, the results around upvar accesses may be incorrect.
     pub fn with_infer(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
+                      body_owner: DefId,
                       region_scope_tree: &'a region::ScopeTree,
                       tables: &'a ty::TypeckTables<'tcx>)
                       -> MemCategorizationContext<'a, 'gcx, 'tcx> {
@@ -436,6 +443,8 @@ pub fn with_infer(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
 
         MemCategorizationContext {
             tcx,
+            body_owner,
+            upvars: tcx.upvars(body_owner),
             region_scope_tree,
             tables,
             rvalue_promotable_map,
@@ -737,21 +746,20 @@ pub fn cat_res(&self,
                 })
             }
 
-            Res::Upvar(var_id, _, fn_node_id) => {
+            Res::Local(var_id) => {
                 let var_nid = self.tcx.hir().hir_to_node_id(var_id);
-                self.cat_upvar(hir_id, span, var_nid, fn_node_id)
-            }
-
-            Res::Local(vid) => {
-                let vnid = self.tcx.hir().hir_to_node_id(vid);
-                Ok(cmt_ {
-                    hir_id,
-                    span,
-                    cat: Categorization::Local(vid),
-                    mutbl: MutabilityCategory::from_local(self.tcx, self.tables, vnid),
-                    ty: expr_ty,
-                    note: NoteNone
-                })
+                if self.upvars.map_or(false, |upvars| upvars.contains_key(&var_id)) {
+                    self.cat_upvar(hir_id, span, var_nid)
+                } else {
+                    Ok(cmt_ {
+                        hir_id,
+                        span,
+                        cat: Categorization::Local(var_id),
+                        mutbl: MutabilityCategory::from_local(self.tcx, self.tables, var_nid),
+                        ty: expr_ty,
+                        note: NoteNone
+                    })
+                }
             }
 
             def => span_bug!(span, "unexpected definition in memory categorization: {:?}", def)
@@ -760,15 +768,12 @@ pub fn cat_res(&self,
 
     // Categorize an upvar, complete with invisible derefs of closure
     // environment and upvar reference as appropriate.
-    fn cat_upvar(&self,
-                 hir_id: hir::HirId,
-                 span: Span,
-                 var_id: ast::NodeId,
-                 fn_node_id: ast::NodeId)
-                 -> McResult<cmt_<'tcx>>
-    {
-        let fn_hir_id = self.tcx.hir().node_to_hir_id(fn_node_id);
-
+    fn cat_upvar(
+        &self,
+        hir_id: hir::HirId,
+        span: Span,
+        var_id: ast::NodeId,
+    ) -> McResult<cmt_<'tcx>> {
         // An upvar can have up to 3 components. We translate first to a
         // `Categorization::Upvar`, which is itself a fiction -- it represents the reference to the
         // field from the environment.
@@ -792,6 +797,10 @@ fn cat_upvar(&self,
         // FnMut          | copied -> &'env mut  | upvar -> &'env mut -> &'up bk
         // FnOnce         | copied               | upvar -> &'up bk
 
+        let closure_expr_def_id = self.body_owner;
+        let fn_hir_id = self.tcx.hir().local_def_id_to_hir_id(
+            LocalDefId::from_def_id(closure_expr_def_id),
+        );
         let ty = self.node_ty(fn_hir_id)?;
         let kind = match ty.sty {
             ty::Generator(..) => ty::ClosureKind::FnOnce,
@@ -813,7 +822,6 @@ fn cat_upvar(&self,
             _ => span_bug!(span, "unexpected type for fn in mem_categorization: {:?}", ty),
         };
 
-        let closure_expr_def_id = self.tcx.hir().local_def_id(fn_node_id);
         let var_hir_id = self.tcx.hir().node_to_hir_id(var_id);
         let upvar_id = ty::UpvarId {
             var_path: ty::UpvarPath { hir_id: var_hir_id },
index c9835dbd5e78f22845da1bede2fdc8b225720755..45e1d983511c0d151c6b4bcf1b7e51ca55348101 100644 (file)
@@ -104,7 +104,7 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
         };
 
         match res {
-            Some(Res::Local(hir_id)) | Some(Res::Upvar(hir_id, ..)) => {
+            Some(Res::Local(hir_id)) => {
                 self.reachable_symbols.insert(hir_id);
             }
             Some(res) => {
index 856b47c7e1b6feb8570c061e65b674c7e44707af..215d4295e44e1ed523bfe00a07aff0b8a9c215ad 100644 (file)
@@ -111,9 +111,10 @@ fn memory_deallocated(
 // For Tag=() and no extra state, we have is a trivial implementation.
 impl AllocationExtra<()> for () { }
 
-impl<Tag, Extra> Allocation<Tag, Extra> {
+// The constructors are all without extra; the extra gets added by a machine hook later.
+impl<Tag> Allocation<Tag> {
     /// Creates a read-only allocation initialized by the given bytes
-    pub fn from_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>, align: Align, extra: Extra) -> Self {
+    pub fn from_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>, align: Align) -> Self {
         let bytes = slice.into().into_owned();
         let undef_mask = UndefMask::new(Size::from_bytes(bytes.len() as u64), true);
         Self {
@@ -122,15 +123,15 @@ pub fn from_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>, align: Align, extra: Extr
             undef_mask,
             align,
             mutability: Mutability::Immutable,
-            extra,
+            extra: (),
         }
     }
 
-    pub fn from_byte_aligned_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>, extra: Extra) -> Self {
-        Allocation::from_bytes(slice, Align::from_bytes(1).unwrap(), extra)
+    pub fn from_byte_aligned_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>) -> Self {
+        Allocation::from_bytes(slice, Align::from_bytes(1).unwrap())
     }
 
-    pub fn undef(size: Size, align: Align, extra: Extra) -> Self {
+    pub fn undef(size: Size, align: Align) -> Self {
         assert_eq!(size.bytes() as usize as u64, size.bytes());
         Allocation {
             bytes: vec![0; size.bytes() as usize],
@@ -138,7 +139,7 @@ pub fn undef(size: Size, align: Align, extra: Extra) -> Self {
             undef_mask: UndefMask::new(size, false),
             align,
             mutability: Mutability::Mutable,
-            extra,
+            extra: (),
         }
     }
 }
index 7985af914ff93e314b9b7ccc8b251772a4a8fcdf..964d6c01d74ad282e39b20e92d55b0c4f140328b 100644 (file)
@@ -72,20 +72,20 @@ pub fn specialized_encode_alloc_id<
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     alloc_id: AllocId,
 ) -> Result<(), E::Error> {
-    let alloc_kind: AllocKind<'tcx> =
+    let alloc: GlobalAlloc<'tcx> =
         tcx.alloc_map.lock().get(alloc_id).expect("no value for AllocId");
-    match alloc_kind {
-        AllocKind::Memory(alloc) => {
+    match alloc {
+        GlobalAlloc::Memory(alloc) => {
             trace!("encoding {:?} with {:#?}", alloc_id, alloc);
             AllocDiscriminant::Alloc.encode(encoder)?;
             alloc.encode(encoder)?;
         }
-        AllocKind::Function(fn_instance) => {
+        GlobalAlloc::Function(fn_instance) => {
             trace!("encoding {:?} with {:#?}", alloc_id, fn_instance);
             AllocDiscriminant::Fn.encode(encoder)?;
             fn_instance.encode(encoder)?;
         }
-        AllocKind::Static(did) => {
+        GlobalAlloc::Static(did) => {
             // referring to statics doesn't need to know about their allocations,
             // just about its DefId
             AllocDiscriminant::Static.encode(encoder)?;
@@ -239,7 +239,7 @@ pub fn decode_alloc_id<'a, 'tcx, D>(&self,
                     assert!(alloc_id.is_none());
                     trace!("creating extern static alloc id at");
                     let did = DefId::decode(decoder)?;
-                    let alloc_id = decoder.tcx().alloc_map.lock().intern_static(did);
+                    let alloc_id = decoder.tcx().alloc_map.lock().create_static_alloc(did);
                     Ok(alloc_id)
                 }
             }
@@ -259,8 +259,10 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
+/// An allocation in the global (tcx-managed) memory can be either a function pointer,
+/// a static, or a "real" allocation with some data in it.
 #[derive(Debug, Clone, Eq, PartialEq, Hash, RustcDecodable, RustcEncodable, HashStable)]
-pub enum AllocKind<'tcx> {
+pub enum GlobalAlloc<'tcx> {
     /// The alloc ID is used as a function pointer
     Function(Instance<'tcx>),
     /// The alloc ID points to a "lazy" static variable that did not get computed (yet).
@@ -272,10 +274,12 @@ pub enum AllocKind<'tcx> {
 
 pub struct AllocMap<'tcx> {
     /// Lets you know what an `AllocId` refers to.
-    id_to_kind: FxHashMap<AllocId, AllocKind<'tcx>>,
+    alloc_map: FxHashMap<AllocId, GlobalAlloc<'tcx>>,
 
-    /// Used to ensure that statics only get one associated `AllocId`.
-    type_interner: FxHashMap<AllocKind<'tcx>, AllocId>,
+    /// Used to ensure that statics and functions only get one associated `AllocId`.
+    /// Should never contain a `GlobalAlloc::Memory`!
+    /// FIXME: Should we just have two separate dedup maps for statics and functions each?
+    dedup: FxHashMap<GlobalAlloc<'tcx>, AllocId>,
 
     /// The `AllocId` to assign to the next requested ID.
     /// Always incremented, never gets smaller.
@@ -285,8 +289,8 @@ pub struct AllocMap<'tcx> {
 impl<'tcx> AllocMap<'tcx> {
     pub fn new() -> Self {
         AllocMap {
-            id_to_kind: Default::default(),
-            type_interner: Default::default(),
+            alloc_map: Default::default(),
+            dedup: Default::default(),
             next_id: AllocId(0),
         }
     }
@@ -308,17 +312,32 @@ pub fn reserve(
         next
     }
 
-    fn intern(&mut self, alloc_kind: AllocKind<'tcx>) -> AllocId {
-        if let Some(&alloc_id) = self.type_interner.get(&alloc_kind) {
+    /// Reserve a new ID *if* this allocation has not been dedup-reserved before.
+    /// Should only be used for function pointers and statics, we don't want
+    /// to dedup IDs for "real" memory!
+    fn reserve_and_set_dedup(&mut self, alloc: GlobalAlloc<'tcx>) -> AllocId {
+        match alloc {
+            GlobalAlloc::Function(..) | GlobalAlloc::Static(..) => {},
+            GlobalAlloc::Memory(..) => bug!("Trying to dedup-reserve memory with real data!"),
+        }
+        if let Some(&alloc_id) = self.dedup.get(&alloc) {
             return alloc_id;
         }
         let id = self.reserve();
-        debug!("creating alloc_kind {:?} with id {}", alloc_kind, id);
-        self.id_to_kind.insert(id, alloc_kind.clone());
-        self.type_interner.insert(alloc_kind, id);
+        debug!("creating alloc {:?} with id {}", alloc, id);
+        self.alloc_map.insert(id, alloc.clone());
+        self.dedup.insert(alloc, id);
         id
     }
 
+    /// Generates an `AllocId` for a static or return a cached one in case this function has been
+    /// called on the same static before.
+    pub fn create_static_alloc(&mut self, static_id: DefId) -> AllocId {
+        self.reserve_and_set_dedup(GlobalAlloc::Static(static_id))
+    }
+
+    /// Generates an `AllocId` for a function.  Depending on the function type,
+    /// this might get deduplicated or assigned a new ID each time.
     pub fn create_fn_alloc(&mut self, instance: Instance<'tcx>) -> AllocId {
         // Functions cannot be identified by pointers, as asm-equal functions can get deduplicated
         // by the linker (we set the "unnamed_addr" attribute for LLVM) and functions can be
@@ -336,53 +355,47 @@ pub fn create_fn_alloc(&mut self, instance: Instance<'tcx>) -> AllocId {
         if is_generic {
             // Get a fresh ID
             let id = self.reserve();
-            self.id_to_kind.insert(id, AllocKind::Function(instance));
+            self.alloc_map.insert(id, GlobalAlloc::Function(instance));
             id
         } else {
             // Deduplicate
-            self.intern(AllocKind::Function(instance))
+            self.reserve_and_set_dedup(GlobalAlloc::Function(instance))
         }
     }
 
+    /// Intern the `Allocation` and return a new `AllocId`, even if there's already an identical
+    /// `Allocation` with a different `AllocId`.
+    /// Statics with identical content will still point to the same `Allocation`, i.e.,
+    /// their data will be deduplicated through `Allocation` interning -- but they
+    /// are different places in memory and as such need different IDs.
+    pub fn create_memory_alloc(&mut self, mem: &'tcx Allocation) -> AllocId {
+        let id = self.reserve();
+        self.set_alloc_id_memory(id, mem);
+        id
+    }
+
     /// Returns `None` in case the `AllocId` is dangling. An `InterpretCx` can still have a
     /// local `Allocation` for that `AllocId`, but having such an `AllocId` in a constant is
     /// illegal and will likely ICE.
     /// This function exists to allow const eval to detect the difference between evaluation-
     /// local dangling pointers and allocations in constants/statics.
     #[inline]
-    pub fn get(&self, id: AllocId) -> Option<AllocKind<'tcx>> {
-        self.id_to_kind.get(&id).cloned()
+    pub fn get(&self, id: AllocId) -> Option<GlobalAlloc<'tcx>> {
+        self.alloc_map.get(&id).cloned()
     }
 
     /// Panics if the `AllocId` does not refer to an `Allocation`
     pub fn unwrap_memory(&self, id: AllocId) -> &'tcx Allocation {
         match self.get(id) {
-            Some(AllocKind::Memory(mem)) => mem,
+            Some(GlobalAlloc::Memory(mem)) => mem,
             _ => bug!("expected allocation id {} to point to memory", id),
         }
     }
 
-    /// Generates an `AllocId` for a static or return a cached one in case this function has been
-    /// called on the same static before.
-    pub fn intern_static(&mut self, static_id: DefId) -> AllocId {
-        self.intern(AllocKind::Static(static_id))
-    }
-
-    /// Intern the `Allocation` and return a new `AllocId`, even if there's already an identical
-    /// `Allocation` with a different `AllocId`.
-    // FIXME: is this really necessary? Can we ensure `FOO` and `BAR` being different after codegen
-    // in `static FOO: u32 = 42; static BAR: u32 = 42;` even if they reuse the same allocation
-    // inside rustc?
-    pub fn allocate(&mut self, mem: &'tcx Allocation) -> AllocId {
-        let id = self.reserve();
-        self.set_alloc_id_memory(id, mem);
-        id
-    }
-
     /// Freeze an `AllocId` created with `reserve` by pointing it at an `Allocation`. Trying to
     /// call this function twice, even with the same `Allocation` will ICE the compiler.
     pub fn set_alloc_id_memory(&mut self, id: AllocId, mem: &'tcx Allocation) {
-        if let Some(old) = self.id_to_kind.insert(id, AllocKind::Memory(mem)) {
+        if let Some(old) = self.alloc_map.insert(id, GlobalAlloc::Memory(mem)) {
             bug!("tried to set allocation id {}, but it was already existing as {:#?}", id, old);
         }
     }
@@ -390,7 +403,7 @@ pub fn set_alloc_id_memory(&mut self, id: AllocId, mem: &'tcx Allocation) {
     /// Freeze an `AllocId` created with `reserve` by pointing it at an `Allocation`. May be called
     /// twice for the same `(AllocId, Allocation)` pair.
     fn set_alloc_id_same_memory(&mut self, id: AllocId, mem: &'tcx Allocation) {
-        self.id_to_kind.insert_same(id, AllocKind::Memory(mem));
+        self.alloc_map.insert_same(id, GlobalAlloc::Memory(mem));
     }
 }
 
index 9e71399d4fdf7eacd9d02e4e12d1932e35b7ae74..4aa83a79d52b8bef5a187e14679eefde153417a2 100644 (file)
@@ -116,13 +116,6 @@ pub fn with_tag<Tag>(self, tag: Tag) -> Pointer<Tag>
     {
         Pointer::new_with_tag(self.alloc_id, self.offset, tag)
     }
-
-    #[inline(always)]
-    pub fn with_default_tag<Tag>(self) -> Pointer<Tag>
-        where Tag: Default
-    {
-        self.with_tag(Tag::default())
-    }
 }
 
 impl<'tcx, Tag> Pointer<Tag> {
index 21792b847db77e2e6fb0319436a0f61868a09d5f..b8d6c1224463128f861704503c083f0756c4de99 100644 (file)
@@ -138,6 +138,9 @@ fn check_data(data: u128, size: u8) {
                          "Scalar value {:#x} exceeds size of {} bytes", data, size);
     }
 
+    /// Tag this scalar with `new_tag` if it is a pointer, leave it unchanged otherwise.
+    ///
+    /// Used by `MemPlace::replace_tag`.
     #[inline]
     pub fn with_tag<Tag>(self, new_tag: Tag) -> Scalar<Tag> {
         match self {
@@ -145,16 +148,12 @@ pub fn with_tag<Tag>(self, new_tag: Tag) -> Scalar<Tag> {
             Scalar::Raw { data, size } => Scalar::Raw { data, size },
         }
     }
-
-    #[inline(always)]
-    pub fn with_default_tag<Tag>(self) -> Scalar<Tag>
-        where Tag: Default
-    {
-        self.with_tag(Tag::default())
-    }
 }
 
 impl<'tcx, Tag> Scalar<Tag> {
+    /// Erase the tag from the scalar, if any.
+    ///
+    /// Used by error reporting code to avoid having the error type depend on `Tag`.
     #[inline]
     pub fn erase_tag(self) -> Scalar {
         match self {
@@ -476,24 +475,10 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     }
 }
 
-impl<'tcx> ScalarMaybeUndef<()> {
-    #[inline]
-    pub fn with_tag<Tag>(self, new_tag: Tag) -> ScalarMaybeUndef<Tag> {
-        match self {
-            ScalarMaybeUndef::Scalar(s) => ScalarMaybeUndef::Scalar(s.with_tag(new_tag)),
-            ScalarMaybeUndef::Undef => ScalarMaybeUndef::Undef,
-        }
-    }
-
-    #[inline(always)]
-    pub fn with_default_tag<Tag>(self) -> ScalarMaybeUndef<Tag>
-        where Tag: Default
-    {
-        self.with_tag(Tag::default())
-    }
-}
-
 impl<'tcx, Tag> ScalarMaybeUndef<Tag> {
+    /// Erase the tag from the scalar, if any.
+    ///
+    /// Used by error reporting code to avoid having the error type depend on `Tag`.
     #[inline]
     pub fn erase_tag(self) -> ScalarMaybeUndef
     {
index d4ef134728eafe5b6514557a6c570b75aa5603f9..6213eda651486424587aaedbf9d22d0555488b3f 100644 (file)
@@ -2562,8 +2562,8 @@ fn fmt_tuple(fmt: &mut Formatter<'_>, places: &[Operand<'_>]) -> fmt::Result {
                             let mut struct_fmt = fmt.debug_struct(&name);
 
                             if let Some(upvars) = tcx.upvars(def_id) {
-                                for (upvar, place) in upvars.iter().zip(places) {
-                                    let var_name = tcx.hir().name_by_hir_id(upvar.var_id());
+                                for (&var_id, place) in upvars.keys().zip(places) {
+                                    let var_name = tcx.hir().name_by_hir_id(var_id);
                                     struct_fmt.field(&var_name.as_str(), place);
                                 }
                             }
@@ -2581,8 +2581,8 @@ fn fmt_tuple(fmt: &mut Formatter<'_>, places: &[Operand<'_>]) -> fmt::Result {
                             let mut struct_fmt = fmt.debug_struct(&name);
 
                             if let Some(upvars) = tcx.upvars(def_id) {
-                                for (upvar, place) in upvars.iter().zip(places) {
-                                    let var_name = tcx.hir().name_by_hir_id(upvar.var_id());
+                                for (&var_id, place) in upvars.keys().zip(places) {
+                                    let var_name = tcx.hir().name_by_hir_id(var_id);
                                     struct_fmt.field(&var_name.as_str(), place);
                                 }
                             }
index f61677fa594993d3061a90068de6ca4dad70cec1..18308f54442210d8aa3ad25106591a4afa4ebc20 100644 (file)
@@ -42,7 +42,7 @@
             load_cached(tcx, id) {
                 let generics: Option<ty::Generics> = tcx.queries.on_disk_cache
                                                         .try_load_query_result(tcx, id);
-                generics.map(|x| tcx.alloc_generics(x))
+                generics.map(|x| &*tcx.arena.alloc(x))
             }
         }
 
             load_cached(tcx, id) {
                 let mir: Option<crate::mir::Body<'tcx>> = tcx.queries.on_disk_cache
                                                             .try_load_query_result(tcx, id);
-                mir.map(|x| tcx.alloc_mir(x))
+                mir.map(|x| &*tcx.arena.alloc(x))
             }
         }
     }
                     .queries.on_disk_cache
                     .try_load_query_result(tcx, id);
 
-                typeck_tables.map(|tables| tcx.alloc_tables(tables))
+                typeck_tables.map(|tables| &*tcx.arena.alloc(tables))
             }
         }
     }
             desc { "generating a postorder list of CrateNums" }
         }
 
-        query upvars(_: DefId) -> Option<&'tcx [hir::Upvar]> {
+        query upvars(_: DefId) -> Option<&'tcx FxIndexMap<hir::HirId, hir::Upvar>> {
             eval_always
         }
         query maybe_unused_trait_import(_: DefId) -> bool {
index a29b173880a081aa21f1fc844c4792eeff8d2b2c..95312d55b3be1c6125d7a40a8c4e7eb0e75fd26c 100644 (file)
@@ -914,8 +914,11 @@ pub fn report_selection_error(
             }
 
             // already reported in the query
-            ConstEvalFailure(_) => {
-                self.tcx.sess.delay_span_bug(span, "constant in type had an ignored error");
+            ConstEvalFailure(err) => {
+                self.tcx.sess.delay_span_bug(
+                    span,
+                    &format!("constant in type had an ignored error: {:?}", err),
+                );
                 return;
             }
 
index ff218911ffb8197afca886679b666f392fca5cf2..85a02220a71068245fa2fd21b0e0988bd4b9a486 100644 (file)
@@ -53,7 +53,7 @@
 use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap,
                                            StableHasher, StableHasherResult,
                                            StableVec};
-use arena::{TypedArena, SyncDroplessArena};
+use arena::SyncDroplessArena;
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use rustc_data_structures::sync::{Lrc, Lock, WorkerLocal};
 use std::any::Any;
 
 use crate::hir;
 
-pub struct AllArenas<'tcx> {
-    pub global: WorkerLocal<GlobalArenas<'tcx>>,
+pub struct AllArenas {
     pub interner: SyncDroplessArena,
 }
 
-impl<'tcx> AllArenas<'tcx> {
+impl AllArenas {
     pub fn new() -> Self {
         AllArenas {
-            global: WorkerLocal::new(|_| GlobalArenas::default()),
             interner: SyncDroplessArena::default(),
         }
     }
 }
 
-/// Internal storage
-#[derive(Default)]
-pub struct GlobalArenas<'tcx> {
-    // internings
-    layout: TypedArena<LayoutDetails>,
-
-    // references
-    generics: TypedArena<ty::Generics>,
-    trait_def: TypedArena<ty::TraitDef>,
-    adt_def: TypedArena<ty::AdtDef>,
-    steal_mir: TypedArena<Steal<Body<'tcx>>>,
-    mir: TypedArena<Body<'tcx>>,
-    tables: TypedArena<ty::TypeckTables<'tcx>>,
-    /// miri allocations
-    const_allocs: TypedArena<interpret::Allocation>,
-}
-
 type InternedSet<'tcx, T> = Lock<FxHashMap<Interned<'tcx, T>, ()>>;
 
 pub struct CtxtInterners<'tcx> {
@@ -1043,7 +1024,7 @@ fn deref(&self) -> &Self::Target {
 
 pub struct GlobalCtxt<'tcx> {
     pub arena: WorkerLocal<Arena<'tcx>>,
-    global_arenas: &'tcx WorkerLocal<GlobalArenas<'tcx>>,
+
     global_interners: CtxtInterners<'tcx>,
 
     cstore: &'tcx CrateStoreDyn,
@@ -1081,11 +1062,6 @@ pub struct GlobalCtxt<'tcx> {
 
     pub queries: query::Queries<'tcx>,
 
-    // Records the captured variables referenced by every closure
-    // expression. Do not track deps for this, just recompute it from
-    // scratch every time.
-    upvars: FxHashMap<DefId, Vec<hir::Upvar>>,
-
     maybe_unused_trait_imports: FxHashSet<DefId>,
     maybe_unused_extern_crates: Vec<(DefId, Span)>,
     /// A map of glob use to a set of names it actually imports. Currently only
@@ -1150,24 +1126,8 @@ pub fn hir(self) -> &'a hir_map::Map<'gcx> {
         &self.hir_map
     }
 
-    pub fn alloc_generics(self, generics: ty::Generics) -> &'gcx ty::Generics {
-        self.global_arenas.generics.alloc(generics)
-    }
-
     pub fn alloc_steal_mir(self, mir: Body<'gcx>) -> &'gcx Steal<Body<'gcx>> {
-        self.global_arenas.steal_mir.alloc(Steal::new(mir))
-    }
-
-    pub fn alloc_mir(self, mir: Body<'gcx>) -> &'gcx Body<'gcx> {
-        self.global_arenas.mir.alloc(mir)
-    }
-
-    pub fn alloc_tables(self, tables: ty::TypeckTables<'gcx>) -> &'gcx ty::TypeckTables<'gcx> {
-        self.global_arenas.tables.alloc(tables)
-    }
-
-    pub fn alloc_trait_def(self, def: ty::TraitDef) -> &'gcx ty::TraitDef {
-        self.global_arenas.trait_def.alloc(def)
+        self.arena.alloc(Steal::new(mir))
     }
 
     pub fn alloc_adt_def(self,
@@ -1177,32 +1137,32 @@ pub fn alloc_adt_def(self,
                          repr: ReprOptions)
                          -> &'gcx ty::AdtDef {
         let def = ty::AdtDef::new(self, did, kind, variants, repr);
-        self.global_arenas.adt_def.alloc(def)
+        self.arena.alloc(def)
     }
 
     pub fn intern_const_alloc(self, alloc: Allocation) -> &'gcx Allocation {
         self.allocation_interner.borrow_mut().intern(alloc, |alloc| {
-            self.global_arenas.const_allocs.alloc(alloc)
+            self.arena.alloc(alloc)
         })
     }
 
     /// Allocates a byte or string literal for `mir::interpret`, read-only
     pub fn allocate_bytes(self, bytes: &[u8]) -> interpret::AllocId {
         // create an allocation that just contains these bytes
-        let alloc = interpret::Allocation::from_byte_aligned_bytes(bytes, ());
+        let alloc = interpret::Allocation::from_byte_aligned_bytes(bytes);
         let alloc = self.intern_const_alloc(alloc);
-        self.alloc_map.lock().allocate(alloc)
+        self.alloc_map.lock().create_memory_alloc(alloc)
     }
 
     pub fn intern_stability(self, stab: attr::Stability) -> &'gcx attr::Stability {
         self.stability_interner.borrow_mut().intern(stab, |stab| {
-            self.global_interners.arena.alloc(stab)
+            self.arena.alloc(stab)
         })
     }
 
     pub fn intern_layout(self, layout: LayoutDetails) -> &'gcx LayoutDetails {
         self.layout_interner.borrow_mut().intern(layout, |layout| {
-            self.global_arenas.layout.alloc(layout)
+            self.arena.alloc(layout)
         })
     }
 
@@ -1250,7 +1210,7 @@ pub fn create_global_ctxt(
         cstore: &'tcx CrateStoreDyn,
         local_providers: ty::query::Providers<'tcx>,
         extern_providers: ty::query::Providers<'tcx>,
-        arenas: &'tcx AllArenas<'tcx>,
+        arenas: &'tcx AllArenas,
         resolutions: ty::Resolutions,
         hir: hir_map::Map<'tcx>,
         on_disk_query_result_cache: query::OnDiskCache<'tcx>,
@@ -1319,7 +1279,6 @@ pub fn create_global_ctxt(
             sess: s,
             cstore,
             arena: WorkerLocal::new(|_| Arena::default()),
-            global_arenas: &arenas.global,
             global_interners: interners,
             dep_graph,
             common,
@@ -1333,12 +1292,6 @@ pub fn create_global_ctxt(
                 }).collect();
                 (k, exports)
             }).collect(),
-            upvars: resolutions.upvars.into_iter().map(|(k, v)| {
-                let vars: Vec<_> = v.into_iter().map(|e| {
-                    e.map_id(|id| hir.node_to_hir_id(id))
-                }).collect();
-                (hir.local_def_id(k), vars)
-            }).collect(),
             maybe_unused_trait_imports:
                 resolutions.maybe_unused_trait_imports
                     .into_iter()
@@ -3059,7 +3012,6 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
         assert_eq!(id, LOCAL_CRATE);
         tcx.arena.alloc(middle::lang_items::collect(tcx))
     };
-    providers.upvars = |tcx, id| tcx.gcx.upvars.get(&id).map(|v| &v[..]);
     providers.maybe_unused_trait_import = |tcx, id| {
         tcx.maybe_unused_trait_imports.contains(&id)
     };
index 6d7b0926c7ae26527fbb131fbec4f251104bbc04..6415122dd3905877fb0268868f6fffbb7cfb35bf 100644 (file)
@@ -549,8 +549,8 @@ enum StructKind {
                     }
                 }
 
+                let count = count.assert_usize(tcx).ok_or(LayoutError::Unknown(ty))?;
                 let element = self.layout_of(element)?;
-                let count = count.unwrap_usize(tcx);
                 let size = element.size.checked_mul(count, dl)
                     .ok_or(LayoutError::SizeOverflow(ty))?;
 
index 0cbc0112a8e10a0bd0b04790e8ab3e0c5c1a5ac9..e89fb53c236194ec230fef70d6d35708d1f1d6eb 100644 (file)
@@ -8,7 +8,7 @@
 pub use self::IntVarValue::*;
 pub use self::fold::TypeFoldable;
 
-use crate::hir::{map as hir_map, UpvarMap, GlobMap, TraitMap};
+use crate::hir::{map as hir_map, GlobMap, TraitMap};
 use crate::hir::Node;
 use crate::hir::def::{Res, DefKind, CtorOf, CtorKind, ExportMap};
 use crate::hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
@@ -51,6 +51,7 @@
 use syntax_pos::Span;
 
 use smallvec;
+use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult,
                                            HashStable};
@@ -75,7 +76,7 @@
 pub use self::binding::BindingMode;
 pub use self::binding::BindingMode::*;
 
-pub use self::context::{TyCtxt, FreeRegionInfo, GlobalArenas, AllArenas, tls, keep_local};
+pub use self::context::{TyCtxt, FreeRegionInfo, AllArenas, tls, keep_local};
 pub use self::context::{Lift, TypeckTables, CtxtInterners, GlobalCtxt};
 pub use self::context::{
     UserTypeAnnotationIndex, UserType, CanonicalUserType,
 
 #[derive(Clone)]
 pub struct Resolutions {
-    pub upvars: UpvarMap,
     pub trait_map: TraitMap,
     pub maybe_unused_trait_imports: NodeSet,
     pub maybe_unused_extern_crates: Vec<(NodeId, Span)>,
@@ -808,7 +808,7 @@ pub struct UpvarBorrow<'tcx> {
     pub region: ty::Region<'tcx>,
 }
 
-pub type UpvarListMap = FxHashMap<DefId, Vec<UpvarId>>;
+pub type UpvarListMap = FxHashMap<DefId, FxIndexMap<hir::HirId, UpvarId>>;
 pub type UpvarCaptureMap<'tcx> = FxHashMap<UpvarId, UpvarCapture<'tcx>>;
 
 #[derive(Copy, Clone)]
index cd617a9368d8547a1cb86b0463f404b30b0a2fcc..513ffd69ccaadfc58309b79de33da5cb3ec21e16 100644 (file)
@@ -595,16 +595,16 @@ fn pretty_print_type(
                 if let Some(hir_id) = self.tcx().hir().as_local_hir_id(did) {
                     p!(write("@{:?}", self.tcx().hir().span_by_hir_id(hir_id)));
                     let mut sep = " ";
-                    for (upvar, upvar_ty) in self.tcx().upvars(did)
+                    for (&var_id, upvar_ty) in self.tcx().upvars(did)
                         .as_ref()
-                        .map_or(&[][..], |v| &v[..])
                         .iter()
+                        .flat_map(|v| v.keys())
                         .zip(upvar_tys)
                     {
                         p!(
                             write("{}{}:",
                                     sep,
-                                    self.tcx().hir().name_by_hir_id(upvar.var_id())),
+                                    self.tcx().hir().name_by_hir_id(var_id)),
                             print(upvar_ty));
                         sep = ", ";
                     }
@@ -638,16 +638,16 @@ fn pretty_print_type(
                         p!(write("@{:?}", self.tcx().hir().span_by_hir_id(hir_id)));
                     }
                     let mut sep = " ";
-                    for (upvar, upvar_ty) in self.tcx().upvars(did)
+                    for (&var_id, upvar_ty) in self.tcx().upvars(did)
                         .as_ref()
-                        .map_or(&[][..], |v| &v[..])
                         .iter()
+                        .flat_map(|v| v.keys())
                         .zip(upvar_tys)
                     {
                         p!(
                             write("{}{}:",
                                     sep,
-                                    self.tcx().hir().name_by_hir_id(upvar.var_id())),
+                                    self.tcx().hir().name_by_hir_id(var_id)),
                             print(upvar_ty));
                         sep = ", ";
                     }
@@ -1462,7 +1462,6 @@ fn name_by_region_index(index: usize) -> InternedString {
                     br
                 }
                 ty::BrAnon(_) |
-                ty::BrFresh(_) |
                 ty::BrEnv => {
                     let name = loop {
                         let name = name_by_region_index(region_index);
index a2bced97102a68393b8307a61f344bc1aadf42c3..e595b52876f4c831a08a18df15249b5cedc098de 100644 (file)
@@ -45,7 +45,7 @@
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::bit_set::BitSet;
 use rustc_data_structures::indexed_vec::IndexVec;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::{FxIndexMap, FxHashMap, FxHashSet};
 use rustc_data_structures::stable_hasher::StableVec;
 use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::fingerprint::Fingerprint;
index 0daa567052d5662ec881cad2b4c366f30b6c5ca4..56d47a7f849cf6eec7c8888087bb29abb881ee67 100644 (file)
@@ -94,7 +94,6 @@ impl fmt::Debug for ty::BoundRegion {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match *self {
             ty::BrAnon(n) => write!(f, "BrAnon({:?})", n),
-            ty::BrFresh(n) => write!(f, "BrFresh({:?})", n),
             ty::BrNamed(did, name) => {
                 write!(f, "BrNamed({:?}:{:?}, {})",
                         did.krate, did.index, name)
index 0a673dd380b5254416da4ea452c86d6f1e7dbc60..ddc4bd3f9f6c3c057cd918147a6eef1937be875e 100644 (file)
@@ -56,9 +56,6 @@ pub enum BoundRegion {
     /// the event of shadowing.
     BrNamed(DefId, InternedString),
 
-    /// Fresh bound identifiers created during GLB computations.
-    BrFresh(u32),
-
     /// Anonymous region for the implicit env pointer parameter
     /// to a closure
     BrEnv,
index d2d5c4fe85c90a8626418eb8bf82f028e4a68c14..35e6c1c5bf5a762cddda221c937dc23519b2ca7b 100644 (file)
@@ -208,6 +208,7 @@ pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
     let rvalue_promotable_map = bccx.tcx.rvalue_promotable_map(def_id);
     euv::ExprUseVisitor::new(&mut clcx,
                              bccx.tcx,
+                             def_id,
                              param_env,
                              &bccx.region_scope_tree,
                              bccx.tables,
index 3892a18b1400e80661871657f621d962044b32e7..e437c08c956ec73123764af4e3880236df599ead 100644 (file)
@@ -44,6 +44,7 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
     let rvalue_promotable_map = bccx.tcx.rvalue_promotable_map(def_id);
     euv::ExprUseVisitor::new(&mut glcx,
                              bccx.tcx,
+                             def_id,
                              param_env,
                              &bccx.region_scope_tree,
                              bccx.tables,
index 42e7a72c43b217cffdcd9615347bd7a3f0772722..f37fd0cb833826d742eb6fe5844c4cacc01d0682 100644 (file)
@@ -20,6 +20,7 @@
 use rustc_codegen_ssa::mir::place::PlaceRef;
 use rustc_target::spec::{HasTargetSpec, Target};
 use std::borrow::Cow;
+use std::ffi::CStr;
 use std::ops::{Deref, Range};
 use std::ptr;
 use std::iter::TrustedLen;
@@ -39,12 +40,15 @@ fn drop(&mut self) {
     }
 }
 
-// This is a really awful way to get a zero-length c-string, but better (and a
-// lot more efficient) than doing str::as_c_str("", ...) every time.
-fn noname() -> *const c_char {
-    static CNULL: c_char = 0;
-    &CNULL
-}
+// FIXME(eddyb) use a checked constructor when they become `const fn`.
+const EMPTY_C_STR: &CStr = unsafe {
+    CStr::from_bytes_with_nul_unchecked(b"\0")
+};
+
+/// Empty string, to be used where LLVM expects an instruction name, indicating
+/// that the instruction is to be left unnamed (i.e. numbered, in textual IR).
+// FIXME(eddyb) pass `&CStr` directly to FFI once it's a thin pointer.
+const UNNAMED: *const c_char = EMPTY_C_STR.as_ptr();
 
 impl BackendTypes for Builder<'_, 'll, 'tcx> {
     type Value = <CodegenCx<'ll, 'tcx> as BackendTypes>::Value;
@@ -100,6 +104,16 @@ impl HasCodegen<'tcx> for Builder<'_, 'll, 'tcx> {
     type CodegenCx = CodegenCx<'ll, 'tcx>;
 }
 
+macro_rules! builder_methods_for_value_instructions {
+    ($($name:ident($($arg:ident),*) => $llvm_capi:ident),+ $(,)?) => {
+        $(fn $name(&mut self, $($arg: &'ll Value),*) -> &'ll Value {
+            unsafe {
+                llvm::$llvm_capi(self.llbuilder, $($arg,)* UNNAMED)
+            }
+        })*
+    }
+}
+
 impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
     fn new_block<'b>(
         cx: &'a CodegenCx<'ll, 'tcx>,
@@ -217,7 +231,7 @@ fn invoke(
                                       then,
                                       catch,
                                       bundle,
-                                      noname())
+                                      UNNAMED)
         }
     }
 
@@ -227,186 +241,72 @@ fn unreachable(&mut self) {
         }
     }
 
-    /* Arithmetic */
-    fn add(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
-        unsafe {
-            llvm::LLVMBuildAdd(self.llbuilder, lhs, rhs, noname())
-        }
-    }
-
-    fn fadd(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
-        unsafe {
-            llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, noname())
-        }
+    builder_methods_for_value_instructions! {
+        add(a, b) => LLVMBuildAdd,
+        fadd(a, b) => LLVMBuildFAdd,
+        sub(a, b) => LLVMBuildSub,
+        fsub(a, b) => LLVMBuildFSub,
+        mul(a, b) => LLVMBuildMul,
+        fmul(a, b) => LLVMBuildFMul,
+        udiv(a, b) => LLVMBuildUDiv,
+        exactudiv(a, b) => LLVMBuildExactUDiv,
+        sdiv(a, b) => LLVMBuildSDiv,
+        exactsdiv(a, b) => LLVMBuildExactSDiv,
+        fdiv(a, b) => LLVMBuildFDiv,
+        urem(a, b) => LLVMBuildURem,
+        srem(a, b) => LLVMBuildSRem,
+        frem(a, b) => LLVMBuildFRem,
+        shl(a, b) => LLVMBuildShl,
+        lshr(a, b) => LLVMBuildLShr,
+        ashr(a, b) => LLVMBuildAShr,
+        and(a, b) => LLVMBuildAnd,
+        or(a, b) => LLVMBuildOr,
+        xor(a, b) => LLVMBuildXor,
+        neg(x) => LLVMBuildNeg,
+        fneg(x) => LLVMBuildFNeg,
+        not(x) => LLVMBuildNot,
     }
 
     fn fadd_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         unsafe {
-            let instr = llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, noname());
+            let instr = llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, UNNAMED);
             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
             instr
         }
     }
 
-    fn sub(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
-        unsafe {
-            llvm::LLVMBuildSub(self.llbuilder, lhs, rhs, noname())
-        }
-    }
-
-    fn fsub(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
-        unsafe {
-            llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, noname())
-        }
-    }
-
     fn fsub_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         unsafe {
-            let instr = llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, noname());
+            let instr = llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, UNNAMED);
             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
             instr
         }
     }
 
-    fn mul(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
-        unsafe {
-            llvm::LLVMBuildMul(self.llbuilder, lhs, rhs, noname())
-        }
-    }
-
-    fn fmul(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
-        unsafe {
-            llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, noname())
-        }
-    }
-
     fn fmul_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         unsafe {
-            let instr = llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, noname());
+            let instr = llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, UNNAMED);
             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
             instr
         }
     }
 
-
-    fn udiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
-        unsafe {
-            llvm::LLVMBuildUDiv(self.llbuilder, lhs, rhs, noname())
-        }
-    }
-
-    fn exactudiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
-        unsafe {
-            llvm::LLVMBuildExactUDiv(self.llbuilder, lhs, rhs, noname())
-        }
-    }
-
-    fn sdiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
-        unsafe {
-            llvm::LLVMBuildSDiv(self.llbuilder, lhs, rhs, noname())
-        }
-    }
-
-    fn exactsdiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
-        unsafe {
-            llvm::LLVMBuildExactSDiv(self.llbuilder, lhs, rhs, noname())
-        }
-    }
-
-    fn fdiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
-        unsafe {
-            llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, noname())
-        }
-    }
-
     fn fdiv_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         unsafe {
-            let instr = llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, noname());
+            let instr = llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, UNNAMED);
             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
             instr
         }
     }
 
-    fn urem(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
-        unsafe {
-            llvm::LLVMBuildURem(self.llbuilder, lhs, rhs, noname())
-        }
-    }
-
-    fn srem(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
-        unsafe {
-            llvm::LLVMBuildSRem(self.llbuilder, lhs, rhs, noname())
-        }
-    }
-
-    fn frem(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
-        unsafe {
-            llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, noname())
-        }
-    }
-
     fn frem_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         unsafe {
-            let instr = llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, noname());
+            let instr = llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, UNNAMED);
             llvm::LLVMRustSetHasUnsafeAlgebra(instr);
             instr
         }
     }
 
-    fn shl(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
-        unsafe {
-            llvm::LLVMBuildShl(self.llbuilder, lhs, rhs, noname())
-        }
-    }
-
-    fn lshr(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
-        unsafe {
-            llvm::LLVMBuildLShr(self.llbuilder, lhs, rhs, noname())
-        }
-    }
-
-    fn ashr(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
-        unsafe {
-            llvm::LLVMBuildAShr(self.llbuilder, lhs, rhs, noname())
-        }
-    }
-
-    fn and(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
-        unsafe {
-            llvm::LLVMBuildAnd(self.llbuilder, lhs, rhs, noname())
-        }
-    }
-
-    fn or(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
-        unsafe {
-            llvm::LLVMBuildOr(self.llbuilder, lhs, rhs, noname())
-        }
-    }
-
-    fn xor(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
-        unsafe {
-            llvm::LLVMBuildXor(self.llbuilder, lhs, rhs, noname())
-        }
-    }
-
-    fn neg(&mut self, v: &'ll Value) -> &'ll Value {
-        unsafe {
-            llvm::LLVMBuildNeg(self.llbuilder, v, noname())
-        }
-    }
-
-    fn fneg(&mut self, v: &'ll Value) -> &'ll Value {
-        unsafe {
-            llvm::LLVMBuildFNeg(self.llbuilder, v, noname())
-        }
-    }
-
-    fn not(&mut self, v: &'ll Value) -> &'ll Value {
-        unsafe {
-            llvm::LLVMBuildNot(self.llbuilder, v, noname())
-        }
-    }
-
     fn checked_binop(
         &mut self,
         oop: OverflowOp,
@@ -492,7 +392,7 @@ fn alloca(&mut self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value {
     fn dynamic_alloca(&mut self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value {
         unsafe {
             let alloca = if name.is_empty() {
-                llvm::LLVMBuildAlloca(self.llbuilder, ty, noname())
+                llvm::LLVMBuildAlloca(self.llbuilder, ty, UNNAMED)
             } else {
                 let name = SmallCStr::new(name);
                 llvm::LLVMBuildAlloca(self.llbuilder, ty,
@@ -510,7 +410,7 @@ fn array_alloca(&mut self,
                         align: Align) -> &'ll Value {
         unsafe {
             let alloca = if name.is_empty() {
-                llvm::LLVMBuildArrayAlloca(self.llbuilder, ty, len, noname())
+                llvm::LLVMBuildArrayAlloca(self.llbuilder, ty, len, UNNAMED)
             } else {
                 let name = SmallCStr::new(name);
                 llvm::LLVMBuildArrayAlloca(self.llbuilder, ty, len,
@@ -523,7 +423,7 @@ fn array_alloca(&mut self,
 
     fn load(&mut self, ptr: &'ll Value, align: Align) -> &'ll Value {
         unsafe {
-            let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname());
+            let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, UNNAMED);
             llvm::LLVMSetAlignment(load, align.bytes() as c_uint);
             load
         }
@@ -531,7 +431,7 @@ fn load(&mut self, ptr: &'ll Value, align: Align) -> &'ll Value {
 
     fn volatile_load(&mut self, ptr: &'ll Value) -> &'ll Value {
         unsafe {
-            let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname());
+            let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, UNNAMED);
             llvm::LLVMSetVolatile(load, llvm::True);
             load
         }
@@ -547,7 +447,7 @@ fn atomic_load(
             let load = llvm::LLVMRustBuildAtomicLoad(
                 self.llbuilder,
                 ptr,
-                noname(),
+                UNNAMED,
                 AtomicOrdering::from_generic(order),
             );
             // LLVM requires the alignment of atomic loads to be at least the size of the type.
@@ -750,88 +650,88 @@ fn atomic_store(&mut self, val: &'ll Value, ptr: &'ll Value,
     fn gep(&mut self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value {
         unsafe {
             llvm::LLVMBuildGEP(self.llbuilder, ptr, indices.as_ptr(),
-                               indices.len() as c_uint, noname())
+                               indices.len() as c_uint, UNNAMED)
         }
     }
 
     fn inbounds_gep(&mut self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value {
         unsafe {
             llvm::LLVMBuildInBoundsGEP(
-                self.llbuilder, ptr, indices.as_ptr(), indices.len() as c_uint, noname())
+                self.llbuilder, ptr, indices.as_ptr(), indices.len() as c_uint, UNNAMED)
         }
     }
 
     fn struct_gep(&mut self, ptr: &'ll Value, idx: u64) -> &'ll Value {
         assert_eq!(idx as c_uint as u64, idx);
         unsafe {
-            llvm::LLVMBuildStructGEP(self.llbuilder, ptr, idx as c_uint, noname())
+            llvm::LLVMBuildStructGEP(self.llbuilder, ptr, idx as c_uint, UNNAMED)
         }
     }
 
     /* Casts */
     fn trunc(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         unsafe {
-            llvm::LLVMBuildTrunc(self.llbuilder, val, dest_ty, noname())
+            llvm::LLVMBuildTrunc(self.llbuilder, val, dest_ty, UNNAMED)
         }
     }
 
     fn sext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         unsafe {
-            llvm::LLVMBuildSExt(self.llbuilder, val, dest_ty, noname())
+            llvm::LLVMBuildSExt(self.llbuilder, val, dest_ty, UNNAMED)
         }
     }
 
     fn fptoui(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         unsafe {
-            llvm::LLVMBuildFPToUI(self.llbuilder, val, dest_ty, noname())
+            llvm::LLVMBuildFPToUI(self.llbuilder, val, dest_ty, UNNAMED)
         }
     }
 
     fn fptosi(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         unsafe {
-            llvm::LLVMBuildFPToSI(self.llbuilder, val, dest_ty,noname())
+            llvm::LLVMBuildFPToSI(self.llbuilder, val, dest_ty,UNNAMED)
         }
     }
 
     fn uitofp(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         unsafe {
-            llvm::LLVMBuildUIToFP(self.llbuilder, val, dest_ty, noname())
+            llvm::LLVMBuildUIToFP(self.llbuilder, val, dest_ty, UNNAMED)
         }
     }
 
     fn sitofp(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         unsafe {
-            llvm::LLVMBuildSIToFP(self.llbuilder, val, dest_ty, noname())
+            llvm::LLVMBuildSIToFP(self.llbuilder, val, dest_ty, UNNAMED)
         }
     }
 
     fn fptrunc(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         unsafe {
-            llvm::LLVMBuildFPTrunc(self.llbuilder, val, dest_ty, noname())
+            llvm::LLVMBuildFPTrunc(self.llbuilder, val, dest_ty, UNNAMED)
         }
     }
 
     fn fpext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         unsafe {
-            llvm::LLVMBuildFPExt(self.llbuilder, val, dest_ty, noname())
+            llvm::LLVMBuildFPExt(self.llbuilder, val, dest_ty, UNNAMED)
         }
     }
 
     fn ptrtoint(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         unsafe {
-            llvm::LLVMBuildPtrToInt(self.llbuilder, val, dest_ty, noname())
+            llvm::LLVMBuildPtrToInt(self.llbuilder, val, dest_ty, UNNAMED)
         }
     }
 
     fn inttoptr(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         unsafe {
-            llvm::LLVMBuildIntToPtr(self.llbuilder, val, dest_ty, noname())
+            llvm::LLVMBuildIntToPtr(self.llbuilder, val, dest_ty, UNNAMED)
         }
     }
 
     fn bitcast(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         unsafe {
-            llvm::LLVMBuildBitCast(self.llbuilder, val, dest_ty, noname())
+            llvm::LLVMBuildBitCast(self.llbuilder, val, dest_ty, UNNAMED)
         }
     }
 
@@ -844,7 +744,7 @@ fn intcast(&mut self, val: &'ll Value, dest_ty: &'ll Type, is_signed: bool) -> &
 
     fn pointercast(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         unsafe {
-            llvm::LLVMBuildPointerCast(self.llbuilder, val, dest_ty, noname())
+            llvm::LLVMBuildPointerCast(self.llbuilder, val, dest_ty, UNNAMED)
         }
     }
 
@@ -852,13 +752,13 @@ fn pointercast(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
     fn icmp(&mut self, op: IntPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         let op = llvm::IntPredicate::from_generic(op);
         unsafe {
-            llvm::LLVMBuildICmp(self.llbuilder, op as c_uint, lhs, rhs, noname())
+            llvm::LLVMBuildICmp(self.llbuilder, op as c_uint, lhs, rhs, UNNAMED)
         }
     }
 
     fn fcmp(&mut self, op: RealPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
         unsafe {
-            llvm::LLVMBuildFCmp(self.llbuilder, op as c_uint, lhs, rhs, noname())
+            llvm::LLVMBuildFCmp(self.llbuilder, op as c_uint, lhs, rhs, UNNAMED)
         }
     }
 
@@ -926,20 +826,20 @@ fn select(
         else_val: &'ll Value,
     ) -> &'ll Value {
         unsafe {
-            llvm::LLVMBuildSelect(self.llbuilder, cond, then_val, else_val, noname())
+            llvm::LLVMBuildSelect(self.llbuilder, cond, then_val, else_val, UNNAMED)
         }
     }
 
     #[allow(dead_code)]
     fn va_arg(&mut self, list: &'ll Value, ty: &'ll Type) -> &'ll Value {
         unsafe {
-            llvm::LLVMBuildVAArg(self.llbuilder, list, ty, noname())
+            llvm::LLVMBuildVAArg(self.llbuilder, list, ty, UNNAMED)
         }
     }
 
     fn extract_element(&mut self, vec: &'ll Value, idx: &'ll Value) -> &'ll Value {
         unsafe {
-            llvm::LLVMBuildExtractElement(self.llbuilder, vec, idx, noname())
+            llvm::LLVMBuildExtractElement(self.llbuilder, vec, idx, UNNAMED)
         }
     }
 
@@ -956,7 +856,7 @@ fn vector_splat(&mut self, num_elts: usize, elt: &'ll Value) -> &'ll Value {
     fn extract_value(&mut self, agg_val: &'ll Value, idx: u64) -> &'ll Value {
         assert_eq!(idx as c_uint as u64, idx);
         unsafe {
-            llvm::LLVMBuildExtractValue(self.llbuilder, agg_val, idx as c_uint, noname())
+            llvm::LLVMBuildExtractValue(self.llbuilder, agg_val, idx as c_uint, UNNAMED)
         }
     }
 
@@ -965,7 +865,7 @@ fn insert_value(&mut self, agg_val: &'ll Value, elt: &'ll Value,
         assert_eq!(idx as c_uint as u64, idx);
         unsafe {
             llvm::LLVMBuildInsertValue(self.llbuilder, agg_val, elt, idx as c_uint,
-                                       noname())
+                                       UNNAMED)
         }
     }
 
@@ -973,7 +873,7 @@ fn landing_pad(&mut self, ty: &'ll Type, pers_fn: &'ll Value,
                        num_clauses: usize) -> &'ll Value {
         unsafe {
             llvm::LLVMBuildLandingPad(self.llbuilder, ty, pers_fn,
-                                      num_clauses as c_uint, noname())
+                                      num_clauses as c_uint, UNNAMED)
         }
     }
 
@@ -1143,14 +1043,14 @@ fn call(
                 llfn,
                 args.as_ptr() as *const &llvm::Value,
                 args.len() as c_uint,
-                bundle, noname()
+                bundle, UNNAMED
             )
         }
     }
 
     fn zext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
         unsafe {
-            llvm::LLVMBuildZExt(self.llbuilder, val, dest_ty, noname())
+            llvm::LLVMBuildZExt(self.llbuilder, val, dest_ty, UNNAMED)
         }
     }
 
@@ -1232,7 +1132,7 @@ pub fn insert_element(
         idx: &'ll Value,
     ) -> &'ll Value {
         unsafe {
-            llvm::LLVMBuildInsertElement(self.llbuilder, vec, elt, idx, noname())
+            llvm::LLVMBuildInsertElement(self.llbuilder, vec, elt, idx, UNNAMED)
         }
     }
 
@@ -1243,7 +1143,7 @@ pub fn shuffle_vector(
         mask: &'ll Value,
     ) -> &'ll Value {
         unsafe {
-            llvm::LLVMBuildShuffleVector(self.llbuilder, v1, v2, mask, noname())
+            llvm::LLVMBuildShuffleVector(self.llbuilder, v1, v2, mask, UNNAMED)
         }
     }
 
@@ -1385,7 +1285,7 @@ fn check_call<'b>(&mut self,
 
     pub fn va_arg(&mut self, list: &'ll Value, ty: &'ll Type) -> &'ll Value {
         unsafe {
-            llvm::LLVMBuildVAArg(self.llbuilder, list, ty, noname())
+            llvm::LLVMBuildVAArg(self.llbuilder, list, ty, UNNAMED)
         }
     }
 
@@ -1408,7 +1308,7 @@ fn call_lifetime_intrinsic(&mut self, intrinsic: &str, ptr: &'ll Value, size: Si
     fn phi(&mut self, ty: &'ll Type, vals: &[&'ll Value], bbs: &[&'ll BasicBlock]) -> &'ll Value {
         assert_eq!(vals.len(), bbs.len());
         let phi = unsafe {
-            llvm::LLVMBuildPhi(self.llbuilder, ty, noname())
+            llvm::LLVMBuildPhi(self.llbuilder, ty, UNNAMED)
         };
         unsafe {
             llvm::LLVMAddIncoming(phi, vals.as_ptr(),
index c713362440d97140b8d185fe00c76049d2942ed4..0b23aac5224c6c8531189aba42e0a741ff778c10 100644 (file)
@@ -12,7 +12,7 @@
 
 use crate::consts::const_alloc_to_llvm;
 use rustc::ty::layout::{HasDataLayout, LayoutOf, self, TyLayout, Size};
-use rustc::mir::interpret::{Scalar, AllocKind, Allocation};
+use rustc::mir::interpret::{Scalar, GlobalAlloc, Allocation};
 use rustc_codegen_ssa::mir::place::PlaceRef;
 
 use libc::{c_uint, c_char};
@@ -310,7 +310,7 @@ fn scalar_to_backend(
             Scalar::Ptr(ptr) => {
                 let alloc_kind = self.tcx.alloc_map.lock().get(ptr.alloc_id);
                 let base_addr = match alloc_kind {
-                    Some(AllocKind::Memory(alloc)) => {
+                    Some(GlobalAlloc::Memory(alloc)) => {
                         let init = const_alloc_to_llvm(self, alloc);
                         if alloc.mutability == Mutability::Mutable {
                             self.static_addr_of_mut(init, alloc.align, None)
@@ -318,10 +318,10 @@ fn scalar_to_backend(
                             self.static_addr_of(init, alloc.align, None)
                         }
                     }
-                    Some(AllocKind::Function(fn_instance)) => {
+                    Some(GlobalAlloc::Function(fn_instance)) => {
                         self.get_fn(fn_instance)
                     }
-                    Some(AllocKind::Static(def_id)) => {
+                    Some(GlobalAlloc::Static(def_id)) => {
                         assert!(self.tcx.is_static(def_id));
                         self.get_static(def_id)
                     }
index b000628a3f70653e9653e519cf47b61cf71aff88..42bd790ca2e9c47662da3e2a8662f0c858a67e55 100644 (file)
@@ -342,9 +342,7 @@ fn fixed_vec_metadata(
     let (size, align) = cx.size_and_align_of(array_or_slice_type);
 
     let upper_bound = match array_or_slice_type.sty {
-        ty::Array(_, len) => {
-            len.unwrap_usize(cx.tcx) as c_longlong
-        }
+        ty::Array(_, len) => len.unwrap_usize(cx.tcx) as c_longlong,
         _ => -1
     };
 
index 57cffa48163e1d6506a857c38776cb9b4d87d21a..b13d8df5525e9f40dd115739c4f342924fb118b2 100644 (file)
@@ -8,6 +8,7 @@
 
 #![feature(box_patterns)]
 #![feature(box_syntax)]
+#![feature(const_cstr_unchecked)]
 #![feature(crate_visibility_modifier)]
 #![feature(custom_attribute)]
 #![feature(extern_types)]
index 9e1d429180367c199e435743644faeaa32cbc9fa..11fac239edf124d8bce7dd17cb86f7ad5d5735f5 100644 (file)
@@ -26,7 +26,7 @@ While the LLVM-specific code will be left in `rustc_codegen_llvm`, all the new t
 
 @irinagpopa started to parametrize the types of `rustc_codegen_llvm` by a generic `Value` type, implemented in LLVM by a reference `&'ll Value`. This work has been extended to all structures inside the `mir` folder and elsewhere, as well as for LLVM's `BasicBlock` and `Type` types.
 
-The two most important structures for the LLVM codegen are `CodegenCx` and `Builder`. They are parametrized by multiple liftime parameters and the type for `Value`.
+The two most important structures for the LLVM codegen are `CodegenCx` and `Builder`. They are parametrized by multiple lifetime parameters and the type for `Value`.
 
 ```rust
 struct CodegenCx<'ll, 'tcx: 'll> {
index 0ae2fbe8071adb5787ae3a228094ef4ddacca1af..b4303cf5c9b2eba60636e57eef98a2e6a118991d 100644 (file)
@@ -98,7 +98,7 @@ pub fn from_const<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
                     _ => bug!("from_const: invalid ScalarPair layout: {:#?}", layout)
                 };
                 let a = Scalar::from(Pointer::new(
-                    bx.tcx().alloc_map.lock().allocate(data),
+                    bx.tcx().alloc_map.lock().create_memory_alloc(data),
                     Size::from_bytes(start as u64),
                 )).into();
                 let a_llval = bx.scalar_to_backend(
index 53682b9bdc2c8ef47605270d39bfb8b1f754de00..6eaa22afce19ac60616909a25d3bf33322d74851 100644 (file)
@@ -440,7 +440,7 @@ fn write_str(&mut self, s: &str) -> fmt::Result {
                 '-' | ':' => self.path.temp_buf.push('.'),
 
                 // Avoid crashing LLVM in certain (LTO-related) situations, see #60925.
-                'm' if self.path.temp_buf.ends_with(".llv") => self.path.temp_buf.push_str("$6d$"),
+                'm' if self.path.temp_buf.ends_with(".llv") => self.path.temp_buf.push_str("$u6d$"),
 
                 // These are legal symbols
                 'a'..='z' | 'A'..='Z' | '0'..='9' | '_' | '.' | '$' => self.path.temp_buf.push(c),
index 5f3bac866d6a786ff9bed2bc8cd3e1f248f5a007..cd792d31187bd865d4b4257482890d3b7d1ec760 100644 (file)
@@ -11,6 +11,7 @@ crate-type = ["dylib"]
 
 [dependencies]
 ena = "0.13"
+indexmap = "1"
 log = "0.4"
 jobserver_crate = { version = "0.1.13", package = "jobserver" }
 lazy_static = "1"
index a2afeffe7305045b53f61d17f36e1875c78a5342..cf73fe8cf85ceeac553ff1db97a0b43fb2f3077a 100644 (file)
@@ -1 +1,6 @@
+use std::hash::BuildHasherDefault;
+
 pub use rustc_hash::{FxHasher, FxHashMap, FxHashSet};
+
+pub type FxIndexMap<K, V> = indexmap::IndexMap<K, V, BuildHasherDefault<FxHasher>>;
+pub type FxIndexSet<V> = indexmap::IndexSet<V, BuildHasherDefault<FxHasher>>;
index 2b844aa24d49c92a6d5bdbd165762f5a00908b31..270d9520627646e23d919014943b01677ebd477b 100644 (file)
@@ -323,6 +323,37 @@ fn hash_stable<W: StableHasherResult>(&self,
     }
 }
 
+impl<K, V, R, CTX> HashStable<CTX> for indexmap::IndexMap<K, V, R>
+    where K: HashStable<CTX> + Eq + Hash,
+          V: HashStable<CTX>,
+          R: BuildHasher,
+{
+    #[inline]
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          ctx: &mut CTX,
+                                          hasher: &mut StableHasher<W>) {
+        self.len().hash_stable(ctx, hasher);
+        for kv in self {
+            kv.hash_stable(ctx, hasher);
+        }
+    }
+}
+
+impl<K, R, CTX> HashStable<CTX> for indexmap::IndexSet<K, R>
+    where K: HashStable<CTX> + Eq + Hash,
+          R: BuildHasher,
+{
+    #[inline]
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          ctx: &mut CTX,
+                                          hasher: &mut StableHasher<W>) {
+        self.len().hash_stable(ctx, hasher);
+        for key in self {
+            key.hash_stable(ctx, hasher);
+        }
+    }
+}
+
 impl<A, CTX> HashStable<CTX> for SmallVec<[A; 1]> where A: HashStable<CTX> {
     #[inline]
     fn hash_stable<W: StableHasherResult>(&self,
index 4a96864dc9d661aed721057dc89c191b213b2abd..9691d0337d7d20091f59e602544aff2dab92b174 100644 (file)
@@ -178,7 +178,6 @@ fn from_owned_resolver(
         ExpansionResult {
             defs: Steal::new(resolver.definitions),
             resolutions: Steal::new(Resolutions {
-                upvars: resolver.upvars,
                 export_map: resolver.export_map,
                 trait_map: resolver.trait_map,
                 glob_map: resolver.glob_map,
@@ -197,7 +196,6 @@ pub fn from_resolver_ref(
         ExpansionResult {
             defs: Steal::new(resolver.definitions.clone()),
             resolutions: Steal::new(Resolutions {
-                upvars: resolver.upvars.clone(),
                 export_map: resolver.export_map.clone(),
                 trait_map: resolver.trait_map.clone(),
                 glob_map: resolver.glob_map.clone(),
index 44b727c6925d94c544e6f53133e22b7d5e6f91c5..f9a12c19e427606dfc7d685bfe9a6a739a747dc9 100644 (file)
@@ -1275,7 +1275,7 @@ fn check_item(
 
 declare_lint! {
     pub ELLIPSIS_INCLUSIVE_RANGE_PATTERNS,
-    Allow,
+    Warn,
     "`...` range patterns are deprecated"
 }
 
index e04372ea280b5dd0c8fab7b8a79cc9588877a606..db452bb4ac7bcbad232534fa8141fff760a1df96 100644 (file)
@@ -94,7 +94,7 @@ fn into_args(self) -> (DefId, DefId) { (self.0.as_def_id(), self.1) }
 provide! { <'tcx> tcx, def_id, other, cdata,
     type_of => { cdata.get_type(def_id.index, tcx) }
     generics_of => {
-        tcx.alloc_generics(cdata.get_generics(def_id.index, tcx.sess))
+        tcx.arena.alloc(cdata.get_generics(def_id.index, tcx.sess))
     }
     predicates_of => { tcx.arena.alloc(cdata.get_predicates(def_id.index, tcx)) }
     predicates_defined_on => {
@@ -102,7 +102,7 @@ fn into_args(self) -> (DefId, DefId) { (self.0.as_def_id(), self.1) }
     }
     super_predicates_of => { tcx.arena.alloc(cdata.get_super_predicates(def_id.index, tcx)) }
     trait_def => {
-        tcx.alloc_trait_def(cdata.get_trait_def(def_id.index, tcx.sess))
+        tcx.arena.alloc(cdata.get_trait_def(def_id.index, tcx.sess))
     }
     adt_def => { cdata.get_adt_def(def_id.index, tcx) }
     adt_destructor => {
@@ -129,7 +129,7 @@ fn into_args(self) -> (DefId, DefId) { (self.0.as_def_id(), self.1) }
             bug!("get_optimized_mir: missing MIR for `{:?}`", def_id)
         });
 
-        let mir = tcx.alloc_mir(mir);
+        let mir = tcx.arena.alloc(mir);
 
         mir
     }
index 5a22c81a5d0578f1d83b52458e1c9b279f73b2f0..31af20fdb77eb2ef88974e1252cd597a7f61c49f 100644 (file)
@@ -348,9 +348,10 @@ fn describe_field_from_ty(
                     // `tcx.upvars(def_id)` returns an `Option`, which is `None` in case
                     // the closure comes from another crate. But in that case we wouldn't
                     // be borrowck'ing it, so we can just unwrap:
-                    let upvar = self.infcx.tcx.upvars(def_id).unwrap()[field.index()];
+                    let (&var_id, _) = self.infcx.tcx.upvars(def_id).unwrap()
+                        .get_index(field.index()).unwrap();
 
-                    self.infcx.tcx.hir().name_by_hir_id(upvar.var_id()).to_string()
+                    self.infcx.tcx.hir().name_by_hir_id(var_id).to_string()
                 }
                 _ => {
                     // Might need a revision when the fields in trait RFC is implemented
@@ -645,12 +646,12 @@ fn closure_span(
         if let hir::ExprKind::Closure(
             .., args_span, _
         ) = expr {
-            for (v, place) in self.infcx.tcx.upvars(def_id)?.iter().zip(places) {
+            for (upvar, place) in self.infcx.tcx.upvars(def_id)?.values().zip(places) {
                 match place {
                     Operand::Copy(place) |
                     Operand::Move(place) if target_place == place => {
                         debug!("closure_span: found captured local {:?}", place);
-                        return Some((*args_span, v.span));
+                        return Some((*args_span, upvar.span));
                     },
                     _ => {}
                 }
index 82be2405701d516d971bc8ce1db456d4afd4a770..4ae4d039d60340e53a00b625c302898c78c0edef 100644 (file)
@@ -149,7 +149,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
         .upvar_list
         .get(&def_id)
         .into_iter()
-        .flatten()
+        .flat_map(|v| v.values())
         .map(|upvar_id| {
             let var_hir_id = upvar_id.var_path.hir_id;
             let var_node_id = tcx.hir().hir_to_node_id(var_hir_id);
index 25415039fc80a7b29f731dd2b2b9918f235b6b35..0d452c99ea16853776aa04db9b3b9e42ebd16ca2 100644 (file)
@@ -274,7 +274,7 @@ fn give_name_from_error_region(
                     }
                 }
 
-                ty::BoundRegion::BrAnon(_) | ty::BoundRegion::BrFresh(_) => None,
+                ty::BoundRegion::BrAnon(_) => None,
             },
 
             ty::ReLateBound(..)
index 74da3f96653e4314612c044c4f3e1414528e1cbc..8aa27eef72a5e022efa1e534520245934713184a 100644 (file)
@@ -332,8 +332,8 @@ fn place_base_conflict<'a, 'gcx: 'tcx, 'tcx>(
                 },
                 (StaticKind::Promoted(promoted_1), StaticKind::Promoted(promoted_2)) => {
                     if promoted_1 == promoted_2 {
-                        if let ty::Array(_, size) = s1.ty.sty {
-                            if size.unwrap_usize(tcx) == 0 {
+                        if let ty::Array(_, len) = s1.ty.sty {
+                            if let Some(0) = len.assert_usize(tcx) {
                                 // Ignore conflicts with promoted [T; 0].
                                 debug!("place_element_conflict: IGNORE-LEN-0-PROMOTED");
                                 return Overlap::Disjoint;
index 5797f9c34786617d01d834d833da6768e8212f74..123b46cb04820dec34d5b106896f6eaab4ac0c7a 100644 (file)
@@ -651,10 +651,9 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
         .get(&fn_def_id)
         .into_iter()
         .flatten()
-        .map(|upvar_id| {
-            let var_hir_id = upvar_id.var_path.hir_id;
+        .map(|(&var_hir_id, &upvar_id)| {
             let var_node_id = tcx_hir.hir_to_node_id(var_hir_id);
-            let capture = hir_tables.upvar_capture(*upvar_id);
+            let capture = hir_tables.upvar_capture(upvar_id);
             let by_ref = match capture {
                 ty::UpvarCapture::ByValue => false,
                 ty::UpvarCapture::ByRef(..) => true,
index 2c68ed58d50d40edbd0ae5649b14c2678e6240dd..dc7aa0f17e88cd20c85f02f8f5bf85716430e589 100644 (file)
@@ -12,7 +12,7 @@
 use rustc::mir::interpret::{ConstEvalErr, ErrorHandled};
 use rustc::mir;
 use rustc::ty::{self, TyCtxt, query::TyCtxtAt};
-use rustc::ty::layout::{self, LayoutOf, VariantIdx, Size};
+use rustc::ty::layout::{self, LayoutOf, VariantIdx};
 use rustc::ty::subst::Subst;
 use rustc::traits::Reveal;
 use rustc::util::common::ErrorReported;
@@ -117,7 +117,7 @@ fn op_to_const<'tcx>(
                 ),
                 Scalar::Raw { .. } => (
                     ecx.tcx.intern_const_alloc(Allocation::from_byte_aligned_bytes(
-                        b"" as &[u8], (),
+                        b"" as &[u8],
                     )),
                     0,
                 ),
@@ -397,27 +397,27 @@ fn ptr_op(
     fn find_foreign_static(
         _def_id: DefId,
         _tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
-        _memory_extra: &(),
     ) -> EvalResult<'tcx, Cow<'tcx, Allocation<Self::PointerTag>>> {
         err!(ReadForeignStatic)
     }
 
     #[inline(always)]
-    fn adjust_static_allocation<'b>(
-        alloc: &'b Allocation,
+    fn tag_allocation<'b>(
+        _id: AllocId,
+        alloc: Cow<'b, Allocation>,
+        _kind: Option<MemoryKind<!>>,
         _memory_extra: &(),
-    ) -> Cow<'b, Allocation<Self::PointerTag>> {
-        // We do not use a tag so we can just cheaply forward the reference
-        Cow::Borrowed(alloc)
+    ) -> (Cow<'b, Allocation<Self::PointerTag>>, Self::PointerTag) {
+        // We do not use a tag so we can just cheaply forward the allocation
+        (alloc, ())
     }
 
     #[inline(always)]
-    fn new_allocation(
-        _size: Size,
-        _extra: &Self::MemoryExtra,
-        _kind: MemoryKind<!>,
-    ) -> (Self::AllocExtra, Self::PointerTag) {
-        ((), ())
+    fn tag_static_base_pointer(
+        _id: AllocId,
+        _memory_extra: &(),
+    ) -> Self::PointerTag {
+        ()
     }
 
     fn box_alloc(
index 69df36348a69e6ffbe47801b1d71cabda1f14a0f..a5be55d16d488b7049ce0c5239d2804988b3db99 100644 (file)
     let lit = match *lit {
         LitKind::Str(ref s, _) => {
             let s = s.as_str();
-            let allocation = Allocation::from_byte_aligned_bytes(s.as_bytes(), ());
+            let allocation = Allocation::from_byte_aligned_bytes(s.as_bytes());
             let allocation = tcx.intern_const_alloc(allocation);
             ConstValue::Slice { data: allocation, start: 0, end: s.len() }
         },
         LitKind::Err(ref s) => {
             let s = s.as_str();
-            let allocation = Allocation::from_byte_aligned_bytes(s.as_bytes(), ());
+            let allocation = Allocation::from_byte_aligned_bytes(s.as_bytes());
             let allocation = tcx.intern_const_alloc(allocation);
             return Ok(tcx.mk_const(ty::Const {
                 val: ConstValue::Slice{ data: allocation, start: 0, end: s.len() },
index d0ea303a93c69e00474b72104a65d4613fa33c6b..5a6b6a74830521a18aaba758b6485451962667b7 100644 (file)
@@ -515,7 +515,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
             let upvars = cx.tcx.upvars(def_id).iter()
                 .flat_map(|upvars| upvars.iter())
                 .zip(substs.upvar_tys(def_id, cx.tcx))
-                .map(|(upvar, ty)| capture_upvar(cx, expr, upvar, ty))
+                .map(|((&var_hir_id, _), ty)| capture_upvar(cx, expr, var_hir_id, ty))
                 .collect();
             ExprKind::Closure {
                 closure_id: def_id,
@@ -960,36 +960,44 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
 
         Res::Def(DefKind::Static, id) => ExprKind::StaticRef { id },
 
-        Res::Local(..) | Res::Upvar(..) => convert_var(cx, expr, res),
+        Res::Local(var_hir_id) => convert_var(cx, expr, var_hir_id),
 
         _ => span_bug!(expr.span, "res `{:?}` not yet implemented", res),
     }
 }
 
-fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
-                               expr: &'tcx hir::Expr,
-                               res: Res)
-                               -> ExprKind<'tcx> {
+fn convert_var(
+    cx: &mut Cx<'_, '_, 'tcx>,
+    expr: &'tcx hir::Expr,
+    var_hir_id: hir::HirId,
+) -> ExprKind<'tcx> {
+    let upvar_index = cx.tables().upvar_list.get(&cx.body_owner)
+        .and_then(|upvars| upvars.get_full(&var_hir_id).map(|(i, _, _)| i));
+
+    debug!("convert_var({:?}): upvar_index={:?}, body_owner={:?}",
+           var_hir_id, upvar_index, cx.body_owner);
+
     let temp_lifetime = cx.region_scope_tree.temporary_scope(expr.hir_id.local_id);
 
-    match res {
-        Res::Local(id) => ExprKind::VarRef { id },
+    match upvar_index {
+        None => ExprKind::VarRef { id: var_hir_id },
 
-        Res::Upvar(var_hir_id, index, closure_expr_id) => {
-            debug!("convert_var(upvar({:?}, {:?}, {:?}))",
-                   var_hir_id,
-                   index,
-                   closure_expr_id);
+        Some(upvar_index) => {
+            let closure_def_id = cx.body_owner;
+            let upvar_id = ty::UpvarId {
+                var_path: ty::UpvarPath {hir_id: var_hir_id},
+                closure_expr_id: LocalDefId::from_def_id(closure_def_id),
+            };
             let var_ty = cx.tables().node_type(var_hir_id);
 
             // FIXME free regions in closures are not right
-            let closure_ty = cx.tables()
-                               .node_type(cx.tcx.hir().node_to_hir_id(closure_expr_id));
+            let closure_ty = cx.tables().node_type(
+                cx.tcx.hir().local_def_id_to_hir_id(upvar_id.closure_expr_id),
+            );
 
             // FIXME we're just hard-coding the idea that the
             // signature will be &self or &mut self and hence will
             // have a bound region with number 0
-            let closure_def_id = cx.tcx.hir().local_def_id(closure_expr_id);
             let region = ty::ReFree(ty::FreeRegion {
                 scope: closure_def_id,
                 bound_region: ty::BoundRegion::BrAnon(0),
@@ -1060,15 +1068,11 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
             // at this point we have `self.n`, which loads up the upvar
             let field_kind = ExprKind::Field {
                 lhs: self_expr.to_ref(),
-                name: Field::new(index),
+                name: Field::new(upvar_index),
             };
 
             // ...but the upvar might be an `&T` or `&mut T` capture, at which
             // point we need an implicit deref
-            let upvar_id = ty::UpvarId {
-                var_path: ty::UpvarPath {hir_id: var_hir_id},
-                closure_expr_id: LocalDefId::from_def_id(closure_def_id),
-            };
             match cx.tables().upvar_capture(upvar_id) {
                 ty::UpvarCapture::ByValue => field_kind,
                 ty::UpvarCapture::ByRef(borrow) => {
@@ -1087,8 +1091,6 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                 }
             }
         }
-
-        _ => span_bug!(expr.span, "type of & not region"),
     }
 }
 
@@ -1178,10 +1180,9 @@ fn overloaded_place<'a, 'gcx, 'tcx>(
 
 fn capture_upvar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                                    closure_expr: &'tcx hir::Expr,
-                                   upvar: &hir::Upvar,
+                                   var_hir_id: hir::HirId,
                                    upvar_ty: Ty<'tcx>)
                                    -> ExprRef<'tcx> {
-    let var_hir_id = upvar.var_id();
     let upvar_id = ty::UpvarId {
         var_path: ty::UpvarPath { hir_id: var_hir_id },
         closure_expr_id: cx.tcx.hir().local_def_id_from_hir_id(closure_expr.hir_id).to_local(),
@@ -1193,7 +1194,7 @@ fn capture_upvar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
         temp_lifetime,
         ty: var_ty,
         span: closure_expr.span,
-        kind: convert_var(cx, closure_expr, upvar.res),
+        kind: convert_var(cx, closure_expr, var_hir_id),
     };
     match upvar_capture {
         ty::UpvarCapture::ByValue => captured_var.to_ref(),
index 80f64e85f9cf9201c11937dd66bbcfc24a8afaeb..f4a23a90dee925b6a6b9ac126d8afa7989ffa587 100644 (file)
@@ -38,6 +38,9 @@ pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
     /// `const`, or the body of a `const fn`.
     constness: hir::Constness,
 
+    /// The `DefId` of the owner of this body.
+    body_owner: DefId,
+
     /// What kind of body is being compiled.
     pub body_owner_kind: hir::BodyOwnerKind,
 
@@ -53,6 +56,7 @@ pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
                src_id: hir::HirId) -> Cx<'a, 'gcx, 'tcx> {
         let tcx = infcx.tcx;
         let src_def_id = tcx.hir().local_def_id_from_hir_id(src_id);
+        let tables = tcx.typeck_tables_of(src_def_id);
         let body_owner_kind = tcx.hir().body_owner_kind_by_hir_id(src_id);
 
         let constness = match body_owner_kind {
@@ -82,8 +86,9 @@ pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
             param_env: tcx.param_env(src_def_id),
             identity_substs: InternalSubsts::identity_for_item(tcx.global_tcx(), src_def_id),
             region_scope_tree: tcx.region_scope_tree(src_def_id),
-            tables: tcx.typeck_tables_of(src_def_id),
+            tables,
             constness,
+            body_owner: src_def_id,
             body_owner_kind,
             check_overflow,
             control_flow_destroyed: Vec::new(),
index 0edf32d3a306cce1d2449f7548b0547bf0583da9..215faee953230913674a78fc4d2a60bfa69d0f21 100644 (file)
@@ -35,6 +35,7 @@ pub(crate) fn check_match<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
 
     MatchVisitor {
         tcx,
+        body_owner: def_id,
         tables: tcx.body_tables(body_id),
         region_scope_tree: &tcx.region_scope_tree(def_id),
         param_env: tcx.param_env(def_id),
@@ -48,6 +49,7 @@ fn create_e0004<'a>(sess: &'a Session, sp: Span, error_message: String) -> Diagn
 
 struct MatchVisitor<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    body_owner: DefId,
     tables: &'a ty::TypeckTables<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     identity_substs: SubstsRef<'tcx>,
@@ -632,6 +634,7 @@ fn check_for_mutation_in_guard(cx: &MatchVisitor<'_, '_>, guard: &hir::Guard) {
         hir::Guard::If(expr) =>
             ExprUseVisitor::new(&mut checker,
                                 cx.tcx,
+                                cx.body_owner,
                                 cx.param_env,
                                 cx.region_scope_tree,
                                 cx.tables,
index 76b11ac2fe6463a4515782d743e1a2b30dc018ee..f1e23655741fc2ae80394720f59190d5fef29e8e 100644 (file)
@@ -86,7 +86,7 @@ pub fn cast(
                             def_id,
                             substs,
                         ).ok_or_else(|| InterpError::TooGeneric.into());
-                        let fn_ptr = self.memory.create_fn_alloc(instance?).with_default_tag();
+                        let fn_ptr = self.memory.create_fn_alloc(instance?);
                         self.write_scalar(Scalar::Ptr(fn_ptr.into()), dest)?;
                     }
                     _ => bug!("reify fn pointer on {:?}", src.layout.ty),
@@ -115,7 +115,7 @@ pub fn cast(
                             substs,
                             ty::ClosureKind::FnOnce,
                         );
-                        let fn_ptr = self.memory.create_fn_alloc(instance).with_default_tag();
+                        let fn_ptr = self.memory.create_fn_alloc(instance);
                         let val = Immediate::Scalar(Scalar::Ptr(fn_ptr.into()).into());
                         self.write_immediate(val, dest)?;
                     }
index d3cbd2bcc03a52e0cd688805be5ff89862494b08..a6153bf055d600a5223ae3c0cf2e6551d0afe6e8 100644 (file)
@@ -15,7 +15,7 @@
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc::mir::interpret::{
     ErrorHandled,
-    GlobalId, Scalar, FrameInfo, AllocId,
+    GlobalId, Scalar, Pointer, FrameInfo, AllocId,
     EvalResult, InterpError,
     truncate, sign_extend,
 };
@@ -43,7 +43,10 @@ pub struct InterpretCx<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'a, 'mir, 'tcx>> {
     pub(crate) stack: Vec<Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>>,
 
     /// A cache for deduplicating vtables
-    pub(super) vtables: FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), AllocId>,
+    pub(super) vtables: FxHashMap<
+        (Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>),
+        Pointer<M::PointerTag>
+    >,
 }
 
 /// A stack frame.
@@ -222,6 +225,11 @@ pub fn memory_mut(&mut self) -> &mut Memory<'a, 'mir, 'tcx, M> {
         &mut self.memory
     }
 
+    #[inline(always)]
+    pub fn tag_static_base_pointer(&self, ptr: Pointer) -> Pointer<M::PointerTag> {
+        self.memory.tag_static_base_pointer(ptr)
+    }
+
     #[inline(always)]
     pub fn stack(&self) -> &[Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>] {
         &self.stack
@@ -360,11 +368,6 @@ pub fn layout_of_local(
         }
     }
 
-    pub fn str_to_immediate(&mut self, s: &str) -> EvalResult<'tcx, Immediate<M::PointerTag>> {
-        let ptr = self.memory.allocate_static_bytes(s.as_bytes()).with_default_tag();
-        Ok(Immediate::new_slice(Scalar::Ptr(ptr), s.len() as u64, self))
-    }
-
     /// Returns the actual dynamic size and alignment of the place at the given type.
     /// Only the "meta" (metadata) part of the place matters.
     /// This can fail to provide an answer for extern types.
index 48b02d8e11b6057dc1f91ab9842e8a494a650b2b..456fc70fc0d1dc9c5df12861943d0081301f3cb4 100644 (file)
@@ -215,7 +215,7 @@ fn write_str(&mut self, s: &str) -> std::fmt::Result {
 pub fn type_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> &'tcx ty::Const<'tcx> {
     let path = AbsolutePathPrinter { tcx, path: String::new() }.print_type(ty).unwrap().path;
     let len = path.len();
-    let alloc = Allocation::from_byte_aligned_bytes(path.into_bytes(), ());
+    let alloc = Allocation::from_byte_aligned_bytes(path.into_bytes());
     let alloc = tcx.intern_const_alloc(alloc);
     tcx.mk_const(ty::Const {
         val: ConstValue::Slice {
index 873c2d2ec6088b1e01e94947b7770e3b6cdecb55..fa0750fa82aa98a988207883546634e85b4c7200 100644 (file)
@@ -5,13 +5,13 @@
 use std::borrow::{Borrow, Cow};
 use std::hash::Hash;
 
-use rustc::hir::{self, def_id::DefId};
+use rustc::hir::def_id::DefId;
 use rustc::mir;
-use rustc::ty::{self, query::TyCtxtAt, layout::Size};
+use rustc::ty::{self, query::TyCtxtAt};
 
 use super::{
     Allocation, AllocId, EvalResult, Scalar, AllocationExtra,
-    InterpretCx, PlaceTy, MPlaceTy, OpTy, ImmTy, MemoryKind,
+    InterpretCx, PlaceTy, OpTy, ImmTy, MemoryKind,
 };
 
 /// Whether this kind of memory is allowed to leak
@@ -65,7 +65,7 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
     /// Tag tracked alongside every pointer. This is used to implement "Stacked Borrows"
     /// <https://www.ralfj.de/blog/2018/08/07/stacked-borrows.html>.
     /// The `default()` is used for pointers to consts, statics, vtables and functions.
-    type PointerTag: ::std::fmt::Debug + Default + Copy + Eq + Hash + 'static;
+    type PointerTag: ::std::fmt::Debug + Copy + Eq + Hash + 'static;
 
     /// Extra data stored in every call frame.
     type FrameExtra;
@@ -90,7 +90,7 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
     /// The memory kind to use for copied statics -- or None if statics should not be mutated
     /// and thus any such attempt will cause a `ModifiedStatic` error to be raised.
     /// Statics are copied under two circumstances: When they are mutated, and when
-    /// `static_with_default_tag` or `find_foreign_static` (see below) returns an owned allocation
+    /// `tag_allocation` or `find_foreign_static` (see below) returns an owned allocation
     /// that is added to the memory so that the work is not done twice.
     const STATIC_KIND: Option<Self::MemoryKinds>;
 
@@ -133,11 +133,12 @@ fn call_intrinsic(
     /// This will only be called once per static and machine; the result is cached in
     /// the machine memory. (This relies on `AllocMap::get_or` being able to add the
     /// owned allocation to the map even when the map is shared.)
+    ///
+    /// This allocation will then be fed to `tag_allocation` to initialize the "extra" state.
     fn find_foreign_static(
         def_id: DefId,
         tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
-        memory_extra: &Self::MemoryExtra,
-    ) -> EvalResult<'tcx, Cow<'tcx, Allocation<Self::PointerTag, Self::AllocExtra>>>;
+    ) -> EvalResult<'tcx, Cow<'tcx, Allocation>>;
 
     /// Called for all binary operations on integer(-like) types when one operand is a pointer
     /// value, and for the `Offset` operation that is inherently about pointers.
@@ -156,36 +157,38 @@ fn box_alloc(
         dest: PlaceTy<'tcx, Self::PointerTag>,
     ) -> EvalResult<'tcx>;
 
-    /// Called to turn an allocation obtained from the `tcx` into one that has
-    /// the right type for this machine.
+    /// Called to initialize the "extra" state of an allocation and make the pointers
+    /// it contains (in relocations) tagged.  The way we construct allocations is
+    /// to always first construct it without extra and then add the extra.
+    /// This keeps uniform code paths for handling both allocations created by CTFE
+    /// for statics, and allocations ceated by Miri during evaluation.
+    ///
+    /// `kind` is the kind of the allocation being tagged; it can be `None` when
+    /// it's a static and `STATIC_KIND` is `None`.
     ///
     /// This should avoid copying if no work has to be done! If this returns an owned
     /// allocation (because a copy had to be done to add tags or metadata), machine memory will
     /// cache the result. (This relies on `AllocMap::get_or` being able to add the
     /// owned allocation to the map even when the map is shared.)
-    fn adjust_static_allocation<'b>(
-        alloc: &'b Allocation,
+    ///
+    /// For static allocations, the tag returned must be the same as the one returned by
+    /// `tag_static_base_pointer`.
+    fn tag_allocation<'b>(
+        id: AllocId,
+        alloc: Cow<'b, Allocation>,
+        kind: Option<MemoryKind<Self::MemoryKinds>>,
         memory_extra: &Self::MemoryExtra,
-    ) -> Cow<'b, Allocation<Self::PointerTag, Self::AllocExtra>>;
-
-    /// Computes the extra state and the tag for a new allocation.
-    fn new_allocation(
-        size: Size,
-        extra: &Self::MemoryExtra,
-        kind: MemoryKind<Self::MemoryKinds>,
-    ) -> (Self::AllocExtra, Self::PointerTag);
-
-    /// Executed when evaluating the `*` operator: Following a reference.
-    /// This has the chance to adjust the tag. It should not change anything else!
-    /// `mutability` can be `None` in case a raw ptr is being dereferenced.
-    #[inline]
-    fn tag_dereference(
-        _ecx: &InterpretCx<'a, 'mir, 'tcx, Self>,
-        place: MPlaceTy<'tcx, Self::PointerTag>,
-        _mutability: Option<hir::Mutability>,
-    ) -> EvalResult<'tcx, Scalar<Self::PointerTag>> {
-        Ok(place.ptr)
-    }
+    ) -> (Cow<'b, Allocation<Self::PointerTag, Self::AllocExtra>>, Self::PointerTag);
+
+    /// Return the "base" tag for the given static allocation: the one that is used for direct
+    /// accesses to this static/const/fn allocation.
+    ///
+    /// Be aware that requesting the `Allocation` for that `id` will lead to cycles
+    /// for cyclic statics!
+    fn tag_static_base_pointer(
+        id: AllocId,
+        memory_extra: &Self::MemoryExtra,
+    ) -> Self::PointerTag;
 
     /// Executes a retagging operation
     #[inline]
index 65a3b04c8b152f1c26eb0762e92eb7dd58a61152..7db963a89aaef94531433be4dd34fd7816f0ea3c 100644 (file)
@@ -18,7 +18,7 @@
 
 use super::{
     Pointer, AllocId, Allocation, GlobalId, AllocationExtra,
-    EvalResult, Scalar, InterpError, AllocKind, PointerArithmetic,
+    EvalResult, Scalar, InterpError, GlobalAlloc, PointerArithmetic,
     Machine, AllocMap, MayLeak, ErrorHandled, CheckInAllocMsg, InboundsCheck,
 };
 
@@ -108,32 +108,44 @@ pub fn new(tcx: TyCtxtAt<'a, 'tcx, 'tcx>) -> Self {
         }
     }
 
-    pub fn create_fn_alloc(&mut self, instance: Instance<'tcx>) -> Pointer {
-        Pointer::from(self.tcx.alloc_map.lock().create_fn_alloc(instance))
+    #[inline]
+    pub fn tag_static_base_pointer(&self, ptr: Pointer) -> Pointer<M::PointerTag> {
+        ptr.with_tag(M::tag_static_base_pointer(ptr.alloc_id, &self.extra))
     }
 
-    pub fn allocate_static_bytes(&mut self, bytes: &[u8]) -> Pointer {
-        Pointer::from(self.tcx.allocate_bytes(bytes))
+    pub fn create_fn_alloc(&mut self, instance: Instance<'tcx>) -> Pointer<M::PointerTag> {
+        let id = self.tcx.alloc_map.lock().create_fn_alloc(instance);
+        self.tag_static_base_pointer(Pointer::from(id))
     }
 
-    pub fn allocate_with(
+    pub fn allocate(
         &mut self,
-        alloc: Allocation<M::PointerTag, M::AllocExtra>,
+        size: Size,
+        align: Align,
         kind: MemoryKind<M::MemoryKinds>,
-    ) -> AllocId {
-        let id = self.tcx.alloc_map.lock().reserve();
-        self.alloc_map.insert(id, (kind, alloc));
-        id
+    ) -> Pointer<M::PointerTag> {
+        let alloc = Allocation::undef(size, align);
+        self.allocate_with(alloc, kind)
     }
 
-    pub fn allocate(
+    pub fn allocate_static_bytes(
         &mut self,
-        size: Size,
-        align: Align,
+        bytes: &[u8],
         kind: MemoryKind<M::MemoryKinds>,
     ) -> Pointer<M::PointerTag> {
-        let (extra, tag) = M::new_allocation(size, &self.extra, kind);
-        Pointer::from(self.allocate_with(Allocation::undef(size, align, extra), kind)).with_tag(tag)
+        let alloc = Allocation::from_byte_aligned_bytes(bytes);
+        self.allocate_with(alloc, kind)
+    }
+
+    pub fn allocate_with(
+        &mut self,
+        alloc: Allocation,
+        kind: MemoryKind<M::MemoryKinds>,
+    ) -> Pointer<M::PointerTag> {
+        let id = self.tcx.alloc_map.lock().reserve();
+        let (alloc, tag) = M::tag_allocation(id, Cow::Owned(alloc), Some(kind), &self.extra);
+        self.alloc_map.insert(id, (kind, alloc.into_owned()));
+        Pointer::from(id).with_tag(tag)
     }
 
     pub fn reallocate(
@@ -193,12 +205,12 @@ pub fn deallocate(
             None => {
                 // Deallocating static memory -- always an error
                 return match self.tcx.alloc_map.lock().get(ptr.alloc_id) {
-                    Some(AllocKind::Function(..)) => err!(DeallocatedWrongMemoryKind(
+                    Some(GlobalAlloc::Function(..)) => err!(DeallocatedWrongMemoryKind(
                         "function".to_string(),
                         format!("{:?}", kind),
                     )),
-                    Some(AllocKind::Static(..)) |
-                    Some(AllocKind::Memory(..)) => err!(DeallocatedWrongMemoryKind(
+                    Some(GlobalAlloc::Static(..)) |
+                    Some(GlobalAlloc::Memory(..)) => err!(DeallocatedWrongMemoryKind(
                         "static".to_string(),
                         format!("{:?}", kind),
                     )),
@@ -305,53 +317,68 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
     /// This attempts to return a reference to an existing allocation if
     /// one can be found in `tcx`. That, however, is only possible if `tcx` and
     /// this machine use the same pointer tag, so it is indirected through
-    /// `M::static_with_default_tag`.
+    /// `M::tag_allocation`.
+    ///
+    /// Notice that every static has two `AllocId` that will resolve to the same
+    /// thing here: one maps to `GlobalAlloc::Static`, this is the "lazy" ID,
+    /// and the other one is maps to `GlobalAlloc::Memory`, this is returned by
+    /// `const_eval_raw` and it is the "resolved" ID.
+    /// The resolved ID is never used by the interpreted progrma, it is hidden.
+    /// The `GlobalAlloc::Memory` branch here is still reachable though; when a static
+    /// contains a reference to memory that was created during its evaluation (i.e., not to
+    /// another static), those inner references only exist in "resolved" form.
     fn get_static_alloc(
         id: AllocId,
         tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
         memory_extra: &M::MemoryExtra,
     ) -> EvalResult<'tcx, Cow<'tcx, Allocation<M::PointerTag, M::AllocExtra>>> {
         let alloc = tcx.alloc_map.lock().get(id);
-        let def_id = match alloc {
-            Some(AllocKind::Memory(mem)) => {
-                // We got tcx memory. Let the machine figure out whether and how to
-                // turn that into memory with the right pointer tag.
-                return Ok(M::adjust_static_allocation(mem, memory_extra))
-            }
-            Some(AllocKind::Function(..)) => {
-                return err!(DerefFunctionPointer)
-            }
-            Some(AllocKind::Static(did)) => {
-                did
-            }
+        let alloc = match alloc {
+            Some(GlobalAlloc::Memory(mem)) =>
+                Cow::Borrowed(mem),
+            Some(GlobalAlloc::Function(..)) =>
+                return err!(DerefFunctionPointer),
             None =>
                 return err!(DanglingPointerDeref),
-        };
-        // We got a "lazy" static that has not been computed yet, do some work
-        trace!("static_alloc: Need to compute {:?}", def_id);
-        if tcx.is_foreign_item(def_id) {
-            return M::find_foreign_static(def_id, tcx, memory_extra);
-        }
-        let instance = Instance::mono(tcx.tcx, def_id);
-        let gid = GlobalId {
-            instance,
-            promoted: None,
-        };
-        // use the raw query here to break validation cycles. Later uses of the static will call the
-        // full query anyway
-        tcx.const_eval_raw(ty::ParamEnv::reveal_all().and(gid)).map_err(|err| {
-            // no need to report anything, the const_eval call takes care of that for statics
-            assert!(tcx.is_static(def_id));
-            match err {
-                ErrorHandled::Reported => InterpError::ReferencedConstant.into(),
-                ErrorHandled::TooGeneric => InterpError::TooGeneric.into(),
+            Some(GlobalAlloc::Static(def_id)) => {
+                // We got a "lazy" static that has not been computed yet.
+                if tcx.is_foreign_item(def_id) {
+                    trace!("static_alloc: foreign item {:?}", def_id);
+                    M::find_foreign_static(def_id, tcx)?
+                } else {
+                    trace!("static_alloc: Need to compute {:?}", def_id);
+                    let instance = Instance::mono(tcx.tcx, def_id);
+                    let gid = GlobalId {
+                        instance,
+                        promoted: None,
+                    };
+                    // use the raw query here to break validation cycles. Later uses of the static
+                    // will call the full query anyway
+                    let raw_const = tcx.const_eval_raw(ty::ParamEnv::reveal_all().and(gid))
+                        .map_err(|err| {
+                            // no need to report anything, the const_eval call takes care of that
+                            // for statics
+                            assert!(tcx.is_static(def_id));
+                            match err {
+                                ErrorHandled::Reported => InterpError::ReferencedConstant,
+                                ErrorHandled::TooGeneric => InterpError::TooGeneric,
+                            }
+                        })?;
+                    // Make sure we use the ID of the resolved memory, not the lazy one!
+                    let id = raw_const.alloc_id;
+                    let allocation = tcx.alloc_map.lock().unwrap_memory(id);
+                    Cow::Borrowed(allocation)
+                }
             }
-        }).map(|raw_const| {
-            let allocation = tcx.alloc_map.lock().unwrap_memory(raw_const.alloc_id);
-            // We got tcx memory. Let the machine figure out whether and how to
-            // turn that into memory with the right pointer tag.
-            M::adjust_static_allocation(allocation, memory_extra)
-        })
+        };
+        // We got tcx memory. Let the machine figure out whether and how to
+        // turn that into memory with the right pointer tag.
+        Ok(M::tag_allocation(
+            id, // always use the ID we got as input, not the "hidden" one.
+            alloc,
+            M::STATIC_KIND.map(MemoryKind::Machine),
+            memory_extra
+        ).0)
     }
 
     pub fn get(&self, id: AllocId) -> EvalResult<'tcx, &Allocation<M::PointerTag, M::AllocExtra>> {
@@ -429,8 +456,8 @@ pub fn get_size_and_align(
         }
         // Could also be a fn ptr or extern static
         match self.tcx.alloc_map.lock().get(id) {
-            Some(AllocKind::Function(..)) => Ok((Size::ZERO, Align::from_bytes(1).unwrap())),
-            Some(AllocKind::Static(did)) => {
+            Some(GlobalAlloc::Function(..)) => Ok((Size::ZERO, Align::from_bytes(1).unwrap())),
+            Some(GlobalAlloc::Static(did)) => {
                 // The only way `get` couldn't have worked here is if this is an extern static
                 assert!(self.tcx.is_foreign_item(did));
                 // Use size and align of the type
@@ -456,7 +483,7 @@ pub fn get_fn(&self, ptr: Pointer<M::PointerTag>) -> EvalResult<'tcx, Instance<'
         }
         trace!("reading fn ptr: {}", ptr.alloc_id);
         match self.tcx.alloc_map.lock().get(ptr.alloc_id) {
-            Some(AllocKind::Function(instance)) => Ok(instance),
+            Some(GlobalAlloc::Function(instance)) => Ok(instance),
             _ => Err(InterpError::ExecuteMemory.into()),
         }
     }
@@ -554,16 +581,16 @@ pub fn dump_allocs(&self, mut allocs: Vec<AllocId>) {
                 Err(()) => {
                     // static alloc?
                     match self.tcx.alloc_map.lock().get(id) {
-                        Some(AllocKind::Memory(alloc)) => {
+                        Some(GlobalAlloc::Memory(alloc)) => {
                             self.dump_alloc_helper(
                                 &mut allocs_seen, &mut allocs_to_print,
                                 msg, alloc, " (immutable)".to_owned()
                             );
                         }
-                        Some(AllocKind::Function(func)) => {
+                        Some(GlobalAlloc::Function(func)) => {
                             trace!("{} {}", msg, func);
                         }
-                        Some(AllocKind::Static(did)) => {
+                        Some(GlobalAlloc::Static(did)) => {
                             trace!("{} {:?}", msg, did);
                         }
                         None => {
index 289379f34a9a3bb8771d4dfe0253f7e97689fde4..899cc40dc32065f3f4078657e9138bf1ab8a43fe 100644 (file)
@@ -37,16 +37,6 @@ pub fn from_scalar(val: Scalar<Tag>) -> Self {
         Immediate::Scalar(ScalarMaybeUndef::Scalar(val))
     }
 
-    #[inline]
-    pub fn erase_tag(self) -> Immediate
-    {
-        match self {
-            Immediate::Scalar(x) => Immediate::Scalar(x.erase_tag()),
-            Immediate::ScalarPair(x, y) =>
-                Immediate::ScalarPair(x.erase_tag(), y.erase_tag()),
-        }
-    }
-
     pub fn new_slice(
         val: Scalar<Tag>,
         len: u64,
@@ -130,15 +120,6 @@ pub enum Operand<Tag=(), Id=AllocId> {
 }
 
 impl<Tag> Operand<Tag> {
-    #[inline]
-    pub fn erase_tag(self) -> Operand
-    {
-        match self {
-            Operand::Immediate(x) => Operand::Immediate(x.erase_tag()),
-            Operand::Indirect(x) => Operand::Indirect(x.erase_tag()),
-        }
-    }
-
     #[inline]
     pub fn to_mem_place(self) -> MemPlace<Tag>
         where Tag: ::std::fmt::Debug
@@ -209,18 +190,6 @@ pub fn to_bits(self) -> EvalResult<'tcx, u128> {
     }
 }
 
-impl<'tcx, Tag> OpTy<'tcx, Tag>
-{
-    #[inline]
-    pub fn erase_tag(self) -> OpTy<'tcx>
-    {
-        OpTy {
-            op: self.op.erase_tag(),
-            layout: self.layout,
-        }
-    }
-}
-
 // Use the existing layout if given (but sanity check in debug mode),
 // or compute the layout.
 #[inline(always)]
@@ -243,7 +212,7 @@ pub(super) fn from_known_layout<'tcx>(
 }
 
 impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> {
-    /// Try reading an immediate in memory; this is interesting particularly for ScalarPair.
+    /// Try reading an immediate in memory; this is interesting particularly for `ScalarPair`.
     /// Returns `None` if the layout does not permit loading this as a value.
     fn try_read_immediate_from_mplace(
         &self,
@@ -444,7 +413,7 @@ pub fn access_local(
         Ok(OpTy { op, layout })
     }
 
-    /// Every place can be read from, so we can turm them into an operand
+    /// Every place can be read from, so we can turn them into an operand
     #[inline(always)]
     pub fn place_to_op(
         &self,
@@ -500,7 +469,7 @@ pub(super) fn eval_place_to_op(
     }
 
     /// Evaluate the operand, returning a place where you can then find the data.
-    /// if you already know the layout, you can save two some table lookups
+    /// If you already know the layout, you can save two table lookups
     /// by passing it in here.
     pub fn eval_operand(
         &self,
@@ -537,44 +506,55 @@ pub(super) fn eval_operands(
         val: &'tcx ty::Const<'tcx>,
         layout: Option<TyLayout<'tcx>>,
     ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
-        let op = match val.val {
-            ConstValue::Param(_) => return err!(TooGeneric),
-            ConstValue::Infer(_) | ConstValue::Placeholder(_) => bug!(),
-            ConstValue::ByRef(ptr, alloc) => {
-                // We rely on mutability being set correctly in that allocation to prevent writes
-                // where none should happen -- and for `static mut`, we copy on demand anyway.
-                Operand::Indirect(
-                    MemPlace::from_ptr(ptr.with_default_tag(), alloc.align)
-                )
-            },
-            ConstValue::Slice { data, start, end } =>
-                Operand::Immediate(Immediate::ScalarPair(
-                    Scalar::from(Pointer::new(
-                        self.tcx.alloc_map.lock().allocate(data),
-                        Size::from_bytes(start as u64),
-                    )).with_default_tag().into(),
-                    Scalar::from_uint(
-                        (end - start) as u64,
-                        self.tcx.data_layout.pointer_size,
-                    ).with_default_tag().into(),
-                )),
-            ConstValue::Scalar(x) =>
-                Operand::Immediate(Immediate::Scalar(x.with_default_tag().into())),
+        let tag_scalar = |scalar| match scalar {
+            Scalar::Ptr(ptr) => Scalar::Ptr(self.tag_static_base_pointer(ptr)),
+            Scalar::Raw { data, size } => Scalar::Raw { data, size },
+        };
+        // Early-return cases.
+        match val.val {
+            ConstValue::Param(_) => return err!(TooGeneric), // FIXME(oli-obk): try to monomorphize
             ConstValue::Unevaluated(def_id, substs) => {
                 let instance = self.resolve(def_id, substs)?;
                 return Ok(OpTy::from(self.const_eval_raw(GlobalId {
                     instance,
                     promoted: None,
                 })?));
-            },
-        };
+            }
+            _ => {}
+        }
+        // Other cases need layout.
         let layout = from_known_layout(layout, || {
             self.layout_of(self.monomorphize(val.ty)?)
         })?;
-        Ok(OpTy {
-            op,
-            layout,
-        })
+        let op = match val.val {
+            ConstValue::ByRef(ptr, _alloc) => {
+                // We rely on mutability being set correctly in that allocation to prevent writes
+                // where none should happen.
+                let ptr = self.tag_static_base_pointer(ptr);
+                Operand::Indirect(MemPlace::from_ptr(ptr, layout.align.abi))
+            },
+            ConstValue::Scalar(x) =>
+                Operand::Immediate(Immediate::Scalar(tag_scalar(x).into())),
+            ConstValue::Slice { data, start, end } => {
+                // We rely on mutability being set correctly in `data` to prevent writes
+                // where none should happen.
+                let ptr = Pointer::new(
+                    self.tcx.alloc_map.lock().create_memory_alloc(data),
+                    Size::from_bytes(start as u64), // offset: `start`
+                );
+                Operand::Immediate(Immediate::new_slice(
+                    self.tag_static_base_pointer(ptr).into(),
+                    (end - start) as u64, // len: `end - start`
+                    self,
+                ))
+            }
+            ConstValue::Param(..) |
+            ConstValue::Infer(..) |
+            ConstValue::Placeholder(..) |
+            ConstValue::Unevaluated(..) =>
+                bug!("eval_const_to_op: Unexpected ConstValue {:?}", val),
+        };
+        Ok(OpTy { op, layout })
     }
 
     /// Read discriminant, return the runtime value as well as the variant index.
index 0ae4e90b7c24d57afb72319874960c5893f79c6e..fac9665d968e2a9b7e21d6119ca56c4ca2e081e7 100644 (file)
@@ -5,7 +5,6 @@
 use std::convert::TryFrom;
 use std::hash::Hash;
 
-use rustc::hir;
 use rustc::mir;
 use rustc::mir::interpret::truncate;
 use rustc::ty::{self, Ty};
@@ -294,7 +293,7 @@ pub fn to_mem_place(self) -> MPlaceTy<'tcx, Tag> {
 impl<'a, 'mir, 'tcx, Tag, M> InterpretCx<'a, 'mir, 'tcx, M>
 where
     // FIXME: Working around https://github.com/rust-lang/rust/issues/54385
-    Tag: ::std::fmt::Debug+Default+Copy+Eq+Hash+'static,
+    Tag: ::std::fmt::Debug + Copy + Eq + Hash + 'static,
     M: Machine<'a, 'mir, 'tcx, PointerTag=Tag>,
     // FIXME: Working around https://github.com/rust-lang/rust/issues/24159
     M::MemoryMap: AllocMap<AllocId, (MemoryKind<M::MemoryKinds>, Allocation<Tag, M::AllocExtra>)>,
@@ -325,29 +324,17 @@ pub fn ref_to_mplace(
 
     // Take an operand, representing a pointer, and dereference it to a place -- that
     // will always be a MemPlace.  Lives in `place.rs` because it creates a place.
-    // This calls the "deref" machine hook, and counts as a deref as far as
-    // Stacked Borrows is concerned.
     pub fn deref_operand(
         &self,
         src: OpTy<'tcx, M::PointerTag>,
     ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
         let val = self.read_immediate(src)?;
         trace!("deref to {} on {:?}", val.layout.ty, *val);
-        let mut place = self.ref_to_mplace(val)?;
-        // Pointer tag tracking might want to adjust the tag.
-        let mutbl = match val.layout.ty.sty {
-            // `builtin_deref` considers boxes immutable, that's useless for our purposes
-            ty::Ref(_, _, mutbl) => Some(mutbl),
-            ty::Adt(def, _) if def.is_box() => Some(hir::MutMutable),
-            ty::RawPtr(_) => None,
-            _ => bug!("Unexpected pointer type {}", val.layout.ty),
-        };
-        place.mplace.ptr = M::tag_dereference(self, place, mutbl)?;
-        Ok(place)
+        self.ref_to_mplace(val)
     }
 
-    /// Offset a pointer to project to a field. Unlike place_field, this is always
-    /// possible without allocating, so it can take &self. Also return the field's layout.
+    /// Offset a pointer to project to a field. Unlike `place_field`, this is always
+    /// possible without allocating, so it can take `&self`. Also return the field's layout.
     /// This supports both struct and array fields.
     #[inline(always)]
     pub fn mplace_field(
@@ -587,18 +574,23 @@ pub(super) fn eval_static_to_mplace(
                     promoted: None
                 };
                 // Just create a lazy reference, so we can support recursive statics.
-                // tcx takes are of assigning every static one and only one unique AllocId.
+                // tcx takes care of assigning every static one and only one unique AllocId.
                 // When the data here is ever actually used, memory will notice,
                 // and it knows how to deal with alloc_id that are present in the
                 // global table but not in its local memory: It calls back into tcx through
                 // a query, triggering the CTFE machinery to actually turn this lazy reference
                 // into a bunch of bytes.  IOW, statics are evaluated with CTFE even when
                 // this InterpretCx uses another Machine (e.g., in miri).  This is what we
-                // want!  This way, computing statics works concistently between codegen
+                // want!  This way, computing statics works consistently between codegen
                 // and miri: They use the same query to eventually obtain a `ty::Const`
                 // and use that for further computation.
-                let alloc = self.tcx.alloc_map.lock().intern_static(cid.instance.def_id());
-                MPlaceTy::from_aligned_ptr(Pointer::from(alloc).with_default_tag(), layout)
+                //
+                // Notice that statics have *two* AllocIds: the lazy one, and the resolved
+                // one.  Here we make sure that the interpreted program never sees the
+                // resolved ID.  Also see the doc comment of `Memory::get_static_alloc`.
+                let alloc_id = self.tcx.alloc_map.lock().create_static_alloc(cid.instance.def_id());
+                let ptr = self.tag_static_base_pointer(Pointer::from(alloc_id));
+                MPlaceTy::from_aligned_ptr(ptr, layout)
             }
         })
     }
@@ -722,7 +714,7 @@ fn write_immediate_no_validate(
     }
 
     /// Write an immediate to memory.
-    /// If you use this you are responsible for validating that things git copied at the
+    /// If you use this you are responsible for validating that things got copied at the
     /// right type.
     fn write_immediate_to_mplace_no_validate(
         &mut self,
@@ -805,7 +797,7 @@ pub fn copy_op(
 
     /// Copies the data from an operand to a place. This does not support transmuting!
     /// Use `copy_op_transmute` if the layouts could disagree.
-    /// Also, if you use this you are responsible for validating that things git copied at the
+    /// Also, if you use this you are responsible for validating that things get copied at the
     /// right type.
     fn copy_op_no_validate(
         &mut self,
@@ -1032,11 +1024,9 @@ pub fn raw_const_to_mplace(
     ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
         // This must be an allocation in `tcx`
         assert!(self.tcx.alloc_map.lock().get(raw.alloc_id).is_some());
+        let ptr = self.tag_static_base_pointer(Pointer::from(raw.alloc_id));
         let layout = self.layout_of(raw.ty)?;
-        Ok(MPlaceTy::from_aligned_ptr(
-            Pointer::new(raw.alloc_id, Size::ZERO).with_default_tag(),
-            layout,
-        ))
+        Ok(MPlaceTy::from_aligned_ptr(ptr, layout))
     }
 
     /// Turn a place with a `dyn Trait` type into a place with the actual dynamic type.
index 4eb79cf56fcf2a764f1ba9a4d4ae3f08a7c7a708..208bba60bf2f20c89b41fb5f5290761038d1d5dc 100644 (file)
@@ -25,7 +25,7 @@ pub fn get_vtable(
             // always use the same vtable for the same (Type, Trait) combination.
             // That's not what happens in rustc, but emulating per-crate deduplication
             // does not sound like it actually makes anything any better.
-            return Ok(Pointer::from(vtable).with_default_tag());
+            return Ok(vtable);
         }
 
         let methods = if let Some(poly_trait_ref) = poly_trait_ref {
@@ -56,7 +56,7 @@ pub fn get_vtable(
         let tcx = &*self.tcx;
 
         let drop = crate::monomorphize::resolve_drop_in_place(*tcx, ty);
-        let drop = self.memory.create_fn_alloc(drop).with_default_tag();
+        let drop = self.memory.create_fn_alloc(drop);
         // no need to do any alignment checks on the memory accesses below, because we know the
         // allocation is correctly aligned as we created it above. Also we're only offsetting by
         // multiples of `ptr_align`, which means that it will stay aligned to `ptr_align`.
@@ -83,7 +83,7 @@ pub fn get_vtable(
                     def_id,
                     substs,
                 ).ok_or_else(|| InterpError::TooGeneric)?;
-                let fn_ptr = self.memory.create_fn_alloc(instance).with_default_tag();
+                let fn_ptr = self.memory.create_fn_alloc(instance);
                 let method_ptr = vtable.offset(ptr_size * (3 + i as u64), self)?;
                 self.memory
                     .get_mut(method_ptr.alloc_id)?
@@ -92,7 +92,7 @@ pub fn get_vtable(
         }
 
         self.memory.mark_immutable(vtable.alloc_id)?;
-        assert!(self.vtables.insert((ty, poly_trait_ref), vtable.alloc_id).is_none());
+        assert!(self.vtables.insert((ty, poly_trait_ref), vtable).is_none());
 
         Ok(vtable)
     }
index 072c6f4fd90e8e9641bcf2264246bc025050f2ab..967496e59645a857a549d0b83fc82e4c3d72ab1a 100644 (file)
@@ -8,7 +8,7 @@
 use rustc::ty;
 use rustc_data_structures::fx::FxHashSet;
 use rustc::mir::interpret::{
-    Scalar, AllocKind, EvalResult, InterpError, CheckInAllocMsg,
+    Scalar, GlobalAlloc, EvalResult, InterpError, CheckInAllocMsg,
 };
 
 use super::{
@@ -174,8 +174,7 @@ fn aggregate_field_path_elem(
                     if let Some(upvars) = tables.upvar_list.get(&def_id) {
                         // Sometimes the index is beyond the number of upvars (seen
                         // for a generator).
-                        if let Some(upvar_id) = upvars.get(field) {
-                            let var_hir_id = upvar_id.var_path.hir_id;
+                        if let Some((&var_hir_id, _)) = upvars.get_index(field) {
                             let var_node_id = self.ecx.tcx.hir().hir_to_node_id(var_hir_id);
                             if let hir::Node::Binding(pat) = self.ecx.tcx.hir().get(var_node_id) {
                                 if let hir::PatKind::Binding(_, _, ident, _) = pat.node {
@@ -403,7 +402,7 @@ fn visit_primitive(&mut self, value: OpTy<'tcx, M::PointerTag>) -> EvalResult<'t
                             "integer pointer in non-ZST reference", self.path);
                         // Skip validation entirely for some external statics
                         let alloc_kind = self.ecx.tcx.alloc_map.lock().get(ptr.alloc_id);
-                        if let Some(AllocKind::Static(did)) = alloc_kind {
+                        if let Some(GlobalAlloc::Static(did)) = alloc_kind {
                             // `extern static` cannot be validated as they have no body.
                             // FIXME: Statics from other crates are also skipped.
                             // They might be checked at a different type, but for now we
@@ -613,7 +612,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
     /// is an indirect operand.
     /// It will error if the bits at the destination do not match the ones described by the layout.
     ///
-    /// `ref_tracking` can be None to avoid recursive checking below references.
+    /// `ref_tracking` can be `None` to avoid recursive checking below references.
     /// This also toggles between "run-time" (no recursion) and "compile-time" (with recursion)
     /// validation (e.g., pointer values are fine in integers at runtime).
     pub fn validate_operand(
index d382e53e91846a55e120524e0e6c0944c7540559..6dc2b007407062d70ca6aa7b029198a7a3342bf5 100644 (file)
@@ -22,7 +22,6 @@
 #![feature(unicode_internals)]
 #![feature(step_trait)]
 #![feature(slice_concat_ext)]
-#![feature(reverse_bits)]
 #![feature(try_blocks)]
 
 #![recursion_limit="256"]
index c1131336f3636a08606c48c619eba604eaec4464..dae5f1b8cd25444d25270d8c58485ce3d3556b5b 100644 (file)
 use rustc::mir::{self, Location, Place, PlaceBase, Promoted, Static, StaticKind};
 use rustc::mir::visit::Visitor as MirVisitor;
 use rustc::mir::mono::MonoItem;
-use rustc::mir::interpret::{Scalar, GlobalId, AllocKind, ErrorHandled};
+use rustc::mir::interpret::{Scalar, GlobalId, GlobalAlloc, ErrorHandled};
 
 use crate::monomorphize::{self, Instance};
 use rustc::util::nodemap::{FxHashSet, FxHashMap, DefIdMap};
@@ -1183,20 +1183,20 @@ fn collect_miri<'a, 'tcx>(
 ) {
     let alloc_kind = tcx.alloc_map.lock().get(alloc_id);
     match alloc_kind {
-        Some(AllocKind::Static(did)) => {
-            let instance = Instance::mono(tcx, did);
+        Some(GlobalAlloc::Static(def_id)) => {
+            let instance = Instance::mono(tcx, def_id);
             if should_monomorphize_locally(tcx, &instance) {
-                trace!("collecting static {:?}", did);
-                output.push(MonoItem::Static(did));
+                trace!("collecting static {:?}", def_id);
+                output.push(MonoItem::Static(def_id));
             }
         }
-        Some(AllocKind::Memory(alloc)) => {
+        Some(GlobalAlloc::Memory(alloc)) => {
             trace!("collecting {:?} with {:#?}", alloc_id, alloc);
             for &((), inner) in alloc.relocations.values() {
                 collect_miri(tcx, inner, output);
             }
         },
-        Some(AllocKind::Function(fn_instance)) => {
+        Some(GlobalAlloc::Function(fn_instance)) => {
             if should_monomorphize_locally(tcx, &fn_instance) {
                 trace!("collecting {:?} with {:#?}", alloc_id, fn_instance);
                 output.push(create_fn_mono_item(fn_instance));
@@ -1263,7 +1263,7 @@ fn collect_const<'a, 'tcx>(
                 collect_miri(tcx, id, output);
             }
         }
-        ConstValue::Unevaluated(did, substs) => {
+        ConstValue::Unevaluated(def_id, substs) => {
             let param_env = ty::ParamEnv::reveal_all();
             let substs = tcx.subst_and_normalize_erasing_regions(
                 param_substs,
@@ -1272,7 +1272,7 @@ fn collect_const<'a, 'tcx>(
             );
             let instance = ty::Instance::resolve(tcx,
                                                 param_env,
-                                                did,
+                                                def_id,
                                                 substs).unwrap();
 
             let cid = GlobalId {
@@ -1283,7 +1283,7 @@ fn collect_const<'a, 'tcx>(
                 Ok(val) => collect_const(tcx, val, param_substs, output),
                 Err(ErrorHandled::Reported) => {},
                 Err(ErrorHandled::TooGeneric) => span_bug!(
-                    tcx.def_span(did), "collection encountered polymorphic constant",
+                    tcx.def_span(def_id), "collection encountered polymorphic constant",
                 ),
             }
         }
index 087f8779b6916fb896a82e47525dba45bf040694..0cefc8c3a92ab2ac3703033f11f865fb0805f0bf 100644 (file)
@@ -125,7 +125,7 @@ fn make_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     debug!("make_shim({:?}) = {:?}", instance, result);
 
-    tcx.alloc_mir(result)
+    tcx.arena.alloc(result)
 }
 
 #[derive(Copy, Clone, Debug, PartialEq)]
index 22b96a9db4750cfbc9033f1c8c8146ddcd7d4117..82193d98655d6a79b19d73bcf9af49654a434a63 100644 (file)
@@ -290,5 +290,5 @@ fn optimized_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx
         &add_call_guards::CriticalCallEdges,
         &dump_mir::Marker("PreCodegen"),
     ]);
-    tcx.alloc_mir(mir)
+    tcx.arena.alloc(mir)
 }
index a416792101f73d5d3ac57015b6b9ff93a1ecda2a..fe94181047fcd3a5b76b3940de3dc4e20dbbb4fc 100644 (file)
@@ -316,8 +316,9 @@ fn in_rvalue(cx: &ConstCx<'_, 'tcx>, rvalue: &Rvalue<'tcx>) -> bool {
                     } else if let ty::Array(_, len) = ty.sty {
                         // FIXME(eddyb) the `cx.mode == Mode::Fn` condition
                         // seems unnecessary, given that this is merely a ZST.
-                        if !(len.unwrap_usize(cx.tcx) == 0 && cx.mode == Mode::Fn) {
-                            return true;
+                        match len.assert_usize(cx.tcx) {
+                            Some(0) if cx.mode == Mode::Fn => {},
+                            _ => return true,
                         }
                     } else {
                         return true;
index 85cd602db591f6947449bc460cba813a661b442b..869cae3d3a8e4711b3af973df84c58e53ae4f848 100644 (file)
@@ -199,8 +199,15 @@ fn check_nested_body(&mut self, body_id: hir::BodyId) -> Promotability {
         let param_env = self.param_env;
         let region_scope_tree = self.tcx.region_scope_tree(item_def_id);
         let tables = self.tables;
-        euv::ExprUseVisitor::new(self, tcx, param_env, &region_scope_tree, tables, None)
-            .consume_body(body);
+        euv::ExprUseVisitor::new(
+            self,
+            tcx,
+            item_def_id,
+            param_env,
+            &region_scope_tree,
+            tables,
+            None,
+        ).consume_body(body);
 
         let body_promotable = self.check_expr(&body.value);
         self.in_fn = outer_in_fn;
index 968a45e241e84b4b860a14845bde74819ee28d33..8e3359c775288f77e237b77e6904ef8dbc0d66e9 100644 (file)
@@ -12,6 +12,7 @@ test = false
 
 [dependencies]
 bitflags = "1.0"
+indexmap = "1"
 log = "0.4"
 syntax = { path = "../libsyntax" }
 rustc = { path = "../librustc" }
index 59e5fc149fc6e76b7f2ab3bbf14ae736d22c3917..21e759ccc650e79b470e2d21118c25ed8580b151 100644 (file)
@@ -29,7 +29,7 @@
 };
 use rustc::hir::def::Namespace::*;
 use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId};
-use rustc::hir::{Upvar, UpvarMap, TraitCandidate, TraitMap, GlobMap};
+use rustc::hir::{TraitCandidate, TraitMap, GlobMap};
 use rustc::ty::{self, DefIdTree};
 use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap};
 use rustc::{bug, span_bug};
@@ -612,7 +612,6 @@ fn is_expected(self, res: Res) -> bool {
                 | Res::Def(DefKind::Const, _)
                 | Res::Def(DefKind::Static, _)
                 | Res::Local(..)
-                | Res::Upvar(..)
                 | Res::Def(DefKind::Fn, _)
                 | Res::Def(DefKind::Method, _)
                 | Res::Def(DefKind::AssocConst, _)
@@ -853,7 +852,7 @@ fn visit_fn(&mut self,
                 function_kind: FnKind<'tcx>,
                 declaration: &'tcx FnDecl,
                 _: Span,
-                node_id: NodeId)
+                _: NodeId)
     {
         debug!("(resolving function) entering function");
         let (rib_kind, asyncness) = match function_kind {
@@ -864,7 +863,7 @@ fn visit_fn(&mut self,
             FnKind::Closure(_) =>
                 // Async closures aren't resolved through `visit_fn`-- they're
                 // processed separately
-                (ClosureRibKind(node_id), &IsAsync::NotAsync),
+                (NormalRibKind, &IsAsync::NotAsync),
         };
 
         // Create a value rib for the function.
@@ -898,12 +897,6 @@ fn visit_fn(&mut self,
         visit::walk_fn_ret_ty(self, &declaration.output);
 
         // Resolve the function body, potentially inside the body of an async closure
-        if let IsAsync::Async { closure_id, .. } = asyncness {
-            let rib_kind = ClosureRibKind(*closure_id);
-            self.ribs[ValueNS].push(Rib::new(rib_kind));
-            self.label_ribs.push(Rib::new(rib_kind));
-        }
-
         match function_kind {
             FnKind::ItemFn(.., body) | FnKind::Method(.., body) => {
                 if let IsAsync::Async { ref arguments, .. } = asyncness {
@@ -926,12 +919,6 @@ fn visit_fn(&mut self,
             }
         };
 
-        // Leave the body of the async closure
-        if asyncness.is_async() {
-            self.label_ribs.pop();
-            self.ribs[ValueNS].pop();
-        }
-
         debug!("(resolving function) leaving function");
 
         self.label_ribs.pop();
@@ -1018,17 +1005,13 @@ enum GenericParameters<'a, 'b> {
                       RibKind<'a>),
 }
 
-/// The rib kind controls the translation of local
-/// definitions (`Res::Local`) to upvars (`Res::Upvar`).
+/// The rib kind restricts certain accesses,
+/// e.g. to a `Res::Local` of an outer item.
 #[derive(Copy, Clone, Debug)]
 enum RibKind<'a> {
-    /// No translation needs to be applied.
+    /// No restriction needs to be applied.
     NormalRibKind,
 
-    /// We passed through a closure scope at the given `NodeId`.
-    /// Translate upvars as appropriate.
-    ClosureRibKind(NodeId /* func id */),
-
     /// We passed through an impl or trait and are now in one of its
     /// methods or associated types. Allow references to ty params that impl or trait
     /// binds. Disallow any other upvars (including other ty params that are
@@ -1668,8 +1651,6 @@ pub struct Resolver<'a> {
     /// Resolutions for labels (node IDs of their corresponding blocks or loops).
     label_res_map: NodeMap<NodeId>,
 
-    pub upvars: UpvarMap,
-    upvars_seen: NodeMap<NodeMap<usize>>,
     pub export_map: ExportMap<NodeId>,
     pub trait_map: TraitMap,
 
@@ -2032,8 +2013,6 @@ pub fn new(session: &'a Session,
             partial_res_map: Default::default(),
             import_res_map: Default::default(),
             label_res_map: Default::default(),
-            upvars: Default::default(),
-            upvars_seen: Default::default(),
             export_map: FxHashMap::default(),
             trait_map: Default::default(),
             module_map,
@@ -2206,7 +2185,7 @@ fn resolve_ident_in_lexical_scope(&mut self,
             if let Some(res) = self.ribs[ns][i].bindings.get(&ident).cloned() {
                 // The ident resolves to a type parameter or local variable.
                 return Some(LexicalScopeBinding::Res(
-                    self.adjust_local_res(ns, i, res, record_used, path_span)
+                    self.validate_res_from_ribs(ns, i, res, record_used, path_span),
                 ));
             }
 
@@ -4008,14 +3987,16 @@ fn lint_if_path_starts_with_module(
             diag);
     }
 
-    // Resolve a local definition, potentially adjusting for closures.
-    fn adjust_local_res(&mut self,
-                        ns: Namespace,
-                        rib_index: usize,
-                        mut res: Res,
-                        record_used: bool,
-                        span: Span) -> Res {
-        debug!("adjust_local_res");
+    // Validate a local resolution (from ribs).
+    fn validate_res_from_ribs(
+        &mut self,
+        ns: Namespace,
+        rib_index: usize,
+        res: Res,
+        record_used: bool,
+        span: Span,
+    ) -> Res {
+        debug!("validate_res_from_ribs({:?})", res);
         let ribs = &self.ribs[ns][rib_index + 1..];
 
         // An invalid forward use of a type parameter from a previous default.
@@ -4037,10 +4018,7 @@ fn adjust_local_res(&mut self,
         }
 
         match res {
-            Res::Upvar(..) => {
-                span_bug!(span, "unexpected {:?} in bindings", res)
-            }
-            Res::Local(node_id) => {
+            Res::Local(_) => {
                 use ResolutionError::*;
                 let mut res_err = None;
 
@@ -4050,30 +4028,6 @@ fn adjust_local_res(&mut self,
                         ForwardTyParamBanRibKind | TyParamAsConstParamTy => {
                             // Nothing to do. Continue.
                         }
-                        ClosureRibKind(function_id) => {
-                            let prev_res = res;
-
-                            let seen = self.upvars_seen
-                                           .entry(function_id)
-                                           .or_default();
-                            if let Some(&index) = seen.get(&node_id) {
-                                res = Res::Upvar(node_id, index, function_id);
-                                continue;
-                            }
-                            let vec = self.upvars
-                                          .entry(function_id)
-                                          .or_default();
-                            let depth = vec.len();
-                            res = Res::Upvar(node_id, depth, function_id);
-
-                            if record_used {
-                                vec.push(Upvar {
-                                    res: prev_res,
-                                    span,
-                                });
-                                seen.insert(node_id, depth);
-                            }
-                        }
                         ItemRibKind | FnItemRibKind | AssocItemRibKind => {
                             // This was an attempt to access an upvar inside a
                             // named function item. This is not allowed, so we
@@ -4103,7 +4057,7 @@ fn adjust_local_res(&mut self,
             Res::Def(DefKind::TyParam, _) | Res::SelfTy(..) => {
                 for rib in ribs {
                     match rib.kind {
-                        NormalRibKind | AssocItemRibKind | ClosureRibKind(..) |
+                        NormalRibKind | AssocItemRibKind |
                         ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind |
                         ConstantItemRibKind | TyParamAsConstParamTy => {
                             // Nothing to do. Continue.
@@ -4483,25 +4437,15 @@ fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) {
                 visit::walk_expr(self, expr);
                 self.current_type_ascription.pop();
             }
-            // Resolve the body of async exprs inside the async closure to which they desugar
-            ExprKind::Async(_, async_closure_id, ref block) => {
-                let rib_kind = ClosureRibKind(async_closure_id);
-                self.ribs[ValueNS].push(Rib::new(rib_kind));
-                self.label_ribs.push(Rib::new(rib_kind));
-                self.visit_block(&block);
-                self.label_ribs.pop();
-                self.ribs[ValueNS].pop();
-            }
             // `async |x| ...` gets desugared to `|x| future_from_generator(|| ...)`, so we need to
             // resolve the arguments within the proper scopes so that usages of them inside the
             // closure are detected as upvars rather than normal closure arg usages.
             ExprKind::Closure(
-                _, IsAsync::Async { closure_id: inner_closure_id, .. }, _,
+                _, IsAsync::Async { .. }, _,
                 ref fn_decl, ref body, _span,
             ) => {
-                let rib_kind = ClosureRibKind(expr.id);
+                let rib_kind = NormalRibKind;
                 self.ribs[ValueNS].push(Rib::new(rib_kind));
-                self.label_ribs.push(Rib::new(rib_kind));
                 // Resolve arguments:
                 let mut bindings_list = FxHashMap::default();
                 for argument in &fn_decl.inputs {
@@ -4513,18 +4457,12 @@ fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) {
 
                 // Now resolve the inner closure
                 {
-                    let rib_kind = ClosureRibKind(inner_closure_id);
-                    self.ribs[ValueNS].push(Rib::new(rib_kind));
-                    self.label_ribs.push(Rib::new(rib_kind));
                     // No need to resolve arguments: the inner closure has none.
                     // Resolve the return type:
                     visit::walk_fn_ret_ty(self, &fn_decl.output);
                     // Resolve the body
                     self.visit_expr(body);
-                    self.label_ribs.pop();
-                    self.ribs[ValueNS].pop();
                 }
-                self.label_ribs.pop();
                 self.ribs[ValueNS].pop();
             }
             _ => {
index 8faa4c71807805159140ba11bcde2fb4f248dc4d..cca5682d90a9bc6abe35e059048d8b33070293d4 100644 (file)
@@ -702,7 +702,7 @@ fn fn_type(seg: &ast::PathSegment) -> bool {
         let span = self.span_from_span(span);
 
         match res {
-            Res::Upvar(id, ..) | Res::Local(id) => {
+            Res::Local(id) => {
                 Some(Ref {
                     kind: RefKind::Variable,
                     span,
index cd53bdc6ed0a04c9a144e3fcd189ac7d6541dddf..cc054adee7bea80ebe5b72923b5357f755f78027 100644 (file)
@@ -2049,7 +2049,7 @@ pub fn ty_of_fn(&self,
         for br in late_bound_in_ret.difference(&late_bound_in_args) {
             let lifetime_name = match *br {
                 ty::BrNamed(_, name) => format!("lifetime `{}`,", name),
-                ty::BrAnon(_) | ty::BrFresh(_) | ty::BrEnv => "an anonymous lifetime".to_string(),
+                ty::BrAnon(_) | ty::BrEnv => "an anonymous lifetime".to_string(),
             };
             let mut err = struct_span_err!(tcx.sess,
                                            decl.output.span(),
index 5cd95a9d834c4af1b547894391af44ccb0ddadcb..9607427baa9ec4d96e3c4b0198329458fbc61d52 100644 (file)
@@ -400,27 +400,36 @@ pub fn check_pat_walk(
                 let expected_ty = self.structurally_resolved_type(pat.span, expected);
                 let (inner_ty, slice_ty) = match expected_ty.sty {
                     ty::Array(inner_ty, size) => {
-                        let size = size.unwrap_usize(tcx);
-                        let min_len = before.len() as u64 + after.len() as u64;
-                        if slice.is_none() {
-                            if min_len != size {
-                                struct_span_err!(
-                                    tcx.sess, pat.span, E0527,
-                                    "pattern requires {} elements but array has {}",
-                                    min_len, size)
-                                    .span_label(pat.span, format!("expected {} elements", size))
+                        if let Some(size) = size.assert_usize(tcx) {
+                            let min_len = before.len() as u64 + after.len() as u64;
+                            if slice.is_none() {
+                                if min_len != size {
+                                    struct_span_err!(
+                                        tcx.sess, pat.span, E0527,
+                                        "pattern requires {} elements but array has {}",
+                                        min_len, size)
+                                        .span_label(pat.span, format!("expected {} elements", size))
+                                        .emit();
+                                }
+                                (inner_ty, tcx.types.err)
+                            } else if let Some(rest) = size.checked_sub(min_len) {
+                                (inner_ty, tcx.mk_array(inner_ty, rest))
+                            } else {
+                                struct_span_err!(tcx.sess, pat.span, E0528,
+                                        "pattern requires at least {} elements but array has {}",
+                                        min_len, size)
+                                    .span_label(pat.span,
+                                        format!("pattern cannot match array of {} elements", size))
                                     .emit();
+                                (inner_ty, tcx.types.err)
                             }
-                            (inner_ty, tcx.types.err)
-                        } else if let Some(rest) = size.checked_sub(min_len) {
-                            (inner_ty, tcx.mk_array(inner_ty, rest))
                         } else {
-                            struct_span_err!(tcx.sess, pat.span, E0528,
-                                    "pattern requires at least {} elements but array has {}",
-                                    min_len, size)
-                                .span_label(pat.span,
-                                    format!("pattern cannot match array of {} elements", size))
-                                .emit();
+                            struct_span_err!(
+                                tcx.sess,
+                                pat.span,
+                                E0730,
+                                "cannot pattern-match on an array without a fixed length",
+                            ).emit();
                             (inner_ty, tcx.types.err)
                         }
                     }
@@ -1080,8 +1089,18 @@ fn check_pat_tuple_struct(
             let msg = format!("expected tuple struct/variant, found {} `{}`",
                               res.descr(),
                               hir::print::to_string(tcx.hir(), |s| s.print_qpath(qpath, false)));
-            struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg)
-                .span_label(pat.span, "not a tuple variant or struct").emit();
+            let mut err = struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg);
+            match (res, &pat.node) {
+                (Res::Def(DefKind::Fn, _), _) | (Res::Def(DefKind::Method, _), _) => {
+                    err.span_label(pat.span, "`fn` calls are not allowed in patterns");
+                    err.help("for more information, visit \
+                              https://doc.rust-lang.org/book/ch18-00-patterns.html");
+                }
+                _ => {
+                    err.span_label(pat.span, "not a tuple variant or struct");
+                }
+            }
+            err.emit();
             on_error();
         };
 
index 61c281d3dd9d22ed477045b5fb512e7a442f2683..a6cd157dc03de0f967c484e496d762bbef9e12a7 100644 (file)
@@ -350,7 +350,7 @@ fn confirm_builtin_call(
 
                     let def_span = match def {
                         Res::Err => None,
-                        Res::Local(id) | Res::Upvar(id, ..) => {
+                        Res::Local(id) => {
                             Some(self.tcx.hir().span_by_hir_id(id))
                         },
                         _ => def
index 1165890fe6432608df3e9d70f9dfd37c887f10b9..b4548ac70911e8224afbf1272d92e66dd3ecfdef 100644 (file)
@@ -385,7 +385,7 @@ fn check_region_bounds_on_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // the moment, give a kind of vague error message.
     if trait_params != impl_params {
         let def_span = tcx.sess.source_map().def_span(span);
-        let span = tcx.hir().get_generics_span(impl_m.def_id).unwrap_or(def_span);
+        let span = tcx.hir().get_generics(impl_m.def_id).map(|g| g.span).unwrap_or(def_span);
         let mut err = struct_span_err!(
             tcx.sess,
             span,
@@ -396,7 +396,7 @@ fn check_region_bounds_on_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         err.span_label(span, "lifetimes do not match method in trait");
         if let Some(sp) = tcx.hir().span_if_local(trait_m.def_id) {
             let def_sp = tcx.sess.source_map().def_span(sp);
-            let sp = tcx.hir().get_generics_span(trait_m.def_id).unwrap_or(def_sp);
+            let sp = tcx.hir().get_generics(trait_m.def_id).map(|g| g.span).unwrap_or(def_sp);
             err.span_label(sp, "lifetimes in impl do not match this method in trait");
         }
         err.emit();
@@ -583,7 +583,7 @@ fn compare_self_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 fn compare_number_of_generics<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     impl_: &ty::AssocItem,
-    impl_span: Span,
+    _impl_span: Span,
     trait_: &ty::AssocItem,
     trait_span: Option<Span>,
 ) -> Result<(), ErrorReported> {
@@ -600,17 +600,44 @@ fn compare_number_of_generics<'a, 'tcx>(
         if impl_count != trait_count {
             err_occurred = true;
 
-            let impl_hir_id = tcx.hir().as_local_hir_id(impl_.def_id).unwrap();
-            let impl_item = tcx.hir().expect_impl_item(impl_hir_id);
-            let span = if impl_item.generics.params.is_empty()
-                || impl_item.generics.span.is_dummy() { // argument position impl Trait (#55374)
-                impl_span
+            let (
+                trait_spans,
+                impl_trait_spans,
+            ) = if let Some(trait_hir_id) = tcx.hir().as_local_hir_id(trait_.def_id) {
+                let trait_item = tcx.hir().expect_trait_item(trait_hir_id);
+                if trait_item.generics.params.is_empty() {
+                    (Some(vec![trait_item.generics.span]), vec![])
+                } else {
+                    let arg_spans: Vec<Span> = trait_item.generics.params.iter()
+                        .map(|p| p.span)
+                        .collect();
+                    let impl_trait_spans: Vec<Span> = trait_item.generics.params.iter()
+                        .filter_map(|p| match p.kind {
+                            GenericParamKind::Type {
+                                synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), ..
+                            } => Some(p.span),
+                            _ => None,
+                        }).collect();
+                    (Some(arg_spans), impl_trait_spans)
+                }
             } else {
-                impl_item.generics.span
+                (trait_span.map(|s| vec![s]), vec![])
             };
 
+            let impl_hir_id = tcx.hir().as_local_hir_id(impl_.def_id).unwrap();
+            let impl_item = tcx.hir().expect_impl_item(impl_hir_id);
+            let impl_item_impl_trait_spans: Vec<Span> = impl_item.generics.params.iter()
+                .filter_map(|p| match p.kind {
+                    GenericParamKind::Type {
+                        synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), ..
+                    } => Some(p.span),
+                    _ => None,
+                }).collect();
+            let spans = impl_item.generics.spans();
+            let span = spans.primary_span();
+
             let mut err = tcx.sess.struct_span_err_with_code(
-                span,
+                spans,
                 &format!(
                     "method `{}` has {} {kind} parameter{} but its trait \
                      declaration has {} {kind} parameter{}",
@@ -626,22 +653,36 @@ fn compare_number_of_generics<'a, 'tcx>(
 
             let mut suffix = None;
 
-            if let Some(span) = trait_span {
-                err.span_label(
-                    span,
-                    format!("expected {} {} parameter{}", trait_count, kind,
-                        if trait_count != 1 { "s" } else { "" })
-                );
+            if let Some(spans) = trait_spans {
+                let mut spans = spans.iter();
+                if let Some(span) = spans.next() {
+                    err.span_label(*span, format!(
+                        "expected {} {} parameter{}",
+                        trait_count,
+                        kind,
+                        if trait_count != 1 { "s" } else { "" },
+                    ));
+                }
+                for span in spans {
+                    err.span_label(*span, "");
+                }
             } else {
                 suffix = Some(format!(", expected {}", trait_count));
             }
 
-            err.span_label(
-                span,
-                format!("found {} {} parameter{}{}", impl_count, kind,
+            if let Some(span) = span {
+                err.span_label(span, format!(
+                    "found {} {} parameter{}{}",
+                    impl_count,
+                    kind,
                     if impl_count != 1 { "s" } else { "" },
-                    suffix.unwrap_or_else(|| String::new())),
-            );
+                    suffix.unwrap_or_else(|| String::new()),
+                ));
+            }
+
+            for span in impl_trait_spans.iter().chain(impl_item_impl_trait_spans.iter()) {
+                err.span_label(*span, "`impl Trait` introduces an implicit type parameter");
+            }
 
             err.emit();
         }
index 7a6d02cc33b210cc3e93d06fa624f1e921d9059b..82d198f0b78f78cc7c0b91b357456b563a3d8c1d 100644 (file)
@@ -5264,7 +5264,7 @@ pub fn instantiate_value_path(&self,
             Err(ErrorReported) => return (tcx.types.err, res),
         };
         let path_segs = match res {
-            Res::Local(_) | Res::Upvar(..) => Vec::new(),
+            Res::Local(_) => vec![],
             Res::Def(kind, def_id) =>
                 AstConv::def_ids_for_value_path_segments(self, segments, self_ty, kind, def_id),
             _ => bug!("instantiate_value_path on {:?}", res),
@@ -5325,14 +5325,11 @@ pub fn instantiate_value_path(&self,
             }
         }));
 
-        match res {
-            Res::Local(hid) | Res::Upvar(hid, ..) => {
-                let ty = self.local_ty(span, hid).decl_ty;
-                let ty = self.normalize_associated_types_in(span, &ty);
-                self.write_ty(hir_id, ty);
-                return (ty, res);
-            }
-            _ => {}
+        if let Res::Local(hid) = res {
+            let ty = self.local_ty(span, hid).decl_ty;
+            let ty = self.normalize_associated_types_in(span, &ty);
+            self.write_ty(hir_id, ty);
+            return (ty, res);
         }
 
         if generics_has_err {
index 62c9c7c8b1c37d9446dd2c565d5f79e620a9a2e1..21d7e483e9d15fd12a24deebaa35657f321d961b 100644 (file)
@@ -200,6 +200,7 @@ pub struct RegionCtxt<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
 
     // id of innermost fn body id
     body_id: hir::HirId,
+    body_owner: DefId,
 
     // call_site scope of innermost fn
     call_site_scope: Option<region::Scope>,
@@ -236,6 +237,7 @@ pub fn new(
             region_scope_tree,
             repeating_scope: initial_repeating_scope,
             body_id: initial_body_id,
+            body_owner: subject,
             call_site_scope: None,
             subject_def_id: subject,
             outlives_environment,
@@ -308,6 +310,7 @@ fn visit_fn_body(
 
         let body_id = body.id();
         self.body_id = body_id.hir_id;
+        self.body_owner = self.tcx.hir().body_owner_def_id(body_id);
 
         let call_site = region::Scope {
             id: body.value.hir_id.local_id,
@@ -466,6 +469,7 @@ fn visit_fn(
         // Save state of current function before invoking
         // `visit_fn_body`.  We will restore afterwards.
         let old_body_id = self.body_id;
+        let old_body_owner = self.body_owner;
         let old_call_site_scope = self.call_site_scope;
         let env_snapshot = self.outlives_environment.push_snapshot_pre_closure();
 
@@ -477,6 +481,7 @@ fn visit_fn(
             .pop_snapshot_post_closure(env_snapshot);
         self.call_site_scope = old_call_site_scope;
         self.body_id = old_body_id;
+        self.body_owner = old_body_owner;
     }
 
     //visit_pat: visit_pat, // (..) see above
@@ -829,6 +834,7 @@ fn with_mc<F, R>(&self, f: F) -> R
     {
         f(mc::MemCategorizationContext::with_infer(
             &self.infcx,
+            self.body_owner,
             &self.region_scope_tree,
             &self.tables.borrow(),
         ))
index c3861f964e4534dfe39e7363ea07a2ec73ed0463..82c173a6f7a57e90b7abd44ee4a6e6353aaf6fb2 100644 (file)
@@ -41,6 +41,7 @@
 use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
 use rustc::infer::UpvarRegion;
 use rustc::ty::{self, Ty, TyCtxt, UpvarSubsts};
+use rustc_data_structures::fx::FxIndexMap;
 use syntax::ast;
 use syntax_pos::Span;
 
@@ -122,18 +123,19 @@ fn analyze_closure(
         };
 
         if let Some(upvars) = self.tcx.upvars(closure_def_id) {
-            let mut upvar_list: Vec<ty::UpvarId> = Vec::with_capacity(upvars.len());
-            for upvar in upvars.iter() {
+            let mut upvar_list: FxIndexMap<hir::HirId, ty::UpvarId> =
+                FxIndexMap::with_capacity_and_hasher(upvars.len(), Default::default());
+            for (&var_hir_id, _) in upvars.iter() {
                 let upvar_id = ty::UpvarId {
                     var_path: ty::UpvarPath {
-                        hir_id: upvar.var_id(),
+                        hir_id: var_hir_id,
                     },
                     closure_expr_id: LocalDefId::from_def_id(closure_def_id),
                 };
                 debug!("seed upvar_id {:?}", upvar_id);
                 // Adding the upvar Id to the list of Upvars, which will be added
                 // to the map for the closure at the end of the for loop.
-                upvar_list.push(upvar_id);
+                upvar_list.insert(var_hir_id, upvar_id);
 
                 let capture_kind = match capture_clause {
                     hir::CaptureByValue => ty::UpvarCapture::ByValue,
@@ -165,6 +167,7 @@ fn analyze_closure(
         }
 
         let body_owner_def_id = self.tcx.hir().body_owner_def_id(body.id());
+        assert_eq!(body_owner_def_id, closure_def_id);
         let region_scope_tree = &self.tcx.region_scope_tree(body_owner_def_id);
         let mut delegate = InferBorrowKind {
             fcx: self,
@@ -176,6 +179,7 @@ fn analyze_closure(
         euv::ExprUseVisitor::with_infer(
             &mut delegate,
             &self.infcx,
+            body_owner_def_id,
             self.param_env,
             region_scope_tree,
             &self.tables.borrow(),
@@ -249,8 +253,7 @@ fn final_upvar_tys(&self, closure_id: hir::HirId) -> Vec<Ty<'tcx>> {
         tcx.upvars(closure_def_id).iter().flat_map(|upvars| {
             upvars
                 .iter()
-                .map(|upvar| {
-                    let var_hir_id = upvar.var_id();
+                .map(|(&var_hir_id, _)| {
                     let upvar_ty = self.node_ty(var_hir_id);
                     let upvar_id = ty::UpvarId {
                         var_path: ty::UpvarPath { hir_id: var_hir_id },
index a856013b719fea3708e40c6f5d60454fadb7f950..a535f776dfe602c336e9b7a3b85792a637821795 100644 (file)
@@ -54,7 +54,6 @@ pub fn resolve_type_vars_in_body(&self, body: &'gcx hir::Body) -> &'gcx ty::Type
         }
         wbcx.visit_body(body);
         wbcx.visit_upvar_capture_map();
-        wbcx.visit_upvar_list_map();
         wbcx.visit_closures();
         wbcx.visit_liberated_fn_sigs();
         wbcx.visit_fru_field_types();
@@ -74,6 +73,11 @@ pub fn resolve_type_vars_in_body(&self, body: &'gcx hir::Body) -> &'gcx ty::Type
         );
         wbcx.tables.used_trait_imports = used_trait_imports;
 
+        wbcx.tables.upvar_list = mem::replace(
+            &mut self.tables.borrow_mut().upvar_list,
+            Default::default(),
+        );
+
         wbcx.tables.tainted_by_errors = self.is_tainted_by_errors();
 
         debug!(
@@ -81,7 +85,7 @@ pub fn resolve_type_vars_in_body(&self, body: &'gcx hir::Body) -> &'gcx ty::Type
             item_def_id, wbcx.tables
         );
 
-        self.tcx.alloc_tables(wbcx.tables)
+        self.tcx.arena.alloc(wbcx.tables)
     }
 }
 
@@ -343,21 +347,6 @@ fn visit_upvar_capture_map(&mut self) {
         }
     }
 
-    /// Runs through the function context's upvar list map and adds the same to
-    /// the TypeckTables. upvarlist is a hashmap of the list of upvars referred
-    /// to in a closure..
-    fn visit_upvar_list_map(&mut self) {
-        for (closure_def_id, upvar_list) in self.fcx.tables.borrow().upvar_list.iter() {
-            debug!(
-                "UpvarIDs captured by closure {:?} are: {:?}",
-                closure_def_id, upvar_list
-            );
-            self.tables
-                .upvar_list
-                .insert(*closure_def_id, upvar_list.to_vec());
-        }
-    }
-
     fn visit_closures(&mut self) {
         let fcx_tables = self.fcx.tables.borrow();
         debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root);
index 3806fd0998b5e8785c16f3b1c77d44a61d4c14f4..c516fbc3bb940ad44460bc716da7e04cf5588e7c 100644 (file)
@@ -763,7 +763,7 @@ fn trait_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::
     let is_marker = tcx.has_attr(def_id, sym::marker);
     let def_path_hash = tcx.def_path_hash(def_id);
     let def = ty::TraitDef::new(def_id, unsafety, paren_sugar, is_auto, is_marker, def_path_hash);
-    tcx.alloc_trait_def(def)
+    tcx.arena.alloc(def)
 }
 
 fn has_late_bound_regions<'a, 'tcx>(
@@ -1110,7 +1110,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty
         .map(|param| (param.def_id, param.index))
         .collect();
 
-    tcx.alloc_generics(ty::Generics {
+    tcx.arena.alloc(ty::Generics {
         parent: parent_def_id,
         parent_count,
         params,
index 6dd3c0113cdcda97b48e906a35fb8731557726fe..b5a50f43875816debe1ef11b32b13a456dcc7cd1 100644 (file)
@@ -4648,6 +4648,38 @@ fn make_recursive_type() -> impl Sized {
 ```
 "##,
 
+E0730: r##"
+An array without a fixed length was pattern-matched.
+
+Example of erroneous code:
+
+```compile_fail,E0730
+#![feature(const_generics)]
+
+fn is_123<const N: usize>(x: [u32; N]) -> bool {
+    match x {
+        [1, 2, 3] => true, // error: cannot pattern-match on an
+                           //        array without a fixed length
+        _ => false
+    }
+}
+```
+
+Ensure that the pattern is consistent with the size of the matched
+array. Additional elements can be matched with `..`:
+
+```
+#![feature(slice_patterns)]
+
+let r = &[1, 2, 3, 4];
+match r {
+    &[a, b, ..] => { // ok!
+        println!("a={}, b={}", a, b);
+    }
+}
+```
+"##,
+
 }
 
 register_diagnostics! {
index efb59c22012bcaad76c538ae27480bca5aee74b8..3555e2e7498b8c1ead3c20043b21d143f6c61cc0 100644 (file)
@@ -3804,7 +3804,7 @@ fn render_attributes(w: &mut dyn fmt::Write, it: &clean::Item, top: bool) -> fmt
         }
     }
     if attrs.len() > 0 {
-        write!(w, "<div class=\"docblock attributes{}\">{}</div>",
+        write!(w, "<span class=\"docblock attributes{}\">{}</span>",
                if top { " top-attr" } else { "" }, &attrs)?;
     }
     Ok(())
index 72a01a49bc66dc2d8ddaf1cda6195062f2bea2eb..82d2c11b2497befb13364d48c7f1c2d5971d37e5 100644 (file)
@@ -162,8 +162,15 @@ if (!DOMTokenList.prototype.remove) {
         var i, from, to, match = window.location.hash.match(/^#?(\d+)(?:-(\d+))?$/);
         if (match) {
             from = parseInt(match[1], 10);
-            to = Math.min(50000, parseInt(match[2] || match[1], 10));
-            from = Math.min(from, to);
+            to = from;
+            if (typeof match[2] !== "undefined") {
+                to = parseInt(match[2], 10);
+            }
+            if (to < from) {
+                var tmp = to;
+                to = from;
+                from = tmp;
+            }
             elem = document.getElementById(from);
             if (!elem) {
                 return;
@@ -180,7 +187,11 @@ if (!DOMTokenList.prototype.remove) {
                 });
             });
             for (i = from; i <= to; ++i) {
-                addClass(document.getElementById(i), "line-highlighted");
+                elem = document.getElementById(i);
+                if (!elem) {
+                    break;
+                }
+                addClass(elem, "line-highlighted");
             }
         } else if (ev !== null && search && !hasClass(search, "hidden") && ev.newURL) {
             addClass(search, "hidden");
index 949af0e2b97464a9c030c054cb9fca16b004569e..fa31a68a75b720b0e320f4320e6465316b645661 100644 (file)
@@ -10,4 +10,5 @@ path = "lib.rs"
 crate-type = ["dylib", "rlib"]
 
 [dependencies]
+indexmap = "1"
 smallvec = { version = "0.6.7", features = ["union", "may_dangle"] }
index c0a8fa9d0016dba395a62aa036d90b78f6b54e9c..80aeecb84d72bb8720d74a89c00a8c06b0036f30 100644 (file)
@@ -217,6 +217,75 @@ fn decode<D: Decoder>(d: &mut D) -> Result<HashSet<T, S>, D::Error> {
     }
 }
 
+impl<K, V, S> Encodable for indexmap::IndexMap<K, V, S>
+    where K: Encodable + Hash + Eq,
+          V: Encodable,
+          S: BuildHasher,
+{
+    fn encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
+        e.emit_map(self.len(), |e| {
+            let mut i = 0;
+            for (key, val) in self {
+                e.emit_map_elt_key(i, |e| key.encode(e))?;
+                e.emit_map_elt_val(i, |e| val.encode(e))?;
+                i += 1;
+            }
+            Ok(())
+        })
+    }
+}
+
+impl<K, V, S> Decodable for indexmap::IndexMap<K, V, S>
+    where K: Decodable + Hash + Eq,
+          V: Decodable,
+          S: BuildHasher + Default,
+{
+    fn decode<D: Decoder>(d: &mut D) -> Result<indexmap::IndexMap<K, V, S>, D::Error> {
+        d.read_map(|d, len| {
+            let state = Default::default();
+            let mut map = indexmap::IndexMap::with_capacity_and_hasher(len, state);
+            for i in 0..len {
+                let key = d.read_map_elt_key(i, |d| Decodable::decode(d))?;
+                let val = d.read_map_elt_val(i, |d| Decodable::decode(d))?;
+                map.insert(key, val);
+            }
+            Ok(map)
+        })
+    }
+}
+
+impl<T, S> Encodable for indexmap::IndexSet<T, S>
+    where T: Encodable + Hash + Eq,
+          S: BuildHasher,
+{
+    fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> {
+        s.emit_seq(self.len(), |s| {
+            let mut i = 0;
+            for e in self {
+                s.emit_seq_elt(i, |s| e.encode(s))?;
+                i += 1;
+            }
+            Ok(())
+        })
+    }
+}
+
+impl<T, S> Decodable for indexmap::IndexSet<T, S>
+    where T: Decodable + Hash + Eq,
+          S: BuildHasher + Default,
+{
+    fn decode<D: Decoder>(d: &mut D) -> Result<indexmap::IndexSet<T, S>, D::Error> {
+        d.read_seq(|d, len| {
+            let state = Default::default();
+            let mut set = indexmap::IndexSet::with_capacity_and_hasher(len, state);
+            for i in 0..len {
+                set.insert(d.read_seq_elt(i, |d| Decodable::decode(d))?);
+            }
+            Ok(set)
+        })
+    }
+}
+
 impl<T: Encodable> Encodable for Rc<[T]> {
     fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> {
         s.emit_seq(self.len(), |s| {
index d22dc9a71a40f110682bb3da5dc00b93a741f72d..cf1dbba0055255883c4096d52520efea6c7983ec 100644 (file)
@@ -22,7 +22,7 @@ libc = { version = "0.2.51", default-features = false, features = ['rustc-dep-of
 compiler_builtins = { version = "0.1.15" }
 profiler_builtins = { path = "../libprofiler_builtins", optional = true }
 unwind = { path = "../libunwind" }
-hashbrown = { version = "0.3.0", features = ['rustc-dep-of-std'] }
+hashbrown = { version = "0.4.0", features = ['rustc-dep-of-std'] }
 
 [dependencies.backtrace]
 version = "0.3.25"
index c8978a94fcda46507e007c3cdf58fc0bfaadc453..5cc7dcdae1fcd5917db45d4210891758b3041df4 100644 (file)
@@ -314,7 +314,6 @@ impl From<String> for Box<dyn Error + Send + Sync> {
     ///     mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
     /// ```
     fn from(err: String) -> Box<dyn Error + Send + Sync> {
-        #[derive(Debug)]
         struct StringError(String);
 
         impl Error for StringError {
@@ -327,6 +326,13 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             }
         }
 
+        // Purposefully skip printing "StringError(..)"
+        impl Debug for StringError {
+            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+                Debug::fmt(&self.0, f)
+            }
+        }
+
         Box::new(StringError(err))
     }
 }
index 9af7bba97aa58de06daab2106874f17909a16cd6..ef7179f0b6f90ae068dd0f67715c06ee40bf3532 100644 (file)
@@ -405,7 +405,7 @@ mod builtin {
     ///
     /// ```compile_fail
     /// #[cfg(not(any(feature = "foo", feature = "bar")))]
-    /// compile_error!("Either feature \"foo\" or \"bar\" must be enabled for this crate.")
+    /// compile_error!("Either feature \"foo\" or \"bar\" must be enabled for this crate.");
     /// ```
     ///
     /// [`panic!`]: ../std/macro.panic.html
index 7f9f3b91a600b49c9e0c19c3d78ba346a5d9a9ec..6b504056e5f879eb75705e88a0218824eced26ef 100644 (file)
@@ -502,12 +502,19 @@ pub fn is_link_local(&self) -> bool {
     ///
     /// The following return false:
     ///
-    /// - private address (10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16)
-    /// - the loopback address (127.0.0.0/8)
-    /// - the link-local address (169.254.0.0/16)
-    /// - the broadcast address (255.255.255.255/32)
-    /// - test addresses used for documentation (192.0.2.0/24, 198.51.100.0/24 and 203.0.113.0/24)
-    /// - the unspecified address (0.0.0.0)
+    /// - private addresses (see [`is_private()`](#method.is_private))
+    /// - the loopback address (see [`is_loopback()`](#method.is_loopback))
+    /// - the link-local address (see [`is_link_local()`](#method.is_link_local))
+    /// - the broadcast address (see [`is_broadcast()`](#method.is_broadcast))
+    /// - addresses used for documentation (see [`is_documentation()`](#method.is_documentation))
+    /// - the unspecified address (see [`is_unspecified()`](#method.is_unspecified)), and the whole
+    ///   0.0.0.0/8 block
+    /// - addresses reserved for future protocols (see
+    /// [`is_ietf_protocol_assignment()`](#method.is_ietf_protocol_assignment), except
+    /// `192.0.0.9/32` and `192.0.0.10/32` which are globally routable
+    /// - addresses reserved for future use (see [`is_reserved()`](#method.is_reserved)
+    /// - addresses reserved for networking devices benchmarking (see
+    /// [`is_benchmarking`](#method.is_benchmarking))
     ///
     /// [ipv4-sr]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
     /// [`true`]: ../../std/primitive.bool.html
@@ -520,16 +527,181 @@ pub fn is_link_local(&self) -> bool {
     /// use std::net::Ipv4Addr;
     ///
     /// fn main() {
+    ///     // private addresses are not global
     ///     assert_eq!(Ipv4Addr::new(10, 254, 0, 0).is_global(), false);
     ///     assert_eq!(Ipv4Addr::new(192, 168, 10, 65).is_global(), false);
     ///     assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_global(), false);
+    ///
+    ///     // the 0.0.0.0/8 block is not global
+    ///     assert_eq!(Ipv4Addr::new(0, 1, 2, 3).is_global(), false);
+    ///     // in particular, the unspecified address is not global
     ///     assert_eq!(Ipv4Addr::new(0, 0, 0, 0).is_global(), false);
+    ///
+    ///     // the loopback address is not global
+    ///     assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_global(), false);
+    ///
+    ///     // link local addresses are not global
+    ///     assert_eq!(Ipv4Addr::new(169, 254, 45, 1).is_global(), false);
+    ///
+    ///     // the broadcast address is not global
+    ///     assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_global(), false);
+    ///
+    ///     // the broadcast address is not global
+    ///     assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_global(), false);
+    ///     assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_global(), false);
+    ///     assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_global(), false);
+    ///
+    ///     // shared addresses are not global
+    ///     assert_eq!(Ipv4Addr::new(100, 100, 0, 0).is_global(), false);
+    ///
+    ///     // addresses reserved for protocol assignment are not global
+    ///     assert_eq!(Ipv4Addr::new(192, 0, 0, 0).is_global(), false);
+    ///     assert_eq!(Ipv4Addr::new(192, 0, 0, 255).is_global(), false);
+    ///
+    ///     // addresses reserved for future use are not global
+    ///     assert_eq!(Ipv4Addr::new(250, 10, 20, 30).is_global(), false);
+    ///
+    ///     // addresses reserved for network devices benchmarking are not global
+    ///     assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_global(), false);
+    ///
+    ///     // All the other addresses are global
+    ///     assert_eq!(Ipv4Addr::new(1, 1, 1, 1).is_global(), true);
     ///     assert_eq!(Ipv4Addr::new(80, 9, 12, 3).is_global(), true);
     /// }
     /// ```
     pub fn is_global(&self) -> bool {
-        !self.is_private() && !self.is_loopback() && !self.is_link_local() &&
-        !self.is_broadcast() && !self.is_documentation() && !self.is_unspecified()
+        // check if this address is 192.0.0.9 or 192.0.0.10. These addresses are the only two
+        // globally routable addresses in the 192.0.0.0/24 range.
+        if u32::from(*self) == 0xc0000009 || u32::from(*self) == 0xc000000a {
+            return true;
+        }
+        !self.is_private()
+            && !self.is_loopback()
+            && !self.is_link_local()
+            && !self.is_broadcast()
+            && !self.is_documentation()
+            && !self.is_shared()
+            && !self.is_ietf_protocol_assignment()
+            && !self.is_reserved()
+            && !self.is_benchmarking()
+            // Make sure the address is not in 0.0.0.0/8
+            && self.octets()[0] != 0
+    }
+
+    /// Returns [`true`] if this address is part of the Shared Address Space defined in
+    /// [IETF RFC 6598] (`100.64.0.0/10`).
+    ///
+    /// [IETF RFC 6598]: https://tools.ietf.org/html/rfc6598
+    /// [`true`]: ../../std/primitive.bool.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ip)]
+    /// use std::net::Ipv4Addr;
+    ///
+    /// fn main() {
+    ///     assert_eq!(Ipv4Addr::new(100, 64, 0, 0).is_shared(), true);
+    ///     assert_eq!(Ipv4Addr::new(100, 127, 255, 255).is_shared(), true);
+    ///     assert_eq!(Ipv4Addr::new(100, 128, 0, 0).is_shared(), false);
+    /// }
+    /// ```
+    pub fn is_shared(&self) -> bool {
+        self.octets()[0] == 100 && (self.octets()[1] & 0b1100_0000 == 0b0100_0000)
+    }
+
+    /// Returns [`true`] if this address is part of `192.0.0.0/24`, which is reserved to
+    /// IANA for IETF protocol assignments, as documented in [IETF RFC 6890].
+    ///
+    /// Note that parts of this block are in use:
+    ///
+    /// - `192.0.0.8/32` is the "IPv4 dummy address" (see [IETF RFC 7600])
+    /// - `192.0.0.9/32` is the "Port Control Protocol Anycast" (see [IETF RFC 7723])
+    /// - `192.0.0.10/32` is used for NAT traversal (see [IETF RFC 8155])
+    ///
+    /// [IETF RFC 6890]: https://tools.ietf.org/html/rfc6890
+    /// [IETF RFC 7600]: https://tools.ietf.org/html/rfc7600
+    /// [IETF RFC 7723]: https://tools.ietf.org/html/rfc7723
+    /// [IETF RFC 8155]: https://tools.ietf.org/html/rfc8155
+    /// [`true`]: ../../std/primitive.bool.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ip)]
+    /// use std::net::Ipv4Addr;
+    ///
+    /// fn main() {
+    ///     assert_eq!(Ipv4Addr::new(192, 0, 0, 0).is_ietf_protocol_assignment(), true);
+    ///     assert_eq!(Ipv4Addr::new(192, 0, 0, 8).is_ietf_protocol_assignment(), true);
+    ///     assert_eq!(Ipv4Addr::new(192, 0, 0, 9).is_ietf_protocol_assignment(), true);
+    ///     assert_eq!(Ipv4Addr::new(192, 0, 0, 255).is_ietf_protocol_assignment(), true);
+    ///     assert_eq!(Ipv4Addr::new(192, 0, 1, 0).is_ietf_protocol_assignment(), false);
+    ///     assert_eq!(Ipv4Addr::new(191, 255, 255, 255).is_ietf_protocol_assignment(), false);
+    /// }
+    /// ```
+    pub fn is_ietf_protocol_assignment(&self) -> bool {
+        self.octets()[0] == 192 && self.octets()[1] == 0 && self.octets()[2] == 0
+    }
+
+    /// Returns [`true`] if this address part of the `198.18.0.0/15` range, which is reserved for
+    /// network devices benchmarking. This range is defined in [IETF RFC 2544] as `192.18.0.0`
+    /// through `198.19.255.255` but [errata 423] corrects it to `198.18.0.0/15`.
+    ///
+    /// [IETF RFC 1112]: https://tools.ietf.org/html/rfc1112
+    /// [errate 423]: https://www.rfc-editor.org/errata/eid423
+    /// [`true`]: ../../std/primitive.bool.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ip)]
+    /// use std::net::Ipv4Addr;
+    ///
+    /// fn main() {
+    ///     assert_eq!(Ipv4Addr::new(198, 17, 255, 255).is_benchmarking(), false);
+    ///     assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_benchmarking(), true);
+    ///     assert_eq!(Ipv4Addr::new(198, 19, 255, 255).is_benchmarking(), true);
+    ///     assert_eq!(Ipv4Addr::new(198, 20, 0, 0).is_benchmarking(), false);
+    /// }
+    /// ```
+    pub fn is_benchmarking(&self) -> bool {
+        self.octets()[0] == 198 && (self.octets()[1] & 0xfe) == 18
+    }
+
+    /// Returns [`true`] if this address is reserved by IANA for future use. [IETF RFC 1112]
+    /// defines the block of reserved addresses as `240.0.0.0/4`. This range normally includes the
+    /// broadcast address `255.255.255.255`, but this implementation explicitely excludes it, since
+    /// it is obviously not reserved for future use.
+    ///
+    /// [IETF RFC 1112]: https://tools.ietf.org/html/rfc1112
+    /// [`true`]: ../../std/primitive.bool.html
+    ///
+    /// # Warning
+    ///
+    /// As IANA assigns new addresses, this method will be
+    /// updated. This may result in non-reserved addresses being
+    /// treated as reserved in code that relies on an outdated version
+    /// of this method.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ip)]
+    /// use std::net::Ipv4Addr;
+    ///
+    /// fn main() {
+    ///     assert_eq!(Ipv4Addr::new(240, 0, 0, 0).is_reserved(), true);
+    ///     assert_eq!(Ipv4Addr::new(255, 255, 255, 254).is_reserved(), true);
+    ///
+    ///     assert_eq!(Ipv4Addr::new(239, 255, 255, 255).is_reserved(), false);
+    ///     // The broadcast address is not considered as reserved for future use by this
+    ///     // implementation
+    ///     assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_reserved(), false);
+    /// }
+    /// ```
+    pub fn is_reserved(&self) -> bool {
+        self.octets()[0] & 240 == 240 && !self.is_broadcast()
     }
 
     /// Returns [`true`] if this is a multicast address (224.0.0.0/4).
@@ -1003,7 +1175,7 @@ pub fn is_global(&self) -> bool {
         }
     }
 
-    /// Returns [`true`] if this is a unique local address (fc00::/7).
+    /// Returns [`true`] if this is a unique local address (`fc00::/7`).
     ///
     /// This property is defined in [IETF RFC 4193].
     ///
@@ -1027,12 +1199,83 @@ pub fn is_unique_local(&self) -> bool {
         (self.segments()[0] & 0xfe00) == 0xfc00
     }
 
-    /// Returns [`true`] if the address is unicast and link-local (fe80::/10).
+    /// Returns [`true`] if the address is a unicast link-local address (`fe80::/64`).
     ///
-    /// This property is defined in [IETF RFC 4291].
+    /// A common mis-conception is to think that "unicast link-local addresses start with
+    /// `fe80::`", but the [IETF RFC 4291] actually defines a stricter format for these addresses:
+    ///
+    /// ```no_rust
+    /// |   10     |
+    /// |  bits    |         54 bits         |          64 bits           |
+    /// +----------+-------------------------+----------------------------+
+    /// |1111111010|           0             |       interface ID         |
+    /// +----------+-------------------------+----------------------------+
+    /// ```
+    ///
+    /// This method validates the format defined in the RFC and won't recognize the following
+    /// addresses such as `fe80:0:0:1::` or `fe81::` as unicast link-local addresses for example.
+    /// If you need a less strict validation use [`is_unicast_link_local()`] instead.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(ip)]
+    ///
+    /// use std::net::Ipv6Addr;
+    ///
+    /// fn main() {
+    ///     let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0);
+    ///     assert!(ip.is_unicast_link_local_strict());
+    ///
+    ///     let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0xffff, 0xffff, 0xffff, 0xffff);
+    ///     assert!(ip.is_unicast_link_local_strict());
+    ///
+    ///     let ip = Ipv6Addr::new(0xfe80, 0, 0, 1, 0, 0, 0, 0);
+    ///     assert!(!ip.is_unicast_link_local_strict());
+    ///     assert!(ip.is_unicast_link_local());
+    ///
+    ///     let ip = Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 0);
+    ///     assert!(!ip.is_unicast_link_local_strict());
+    ///     assert!(ip.is_unicast_link_local());
+    /// }
+    /// ```
+    ///
+    /// # See also
+    ///
+    /// - [IETF RFC 4291 section 2.5.6]
+    /// - [RFC 4291 errata 4406]
+    /// - [`is_unicast_link_local()`]
     ///
     /// [IETF RFC 4291]: https://tools.ietf.org/html/rfc4291
+    /// [IETF RFC 4291 section 2.5.6]: https://tools.ietf.org/html/rfc4291#section-2.5.6
     /// [`true`]: ../../std/primitive.bool.html
+    /// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406
+    /// [`is_unicast_link_local()`]: ../../std/net/struct.Ipv6Addr.html#method.is_unicast_link_local
+    ///
+    pub fn is_unicast_link_local_strict(&self) -> bool {
+        (self.segments()[0] & 0xffff) == 0xfe80
+            && (self.segments()[1] & 0xffff) == 0
+            && (self.segments()[2] & 0xffff) == 0
+            && (self.segments()[3] & 0xffff) == 0
+    }
+
+    /// Returns [`true`] if the address is a unicast link-local address (`fe80::/10`).
+    ///
+    /// This method returns [`true`] for addresses in the range reserved by [RFC 4291 section 2.4],
+    /// i.e. addresses with the following format:
+    ///
+    /// ```no_rust
+    /// |   10     |
+    /// |  bits    |         54 bits         |          64 bits           |
+    /// +----------+-------------------------+----------------------------+
+    /// |1111111010|    arbitratry value     |       interface ID         |
+    /// +----------+-------------------------+----------------------------+
+    /// ```
+    ///
+    /// As a result, this method consider addresses such as `fe80:0:0:1::` or `fe81::` to be
+    /// unicast link-local addresses, whereas [`is_unicast_link_local_strict()`] does not. If you
+    /// need a strict validation fully compliant with the RFC, use
+    /// [`is_unicast_link_local_strict()`].
     ///
     /// # Examples
     ///
@@ -1042,19 +1285,49 @@ pub fn is_unique_local(&self) -> bool {
     /// use std::net::Ipv6Addr;
     ///
     /// fn main() {
-    ///     assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_unicast_link_local(),
-    ///                false);
-    ///     assert_eq!(Ipv6Addr::new(0xfe8a, 0, 0, 0, 0, 0, 0, 0).is_unicast_link_local(), true);
+    ///     let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 0);
+    ///     assert!(ip.is_unicast_link_local());
+    ///
+    ///     let ip = Ipv6Addr::new(0xfe80, 0, 0, 0, 0xffff, 0xffff, 0xffff, 0xffff);
+    ///     assert!(ip.is_unicast_link_local());
+    ///
+    ///     let ip = Ipv6Addr::new(0xfe80, 0, 0, 1, 0, 0, 0, 0);
+    ///     assert!(ip.is_unicast_link_local());
+    ///     assert!(!ip.is_unicast_link_local_strict());
+    ///
+    ///     let ip = Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 0);
+    ///     assert!(ip.is_unicast_link_local());
+    ///     assert!(!ip.is_unicast_link_local_strict());
     /// }
     /// ```
+    ///
+    /// # See also
+    ///
+    /// - [IETF RFC 4291 section 2.4]
+    /// - [RFC 4291 errata 4406]
+    ///
+    /// [IETF RFC 4291 section 2.4]: https://tools.ietf.org/html/rfc4291#section-2.4
+    /// [`true`]: ../../std/primitive.bool.html
+    /// [RFC 4291 errata 4406]: https://www.rfc-editor.org/errata/eid4406
+    /// [`is_unicast_link_local_strict()`]: ../../std/net/struct.Ipv6Addr.html#method.is_unicast_link_local_strict
+    ///
     pub fn is_unicast_link_local(&self) -> bool {
         (self.segments()[0] & 0xffc0) == 0xfe80
     }
 
-    /// Returns [`true`] if this is a deprecated unicast site-local address
-    /// (fec0::/10).
+    /// Returns [`true`] if this is a deprecated unicast site-local address (fec0::/10). The
+    /// unicast site-local address format is defined in [RFC 4291 section 2.5.7] as:
+    ///
+    /// ```no_rust
+    /// |   10     |
+    /// |  bits    |         54 bits         |         64 bits            |
+    /// +----------+-------------------------+----------------------------+
+    /// |1111111011|        subnet ID        |       interface ID         |
+    /// +----------+-------------------------+----------------------------+
+    /// ```
     ///
     /// [`true`]: ../../std/primitive.bool.html
+    /// [RFC 4291 section 2.5.7]: https://tools.ietf.org/html/rfc4291#section-2.5.7
     ///
     /// # Examples
     ///
@@ -1069,6 +1342,14 @@ pub fn is_unicast_link_local(&self) -> bool {
     ///     assert_eq!(Ipv6Addr::new(0xfec2, 0, 0, 0, 0, 0, 0, 0).is_unicast_site_local(), true);
     /// }
     /// ```
+    ///
+    /// # Warning
+    ///
+    /// As per [RFC 3879], the whole `FEC0::/10` prefix is
+    /// deprecated. New software must not support site-local
+    /// addresses.
+    ///
+    /// [RFC 3879]: https://tools.ietf.org/html/rfc3879
     pub fn is_unicast_site_local(&self) -> bool {
         (self.segments()[0] & 0xffc0) == 0xfec0
     }
@@ -1104,12 +1385,20 @@ pub fn is_documentation(&self) -> bool {
     ///
     /// - the loopback address
     /// - the link-local addresses
-    /// - the (deprecated) site-local addresses
     /// - unique local addresses
     /// - the unspecified address
     /// - the address range reserved for documentation
     ///
+    /// This method returns [`true`] for site-local addresses as per [RFC 4291 section 2.5.7]
+    ///
+    /// ```no_rust
+    /// The special behavior of [the site-local unicast] prefix defined in [RFC3513] must no longer
+    /// be supported in new implementations (i.e., new implementations must treat this prefix as
+    /// Global Unicast).
+    /// ```
+    ///
     /// [`true`]: ../../std/primitive.bool.html
+    /// [RFC 4291 section 2.5.7]: https://tools.ietf.org/html/rfc4291#section-2.5.7
     ///
     /// # Examples
     ///
@@ -1126,9 +1415,11 @@ pub fn is_documentation(&self) -> bool {
     /// ```
     pub fn is_unicast_global(&self) -> bool {
         !self.is_multicast()
-            && !self.is_loopback() && !self.is_unicast_link_local()
-            && !self.is_unicast_site_local() && !self.is_unique_local()
-            && !self.is_unspecified() && !self.is_documentation()
+            && !self.is_loopback()
+            && !self.is_unicast_link_local()
+            && !self.is_unique_local()
+            && !self.is_unspecified()
+            && !self.is_documentation()
     }
 
     /// Returns the address's multicast scope if the address is multicast.
@@ -1510,8 +1801,8 @@ fn from(ip: u128) -> Ipv6Addr {
 #[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
     use crate::net::*;
-    use crate::net::Ipv6MulticastScope::*;
     use crate::net::test::{tsa, sa6, sa4};
+    use crate::str::FromStr;
 
     #[test]
     fn test_from_str_ipv4() {
@@ -1675,164 +1966,491 @@ fn ipv6_to_ipv4() {
 
     #[test]
     fn ip_properties() {
-        fn check4(octets: &[u8; 4], unspec: bool, loopback: bool,
-                  global: bool, multicast: bool, documentation: bool) {
-            let ip = IpAddr::V4(Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3]));
-            assert_eq!(ip.is_unspecified(), unspec);
-            assert_eq!(ip.is_loopback(), loopback);
-            assert_eq!(ip.is_global(), global);
-            assert_eq!(ip.is_multicast(), multicast);
-            assert_eq!(ip.is_documentation(), documentation);
+        macro_rules! ip {
+            ($s:expr) => {
+                IpAddr::from_str($s).unwrap()
+            }
         }
 
-        fn check6(str_addr: &str, unspec: bool, loopback: bool,
-                  global: bool, u_doc: bool, mcast: bool) {
-            let ip = IpAddr::V6(str_addr.parse().unwrap());
-            assert_eq!(ip.is_unspecified(), unspec);
-            assert_eq!(ip.is_loopback(), loopback);
-            assert_eq!(ip.is_global(), global);
-            assert_eq!(ip.is_documentation(), u_doc);
-            assert_eq!(ip.is_multicast(), mcast);
+        macro_rules! check {
+            ($s:expr) => {
+                check!($s, 0);
+            };
+
+            ($s:expr, $mask:expr) => {{
+                let unspec: u8 = 1 << 0;
+                let loopback: u8 = 1 << 1;
+                let global: u8 = 1 << 2;
+                let multicast: u8 = 1 << 3;
+                let doc: u8 = 1 << 4;
+
+                if ($mask & unspec) == unspec {
+                    assert!(ip!($s).is_unspecified());
+                } else {
+                    assert!(!ip!($s).is_unspecified());
+                }
+
+                if ($mask & loopback) == loopback {
+                    assert!(ip!($s).is_loopback());
+                } else {
+                    assert!(!ip!($s).is_loopback());
+                }
+
+                if ($mask & global) == global {
+                    assert!(ip!($s).is_global());
+                } else {
+                    assert!(!ip!($s).is_global());
+                }
+
+                if ($mask & multicast) == multicast {
+                    assert!(ip!($s).is_multicast());
+                } else {
+                    assert!(!ip!($s).is_multicast());
+                }
+
+                if ($mask & doc) == doc {
+                    assert!(ip!($s).is_documentation());
+                } else {
+                    assert!(!ip!($s).is_documentation());
+                }
+            }}
         }
 
-        //     address                unspec loopbk global multicast doc
-        check4(&[0, 0, 0, 0],         true,  false, false,  false,   false);
-        check4(&[0, 0, 0, 1],         false, false, true,   false,   false);
-        check4(&[0, 1, 0, 0],         false, false, true,   false,   false);
-        check4(&[10, 9, 8, 7],        false, false, false,  false,   false);
-        check4(&[127, 1, 2, 3],       false, true,  false,  false,   false);
-        check4(&[172, 31, 254, 253],  false, false, false,  false,   false);
-        check4(&[169, 254, 253, 242], false, false, false,  false,   false);
-        check4(&[192, 0, 2, 183],     false, false, false,  false,   true);
-        check4(&[192, 1, 2, 183],     false, false, true,   false,   false);
-        check4(&[192, 168, 254, 253], false, false, false,  false,   false);
-        check4(&[198, 51, 100, 0],    false, false, false,  false,   true);
-        check4(&[203, 0, 113, 0],     false, false, false,  false,   true);
-        check4(&[203, 2, 113, 0],     false, false, true,   false,   false);
-        check4(&[224, 0, 0, 0],       false, false, true,   true,    false);
-        check4(&[239, 255, 255, 255], false, false, true,   true,    false);
-        check4(&[255, 255, 255, 255], false, false, false,  false,   false);
-
-        //     address                            unspec loopbk global doc    mcast
-        check6("::",                              true,  false, false, false, false);
-        check6("::1",                             false, true,  false, false, false);
-        check6("::0.0.0.2",                       false, false, true,  false, false);
-        check6("1::",                             false, false, true,  false, false);
-        check6("fc00::",                          false, false, false, false, false);
-        check6("fdff:ffff::",                     false, false, false, false, false);
-        check6("fe80:ffff::",                     false, false, false, false, false);
-        check6("febf:ffff::",                     false, false, false, false, false);
-        check6("fec0::",                          false, false, false, false, false);
-        check6("ff01::",                          false, false, false, false, true);
-        check6("ff02::",                          false, false, false, false, true);
-        check6("ff03::",                          false, false, false, false, true);
-        check6("ff04::",                          false, false, false, false, true);
-        check6("ff05::",                          false, false, false, false, true);
-        check6("ff08::",                          false, false, false, false, true);
-        check6("ff0e::",                          false, false, true,  false, true);
-        check6("2001:db8:85a3::8a2e:370:7334",    false, false, false, true,  false);
-        check6("102:304:506:708:90a:b0c:d0e:f10", false, false, true,  false, false);
+        let unspec: u8 = 1 << 0;
+        let loopback: u8 = 1 << 1;
+        let global: u8 = 1 << 2;
+        let multicast: u8 = 1 << 3;
+        let doc: u8 = 1 << 4;
+
+        check!("0.0.0.0", unspec);
+        check!("0.0.0.1");
+        check!("0.1.0.0");
+        check!("10.9.8.7");
+        check!("127.1.2.3", loopback);
+        check!("172.31.254.253");
+        check!("169.254.253.242");
+        check!("192.0.2.183", doc);
+        check!("192.1.2.183", global);
+        check!("192.168.254.253");
+        check!("198.51.100.0", doc);
+        check!("203.0.113.0", doc);
+        check!("203.2.113.0", global);
+        check!("224.0.0.0", global|multicast);
+        check!("239.255.255.255", global|multicast);
+        check!("255.255.255.255");
+        // make sure benchmarking addresses are not global
+        check!("198.18.0.0");
+        check!("198.18.54.2");
+        check!("198.19.255.255");
+        // make sure addresses reserved for protocol assignment are not global
+        check!("192.0.0.0");
+        check!("192.0.0.255");
+        check!("192.0.0.100");
+        // make sure reserved addresses are not global
+        check!("240.0.0.0");
+        check!("251.54.1.76");
+        check!("254.255.255.255");
+        // make sure shared addresses are not global
+        check!("100.64.0.0");
+        check!("100.127.255.255");
+        check!("100.100.100.0");
+
+        check!("::", unspec);
+        check!("::1", loopback);
+        check!("::0.0.0.2", global);
+        check!("1::", global);
+        check!("fc00::");
+        check!("fdff:ffff::");
+        check!("fe80:ffff::");
+        check!("febf:ffff::");
+        check!("fec0::", global);
+        check!("ff01::", multicast);
+        check!("ff02::", multicast);
+        check!("ff03::", multicast);
+        check!("ff04::", multicast);
+        check!("ff05::", multicast);
+        check!("ff08::", multicast);
+        check!("ff0e::", global|multicast);
+        check!("2001:db8:85a3::8a2e:370:7334", doc);
+        check!("102:304:506:708:90a:b0c:d0e:f10", global);
     }
 
     #[test]
     fn ipv4_properties() {
-        fn check(octets: &[u8; 4], unspec: bool, loopback: bool,
-                 private: bool, link_local: bool, global: bool,
-                 multicast: bool, broadcast: bool, documentation: bool) {
-            let ip = Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3]);
-            assert_eq!(octets, &ip.octets());
-
-            assert_eq!(ip.is_unspecified(), unspec);
-            assert_eq!(ip.is_loopback(), loopback);
-            assert_eq!(ip.is_private(), private);
-            assert_eq!(ip.is_link_local(), link_local);
-            assert_eq!(ip.is_global(), global);
-            assert_eq!(ip.is_multicast(), multicast);
-            assert_eq!(ip.is_broadcast(), broadcast);
-            assert_eq!(ip.is_documentation(), documentation);
+        macro_rules! ip {
+            ($s:expr) => {
+                Ipv4Addr::from_str($s).unwrap()
+            }
         }
 
-        //    address                unspec loopbk privt  linloc global multicast brdcast doc
-        check(&[0, 0, 0, 0],         true,  false, false, false, false,  false,    false,  false);
-        check(&[0, 0, 0, 1],         false, false, false, false, true,   false,    false,  false);
-        check(&[0, 1, 0, 0],         false, false, false, false, true,   false,    false,  false);
-        check(&[10, 9, 8, 7],        false, false, true,  false, false,  false,    false,  false);
-        check(&[127, 1, 2, 3],       false, true,  false, false, false,  false,    false,  false);
-        check(&[172, 31, 254, 253],  false, false, true,  false, false,  false,    false,  false);
-        check(&[169, 254, 253, 242], false, false, false, true,  false,  false,    false,  false);
-        check(&[192, 0, 2, 183],     false, false, false, false, false,  false,    false,  true);
-        check(&[192, 1, 2, 183],     false, false, false, false, true,   false,    false,  false);
-        check(&[192, 168, 254, 253], false, false, true,  false, false,  false,    false,  false);
-        check(&[198, 51, 100, 0],    false, false, false, false, false,  false,    false,  true);
-        check(&[203, 0, 113, 0],     false, false, false, false, false,  false,    false,  true);
-        check(&[203, 2, 113, 0],     false, false, false, false, true,   false,    false,  false);
-        check(&[224, 0, 0, 0],       false, false, false, false, true,   true,     false,  false);
-        check(&[239, 255, 255, 255], false, false, false, false, true,   true,     false,  false);
-        check(&[255, 255, 255, 255], false, false, false, false, false,  false,    true,   false);
+        macro_rules! check {
+            ($s:expr) => {
+                check!($s, 0);
+            };
+
+            ($s:expr, $mask:expr) => {{
+                let unspec: u16 = 1 << 0;
+                let loopback: u16 = 1 << 1;
+                let private: u16 = 1 << 2;
+                let link_local: u16 = 1 << 3;
+                let global: u16 = 1 << 4;
+                let multicast: u16 = 1 << 5;
+                let broadcast: u16 = 1 << 6;
+                let documentation: u16 = 1 << 7;
+                let benchmarking: u16 = 1 << 8;
+                let ietf_protocol_assignment: u16 = 1 << 9;
+                let reserved: u16 = 1 << 10;
+                let shared: u16 = 1 << 11;
+
+                if ($mask & unspec) == unspec {
+                    assert!(ip!($s).is_unspecified());
+                } else {
+                    assert!(!ip!($s).is_unspecified());
+                }
+
+                if ($mask & loopback) == loopback {
+                    assert!(ip!($s).is_loopback());
+                } else {
+                    assert!(!ip!($s).is_loopback());
+                }
+
+                if ($mask & private) == private {
+                    assert!(ip!($s).is_private());
+                } else {
+                    assert!(!ip!($s).is_private());
+                }
+
+                if ($mask & link_local) == link_local {
+                    assert!(ip!($s).is_link_local());
+                } else {
+                    assert!(!ip!($s).is_link_local());
+                }
+
+                if ($mask & global) == global {
+                    assert!(ip!($s).is_global());
+                } else {
+                    assert!(!ip!($s).is_global());
+                }
+
+                if ($mask & multicast) == multicast {
+                    assert!(ip!($s).is_multicast());
+                } else {
+                    assert!(!ip!($s).is_multicast());
+                }
+
+                if ($mask & broadcast) == broadcast {
+                    assert!(ip!($s).is_broadcast());
+                } else {
+                    assert!(!ip!($s).is_broadcast());
+                }
+
+                if ($mask & documentation) == documentation {
+                    assert!(ip!($s).is_documentation());
+                } else {
+                    assert!(!ip!($s).is_documentation());
+                }
+
+                if ($mask & benchmarking) == benchmarking {
+                    assert!(ip!($s).is_benchmarking());
+                } else {
+                    assert!(!ip!($s).is_benchmarking());
+                }
+
+                if ($mask & ietf_protocol_assignment) == ietf_protocol_assignment {
+                    assert!(ip!($s).is_ietf_protocol_assignment());
+                } else {
+                    assert!(!ip!($s).is_ietf_protocol_assignment());
+                }
+
+                if ($mask & reserved) == reserved {
+                    assert!(ip!($s).is_reserved());
+                } else {
+                    assert!(!ip!($s).is_reserved());
+                }
+
+                if ($mask & shared) == shared {
+                    assert!(ip!($s).is_shared());
+                } else {
+                    assert!(!ip!($s).is_shared());
+                }
+            }}
+        }
+
+        let unspec: u16 = 1 << 0;
+        let loopback: u16 = 1 << 1;
+        let private: u16 = 1 << 2;
+        let link_local: u16 = 1 << 3;
+        let global: u16 = 1 << 4;
+        let multicast: u16 = 1 << 5;
+        let broadcast: u16 = 1 << 6;
+        let documentation: u16 = 1 << 7;
+        let benchmarking: u16 = 1 << 8;
+        let ietf_protocol_assignment: u16 = 1 << 9;
+        let reserved: u16 = 1 << 10;
+        let shared: u16 = 1 << 11;
+
+        check!("0.0.0.0", unspec);
+        check!("0.0.0.1");
+        check!("0.1.0.0");
+        check!("10.9.8.7", private);
+        check!("127.1.2.3", loopback);
+        check!("172.31.254.253", private);
+        check!("169.254.253.242", link_local);
+        check!("192.0.2.183", documentation);
+        check!("192.1.2.183", global);
+        check!("192.168.254.253", private);
+        check!("198.51.100.0", documentation);
+        check!("203.0.113.0", documentation);
+        check!("203.2.113.0", global);
+        check!("224.0.0.0", global|multicast);
+        check!("239.255.255.255", global|multicast);
+        check!("255.255.255.255", broadcast);
+        check!("198.18.0.0", benchmarking);
+        check!("198.18.54.2", benchmarking);
+        check!("198.19.255.255", benchmarking);
+        check!("192.0.0.0", ietf_protocol_assignment);
+        check!("192.0.0.255", ietf_protocol_assignment);
+        check!("192.0.0.100", ietf_protocol_assignment);
+        check!("240.0.0.0", reserved);
+        check!("251.54.1.76", reserved);
+        check!("254.255.255.255", reserved);
+        check!("100.64.0.0", shared);
+        check!("100.127.255.255", shared);
+        check!("100.100.100.0", shared);
     }
 
     #[test]
     fn ipv6_properties() {
-        fn check(str_addr: &str, octets: &[u8; 16], unspec: bool, loopback: bool,
-                 unique_local: bool, global: bool,
-                 u_link_local: bool, u_site_local: bool, u_global: bool, u_doc: bool,
-                 m_scope: Option<Ipv6MulticastScope>) {
-            let ip: Ipv6Addr = str_addr.parse().unwrap();
-            assert_eq!(str_addr, ip.to_string());
-            assert_eq!(&ip.octets(), octets);
-            assert_eq!(Ipv6Addr::from(*octets), ip);
-
-            assert_eq!(ip.is_unspecified(), unspec);
-            assert_eq!(ip.is_loopback(), loopback);
-            assert_eq!(ip.is_unique_local(), unique_local);
-            assert_eq!(ip.is_global(), global);
-            assert_eq!(ip.is_unicast_link_local(), u_link_local);
-            assert_eq!(ip.is_unicast_site_local(), u_site_local);
-            assert_eq!(ip.is_unicast_global(), u_global);
-            assert_eq!(ip.is_documentation(), u_doc);
-            assert_eq!(ip.multicast_scope(), m_scope);
-            assert_eq!(ip.is_multicast(), m_scope.is_some());
+        macro_rules! ip {
+            ($s:expr) => {
+                Ipv6Addr::from_str($s).unwrap()
+            }
+        }
+
+        macro_rules! check {
+            ($s:expr, &[$($octet:expr),*], $mask:expr) => {
+                assert_eq!($s, ip!($s).to_string());
+                let octets = &[$($octet),*];
+                assert_eq!(&ip!($s).octets(), octets);
+                assert_eq!(Ipv6Addr::from(*octets), ip!($s));
+
+                let unspecified: u16 = 1 << 0;
+                let loopback: u16 = 1 << 1;
+                let unique_local: u16 = 1 << 2;
+                let global: u16 = 1 << 3;
+                let unicast_link_local: u16 = 1 << 4;
+                let unicast_link_local_strict: u16 = 1 << 5;
+                let unicast_site_local: u16 = 1 << 6;
+                let unicast_global: u16 = 1 << 7;
+                let documentation: u16 = 1 << 8;
+                let multicast_interface_local: u16 = 1 << 9;
+                let multicast_link_local: u16 = 1 << 10;
+                let multicast_realm_local: u16 = 1 << 11;
+                let multicast_admin_local: u16 = 1 << 12;
+                let multicast_site_local: u16 = 1 << 13;
+                let multicast_organization_local: u16 = 1 << 14;
+                let multicast_global: u16 = 1 << 15;
+                let multicast: u16 = multicast_interface_local
+                    | multicast_admin_local
+                    | multicast_global
+                    | multicast_link_local
+                    | multicast_realm_local
+                    | multicast_site_local
+                    | multicast_organization_local;
+
+                if ($mask & unspecified) == unspecified {
+                    assert!(ip!($s).is_unspecified());
+                } else {
+                    assert!(!ip!($s).is_unspecified());
+                }
+                if ($mask & loopback) == loopback {
+                    assert!(ip!($s).is_loopback());
+                } else {
+                    assert!(!ip!($s).is_loopback());
+                }
+                if ($mask & unique_local) == unique_local {
+                    assert!(ip!($s).is_unique_local());
+                } else {
+                    assert!(!ip!($s).is_unique_local());
+                }
+                if ($mask & global) == global {
+                    assert!(ip!($s).is_global());
+                } else {
+                    assert!(!ip!($s).is_global());
+                }
+                if ($mask & unicast_link_local) == unicast_link_local {
+                    assert!(ip!($s).is_unicast_link_local());
+                } else {
+                    assert!(!ip!($s).is_unicast_link_local());
+                }
+                if ($mask & unicast_link_local_strict) == unicast_link_local_strict {
+                    assert!(ip!($s).is_unicast_link_local_strict());
+                } else {
+                    assert!(!ip!($s).is_unicast_link_local_strict());
+                }
+                if ($mask & unicast_site_local) == unicast_site_local {
+                    assert!(ip!($s).is_unicast_site_local());
+                } else {
+                    assert!(!ip!($s).is_unicast_site_local());
+                }
+                if ($mask & unicast_global) == unicast_global {
+                    assert!(ip!($s).is_unicast_global());
+                } else {
+                    assert!(!ip!($s).is_unicast_global());
+                }
+                if ($mask & documentation) == documentation {
+                    assert!(ip!($s).is_documentation());
+                } else {
+                    assert!(!ip!($s).is_documentation());
+                }
+                if ($mask & multicast) != 0 {
+                    assert!(ip!($s).multicast_scope().is_some());
+                    assert!(ip!($s).is_multicast());
+                } else {
+                    assert!(ip!($s).multicast_scope().is_none());
+                    assert!(!ip!($s).is_multicast());
+                }
+                if ($mask & multicast_interface_local) == multicast_interface_local {
+                    assert_eq!(ip!($s).multicast_scope().unwrap(),
+                               Ipv6MulticastScope::InterfaceLocal);
+                }
+                if ($mask & multicast_link_local) == multicast_link_local {
+                    assert_eq!(ip!($s).multicast_scope().unwrap(),
+                               Ipv6MulticastScope::LinkLocal);
+                }
+                if ($mask & multicast_realm_local) == multicast_realm_local {
+                    assert_eq!(ip!($s).multicast_scope().unwrap(),
+                               Ipv6MulticastScope::RealmLocal);
+                }
+                if ($mask & multicast_admin_local) == multicast_admin_local {
+                    assert_eq!(ip!($s).multicast_scope().unwrap(),
+                               Ipv6MulticastScope::AdminLocal);
+                }
+                if ($mask & multicast_site_local) == multicast_site_local {
+                    assert_eq!(ip!($s).multicast_scope().unwrap(),
+                               Ipv6MulticastScope::SiteLocal);
+                }
+                if ($mask & multicast_organization_local) == multicast_organization_local {
+                    assert_eq!(ip!($s).multicast_scope().unwrap(),
+                               Ipv6MulticastScope::OrganizationLocal);
+                }
+                if ($mask & multicast_global) == multicast_global {
+                    assert_eq!(ip!($s).multicast_scope().unwrap(),
+                               Ipv6MulticastScope::Global);
+                }
+            }
         }
 
-        //    unspec loopbk uniqlo global unill  unisl  uniglo doc    mscope
-        check("::", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-              true,  false, false, false, false, false, false, false, None);
-        check("::1", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
-              false, true,  false, false, false, false, false, false, None);
-        check("::0.0.0.2", &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2],
-              false, false, false, true,  false, false, true,  false, None);
-        check("1::", &[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-              false, false, false, true,  false, false, true,  false, None);
-        check("fc00::", &[0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-              false, false, true,  false, false, false, false, false, None);
-        check("fdff:ffff::", &[0xfd, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-              false, false, true,  false, false, false, false, false, None);
-        check("fe80:ffff::", &[0xfe, 0x80, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-              false, false, false, false, true,  false, false, false, None);
-        check("febf:ffff::", &[0xfe, 0xbf, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-              false, false, false, false, true,  false, false, false, None);
-        check("fec0::", &[0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-              false, false, false, false, false, true,  false, false, None);
-        check("ff01::", &[0xff, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-              false, false, false, false, false, false, false, false, Some(InterfaceLocal));
-        check("ff02::", &[0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-              false, false, false, false, false, false, false, false, Some(LinkLocal));
-        check("ff03::", &[0xff, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-              false, false, false, false, false, false, false, false, Some(RealmLocal));
-        check("ff04::", &[0xff, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-              false, false, false, false, false, false, false, false, Some(AdminLocal));
-        check("ff05::", &[0xff, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-              false, false, false, false, false, false, false, false, Some(SiteLocal));
-        check("ff08::", &[0xff, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-              false, false, false, false, false, false, false, false, Some(OrganizationLocal));
-        check("ff0e::", &[0xff, 0xe, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-              false, false, false, true,  false, false, false, false, Some(Global));
-        check("2001:db8:85a3::8a2e:370:7334",
-              &[0x20, 1, 0xd, 0xb8, 0x85, 0xa3, 0, 0, 0, 0, 0x8a, 0x2e, 3, 0x70, 0x73, 0x34],
-              false, false, false, false, false, false, false, true, None);
-        check("102:304:506:708:90a:b0c:d0e:f10",
-              &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
-              false, false, false, true,  false, false, true,  false, None);
+        let unspecified: u16 = 1 << 0;
+        let loopback: u16 = 1 << 1;
+        let unique_local: u16 = 1 << 2;
+        let global: u16 = 1 << 3;
+        let unicast_link_local: u16 = 1 << 4;
+        let unicast_link_local_strict: u16 = 1 << 5;
+        let unicast_site_local: u16 = 1 << 6;
+        let unicast_global: u16 = 1 << 7;
+        let documentation: u16 = 1 << 8;
+        let multicast_interface_local: u16 = 1 << 9;
+        let multicast_link_local: u16 = 1 << 10;
+        let multicast_realm_local: u16 = 1 << 11;
+        let multicast_admin_local: u16 = 1 << 12;
+        let multicast_site_local: u16 = 1 << 13;
+        let multicast_organization_local: u16 = 1 << 14;
+        let multicast_global: u16 = 1 << 15;
+
+        check!("::",
+               &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+               unspecified);
+
+        check!("::1",
+               &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
+               loopback);
+
+        check!("::0.0.0.2",
+               &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2],
+               global | unicast_global);
+
+        check!("1::",
+               &[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+               global | unicast_global);
+
+        check!("fc00::",
+               &[0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+               unique_local);
+
+        check!("fdff:ffff::",
+               &[0xfd, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+               unique_local);
+
+        check!("fe80:ffff::",
+               &[0xfe, 0x80, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+               unicast_link_local);
+
+        check!("fe80::",
+               &[0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+               unicast_link_local|unicast_link_local_strict);
+
+        check!("febf:ffff::",
+               &[0xfe, 0xbf, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+               unicast_link_local);
+
+        check!("febf::",
+               &[0xfe, 0xbf, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+               unicast_link_local);
+
+        check!("febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
+               &[0xfe, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
+               unicast_link_local);
+
+        check!("fe80::ffff:ffff:ffff:ffff",
+               &[0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
+               unicast_link_local|unicast_link_local_strict);
+
+        check!("fe80:0:0:1::",
+               &[0xfe, 0x80, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
+               unicast_link_local);
+
+        check!("fec0::",
+               &[0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+               unicast_site_local|unicast_global|global);
+
+        check!("ff01::",
+               &[0xff, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+               multicast_interface_local);
+
+        check!("ff02::",
+               &[0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+               multicast_link_local);
+
+        check!("ff03::",
+               &[0xff, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+               multicast_realm_local);
+
+        check!("ff04::",
+               &[0xff, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+               multicast_admin_local);
+
+        check!("ff05::",
+               &[0xff, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+               multicast_site_local);
+
+        check!("ff08::",
+               &[0xff, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+               multicast_organization_local);
+
+        check!("ff0e::",
+               &[0xff, 0xe, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+               multicast_global | global);
+
+        check!("2001:db8:85a3::8a2e:370:7334",
+               &[0x20, 1, 0xd, 0xb8, 0x85, 0xa3, 0, 0, 0, 0, 0x8a, 0x2e, 3, 0x70, 0x73, 0x34],
+               documentation);
+
+        check!("102:304:506:708:90a:b0c:d0e:f10",
+               &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
+               global| unicast_global);
     }
 
     #[test]
index b96f13335b2fecf8833a692b2aacf45c93a99ad2..bf6eab4ec914852f51989d9b08aec975eca65db0 100644 (file)
@@ -111,7 +111,7 @@ pub fn find_unwind_attr(diagnostic: Option<&Handler>, attrs: &[Attribute]) -> Op
 }
 
 /// Represents the #[stable], #[unstable], #[rustc_{deprecated,const_unstable}] attributes.
-#[derive(RustcEncodable, RustcDecodable, Clone, Debug, PartialEq, Eq, Hash)]
+#[derive(RustcEncodable, RustcDecodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
 pub struct Stability {
     pub level: StabilityLevel,
     pub feature: Symbol,
@@ -127,7 +127,7 @@ pub struct Stability {
 }
 
 /// The available stability levels.
-#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Eq, Hash)]
+#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Copy, Clone, Debug, Eq, Hash)]
 pub enum StabilityLevel {
     // Reason for the current stability level and the relevant rust-lang issue
     Unstable { reason: Option<Symbol>, issue: u32 },
@@ -151,7 +151,7 @@ pub fn is_stable(&self) -> bool {
     }
 }
 
-#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Eq, Hash)]
+#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Copy, Clone, Debug, Eq, Hash)]
 pub struct RustcDeprecation {
     pub since: Symbol,
     pub reason: Symbol,
index b3d49524d7668599e9d37ed6d46907db65981776..2e4d4c091398ea5770080490b260312ca6c8c186 100644 (file)
@@ -858,8 +858,8 @@ pub fn unexpected_try_recover(
                     Applicability::MaybeIncorrect,
                 );
             } else {
-                err.note("type ascription is a nightly-only feature that lets \
-                          you annotate an expression with a type: `<expr>: <type>`")
+                err.note("#![feature(type_ascription)] lets you annotate an \
+                          expression with a type: `<expr>: <type>`")
                     .span_note(
                         lhs_span,
                         "this expression expects an ascribed type after the colon",
index 746e9cad4962ca4057e9214ef433aedaedade7f2..7bc95ad03693880920f7481ace84b5d9b08fb33a 100644 (file)
@@ -5050,21 +5050,22 @@ fn parse_const_param(&mut self, preceding_attrs: Vec<Attribute>) -> PResult<'a,
     /// where   typaramseq = ( typaram ) | ( typaram , typaramseq )
     fn parse_generics(&mut self) -> PResult<'a, ast::Generics> {
         let span_lo = self.span;
-        if self.eat_lt() {
+        let (params, span) = if self.eat_lt() {
             let params = self.parse_generic_params()?;
             self.expect_gt()?;
-            Ok(ast::Generics {
-                params,
-                where_clause: WhereClause {
-                    id: ast::DUMMY_NODE_ID,
-                    predicates: Vec::new(),
-                    span: DUMMY_SP,
-                },
-                span: span_lo.to(self.prev_span),
-            })
+            (params, span_lo.to(self.prev_span))
         } else {
-            Ok(ast::Generics::default())
-        }
+            (vec![], self.prev_span.between(self.span))
+        };
+        Ok(ast::Generics {
+            params,
+            where_clause: WhereClause {
+                id: ast::DUMMY_NODE_ID,
+                predicates: Vec::new(),
+                span: DUMMY_SP,
+            },
+            span,
+        })
     }
 
     /// Parses generic args (within a path segment) with recovery for extra leading angle brackets.
@@ -7205,44 +7206,41 @@ fn parse_item_implementation(
             return Ok(Some(item));
         }
 
-        // `unsafe async fn` or `async fn`
-        if (
-            self.check_keyword(kw::Unsafe) &&
-            self.is_keyword_ahead(1, &[kw::Async])
-        ) || (
-            self.check_keyword(kw::Async) &&
-            self.is_keyword_ahead(1, &[kw::Fn])
-        )
-        {
-            // ASYNC FUNCTION ITEM
-            let unsafety = self.parse_unsafety();
-            self.expect_keyword(kw::Async)?;
-            let async_span = self.prev_span;
-            self.expect_keyword(kw::Fn)?;
-            let fn_span = self.prev_span;
-            let (ident, item_, extra_attrs) =
-                self.parse_item_fn(unsafety,
-                                   respan(async_span, IsAsync::Async {
-                                       closure_id: ast::DUMMY_NODE_ID,
-                                       return_impl_trait_id: ast::DUMMY_NODE_ID,
-                                       arguments: Vec::new(),
-                                   }),
-                                   respan(fn_span, Constness::NotConst),
-                                   Abi::Rust)?;
-            let prev_span = self.prev_span;
-            let item = self.mk_item(lo.to(prev_span),
-                                    ident,
-                                    item_,
-                                    visibility,
-                                    maybe_append(attrs, extra_attrs));
-            if self.span.rust_2015() {
-                self.diagnostic().struct_span_err_with_code(
-                    async_span,
-                    "`async fn` is not permitted in the 2015 edition",
-                    DiagnosticId::Error("E0670".into())
-                ).emit();
+        // Parse `async unsafe? fn`.
+        if self.check_keyword(kw::Async) {
+            let async_span = self.span;
+            if self.is_keyword_ahead(1, &[kw::Fn])
+                || self.is_keyword_ahead(2, &[kw::Fn])
+            {
+                // ASYNC FUNCTION ITEM
+                self.bump(); // `async`
+                let unsafety = self.parse_unsafety(); // `unsafe`?
+                self.expect_keyword(kw::Fn)?; // `fn`
+                let fn_span = self.prev_span;
+                let (ident, item_, extra_attrs) =
+                    self.parse_item_fn(unsafety,
+                                    respan(async_span, IsAsync::Async {
+                                        closure_id: ast::DUMMY_NODE_ID,
+                                        return_impl_trait_id: ast::DUMMY_NODE_ID,
+                                        arguments: Vec::new(),
+                                    }),
+                                    respan(fn_span, Constness::NotConst),
+                                    Abi::Rust)?;
+                let prev_span = self.prev_span;
+                let item = self.mk_item(lo.to(prev_span),
+                                        ident,
+                                        item_,
+                                        visibility,
+                                        maybe_append(attrs, extra_attrs));
+                if self.span.rust_2015() {
+                    self.diagnostic().struct_span_err_with_code(
+                        async_span,
+                        "`async fn` is not permitted in the 2015 edition",
+                        DiagnosticId::Error("E0670".into())
+                    ).emit();
+                }
+                return Ok(Some(item));
             }
-            return Ok(Some(item));
         }
         if self.check_keyword(kw::Unsafe) &&
             self.is_keyword_ahead(1, &[kw::Trait, kw::Auto])
index 8bd0d74cd1710673bd62e8a34d22a1c7118e04f9..810a98e4a014cb4f54fbfefc28352286cce9f131 100644 (file)
@@ -1536,7 +1536,7 @@ fn calc_result(desc: &TestDesc, task_result: Result<(), Box<dyn Any + Send>>) ->
                 if desc.allow_fail {
                     TrAllowedFail
                 } else {
-                    TrFailedMsg(format!("Panic did not include expected string '{}'", msg))
+                    TrFailedMsg(format!("panic did not include expected string '{}'", msg))
                 }
             }
         }
@@ -1890,7 +1890,7 @@ fn f() {
             panic!("an error message");
         }
         let expected = "foobar";
-        let failed_msg = "Panic did not include expected string";
+        let failed_msg = "panic did not include expected string";
         let desc = TestDescAndFn {
             desc: TestDesc {
                 name: StaticTestName("whatever"),
index 4efebe31651d5520bcba968878dbb8a4971d2045..788592fb2740d560d0614a77035b319b9d07aa38 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 4efebe31651d5520bcba968878dbb8a4971d2045
+Subproject commit 788592fb2740d560d0614a77035b319b9d07aa38
index 4801369cfd1a8a3ffeb0fba3aaaa17f829669c56..5276869a702eeb0c83e2c597d46cc5d4b7cf54fc 100644 (file)
@@ -1,5 +1,6 @@
 // run-pass
 #![allow(dead_code, unreachable_patterns)]
+#![allow(ellipsis_inclusive_range_patterns)]
 
 struct Foo;
 
@@ -23,4 +24,17 @@ fn main() {
         <Foo as HasNum>::NUM ... <Foo>::NUM => true,
         _ => false,
     });
+
+    assert!(match 2 {
+        Foo::NUM ..= 3 => true,
+        _ => false,
+    });
+    assert!(match 0 {
+        -1 ..= <Foo as HasNum>::NUM => true,
+        _ => false,
+    });
+    assert!(match 1 {
+        <Foo as HasNum>::NUM ..= <Foo>::NUM => true,
+        _ => false,
+    });
 }
index b3729a79615a647b5827a40dbf85b4a2ff1a8e76..19b3045784f86aab3b465914a8798e7f423b4e08 100644 (file)
@@ -1,6 +1,8 @@
 // run-pass
 // Parsing of range patterns
 
+#![allow(ellipsis_inclusive_range_patterns)]
+
 const NUM1: i32 = 10;
 
 mod m {
@@ -11,4 +13,8 @@ fn main() {
     if let NUM1 ... m::NUM2 = 10 {} else { panic!() }
     if let ::NUM1 ... ::m::NUM2 = 11 {} else { panic!() }
     if let -13 ... -10 = 12 { panic!() } else {}
+
+    if let NUM1 ..= m::NUM2 = 10 {} else { panic!() }
+    if let ::NUM1 ..= ::m::NUM2 = 11 {} else { panic!() }
+    if let -13 ..= -10 = 12 { panic!() } else {}
 }
index 19d65860179b2628a598479fe69bf664bdbeabd5..3d3240d434292933365912ac5d50a6fe6857e27e 100644 (file)
@@ -1,4 +1,4 @@
-#![feature(const_int_conversion, reverse_bits)]
+#![feature(const_int_conversion)]
 
 const REVERSE: u32 = 0x12345678_u32.reverse_bits();
 const FROM_BE_BYTES: i32 = i32::from_be_bytes([0x12, 0x34, 0x56, 0x78]);
index 399b577dccb2f96f7f80926c0ee9a04887d2c995..eb1a3f3a9f9cbed7f587c9a1dcfc41f726acf78f 100644 (file)
@@ -41,7 +41,7 @@ fn new(failing_op: usize) -> Self {
             data: RefCell::new(vec![])
         }
     }
-    fn alloc(&self) -> Ptr {
+    fn alloc(&self) -> Ptr<'_> {
         self.cur_ops.set(self.cur_ops.get() + 1);
 
         if self.cur_ops.get() == self.failing_op {
@@ -53,6 +53,20 @@ fn alloc(&self) -> Ptr {
         data.push(true);
         Ptr(addr, self)
     }
+    // FIXME(#47949) Any use of this indicates a bug in rustc: we should never
+    // be leaking values in the cases here.
+    //
+    // Creates a `Ptr<'_>` and checks that the allocated value is leaked if the
+    // `failing_op` is in the list of exception.
+    fn alloc_leaked(&self, exceptions: Vec<usize>) -> Ptr<'_> {
+        let ptr = self.alloc();
+
+        if exceptions.iter().any(|operation| *operation == self.failing_op) {
+            let mut data = self.data.borrow_mut();
+            data[ptr.0] = false;
+        }
+        ptr
+    }
 }
 
 struct Ptr<'a>(usize, &'a Allocator);
@@ -255,6 +269,72 @@ fn subslice_pattern_reassign(a: &Allocator) {
     let[_, _y..] = ar;
 }
 
+fn panic_after_return(a: &Allocator) -> Ptr<'_> {
+    // Panic in the drop of `p` or `q` can leak
+    let exceptions = vec![8, 9];
+    a.alloc();
+    let p = a.alloc();
+    {
+        a.alloc();
+        let p = a.alloc();
+        // FIXME (#47949) We leak values when we panic in a destructor after
+        // evaluating an expression with `rustc_mir::build::Builder::into`.
+        a.alloc_leaked(exceptions)
+    }
+}
+
+fn panic_after_return_expr(a: &Allocator) -> Ptr<'_> {
+    // Panic in the drop of `p` or `q` can leak
+    let exceptions = vec![8, 9];
+    a.alloc();
+    let p = a.alloc();
+    {
+        a.alloc();
+        let q = a.alloc();
+        // FIXME (#47949)
+        return a.alloc_leaked(exceptions);
+    }
+}
+
+fn panic_after_init(a: &Allocator) {
+    // Panic in the drop of `r` can leak
+    let exceptions = vec![8];
+    a.alloc();
+    let p = a.alloc();
+    let q = {
+        a.alloc();
+        let r = a.alloc();
+        // FIXME (#47949)
+        a.alloc_leaked(exceptions)
+    };
+}
+
+fn panic_after_init_temp(a: &Allocator) {
+    // Panic in the drop of `r` can leak
+    let exceptions = vec![8];
+    a.alloc();
+    let p = a.alloc();
+    {
+        a.alloc();
+        let r = a.alloc();
+        // FIXME (#47949)
+        a.alloc_leaked(exceptions)
+    };
+}
+
+fn panic_after_init_by_loop(a: &Allocator) {
+    // Panic in the drop of `r` can leak
+    let exceptions = vec![8];
+    a.alloc();
+    let p = a.alloc();
+    let q = loop {
+        a.alloc();
+        let r = a.alloc();
+        // FIXME (#47949)
+        break a.alloc_leaked(exceptions);
+    };
+}
+
 fn run_test<F>(mut f: F)
     where F: FnMut(&Allocator)
 {
@@ -342,5 +422,15 @@ fn main() {
     run_test(|a| slice_pattern_reassign(a));
     run_test(|a| subslice_pattern_reassign(a));
 
+    run_test(|a| {
+        panic_after_return(a);
+    });
+    run_test(|a| {
+        panic_after_return_expr(a);
+    });
+    run_test(|a| panic_after_init(a));
+    run_test(|a| panic_after_init_temp(a));
+    run_test(|a| panic_after_init_by_loop(a));
+
     run_test_nopanic(|a| union1(a));
 }
index 6bf857a11f81657e0935f1bcd585f22d7ff5b41b..a648ff17492eedd11ee2fe56bcd961b5756f2267 100644 (file)
@@ -1,5 +1,7 @@
 // Test old and new syntax for inclusive range patterns.
 
+#![allow(ellipsis_inclusive_range_patterns)]
+
 fn main() {
     assert!(match 42 { 0 ... 100 => true, _ => false });
     assert!(match 42 { 0 ..= 100 => true, _ => false });
index 2470e37e1820b13a2cb5944c54036e94aefd6de7..dee7f25d7bb3a8a36491e7a760683a5b93f3dd31 100644 (file)
@@ -1,5 +1,6 @@
 // run-pass
 #![allow(illegal_floating_point_literal_pattern)] // FIXME #41620
+#![allow(ellipsis_inclusive_range_patterns)]
 
 // regression test for the model lexer handling the DOTDOTDOT syntax (#15877)
 
index 8913009f6915654f1fa11f61822311ce68c3c8a8..04570055763a96b0dfdde00cc9b4dd68b1703da8 100644 (file)
@@ -2,7 +2,7 @@
 #![allow(dead_code)]
 fn test1(x: i8) -> i32 {
   match x {
-    1...10 => 0,
+    1..=10 => 0,
     _ => 1,
   }
 }
index 971e6b554cca704c4426171959d8e3e998f44d21..a6ee046edec8b03d173b223ceb38ff9f94e41877 100644 (file)
@@ -3,7 +3,7 @@
 // ignore-tidy-linelength
 
 pub trait Foo {
-    // @has foo/trait.Foo.html '//h3[@id="tymethod.foo"]//div[@class="docblock attributes"]' '#[must_use]'
+    // @has foo/trait.Foo.html '//h3[@id="tymethod.foo"]//span[@class="docblock attributes"]' '#[must_use]'
     #[must_use]
     fn foo();
 }
@@ -12,11 +12,11 @@ pub trait Foo {
 pub struct Bar;
 
 impl Bar {
-    // @has foo/struct.Bar.html '//h4[@id="method.bar"]//div[@class="docblock attributes"]' '#[must_use]'
+    // @has foo/struct.Bar.html '//h4[@id="method.bar"]//span[@class="docblock attributes"]' '#[must_use]'
     #[must_use]
     pub fn bar() {}
 
-    // @has foo/struct.Bar.html '//h4[@id="method.bar2"]//div[@class="docblock attributes"]' '#[must_use]'
+    // @has foo/struct.Bar.html '//h4[@id="method.bar2"]//span[@class="docblock attributes"]' '#[must_use]'
     #[must_use]
     pub fn bar2() {}
 }
index 6fa013e5c54ca6764f175da94a6a2b2c47ea41fa..38261ca4570eb96d0475010c1fe7fc238064e1b1 100644 (file)
@@ -122,7 +122,7 @@ fn async_fn_with_internal_borrow(y: u8) -> impl Future<Output = u8> {
     }
 }
 
-unsafe async fn unsafe_async_fn(x: u8) -> u8 {
+async unsafe fn unsafe_async_fn(x: u8) -> u8 {
     wake_and_yield_once().await;
     x
 }
index 1b807588d6ac2c78fb72ba1d3e06461a516f049e..7d8b7a257dad973c92fcfd5580f4be9551d85995 100644 (file)
@@ -122,7 +122,7 @@ fn async_fn_with_internal_borrow(y: u8) -> impl Future<Output = u8> {
     }
 }
 
-unsafe async fn unsafe_async_fn(x: u8) -> u8 {
+async unsafe fn unsafe_async_fn(x: u8) -> u8 {
     await!(wake_and_yield_once());
     x
 }
index a6dbcf36077a728b704effd7ccff75c735edcb37..f22b7da811949293aaea9b318b6dbdede47f29a0 100644 (file)
@@ -4,7 +4,7 @@ error[E0502]: cannot borrow `*ptr` as immutable because it is also borrowed as m
 LL |   let mut test = |foo: &Foo| {
    |                  ----------- mutable borrow occurs here
 LL |     ptr = box Foo { x: ptr.x + 1 };
-   |     --- first borrow occurs due to use of `ptr` in closure
+   |                        --- first borrow occurs due to use of `ptr` in closure
 LL |   };
 LL |   test(&*ptr);
    |   ---- ^^^^^ immutable borrow occurs here
index cc6d5c55bd58f6652ebda2dc58a3c3938e5cf78b..4c7c0d1a0dfa514f5beea8594406e3ed5e0d70b3 100644 (file)
@@ -36,13 +36,13 @@ LL |     fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d
    |                        ^^
 
 error[E0195]: lifetime parameters or bounds on method `wrong_bound2` do not match the trait declaration
-  --> $DIR/regions-bound-missing-bound-in-impl.rs:41:5
+  --> $DIR/regions-bound-missing-bound-in-impl.rs:41:20
    |
 LL |     fn wrong_bound2<'b,'c,'d:'a+'b>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>);
    |                    ---------------- lifetimes in impl do not match this method in trait
 ...
 LL |     fn wrong_bound2(self, b: Inv, c: Inv, d: Inv) {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetimes do not match method in trait
+   |                    ^ lifetimes do not match method in trait
 
 error[E0276]: impl has stricter requirements than trait
   --> $DIR/regions-bound-missing-bound-in-impl.rs:48:5
diff --git a/src/test/ui/const-generics/const-generic-array-wrapper.rs b/src/test/ui/const-generics/const-generic-array-wrapper.rs
new file mode 100644 (file)
index 0000000..adffe32
--- /dev/null
@@ -0,0 +1,18 @@
+// run-pass
+
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+struct Foo<T, const N: usize>([T; {N}]);
+
+impl<T, const N: usize> Foo<T, {N}> {
+    fn foo(&self) -> usize {
+        {N}
+    }
+}
+
+fn main() {
+    let foo = Foo([0u32; 21]);
+    assert_eq!(foo.0, [0u32; 21]);
+    assert_eq!(foo.foo(), 21);
+}
diff --git a/src/test/ui/const-generics/const-generic-array-wrapper.stderr b/src/test/ui/const-generics/const-generic-array-wrapper.stderr
new file mode 100644 (file)
index 0000000..f92e11d
--- /dev/null
@@ -0,0 +1,6 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/const-generic-array-wrapper.rs:3:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+
diff --git a/src/test/ui/const-generics/issue-61422.rs b/src/test/ui/const-generics/issue-61422.rs
new file mode 100644 (file)
index 0000000..3ccf38e
--- /dev/null
@@ -0,0 +1,15 @@
+// run-pass
+
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+use std::mem;
+
+fn foo<const SIZE: usize>() {
+    let arr: [u8; SIZE] = unsafe {
+        let mut array: [u8; SIZE] = mem::uninitialized();
+        array
+    };
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/issue-61422.stderr b/src/test/ui/const-generics/issue-61422.stderr
new file mode 100644 (file)
index 0000000..4cb76ec
--- /dev/null
@@ -0,0 +1,6 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/issue-61422.rs:3:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+
diff --git a/src/test/ui/const-generics/mut-ref-const-param-array.rs b/src/test/ui/const-generics/mut-ref-const-param-array.rs
new file mode 100644 (file)
index 0000000..f930fb8
--- /dev/null
@@ -0,0 +1,19 @@
+// run-pass
+
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+use std::ops::AddAssign;
+
+fn inc<T: AddAssign + Clone, const N: usize>(v: &mut [T; N]) -> &mut [T; N] {
+    for x in v.iter_mut() {
+        *x += x.clone();
+    }
+    v
+}
+
+fn main() {
+    let mut v = [1, 2, 3];
+    inc(&mut v);
+    assert_eq!(v, [2, 4, 6]);
+}
diff --git a/src/test/ui/const-generics/mut-ref-const-param-array.stderr b/src/test/ui/const-generics/mut-ref-const-param-array.stderr
new file mode 100644 (file)
index 0000000..261d357
--- /dev/null
@@ -0,0 +1,6 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/mut-ref-const-param-array.rs:3:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+
diff --git a/src/test/ui/const-generics/transparent-maybeunit-array-wrapper.rs b/src/test/ui/const-generics/transparent-maybeunit-array-wrapper.rs
new file mode 100644 (file)
index 0000000..7940481
--- /dev/null
@@ -0,0 +1,11 @@
+// run-pass
+
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+use std::mem::MaybeUninit;
+
+#[repr(transparent)]
+pub struct MaybeUninitWrapper<const N: usize>(MaybeUninit<[u64; N]>);
+
+fn main() {}
diff --git a/src/test/ui/const-generics/transparent-maybeunit-array-wrapper.stderr b/src/test/ui/const-generics/transparent-maybeunit-array-wrapper.stderr
new file mode 100644 (file)
index 0000000..661bbd1
--- /dev/null
@@ -0,0 +1,6 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/transparent-maybeunit-array-wrapper.rs:3:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+
index ea409439ed6041e48b0babc1738480e66d3bb021..b80e616eae77e453a07d35ec79e512cbd7885593 100644 (file)
@@ -1,5 +1,3 @@
-#![feature(reverse_bits)]
-
 fn main() {
     let x: &'static i32 = &(5_i32.reverse_bits());
         //~^ ERROR temporary value dropped while borrowed
index 65330e282c96620de7e8793cc14aa0491423192e..237f9627219bd52ac517df131822ab5a17562f3a 100644 (file)
@@ -1,5 +1,5 @@
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/const-int-conversion.rs:4:28
+  --> $DIR/const-int-conversion.rs:2:28
    |
 LL |     let x: &'static i32 = &(5_i32.reverse_bits());
    |            ------------    ^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
@@ -10,7 +10,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/const-int-conversion.rs:6:28
+  --> $DIR/const-int-conversion.rs:4:28
    |
 LL |     let y: &'static i32 = &(i32::from_be_bytes([0x12, 0x34, 0x56, 0x78]));
    |            ------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
@@ -21,7 +21,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/const-int-conversion.rs:8:28
+  --> $DIR/const-int-conversion.rs:6:28
    |
 LL |     let z: &'static i32 = &(i32::from_le_bytes([0x12, 0x34, 0x56, 0x78]));
    |            ------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
@@ -32,7 +32,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/const-int-conversion.rs:10:28
+  --> $DIR/const-int-conversion.rs:8:28
    |
 LL |     let a: &'static i32 = &(i32::from_be(i32::from_ne_bytes([0x80, 0, 0, 0])));
    |            ------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
@@ -43,7 +43,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/const-int-conversion.rs:12:29
+  --> $DIR/const-int-conversion.rs:10:29
    |
 LL |     let b: &'static [u8] = &(0x12_34_56_78_i32.to_be_bytes());
    |            -------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
@@ -54,7 +54,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/const-int-conversion.rs:14:29
+  --> $DIR/const-int-conversion.rs:12:29
    |
 LL |     let c: &'static [u8] = &(0x12_34_56_78_i32.to_le_bytes());
    |            -------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
@@ -65,7 +65,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/const-int-conversion.rs:16:29
+  --> $DIR/const-int-conversion.rs:14:29
    |
 LL |     let d: &'static [u8] = &(i32::min_value().to_be().to_ne_bytes());
    |            -------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
index c141f8a882820f05ada27e1c02bb711c6ebe4cae..3dd910019bfd08337c6a9db1f118e8e0e5488643 100644 (file)
@@ -8,5 +8,15 @@ impl Foo for Bar {
     fn foo(x: bool) -> Self { Bar } //~ ERROR E0049
 }
 
+trait Fuzz {
+    fn fuzz<A: Default, B>(x: A, y: B) -> Self;
+}
+
+struct Baz;
+
+impl Fuzz for Baz {
+    fn fuzz(x: bool, y: bool) -> Self { Baz } //~ ERROR E0049
+}
+
 fn main() {
 }
index 7e9b9e8efb9a815fd4586501459accfdd3dcf444..c0cd31faa90d60056cc31fe6d5a0446fe7b28e43 100644 (file)
@@ -1,12 +1,23 @@
 error[E0049]: method `foo` has 0 type parameters but its trait declaration has 1 type parameter
-  --> $DIR/E0049.rs:8:5
+  --> $DIR/E0049.rs:8:11
    |
 LL |     fn foo<T: Default>(x: T) -> Self;
-   |     --------------------------------- expected 1 type parameter
+   |            - expected 1 type parameter
 ...
 LL |     fn foo(x: bool) -> Self { Bar }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^ found 0 type parameters
+   |           ^ found 0 type parameters
 
-error: aborting due to previous error
+error[E0049]: method `fuzz` has 0 type parameters but its trait declaration has 2 type parameters
+  --> $DIR/E0049.rs:18:12
+   |
+LL |     fn fuzz<A: Default, B>(x: A, y: B) -> Self;
+   |             -           -
+   |             |
+   |             expected 2 type parameters
+...
+LL |     fn fuzz(x: bool, y: bool) -> Self { Baz }
+   |            ^ found 0 type parameters
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0049`.
diff --git a/src/test/ui/error-codes/E0730.rs b/src/test/ui/error-codes/E0730.rs
new file mode 100644 (file)
index 0000000..e5048d6
--- /dev/null
@@ -0,0 +1,11 @@
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+fn is_123<const N: usize>(x: [u32; N]) -> bool {
+    match x {
+        [1, 2, 3] => true, //~ ERROR cannot pattern-match on an array without a fixed length
+        _ => false
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0730.stderr b/src/test/ui/error-codes/E0730.stderr
new file mode 100644 (file)
index 0000000..f928126
--- /dev/null
@@ -0,0 +1,15 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/E0730.rs:1:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+
+error[E0730]: cannot pattern-match on an array without a fixed length
+  --> $DIR/E0730.rs:6:9
+   |
+LL |         [1, 2, 3] => true,
+   |         ^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0730`.
index fb17934fa9b21e536ac2fecbf3d3e3bba625e22f..0eec9fb3ee647c3143b0c7bc4d8e695f48c07fcd 100644 (file)
@@ -6,7 +6,7 @@
 
 // run-rustfix
 // ignore-wasm32 no external library to link to.
-// compile-flags: -g -Z continue-parse-after-error
+// compile-flags: -g
 #![feature(rustc_private)]
 extern crate libc;
 
index f2585f5199ea6f62561790f5f13bb9f0bd845a9a..ca5d7ddf27e3ab9a1f84e5bc9edd1795a4f6ccf4 100644 (file)
@@ -6,7 +6,7 @@
 
 // run-rustfix
 // ignore-wasm32 no external library to link to.
-// compile-flags: -g -Z continue-parse-after-error
+// compile-flags: -g
 #![feature(rustc_private)]
 extern crate libc;
 
index 8ca98fc266a0188a6ff412a9dd5593c966a4eae2..69fed2cb69ad8898a240b80f59f9cb05f7616d02 100644 (file)
@@ -1,4 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
 // ignore-tidy-tab
 
 fn main() {
index 227ec27efc87fd9b70a79431f81541ce5f3923f2..d202044a2bb9726e1c7d682ac8478fa0fefa2462 100644 (file)
@@ -1,5 +1,5 @@
 error: incorrect unicode escape sequence
-  --> $DIR/format-string-error-2.rs:78:20
+  --> $DIR/format-string-error-2.rs:77:20
    |
 LL |     println!("\x7B}\u8 {", 1);
    |                    ^^-
@@ -7,7 +7,7 @@ LL |     println!("\x7B}\u8 {", 1);
    |                      help: format of unicode escape sequences uses braces: `\u{8}`
 
 error: invalid format string: expected `'}'`, found `'a'`
-  --> $DIR/format-string-error-2.rs:6:5
+  --> $DIR/format-string-error-2.rs:5:5
    |
 LL |     format!("{
    |              - because of this opening brace
@@ -17,7 +17,7 @@ LL |     a");
    = note: if you intended to print `{`, you can escape it using `{{`
 
 error: invalid format string: expected `'}'`, found `'b'`
-  --> $DIR/format-string-error-2.rs:10:5
+  --> $DIR/format-string-error-2.rs:9:5
    |
 LL |     format!("{ \
    |              - because of this opening brace
@@ -28,7 +28,7 @@ LL |     b");
    = note: if you intended to print `{`, you can escape it using `{{`
 
 error: invalid format string: expected `'}'`, found `'\'`
-  --> $DIR/format-string-error-2.rs:12:18
+  --> $DIR/format-string-error-2.rs:11:18
    |
 LL |     format!(r#"{ \
    |                - ^ expected `}` in format string
@@ -38,7 +38,7 @@ LL |     format!(r#"{ \
    = note: if you intended to print `{`, you can escape it using `{{`
 
 error: invalid format string: expected `'}'`, found `'\'`
-  --> $DIR/format-string-error-2.rs:16:18
+  --> $DIR/format-string-error-2.rs:15:18
    |
 LL |     format!(r#"{ \n
    |                - ^ expected `}` in format string
@@ -48,7 +48,7 @@ LL |     format!(r#"{ \n
    = note: if you intended to print `{`, you can escape it using `{{`
 
 error: invalid format string: expected `'}'`, found `'e'`
-  --> $DIR/format-string-error-2.rs:22:5
+  --> $DIR/format-string-error-2.rs:21:5
    |
 LL |     format!("{ \n
    |              - because of this opening brace
@@ -59,7 +59,7 @@ LL |     e");
    = note: if you intended to print `{`, you can escape it using `{{`
 
 error: invalid format string: expected `'}'`, found `'a'`
-  --> $DIR/format-string-error-2.rs:26:5
+  --> $DIR/format-string-error-2.rs:25:5
    |
 LL |     {
    |     - because of this opening brace
@@ -69,7 +69,7 @@ LL |     a");
    = note: if you intended to print `{`, you can escape it using `{{`
 
 error: invalid format string: expected `'}'`, found `'a'`
-  --> $DIR/format-string-error-2.rs:30:5
+  --> $DIR/format-string-error-2.rs:29:5
    |
 LL |     {
    |     - because of this opening brace
@@ -79,7 +79,7 @@ LL |     a
    = note: if you intended to print `{`, you can escape it using `{{`
 
 error: invalid format string: expected `'}'`, found `'b'`
-  --> $DIR/format-string-error-2.rs:36:5
+  --> $DIR/format-string-error-2.rs:35:5
    |
 LL |     { \
    |     - because of this opening brace
@@ -90,7 +90,7 @@ LL |     b");
    = note: if you intended to print `{`, you can escape it using `{{`
 
 error: invalid format string: expected `'}'`, found `'b'`
-  --> $DIR/format-string-error-2.rs:41:5
+  --> $DIR/format-string-error-2.rs:40:5
    |
 LL |     { \
    |     - because of this opening brace
@@ -101,7 +101,7 @@ LL |     b \
    = note: if you intended to print `{`, you can escape it using `{{`
 
 error: invalid format string: expected `'}'`, found `'\'`
-  --> $DIR/format-string-error-2.rs:46:8
+  --> $DIR/format-string-error-2.rs:45:8
    |
 LL | raw  { \
    |      - ^ expected `}` in format string
@@ -111,7 +111,7 @@ LL | raw  { \
    = note: if you intended to print `{`, you can escape it using `{{`
 
 error: invalid format string: expected `'}'`, found `'\'`
-  --> $DIR/format-string-error-2.rs:51:8
+  --> $DIR/format-string-error-2.rs:50:8
    |
 LL | raw  { \n
    |      - ^ expected `}` in format string
@@ -121,7 +121,7 @@ LL | raw  { \n
    = note: if you intended to print `{`, you can escape it using `{{`
 
 error: invalid format string: expected `'}'`, found `'e'`
-  --> $DIR/format-string-error-2.rs:58:5
+  --> $DIR/format-string-error-2.rs:57:5
    |
 LL |   { \n
    |   - because of this opening brace
@@ -132,7 +132,7 @@ LL |     e");
    = note: if you intended to print `{`, you can escape it using `{{`
 
 error: invalid format string: expected `'}'`, found `'a'`
-  --> $DIR/format-string-error-2.rs:68:5
+  --> $DIR/format-string-error-2.rs:67:5
    |
 LL |     {
    |     - because of this opening brace
@@ -142,13 +142,13 @@ LL |     asdf}
    = note: if you intended to print `{`, you can escape it using `{{`
 
 error: 1 positional argument in format string, but no arguments were given
-  --> $DIR/format-string-error-2.rs:71:17
+  --> $DIR/format-string-error-2.rs:70:17
    |
 LL |     println!("\t{}");
    |                 ^^
 
 error: invalid format string: expected `'}'` but string was terminated
-  --> $DIR/format-string-error-2.rs:75:27
+  --> $DIR/format-string-error-2.rs:74:27
    |
 LL |     println!("\x7B}\u{8} {", 1);
    |                          -^ expected `'}'` in format string
@@ -158,7 +158,7 @@ LL |     println!("\x7B}\u{8} {", 1);
    = note: if you intended to print `{`, you can escape it using `{{`
 
 error: invalid format string: unmatched `}` found
-  --> $DIR/format-string-error-2.rs:82:21
+  --> $DIR/format-string-error-2.rs:81:21
    |
 LL |     println!(r#"\x7B}\u{8} {"#, 1);
    |                     ^ unmatched `}` in format string
@@ -166,7 +166,7 @@ LL |     println!(r#"\x7B}\u{8} {"#, 1);
    = note: if you intended to print `}`, you can escape it using `}}`
 
 error: invalid format string: unmatched `}` found
-  --> $DIR/format-string-error-2.rs:85:21
+  --> $DIR/format-string-error-2.rs:84:21
    |
 LL |     println!(r#"\x7B}\u8 {"#, 1);
    |                     ^ unmatched `}` in format string
index eee97fe9587c288953130d2acfd004eb304b44aa..0bb24365ef42b49d8738a0e057e32b4c61bdd18b 100644 (file)
@@ -2,7 +2,9 @@ error[E0164]: expected tuple struct/variant, found method `<A>::new`
   --> $DIR/fn-in-pat.rs:11:9
    |
 LL |         A::new() => (),
-   |         ^^^^^^^^ not a tuple variant or struct
+   |         ^^^^^^^^ `fn` calls are not allowed in patterns
+   |
+   = help: for more information, visit https://doc.rust-lang.org/book/ch18-00-patterns.html
 
 error: aborting due to previous error
 
index 2e4f048a4e406d393b73922fa3906b13641267cb..dfac9c0f1ef86e3265aead23c37623a93e42c9f8 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: -Z parse-only -Z continue-parse-after-error
+// compile-flags: -Z parse-only
 
 fn f() -> impl A + {} // OK
 fn f() -> impl A + B {} // OK
index 2a9d913171c3eed222679f0fd42f7de0919c80d0..dfe7b3f6b5f9c74262ad17deb52589e915479832 100644 (file)
@@ -5,7 +5,7 @@ LL |     let mut test = |foo: &Foo| {
    |                    ----------- mutable borrow occurs here
 LL |         println!("access {}", foo.x);
 LL |         ptr = box Foo { x: ptr.x + 1 };
-   |         --- first borrow occurs due to use of `ptr` in closure
+   |                            --- first borrow occurs due to use of `ptr` in closure
 ...
 LL |     test(&*ptr);
    |     ---- ^^^^^ immutable borrow occurs here
index a28ea0d09f8f0fca7452fabb99118a15dc7155b0..cf36953546549c10e1d64d3f7c91d16c84062986 100644 (file)
@@ -89,7 +89,7 @@ error: expected type, found `4`
 LL |     println!("{}", a: &mut 4);
    |                            ^ expecting a type here because of type ascription
    |
-   = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+   = note: #![feature(type_ascription)] lets you annotate an expression with a type: `<expr>: <type>`
 note: this expression expects an ascribed type after the colon
   --> $DIR/issue-22644.rs:34:20
    |
index 2bbb32bf2b3725855ec0d86156a8b5c3bc668ab5..8d05c32d5de91d20ca2ff62ed5c3111759f23020 100644 (file)
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 enum Bird {
     pub Duck,
     //~^ ERROR unnecessary visibility qualifier
index cfdbf6c7287263daaf590339307b1157dd510d36..851bc5dfbdd9e20ebd4df7287d91b328fc91ae31 100644 (file)
@@ -1,11 +1,11 @@
 error: unnecessary visibility qualifier
-  --> $DIR/issue-28433.rs:4:5
+  --> $DIR/issue-28433.rs:2:5
    |
 LL |     pub Duck,
    |     ^^^ `pub` not permitted here
 
 error: unnecessary visibility qualifier
-  --> $DIR/issue-28433.rs:7:5
+  --> $DIR/issue-28433.rs:5:5
    |
 LL |     pub(crate) Dove
    |     ^^^^^^^^^^ `pub` not permitted here
index 7899c8d30f1ddca60eea74c71ded0ba3b83918c1..01f395377701751b7d82e155c205c5154d52954f 100644 (file)
@@ -4,7 +4,7 @@ error: expected type, found `42`
 LL |     Test::Drill(field: 42);
    |                        ^^ expecting a type here because of type ascription
    |
-   = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+   = note: #![feature(type_ascription)] lets you annotate an expression with a type: `<expr>: <type>`
 note: this expression expects an ascribed type after the colon
   --> $DIR/issue-34255-1.rs:8:17
    |
index 1d006fbdee4b56cf4d5e610432eff086ce51325a..2e64853697a1bd450b9b6ab6ab3a2a55cdeed84c 100644 (file)
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 struct Foo<Self>(Self);
 //~^ ERROR expected identifier, found keyword `Self`
 //~^^ ERROR E0392
index 2e44086161110750cffbab6565a8543c08b99f09..f3f94198465d878463b34a40e3af4cec4b7de64f 100644 (file)
@@ -1,17 +1,17 @@
 error: expected identifier, found keyword `Self`
-  --> $DIR/issue-36638.rs:3:12
+  --> $DIR/issue-36638.rs:1:12
    |
 LL | struct Foo<Self>(Self);
    |            ^^^^ expected identifier, found keyword
 
 error: expected identifier, found keyword `Self`
-  --> $DIR/issue-36638.rs:7:11
+  --> $DIR/issue-36638.rs:5:11
    |
 LL | trait Bar<Self> {}
    |           ^^^^ expected identifier, found keyword
 
 error[E0392]: parameter `Self` is never used
-  --> $DIR/issue-36638.rs:3:12
+  --> $DIR/issue-36638.rs:1:12
    |
 LL | struct Foo<Self>(Self);
    |            ^^^^ unused parameter
index 835094c4fdc5e2822a584d010d1650cf0c8526fc..140f19f1ff7746f0ed898c405acb7bd5564d4b8d 100644 (file)
@@ -1,8 +1,8 @@
 error[E0049]: method `foo` has 1 type parameter but its trait declaration has 0 type parameters
-  --> $DIR/issue-36708.rs:8:11
+  --> $DIR/issue-36708.rs:8:12
    |
 LL |     fn foo<T>() {}
-   |           ^^^ found 1 type parameter, expected 0
+   |            ^ found 1 type parameter, expected 0
 
 error: aborting due to previous error
 
index 1334f249256d625471e2cbe1f7f9c92925e6d35a..3928a3cd532015e1bd8da5f6ff7a3ca4e81cb580 100644 (file)
@@ -2,7 +2,9 @@ error[E0164]: expected tuple struct/variant, found method `<Path>::new`
   --> $DIR/issue-55587.rs:4:9
    |
 LL |     let Path::new();
-   |         ^^^^^^^^^^^ not a tuple variant or struct
+   |         ^^^^^^^^^^^ `fn` calls are not allowed in patterns
+   |
+   = help: for more information, visit https://doc.rust-lang.org/book/ch18-00-patterns.html
 
 error: aborting due to previous error
 
index 4a71932d1df182555c1221a9ceb8ce4b304092ad..ecfa5c69e2f038ed19bbc6264e017d0d839c4739 100644 (file)
@@ -10,6 +10,7 @@ impl Foo for u32 {
     fn foo(&self, t: impl Clone) {}
 //~^ ERROR method `foo` has 1 type parameter but its trait declaration has 0 type parameters
 //~| NOTE found 1 type parameter
+//~| NOTE `impl Trait` introduces an implicit type parameter
 }
 
 fn main() {}
index af7fdde9a8ed1d5a83487d5244e21100901ecd7a..30322f88cca42aa6020b8d84c665b06d86ad508e 100644 (file)
@@ -1,11 +1,14 @@
 error[E0049]: method `foo` has 1 type parameter but its trait declaration has 0 type parameters
-  --> $DIR/type-arg-mismatch-due-to-impl-trait.rs:10:5
+  --> $DIR/type-arg-mismatch-due-to-impl-trait.rs:10:22
    |
 LL |     fn foo(&self, t: Self::T);
-   |     -------------------------- expected 0 type parameters
+   |           - expected 0 type parameters
 ...
 LL |     fn foo(&self, t: impl Clone) {}
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found 1 type parameter
+   |                      ^^^^^^^^^^
+   |                      |
+   |                      found 1 type parameter
+   |                      `impl Trait` introduces an implicit type parameter
 
 error: aborting due to previous error
 
index cb5a52a3e081a75668a83902803fca0418b88ddb..8ae8018c2ff25f41d8018b21593eb9b1c35440b3 100644 (file)
@@ -14,7 +14,7 @@ error: expected type, found keyword `loop`
 LL |     loop { break 'label: loop { break 'label 42; }; }
    |                          ^^^^ expecting a type here because of type ascription
    |
-   = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+   = note: #![feature(type_ascription)] lets you annotate an expression with a type: `<expr>: <type>`
 note: this expression expects an ascribed type after the colon
   --> $DIR/lifetime_starts_expressions.rs:6:12
    |
index 6ca53816e3c6b0f892a6a725fccf96b66ec831a7..3a52996195c0d6e9b1b11ba59c2fe9deb452d55a 100644 (file)
@@ -1,10 +1,32 @@
 // compile-pass
 
+#![allow(ellipsis_inclusive_range_patterns)]
 #![allow(unreachable_patterns)]
 #![allow(unused_variables)]
 #![warn(unused_parens)]
 
 fn main() {
+    match 1 {
+        (_) => {}         //~ WARNING: unnecessary parentheses around pattern
+        (y) => {}         //~ WARNING: unnecessary parentheses around pattern
+        (ref r) => {}     //~ WARNING: unnecessary parentheses around pattern
+        (e @ 1...2) => {} //~ WARNING: unnecessary parentheses around outer pattern
+        (1...2) => {}     // Non ambiguous range pattern should not warn
+        e @ (3...4) => {} // Non ambiguous range pattern should not warn
+    }
+
+    match &1 {
+        (e @ &(1...2)) => {} //~ WARNING: unnecessary parentheses around outer pattern
+        &(_) => {}           //~ WARNING: unnecessary parentheses around pattern
+        e @ &(1...2) => {}   // Ambiguous range pattern should not warn
+        &(1...2) => {}       // Ambiguous range pattern should not warn
+    }
+
+    match &1 {
+        e @ &(1...2) | e @ &(3...4) => {} // Complex ambiguous pattern should not warn
+        &_ => {}
+    }
+
     match 1 {
         (_) => {}         //~ WARNING: unnecessary parentheses around pattern
         (y) => {}         //~ WARNING: unnecessary parentheses around pattern
@@ -15,14 +37,14 @@ fn main() {
     }
 
     match &1 {
-        (e @ &(1...2)) => {} //~ WARNING: unnecessary parentheses around outer pattern
+        (e @ &(1..=2)) => {} //~ WARNING: unnecessary parentheses around outer pattern
         &(_) => {}           //~ WARNING: unnecessary parentheses around pattern
-        e @ &(1...2) => {}   // Ambiguous range pattern should not warn
+        e @ &(1..=2) => {}   // Ambiguous range pattern should not warn
         &(1..=2) => {}       // Ambiguous range pattern should not warn
     }
 
     match &1 {
-        e @ &(1...2) | e @ &(3..=4) => {} // Complex ambiguous pattern should not warn
+        e @ &(1..=2) | e @ &(3..=4) => {} // Complex ambiguous pattern should not warn
         &_ => {}
     }
 }
index 3cf321b072f40fe57b552cc1752f824c71e33d74..3b312198952a5b66cb51073302e3c2f8bf4283c9 100644 (file)
@@ -1,41 +1,77 @@
 warning: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:9:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:10:9
    |
 LL |         (_) => {}
    |         ^^^ help: remove these parentheses
    |
 note: lint level defined here
-  --> $DIR/issue-54538-unused-parens-lint.rs:5:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:6:9
    |
 LL | #![warn(unused_parens)]
    |         ^^^^^^^^^^^^^
 
 warning: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:10:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:11:9
    |
 LL |         (y) => {}
    |         ^^^ help: remove these parentheses
 
 warning: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:11:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:12:9
    |
 LL |         (ref r) => {}
    |         ^^^^^^^ help: remove these parentheses
 
 warning: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:12:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:13:9
    |
-LL |         (e @ 1..=2) => {}
+LL |         (e @ 1...2) => {}
    |         ^^^^^^^^^^^ help: remove these parentheses
 
 warning: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:18:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:19:9
    |
 LL |         (e @ &(1...2)) => {}
    |         ^^^^^^^^^^^^^^ help: remove these parentheses
 
 warning: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:19:10
+  --> $DIR/issue-54538-unused-parens-lint.rs:20:10
+   |
+LL |         &(_) => {}
+   |          ^^^ help: remove these parentheses
+
+warning: unnecessary parentheses around pattern
+  --> $DIR/issue-54538-unused-parens-lint.rs:31:9
+   |
+LL |         (_) => {}
+   |         ^^^ help: remove these parentheses
+
+warning: unnecessary parentheses around pattern
+  --> $DIR/issue-54538-unused-parens-lint.rs:32:9
+   |
+LL |         (y) => {}
+   |         ^^^ help: remove these parentheses
+
+warning: unnecessary parentheses around pattern
+  --> $DIR/issue-54538-unused-parens-lint.rs:33:9
+   |
+LL |         (ref r) => {}
+   |         ^^^^^^^ help: remove these parentheses
+
+warning: unnecessary parentheses around pattern
+  --> $DIR/issue-54538-unused-parens-lint.rs:34:9
+   |
+LL |         (e @ 1..=2) => {}
+   |         ^^^^^^^^^^^ help: remove these parentheses
+
+warning: unnecessary parentheses around pattern
+  --> $DIR/issue-54538-unused-parens-lint.rs:40:9
+   |
+LL |         (e @ &(1..=2)) => {}
+   |         ^^^^^^^^^^^^^^ help: remove these parentheses
+
+warning: unnecessary parentheses around pattern
+  --> $DIR/issue-54538-unused-parens-lint.rs:41:10
    |
 LL |         &(_) => {}
    |          ^^^ help: remove these parentheses
index 4e24621706bdb91864ed914339081cd3d6d51b6f..bd918428351b9fbdb7c0acf6f0288792dca23cf1 100644 (file)
@@ -2,13 +2,17 @@ error[E0164]: expected tuple struct/variant, found method `<Path>::new`
   --> $DIR/match-fn-call.rs:6:9
    |
 LL |         Path::new("foo") => println!("foo"),
-   |         ^^^^^^^^^^^^^^^^ not a tuple variant or struct
+   |         ^^^^^^^^^^^^^^^^ `fn` calls are not allowed in patterns
+   |
+   = help: for more information, visit https://doc.rust-lang.org/book/ch18-00-patterns.html
 
 error[E0164]: expected tuple struct/variant, found method `<Path>::new`
   --> $DIR/match-fn-call.rs:8:9
    |
 LL |         Path::new("bar") => println!("bar"),
-   |         ^^^^^^^^^^^^^^^^ not a tuple variant or struct
+   |         ^^^^^^^^^^^^^^^^ `fn` calls are not allowed in patterns
+   |
+   = help: for more information, visit https://doc.rust-lang.org/book/ch18-00-patterns.html
 
 error: aborting due to 2 previous errors
 
index 99069183e4eda15fc97d9876f455a38ecb1e7150..a0cc773d20edd3cd184a5598f3b616b92454b25b 100644 (file)
@@ -8,31 +8,31 @@
 
 fn main() {
     match 5 {
-      1 ... 10 => { }
-      5 ... 6 => { }
+      1 ..= 10 => { }
+      5 ..= 6 => { }
       _ => {}
     };
 
     match 5 {
-      3 ... 6 => { }
-      4 ... 6 => { }
+      3 ..= 6 => { }
+      4 ..= 6 => { }
       _ => {}
     };
 
     match 5 {
-      4 ... 6 => { }
-      4 ... 6 => { }
+      4 ..= 6 => { }
+      4 ..= 6 => { }
       _ => {}
     };
 
     match 'c' {
-      'A' ... 'z' => {}
-      'a' ... 'z' => {}
+      'A' ..= 'z' => {}
+      'a' ..= 'z' => {}
       _ => {}
     };
 
     match 1.0f64 {
-      0.01f64 ... 6.5f64 => {}
+      0.01f64 ..= 6.5f64 => {}
       0.02f64 => {}
       _ => {}
     };
index 0f5ab7fff384050684ab068f5d14fe3c0e9d7119..f481e56c85e56bef00f4bd87f86c6e0752b6f865 100644 (file)
@@ -1,7 +1,7 @@
 error: unreachable pattern
   --> $DIR/match-range-fail-dominate.rs:12:7
    |
-LL |       5 ... 6 => { }
+LL |       5 ..= 6 => { }
    |       ^^^^^^^
    |
 note: lint level defined here
@@ -13,25 +13,25 @@ LL | #![deny(unreachable_patterns)]
 error: unreachable pattern
   --> $DIR/match-range-fail-dominate.rs:18:7
    |
-LL |       4 ... 6 => { }
+LL |       4 ..= 6 => { }
    |       ^^^^^^^
 
 error: unreachable pattern
   --> $DIR/match-range-fail-dominate.rs:24:7
    |
-LL |       4 ... 6 => { }
+LL |       4 ..= 6 => { }
    |       ^^^^^^^
 
 error: unreachable pattern
   --> $DIR/match-range-fail-dominate.rs:30:7
    |
-LL |       'a' ... 'z' => {}
+LL |       'a' ..= 'z' => {}
    |       ^^^^^^^^^^^
 
 warning: floating-point types cannot be used in patterns
   --> $DIR/match-range-fail-dominate.rs:35:7
    |
-LL |       0.01f64 ... 6.5f64 => {}
+LL |       0.01f64 ..= 6.5f64 => {}
    |       ^^^^^^^
    |
    = note: #[warn(illegal_floating_point_literal_pattern)] on by default
@@ -41,7 +41,7 @@ LL |       0.01f64 ... 6.5f64 => {}
 warning: floating-point types cannot be used in patterns
   --> $DIR/match-range-fail-dominate.rs:35:19
    |
-LL |       0.01f64 ... 6.5f64 => {}
+LL |       0.01f64 ..= 6.5f64 => {}
    |                   ^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
@@ -65,7 +65,7 @@ LL |       0.02f64 => {}
 warning: floating-point types cannot be used in patterns
   --> $DIR/match-range-fail-dominate.rs:35:7
    |
-LL |       0.01f64 ... 6.5f64 => {}
+LL |       0.01f64 ..= 6.5f64 => {}
    |       ^^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
index 135de0445a79989d0c82d367e8443c800f42d342..186f25a3c89db100d25a30b842221820b31d436f 100644 (file)
@@ -7,11 +7,11 @@ LL |             let mut closure1 = || p = &y;
    = note: defining type: DefId(0:14 ~ escape_upvar_nested[317d]::test[0]::{{closure}}[0]::{{closure}}[0]) with closure substs [
                i16,
                extern "rust-call" fn(()),
-               &'_#1r mut &'_#2r i32,
-               &'_#3r i32,
+               &'_#1r i32,
+               &'_#2r mut &'_#3r i32,
            ]
    = note: number of external vids: 4
-   = note: where '_#3r: '_#2r
+   = note: where '_#1r: '_#3r
 
 note: External requirements
   --> $DIR/escape-upvar-nested.rs:20:27
@@ -26,11 +26,11 @@ LL | |         };
    = note: defining type: DefId(0:13 ~ escape_upvar_nested[317d]::test[0]::{{closure}}[0]) with closure substs [
                i16,
                extern "rust-call" fn(()),
-               &'_#1r mut &'_#2r i32,
-               &'_#3r i32,
+               &'_#1r i32,
+               &'_#2r mut &'_#3r i32,
            ]
    = note: number of external vids: 4
-   = note: where '_#3r: '_#2r
+   = note: where '_#1r: '_#3r
 
 note: No external requirements
   --> $DIR/escape-upvar-nested.rs:13:1
index 8c37ab7b768c3cc930fe1136427d31a9a20c73da..0df2c0f69a71b32757f0718c038bb5cf594eb566 100644 (file)
@@ -7,11 +7,11 @@ LL |         let mut closure = || p = &y;
    = note: defining type: DefId(0:13 ~ escape_upvar_ref[317d]::test[0]::{{closure}}[0]) with closure substs [
                i16,
                extern "rust-call" fn(()),
-               &'_#1r mut &'_#2r i32,
-               &'_#3r i32,
+               &'_#1r i32,
+               &'_#2r mut &'_#3r i32,
            ]
    = note: number of external vids: 4
-   = note: where '_#3r: '_#2r
+   = note: where '_#1r: '_#3r
 
 note: No external requirements
   --> $DIR/escape-upvar-ref.rs:17:1
index 0b52e46c45989b9ea2d76ce845edb3d1912b2471..1399694a79b6ab4d03da60a7051d18442e328c58 100644 (file)
@@ -27,9 +27,9 @@ impl Range for ThreeDigits {
 
 fn digits(x: u8) -> u32 {
     match x {
-        OneDigit::FIRST...OneDigit::LAST => 1,
-        TwoDigits::FIRST...TwoDigits::LAST => 2,
-        ThreeDigits::FIRST...ThreeDigits::LAST => 3,
+        OneDigit::FIRST..=OneDigit::LAST => 1,
+        TwoDigits::FIRST..=TwoDigits::LAST => 2,
+        ThreeDigits::FIRST..=ThreeDigits::LAST => 3,
         _ => unreachable!(),
     }
 }
index ed9c996d4ccef9a619d806d61859928ccef64346..b238a9ca22674a70820117fc93e593326a57b601 100644 (file)
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 // Test you can't use a higher-ranked trait bound inside of a qualified
 // path (just won't parse).
 
index ceea4625e3eb3cb7ba64ff2a348897dfc883de48..ada0f268a8d6bd0e79b48a48b85dba5b9af080c0 100644 (file)
@@ -1,5 +1,5 @@
 error: expected identifier, found keyword `for`
-  --> $DIR/associated-types-project-from-hrtb-explicit.rs:12:21
+  --> $DIR/associated-types-project-from-hrtb-explicit.rs:10:21
    |
 LL | fn foo2<I>(x: <I as for<'x> Foo<&'x isize>>::A)
    |                     ^^^ expected identifier, found keyword
@@ -9,7 +9,7 @@ LL | fn foo2<I>(x: <I as r#for<'x> Foo<&'x isize>>::A)
    |                     ^^^^^
 
 error: expected one of `::` or `>`, found `Foo`
-  --> $DIR/associated-types-project-from-hrtb-explicit.rs:12:29
+  --> $DIR/associated-types-project-from-hrtb-explicit.rs:10:29
    |
 LL | fn foo2<I>(x: <I as for<'x> Foo<&'x isize>>::A)
    |                             ^^^ expected one of `::` or `>` here
index 151c6e1527ff566aa23bd7fda87327591c8ed65e..9f301db09956e87cc2c1257a38a5b7c385a4ea29 100644 (file)
@@ -1,6 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
-
 extern
     "C"suffix //~ ERROR suffixes on an ABI spec are invalid
     fn foo() {}
index e53b1498332d113f351f3d75c242fecb320358cc..208fcf43d917726860f7d77ee81ba5ac8395ce2e 100644 (file)
@@ -1,53 +1,53 @@
 error: suffixes on an ABI spec are invalid
-  --> $DIR/bad-lit-suffixes.rs:5:5
+  --> $DIR/bad-lit-suffixes.rs:2:5
    |
 LL |     "C"suffix
    |     ^^^^^^^^^ invalid suffix `suffix`
 
 error: suffixes on an ABI spec are invalid
-  --> $DIR/bad-lit-suffixes.rs:9:5
+  --> $DIR/bad-lit-suffixes.rs:6:5
    |
 LL |     "C"suffix
    |     ^^^^^^^^^ invalid suffix `suffix`
 
 error: suffixes on a string literal are invalid
-  --> $DIR/bad-lit-suffixes.rs:13:5
+  --> $DIR/bad-lit-suffixes.rs:10:5
    |
 LL |     ""suffix;
    |     ^^^^^^^^ invalid suffix `suffix`
 
 error: suffixes on a byte string literal are invalid
-  --> $DIR/bad-lit-suffixes.rs:14:5
+  --> $DIR/bad-lit-suffixes.rs:11:5
    |
 LL |     b""suffix;
    |     ^^^^^^^^^ invalid suffix `suffix`
 
 error: suffixes on a string literal are invalid
-  --> $DIR/bad-lit-suffixes.rs:15:5
+  --> $DIR/bad-lit-suffixes.rs:12:5
    |
 LL |     r#""#suffix;
    |     ^^^^^^^^^^^ invalid suffix `suffix`
 
 error: suffixes on a byte string literal are invalid
-  --> $DIR/bad-lit-suffixes.rs:16:5
+  --> $DIR/bad-lit-suffixes.rs:13:5
    |
 LL |     br#""#suffix;
    |     ^^^^^^^^^^^^ invalid suffix `suffix`
 
 error: suffixes on a char literal are invalid
-  --> $DIR/bad-lit-suffixes.rs:17:5
+  --> $DIR/bad-lit-suffixes.rs:14:5
    |
 LL |     'a'suffix;
    |     ^^^^^^^^^ invalid suffix `suffix`
 
 error: suffixes on a byte literal are invalid
-  --> $DIR/bad-lit-suffixes.rs:18:5
+  --> $DIR/bad-lit-suffixes.rs:15:5
    |
 LL |     b'a'suffix;
    |     ^^^^^^^^^^ invalid suffix `suffix`
 
 error: invalid width `1024` for integer literal
-  --> $DIR/bad-lit-suffixes.rs:20:5
+  --> $DIR/bad-lit-suffixes.rs:17:5
    |
 LL |     1234u1024;
    |     ^^^^^^^^^
@@ -55,7 +55,7 @@ LL |     1234u1024;
    = help: valid widths are 8, 16, 32, 64 and 128
 
 error: invalid width `1024` for integer literal
-  --> $DIR/bad-lit-suffixes.rs:21:5
+  --> $DIR/bad-lit-suffixes.rs:18:5
    |
 LL |     1234i1024;
    |     ^^^^^^^^^
@@ -63,7 +63,7 @@ LL |     1234i1024;
    = help: valid widths are 8, 16, 32, 64 and 128
 
 error: invalid width `1024` for float literal
-  --> $DIR/bad-lit-suffixes.rs:22:5
+  --> $DIR/bad-lit-suffixes.rs:19:5
    |
 LL |     1234f1024;
    |     ^^^^^^^^^
@@ -71,7 +71,7 @@ LL |     1234f1024;
    = help: valid widths are 32 and 64
 
 error: invalid width `1024` for float literal
-  --> $DIR/bad-lit-suffixes.rs:23:5
+  --> $DIR/bad-lit-suffixes.rs:20:5
    |
 LL |     1234.5f1024;
    |     ^^^^^^^^^^^
@@ -79,7 +79,7 @@ LL |     1234.5f1024;
    = help: valid widths are 32 and 64
 
 error: invalid suffix `suffix` for integer literal
-  --> $DIR/bad-lit-suffixes.rs:25:5
+  --> $DIR/bad-lit-suffixes.rs:22:5
    |
 LL |     1234suffix;
    |     ^^^^^^^^^^ invalid suffix `suffix`
@@ -87,7 +87,7 @@ LL |     1234suffix;
    = help: the suffix must be one of the integral types (`u32`, `isize`, etc)
 
 error: invalid suffix `suffix` for integer literal
-  --> $DIR/bad-lit-suffixes.rs:26:5
+  --> $DIR/bad-lit-suffixes.rs:23:5
    |
 LL |     0b101suffix;
    |     ^^^^^^^^^^^ invalid suffix `suffix`
@@ -95,7 +95,7 @@ LL |     0b101suffix;
    = help: the suffix must be one of the integral types (`u32`, `isize`, etc)
 
 error: invalid suffix `suffix` for float literal
-  --> $DIR/bad-lit-suffixes.rs:27:5
+  --> $DIR/bad-lit-suffixes.rs:24:5
    |
 LL |     1.0suffix;
    |     ^^^^^^^^^ invalid suffix `suffix`
@@ -103,7 +103,7 @@ LL |     1.0suffix;
    = help: valid suffixes are `f32` and `f64`
 
 error: invalid suffix `suffix` for float literal
-  --> $DIR/bad-lit-suffixes.rs:28:5
+  --> $DIR/bad-lit-suffixes.rs:25:5
    |
 LL |     1.0e10suffix;
    |     ^^^^^^^^^^^^ invalid suffix `suffix`
index 360e7939c955655eda0bb08eb76c95e53b778b7e..9122cb49ebc1a47731a634b6df8f0c9ee8436511 100644 (file)
@@ -1,4 +1,4 @@
-// compile-flags: -Z parse-only -Z continue-parse-after-error
+// compile-flags: -Z parse-only
 
 struct S<
     T: 'a + Tr, // OK
index 7870555aebb23d003fdb88f3c54e939d9e27f567..5b6f080360336c48dd3bb2639dc1d3d0587d7c00 100644 (file)
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 struct X {
     a: u8 /** document a */,
     //~^ ERROR found a documentation comment that doesn't document anything
index b84f353b8f1a44604da4a547e42edd47299fd175..e3b32a7f03543fbd10e5fbf21278c1a9aa8bd508 100644 (file)
@@ -1,5 +1,5 @@
 error[E0585]: found a documentation comment that doesn't document anything
-  --> $DIR/doc-after-struct-field.rs:4:11
+  --> $DIR/doc-after-struct-field.rs:2:11
    |
 LL |     a: u8 /** document a */,
    |           ^^^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL |     a: u8 /** document a */,
    = help: doc comments must come before what they document, maybe a comment was intended with `//`?
 
 error[E0585]: found a documentation comment that doesn't document anything
-  --> $DIR/doc-after-struct-field.rs:10:11
+  --> $DIR/doc-after-struct-field.rs:8:11
    |
 LL |     a: u8 /// document a
    |           ^^^^^^^^^^^^^^
index d33520baebe07b95cc9fb1f2ba59b527c99e2b5e..eb355136f1e66becf6ba59f985919c15f07c5c8d 100644 (file)
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 fn main() {
     /// document
     //~^ ERROR found a documentation comment that doesn't document anything
index a1ca88cf314877012621a3c687b73bd4338f8741..56241de7092477680c437a26e362eb16aada8b2d 100644 (file)
@@ -1,5 +1,5 @@
 error[E0585]: found a documentation comment that doesn't document anything
-  --> $DIR/doc-before-fn-rbrace.rs:4:5
+  --> $DIR/doc-before-fn-rbrace.rs:2:5
    |
 LL |     /// document
    |     ^^^^^^^^^^^^
index d9777be63d280e185253a13d32b2bd96a91bcfb5..76263ad92885d9d2ce9f9451275edc124e613c95 100644 (file)
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 fn /// document
 foo() {}
 //~^^ ERROR expected identifier, found doc comment `/// document`
index 4bc5e6f65d804e418d0d2eb60103c07bb331817d..940d293b6786ce86c7000d67ba10126691bcaf19 100644 (file)
@@ -1,5 +1,5 @@
 error: expected identifier, found doc comment `/// document`
-  --> $DIR/doc-before-identifier.rs:3:4
+  --> $DIR/doc-before-identifier.rs:1:4
    |
 LL | fn /// document
    |    ^^^^^^^^^^^^ expected identifier, found doc comment
index 4e0b65ef496db5a613147fd3bc5213ff692d388a..c65a0a93184c0ea5f65d8ed34df626c27fc36d96 100644 (file)
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 mod Foo {
     /// document
     //~^ ERROR expected item after doc comment
index 4eaf351f676c8963906faec647d7db7c6fc49a81..d5749c66cd2900d67961b45487d1bf5cd6d07217 100644 (file)
@@ -1,5 +1,5 @@
 error: expected item after doc comment
-  --> $DIR/doc-before-mod-rbrace.rs:4:5
+  --> $DIR/doc-before-mod-rbrace.rs:2:5
    |
 LL |     /// document
    |     ^^^^^^^^^^^^ this doc comment doesn't document anything
index e7055f6a5fcb4aa6a272196a33b74f45450c92c8..3866a3105c25aea4e23eb5b1f1d068d9637f808a 100644 (file)
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 struct X {
     a: u8,
     /// document
index f2824f85ca98a92cdaec28ecfb12fe90c66a4661..19f90677398ea4fb821e4ef8f727d1bcfe6b9f71 100644 (file)
@@ -1,5 +1,5 @@
 error[E0585]: found a documentation comment that doesn't document anything
-  --> $DIR/doc-before-struct-rbrace-1.rs:5:5
+  --> $DIR/doc-before-struct-rbrace-1.rs:3:5
    |
 LL |     /// document
    |     ^^^^^^^^^^^^
index d5c2a314cbbf863969637cdd9305c67a239dd32b..dda138f1a8835142596a9e7e72ef82f309957dec 100644 (file)
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 struct X {
     a: u8 /// document
     //~^ ERROR found a documentation comment that doesn't document anything
index ba3e884263ca3b2a295257f246b1f6cb4063ee2d..b25ccab79f94a102a1413bfb59cc2c018df78a84 100644 (file)
@@ -1,5 +1,5 @@
 error[E0585]: found a documentation comment that doesn't document anything
-  --> $DIR/doc-before-struct-rbrace-2.rs:4:11
+  --> $DIR/doc-before-struct-rbrace-2.rs:2:11
    |
 LL |     a: u8 /// document
    |           ^^^^^^^^^^^^
index d3f32255c31d798ef7beb13f26272f08d763c4ad..186a955c3135bb31c21f7f1a333d0e2c336cb1e9 100644 (file)
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 struct Bar<T> { x: T } where T: Copy //~ ERROR expected item, found keyword `where`
 
 fn main() {}
index 03e556da268f09c1cd79cfed63bb5de3d0509cf7..9c7fdf6ccb416320aaeb7e0b428f6dbf20ce3993 100644 (file)
@@ -1,5 +1,5 @@
 error: expected item, found keyword `where`
-  --> $DIR/issue-17904-2.rs:3:24
+  --> $DIR/issue-17904-2.rs:1:24
    |
 LL | struct Bar<T> { x: T } where T: Copy
    |                        ^^^^^ expected item
index 6112623041a7d18a3010d5de55e95bec86c65a72..7d6a54f4be12e82df1c2eb2afe374484415a9de1 100644 (file)
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 struct Baz<U> where U: Eq(U); //This is parsed as the new Fn* style parenthesis syntax.
 struct Baz<U> where U: Eq(U) -> R; // Notice this parses as well.
 struct Baz<U>(U) where U: Eq; // This rightfully signals no error as well.
index a44700936200d8a87152bc10863b5a007af420fd..38f30099ed59cd8f3419372830dde449be9b6007 100644 (file)
@@ -1,5 +1,5 @@
 error: expected one of `:`, `==`, or `=`, found `;`
-  --> $DIR/issue-17904.rs:6:33
+  --> $DIR/issue-17904.rs:4:33
    |
 LL | struct Foo<T> where T: Copy, (T);
    |                                 ^ expected one of `:`, `==`, or `=` here
index 7191a3234c0837828a3f8b1ab5149c0baa97c6b4..82f7ce62b9457804dc80c7c30a9c6d942ec3aaa2 100644 (file)
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 trait Trait<T> { type Item; }
 
 pub fn test<W, I: Trait<Item=(), W> >() {}
index 7022019a22f26c4aed51ba70aa39693ad023da81..08b230a14f50ebc8ba6213b4fb9997548a029da4 100644 (file)
@@ -1,5 +1,5 @@
 error: associated type bindings must be declared after generic parameters
-  --> $DIR/issue-32214.rs:5:25
+  --> $DIR/issue-32214.rs:3:25
    |
 LL | pub fn test<W, I: Trait<Item=(), W> >() {}
    |                         -------^^^
index 49e7a2f536f2a21ca59334561a4e56dfe16e4780..f31c00e5cc3fb8f5f7cd2dbea1c5e0de77335c3e 100644 (file)
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 pub fn test() {
     foo(|_|) //~ ERROR expected expression, found `)`
 }
index f812646ca58817a38e140f50f68281aafbc8d334..cdd779a93ef910736fb315b6cff60bc4357ac6a4 100644 (file)
@@ -1,5 +1,5 @@
 error: expected expression, found `)`
-  --> $DIR/issue-32505.rs:4:12
+  --> $DIR/issue-32505.rs:2:12
    |
 LL |     foo(|_|)
    |            ^ expected expression
index da36537f0f3070b452dd6f985a0943cf45e8b4b2..7df98073e35702427d6266cb7d004d780406dab8 100644 (file)
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 fn main() {
     0b121; //~ ERROR invalid digit for a base 2 literal
     0b10_10301; //~ ERROR invalid digit for a base 2 literal
index 15959f671b634e068411cbdb517487c1d87740ba..992b3d2487e5343048a77235b707b18891773ce2 100644 (file)
@@ -1,53 +1,53 @@
 error: invalid digit for a base 2 literal
-  --> $DIR/lex-bad-binary-literal.rs:4:8
+  --> $DIR/lex-bad-binary-literal.rs:2:8
    |
 LL |     0b121;
    |        ^
 
 error: invalid digit for a base 2 literal
-  --> $DIR/lex-bad-binary-literal.rs:5:12
+  --> $DIR/lex-bad-binary-literal.rs:3:12
    |
 LL |     0b10_10301;
    |            ^
 
 error: invalid digit for a base 2 literal
-  --> $DIR/lex-bad-binary-literal.rs:6:7
+  --> $DIR/lex-bad-binary-literal.rs:4:7
    |
 LL |     0b30;
    |       ^
 
 error: invalid digit for a base 2 literal
-  --> $DIR/lex-bad-binary-literal.rs:7:7
+  --> $DIR/lex-bad-binary-literal.rs:5:7
    |
 LL |     0b41;
    |       ^
 
 error: invalid digit for a base 2 literal
-  --> $DIR/lex-bad-binary-literal.rs:8:7
+  --> $DIR/lex-bad-binary-literal.rs:6:7
    |
 LL |     0b5;
    |       ^
 
 error: invalid digit for a base 2 literal
-  --> $DIR/lex-bad-binary-literal.rs:9:7
+  --> $DIR/lex-bad-binary-literal.rs:7:7
    |
 LL |     0b6;
    |       ^
 
 error: invalid digit for a base 2 literal
-  --> $DIR/lex-bad-binary-literal.rs:10:7
+  --> $DIR/lex-bad-binary-literal.rs:8:7
    |
 LL |     0b7;
    |       ^
 
 error: invalid digit for a base 2 literal
-  --> $DIR/lex-bad-binary-literal.rs:11:7
+  --> $DIR/lex-bad-binary-literal.rs:9:7
    |
 LL |     0b8;
    |       ^
 
 error: invalid digit for a base 2 literal
-  --> $DIR/lex-bad-binary-literal.rs:12:7
+  --> $DIR/lex-bad-binary-literal.rs:10:7
    |
 LL |     0b9;
    |       ^
index 67134c14cded3688ae0659e6bdd877cba7a37d3f..cf8440ca488ccaeeff1e75c5d2809b9bb1c851ad 100644 (file)
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 fn main() {
     0o1.0; //~ ERROR: octal float literal is not supported
     0o2f32; //~ ERROR: octal float literal is not supported
index 6d6cd3cc17129928db8b97a97233823bb2151ea6..84e27f7366d0c18c752d38287f7046f4cac74f72 100644 (file)
 error: octal float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:4:5
+  --> $DIR/lex-bad-numeric-literals.rs:2:5
    |
 LL |     0o1.0;
    |     ^^^^^
 
 error: octal float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:6:5
+  --> $DIR/lex-bad-numeric-literals.rs:4:5
    |
 LL |     0o3.0f32;
    |     ^^^^^
 
 error: octal float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:7:5
+  --> $DIR/lex-bad-numeric-literals.rs:5:5
    |
 LL |     0o4e4;
    |     ^^^^^
 
 error: octal float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:8:5
+  --> $DIR/lex-bad-numeric-literals.rs:6:5
    |
 LL |     0o5.0e5;
    |     ^^^^^^^
 
 error: octal float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:9:5
+  --> $DIR/lex-bad-numeric-literals.rs:7:5
    |
 LL |     0o6e6f32;
    |     ^^^^^
 
 error: octal float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:10:5
+  --> $DIR/lex-bad-numeric-literals.rs:8:5
    |
 LL |     0o7.0e7f64;
    |     ^^^^^^^
 
 error: hexadecimal float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:11:5
+  --> $DIR/lex-bad-numeric-literals.rs:9:5
    |
 LL |     0x8.0e+9;
    |     ^^^^^^^^
 
 error: hexadecimal float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:12:5
+  --> $DIR/lex-bad-numeric-literals.rs:10:5
    |
 LL |     0x9.0e-9;
    |     ^^^^^^^^
 
 error: no valid digits found for number
-  --> $DIR/lex-bad-numeric-literals.rs:13:5
+  --> $DIR/lex-bad-numeric-literals.rs:11:5
    |
 LL |     0o;
    |     ^^
 
 error: expected at least one digit in exponent
-  --> $DIR/lex-bad-numeric-literals.rs:14:8
+  --> $DIR/lex-bad-numeric-literals.rs:12:8
    |
 LL |     1e+;
    |        ^
 
 error: hexadecimal float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:15:5
+  --> $DIR/lex-bad-numeric-literals.rs:13:5
    |
 LL |     0x539.0;
    |     ^^^^^^^
 
 error: no valid digits found for number
-  --> $DIR/lex-bad-numeric-literals.rs:20:5
+  --> $DIR/lex-bad-numeric-literals.rs:18:5
    |
 LL |     0x;
    |     ^^
 
 error: no valid digits found for number
-  --> $DIR/lex-bad-numeric-literals.rs:21:5
+  --> $DIR/lex-bad-numeric-literals.rs:19:5
    |
 LL |     0xu32;
    |     ^^
 
 error: no valid digits found for number
-  --> $DIR/lex-bad-numeric-literals.rs:22:5
+  --> $DIR/lex-bad-numeric-literals.rs:20:5
    |
 LL |     0ou32;
    |     ^^
 
 error: no valid digits found for number
-  --> $DIR/lex-bad-numeric-literals.rs:23:5
+  --> $DIR/lex-bad-numeric-literals.rs:21:5
    |
 LL |     0bu32;
    |     ^^
 
 error: no valid digits found for number
-  --> $DIR/lex-bad-numeric-literals.rs:24:5
+  --> $DIR/lex-bad-numeric-literals.rs:22:5
    |
 LL |     0b;
    |     ^^
 
 error: octal float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:26:5
+  --> $DIR/lex-bad-numeric-literals.rs:24:5
    |
 LL |     0o123.456;
    |     ^^^^^^^^^
 
 error: binary float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:28:5
+  --> $DIR/lex-bad-numeric-literals.rs:26:5
    |
 LL |     0b111.101;
    |     ^^^^^^^^^
 
 error: octal float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:5:5
+  --> $DIR/lex-bad-numeric-literals.rs:3:5
    |
 LL |     0o2f32;
    |     ^^^^^^ not supported
 
 error: integer literal is too large
-  --> $DIR/lex-bad-numeric-literals.rs:16:5
+  --> $DIR/lex-bad-numeric-literals.rs:14:5
    |
 LL |     9900000000000000000000000000999999999999999999999999999999;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: integer literal is too large
-  --> $DIR/lex-bad-numeric-literals.rs:18:5
+  --> $DIR/lex-bad-numeric-literals.rs:16:5
    |
 LL |     9900000000000000000000000000999999999999999999999999999999;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: octal float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:25:5
+  --> $DIR/lex-bad-numeric-literals.rs:23:5
    |
 LL |     0o123f64;
    |     ^^^^^^^^ not supported
 
 error: binary float literal is not supported
-  --> $DIR/lex-bad-numeric-literals.rs:27:5
+  --> $DIR/lex-bad-numeric-literals.rs:25:5
    |
 LL |     0b101f64;
    |     ^^^^^^^^ not supported
index f4cc2c5c420fa5d27b304e3b312e109a88c37287..49631f16bdbd78148a1f91b8ac42c2108a9f76a7 100644 (file)
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 fn main() {
     0o18; //~ ERROR invalid digit for a base 8 literal
     0o1234_9_5670;  //~ ERROR invalid digit for a base 8 literal
index 01f4c236c9f3bfb2cbe5fadf763eeb83c563d4d3..2cb8ca5ded0ad47999a38ae489bed9e582a4b95a 100644 (file)
@@ -1,11 +1,11 @@
 error: invalid digit for a base 8 literal
-  --> $DIR/lex-bad-octal-literal.rs:4:8
+  --> $DIR/lex-bad-octal-literal.rs:2:8
    |
 LL |     0o18;
    |        ^
 
 error: invalid digit for a base 8 literal
-  --> $DIR/lex-bad-octal-literal.rs:5:12
+  --> $DIR/lex-bad-octal-literal.rs:3:12
    |
 LL |     0o1234_9_5670;
    |            ^
index 9294bebc5148ce057b694c658df6f7b953aed35c..544e4aa7b1b09d7e13f8ddf5276de830153bc577 100644 (file)
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 macro_rules! ignored_item {
     () => {
         fn foo() {}
index b37bd583060c5c72d941a776daa9424b1a1f7d79..e40919cda945f0b5b42201730e35cdd2453a5238 100644 (file)
@@ -1,5 +1,5 @@
 error: macro expansion ignores token `,` and any following
-  --> $DIR/macro-incomplete-parse.rs:7:9
+  --> $DIR/macro-incomplete-parse.rs:5:9
    |
 LL |         ,
    |         ^
@@ -10,7 +10,7 @@ LL | ignored_item!();
    = note: the usage of `ignored_item!` is likely invalid in item context
 
 error: expected one of `.`, `;`, `?`, `}`, or an operator, found `,`
-  --> $DIR/macro-incomplete-parse.rs:12:14
+  --> $DIR/macro-incomplete-parse.rs:10:14
    |
 LL |     () => ( 1,
    |              ^ expected one of `.`, `;`, `?`, `}`, or an operator here
@@ -19,7 +19,7 @@ LL |     ignored_expr!();
    |     ---------------- in this macro invocation
 
 error: macro expansion ignores token `,` and any following
-  --> $DIR/macro-incomplete-parse.rs:18:14
+  --> $DIR/macro-incomplete-parse.rs:16:14
    |
 LL |     () => ( 1, 2 )
    |              ^
index b871000ac1284785d50afe4e6f8d9ed9fc4686f2..9ac03cedc3f3ef6818d329849cf66fc8cf7085fd 100644 (file)
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 pub fn main() {
     let s = "\u{lol}";
      //~^ ERROR invalid character in unicode escape: l
index ca96b00aa7bc55153b5e7137e4e7f016afa79acf..a35c5f0f216588f31a5a0bd1cb55d79d85b53a59 100644 (file)
@@ -1,5 +1,5 @@
 error: invalid character in unicode escape: l
-  --> $DIR/new-unicode-escapes-4.rs:4:17
+  --> $DIR/new-unicode-escapes-4.rs:2:17
    |
 LL |     let s = "\u{lol}";
    |                 ^
index 57201f2d91afd6e77806d411de8b1790d5aadcc9..d1cd8ad53114b1f763fe45163a605a7d36b3013f 100644 (file)
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 trait A {
     fn foo(*mut self); //~ ERROR cannot pass `self` by raw pointer
     fn baz(*const self); //~ ERROR cannot pass `self` by raw pointer
index 96d8b56bf9ac3940f8a0380bafcaac220097811a..23323945ee4b6c2498691f6531fba62e06c30eff 100644 (file)
@@ -1,35 +1,35 @@
 error: cannot pass `self` by raw pointer
-  --> $DIR/no-unsafe-self.rs:4:17
+  --> $DIR/no-unsafe-self.rs:2:17
    |
 LL |     fn foo(*mut self);
    |                 ^^^^ cannot pass `self` by raw pointer
 
 error: cannot pass `self` by raw pointer
-  --> $DIR/no-unsafe-self.rs:5:19
+  --> $DIR/no-unsafe-self.rs:3:19
    |
 LL |     fn baz(*const self);
    |                   ^^^^ cannot pass `self` by raw pointer
 
 error: cannot pass `self` by raw pointer
-  --> $DIR/no-unsafe-self.rs:6:13
+  --> $DIR/no-unsafe-self.rs:4:13
    |
 LL |     fn bar(*self);
    |             ^^^^ cannot pass `self` by raw pointer
 
 error: cannot pass `self` by raw pointer
-  --> $DIR/no-unsafe-self.rs:11:17
+  --> $DIR/no-unsafe-self.rs:9:17
    |
 LL |     fn foo(*mut self) { }
    |                 ^^^^ cannot pass `self` by raw pointer
 
 error: cannot pass `self` by raw pointer
-  --> $DIR/no-unsafe-self.rs:12:19
+  --> $DIR/no-unsafe-self.rs:10:19
    |
 LL |     fn baz(*const self) { }
    |                   ^^^^ cannot pass `self` by raw pointer
 
 error: cannot pass `self` by raw pointer
-  --> $DIR/no-unsafe-self.rs:13:13
+  --> $DIR/no-unsafe-self.rs:11:13
    |
 LL |     fn bar(*self) { }
    |             ^^^^ cannot pass `self` by raw pointer
index a780304c2d51e68a4a4b057976d48d10909266d9..c3e600e771bdf0594123e20ae491e306c7fb85d4 100644 (file)
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 // Make sure that inclusive ranges with `...` syntax don't parse.
 
 use std::ops::RangeToInclusive;
index 21ad26d8d25538ecafb502d36c61406fd7f06779..f877c5c6f79de688f5e3b903c138f6ad01adc554 100644 (file)
@@ -1,5 +1,5 @@
 error: unexpected token: `...`
-  --> $DIR/range_inclusive_dotdotdot.rs:8:12
+  --> $DIR/range_inclusive_dotdotdot.rs:6:12
    |
 LL |     return ...1;
    |            ^^^
@@ -13,7 +13,7 @@ LL |     return ..=1;
    |            ^^^
 
 error: unexpected token: `...`
-  --> $DIR/range_inclusive_dotdotdot.rs:14:13
+  --> $DIR/range_inclusive_dotdotdot.rs:12:13
    |
 LL |     let x = ...0;
    |             ^^^
@@ -27,7 +27,7 @@ LL |     let x = ..=0;
    |             ^^^
 
 error: unexpected token: `...`
-  --> $DIR/range_inclusive_dotdotdot.rs:18:14
+  --> $DIR/range_inclusive_dotdotdot.rs:16:14
    |
 LL |     let x = 5...5;
    |              ^^^
@@ -41,7 +41,7 @@ LL |     let x = 5..=5;
    |              ^^^
 
 error: unexpected token: `...`
-  --> $DIR/range_inclusive_dotdotdot.rs:22:15
+  --> $DIR/range_inclusive_dotdotdot.rs:20:15
    |
 LL |     for _ in 0...1 {}
    |               ^^^
index 2800e4090cf7938d8569b66cce7c633372a306dd..3b50fb8036ada911eab0393b8aeaa06ef8ce4851 100644 (file)
@@ -1,6 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
-
 pub fn main() {
     br"é";  //~ ERROR raw byte string must be ASCII
     br##~"a"~##;  //~ ERROR only `#` is allowed in raw string delimitation
index a7f1af0a3474cf9988fc1e96c3e570cb514b51ab..671ed97d1b52a2e658e0eaa430d1a7c6f9ca24b1 100644 (file)
@@ -1,11 +1,11 @@
 error: raw byte string must be ASCII: \u{e9}
-  --> $DIR/raw-byte-string-literals.rs:5:8
+  --> $DIR/raw-byte-string-literals.rs:2:8
    |
 LL |     br"é";
    |        ^
 
 error: found invalid character; only `#` is allowed in raw string delimitation: ~
-  --> $DIR/raw-byte-string-literals.rs:6:6
+  --> $DIR/raw-byte-string-literals.rs:3:6
    |
 LL |     br##~"a"~##;
    |      ^^^
index da42da84acf2ef26a57003e60a2d0d3b37ba6c40..331bfff84f106a778f7f68cf6bfc5aa2d345b6c0 100644 (file)
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 fn main() {
     enum Test {
         Very
index 10b4aba4053bdd60d5dd27a06f5d12e235fcb8f2..81c7ae337dbebe0c12e91256032adaaa52691634 100644 (file)
@@ -1,17 +1,17 @@
 error: missing comma
-  --> $DIR/recover-enum.rs:5:13
+  --> $DIR/recover-enum.rs:3:13
    |
 LL |         Very
    |             ^ help: missing comma
 
 error: missing comma
-  --> $DIR/recover-enum.rs:7:19
+  --> $DIR/recover-enum.rs:5:19
    |
 LL |         Bad(usize)
    |                   ^ help: missing comma
 
 error: missing comma
-  --> $DIR/recover-enum.rs:9:27
+  --> $DIR/recover-enum.rs:7:27
    |
 LL |         Stuff { a: usize }
    |                           ^ help: missing comma
index 7f2f2cc7ab039b8897de9b75a0f34e3fb51414a8..0c9420889553b2a17fb388180a20b669337a55b3 100644 (file)
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 fn main() {
     enum Test {
         Var1,
index d1984a54e2f079b4b7b63bb4699a8cc2251a4fd3..9ed2e6f5eb6c4e26e384bd7abc8b0ef95d35d18e 100644 (file)
@@ -1,11 +1,11 @@
 error: expected type, found `{`
-  --> $DIR/recover-enum2.rs:8:18
+  --> $DIR/recover-enum2.rs:6:18
    |
 LL |             abc: {},
    |                  ^
 
 error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `{`
-  --> $DIR/recover-enum2.rs:27:22
+  --> $DIR/recover-enum2.rs:25:22
    |
 LL |             Nope(i32 {})
    |                      ^ expected one of 7 possible tokens here
index 1eba6d7d52877fa80ff1dc22e06aad06e3794433..150d74f07428d97cf519db0d0457604c84e89713 100644 (file)
@@ -4,7 +4,7 @@ error: expected type, found `3`
 LL |     let x = Enum::Foo(a: 3, b: 4);
    |                          ^ expecting a type here because of type ascription
    |
-   = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+   = note: #![feature(type_ascription)] lets you annotate an expression with a type: `<expr>: <type>`
 note: this expression expects an ascribed type after the colon
   --> $DIR/recover-from-bad-variant.rs:7:23
    |
index 500591b2ad138ddd723125b7d805cfe1c5f34086..bfa5b454c0a8b37b1c6f0e56bef757fd63f68c25 100644 (file)
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 fn main() {
     struct Test {
         Very
index 8e11d6b29a58436113230203ef8808beefe05cb1..1b72184b0c8861fc3b84dfd8e011d027bc1e9f46 100644 (file)
@@ -1,5 +1,5 @@
 error: expected `:`, found `Bad`
-  --> $DIR/recover-struct.rs:6:9
+  --> $DIR/recover-struct.rs:4:9
    |
 LL |         Very
    |             - expected `:`
index 3412788668ac2583d46e59388916eded24f2e587..9fe4a148a56aa0adb1001a32c45ac9b3d4467b06 100644 (file)
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 struct S {
     let foo: (),
     //~^  ERROR expected identifier, found keyword `let`
index 0d489beae123aca8cd600a1b0547db2d651796c0..d6e38be4869eb3fd6502655ec2c8ce4e0f60ea60 100644 (file)
@@ -1,5 +1,5 @@
 error: expected identifier, found keyword `let`
-  --> $DIR/removed-syntax-field-let.rs:4:5
+  --> $DIR/removed-syntax-field-let.rs:2:5
    |
 LL |     let foo: (),
    |     ^^^ expected identifier, found keyword
@@ -9,7 +9,7 @@ LL |     r#let foo: (),
    |     ^^^^^
 
 error: expected `:`, found `foo`
-  --> $DIR/removed-syntax-field-let.rs:4:9
+  --> $DIR/removed-syntax-field-let.rs:2:9
    |
 LL |     let foo: (),
    |         ^^^ expected `:`
index 89a2953ad0fd4a1721655a7e27f76f2812dbe924..3213e068053714e8e8556d10c667a35a5311c321 100644 (file)
@@ -1,5 +1,4 @@
 // compile-pass
-// compile-flags: -Z continue-parse-after-error
 
 #![feature(box_syntax)]
 #![allow(bare_trait_objects)]
index d77ff80ca2597c0f0b3dbeb961fcbb352e082e43..02563847ef32694e055ea88466bb3e2b0a32bd49 100644 (file)
@@ -1,11 +1,7 @@
-// compile-flags: -Z continue-parse-after-error
-
-trait Foo {
-}
+trait Foo {}
 
 struct Bar;
 
-impl Foo + Owned for Bar { //~ ERROR expected a trait, found type
-}
+impl Foo + Owned for Bar {} //~ ERROR expected a trait, found type
 
 fn main() { }
index a712f68044ec088e2cfe13e3e93253ce31a4e5a8..8d2d5e3d7ddd2582d05b0091dc9bb243e403af71 100644 (file)
@@ -1,7 +1,7 @@
 error: expected a trait, found type
-  --> $DIR/trait-bounds-not-on-impl.rs:8:6
+  --> $DIR/trait-bounds-not-on-impl.rs:5:6
    |
-LL | impl Foo + Owned for Bar {
+LL | impl Foo + Owned for Bar {}
    |      ^^^^^^^^^^^
 
 error: aborting due to previous error
index e81b019b6468fa955758877e4db374129d288797..048e028be1ca171c7df53c4fb1c6011eef19652f 100644 (file)
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 #![feature(optin_builtin_traits)]
 #![allow(bare_trait_objects)]
 
index a36727ffeaf103158e827766035c5730e3d4394a..f53afdff5e7c2615e4d7e1abe75fe160fd73145a 100644 (file)
@@ -1,23 +1,23 @@
 error[E0178]: expected a path on the left-hand side of `+`, not `((Auto))`
-  --> $DIR/trait-object-bad-parens.rs:9:16
+  --> $DIR/trait-object-bad-parens.rs:7:16
    |
 LL |     let _: Box<((Auto)) + Auto>;
    |                ^^^^^^^^^^^^^^^ expected a path
 
 error[E0178]: expected a path on the left-hand side of `+`, not `(Auto + Auto)`
-  --> $DIR/trait-object-bad-parens.rs:11:16
+  --> $DIR/trait-object-bad-parens.rs:9:16
    |
 LL |     let _: Box<(Auto + Auto) + Auto>;
    |                ^^^^^^^^^^^^^^^^^^^^ expected a path
 
 error[E0178]: expected a path on the left-hand side of `+`, not `(Auto)`
-  --> $DIR/trait-object-bad-parens.rs:13:16
+  --> $DIR/trait-object-bad-parens.rs:11:16
    |
 LL |     let _: Box<(Auto +) + Auto>;
    |                ^^^^^^^^^^^^^^^ expected a path
 
 error[E0178]: expected a path on the left-hand side of `+`, not `(dyn Auto)`
-  --> $DIR/trait-object-bad-parens.rs:15:16
+  --> $DIR/trait-object-bad-parens.rs:13:16
    |
 LL |     let _: Box<(dyn Auto) + Auto>;
    |                ^^^^^^^^^^^^^^^^^ expected a path
index d5598afd6f4fdffcfd2e757f7ea61ed0d8ffaf51..5bbda4296ca7eef4f9cf078049615d2f4ae69dfc 100644 (file)
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 #![allow(bare_trait_objects)]
 
 trait Trait {}
index 55f14c978760f7e790cdf69df1ac463e10f01911..a31b7aea8fee6f9d0117aece4e62e45dfa6e2462 100644 (file)
@@ -1,23 +1,23 @@
 error: parenthesized lifetime bounds are not supported
-  --> $DIR/trait-object-lifetime-parens.rs:7:21
+  --> $DIR/trait-object-lifetime-parens.rs:5:21
    |
 LL | fn f<'a, T: Trait + ('a)>() {}
    |                     ^^^^ help: remove the parentheses
 
 error: parenthesized lifetime bounds are not supported
-  --> $DIR/trait-object-lifetime-parens.rs:10:24
+  --> $DIR/trait-object-lifetime-parens.rs:8:24
    |
 LL |     let _: Box<Trait + ('a)>;
    |                        ^^^^ help: remove the parentheses
 
 error: expected `:`, found `)`
-  --> $DIR/trait-object-lifetime-parens.rs:11:19
+  --> $DIR/trait-object-lifetime-parens.rs:9:19
    |
 LL |     let _: Box<('a) + Trait>;
    |                   ^ expected `:`
 
 error: chained comparison operators require parentheses
-  --> $DIR/trait-object-lifetime-parens.rs:11:15
+  --> $DIR/trait-object-lifetime-parens.rs:9:15
    |
 LL |     let _: Box<('a) + Trait>;
    |               ^^^^^^^^^^^^^^^
@@ -26,7 +26,7 @@ LL |     let _: Box<('a) + Trait>;
    = help: or use `(...)` if you meant to specify fn arguments
 
 error: expected type, found `'a`
-  --> $DIR/trait-object-lifetime-parens.rs:11:17
+  --> $DIR/trait-object-lifetime-parens.rs:9:17
    |
 LL |     let _: Box<('a) + Trait>;
    |         -       ^^
index d322e9ffe68cdfaea5b360b7e13279036911ee2c..b4bb484182466f34774171fde6c02d11cf59d094 100644 (file)
@@ -1,4 +1,2 @@
-// compile-flags: -Z continue-parse-after-error
-
 use std::any:: as foo; //~ ERROR expected identifier, found keyword `as`
 //~^ ERROR: expected one of `::`, `;`, or `as`, found `foo`
index 36917523555b93ca0d03c2f05ac6187f9c4eb3e6..076440025435044e2c0624cb2687cfbbe24e2272 100644 (file)
@@ -1,5 +1,5 @@
 error: expected identifier, found keyword `as`
-  --> $DIR/use-as-where-use-ends-with-mod-sep.rs:3:16
+  --> $DIR/use-as-where-use-ends-with-mod-sep.rs:1:16
    |
 LL | use std::any:: as foo;
    |                ^^ expected identifier, found keyword
@@ -9,7 +9,7 @@ LL | use std::any:: r#as foo;
    |                ^^^^
 
 error: expected one of `::`, `;`, or `as`, found `foo`
-  --> $DIR/use-as-where-use-ends-with-mod-sep.rs:3:19
+  --> $DIR/use-as-where-use-ends-with-mod-sep.rs:1:19
    |
 LL | use std::any:: as foo;
    |                   ^^^ expected one of `::`, `;`, or `as` here
index 45dacf22cfa3a489837b3e02a34f50fb253b56d5..e80db5372b609437863c499592b15a8de48c67a4 100644 (file)
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 // Empty predicate list is OK
 fn equal1<T>(_: &T, _: &T) -> bool where {
     true
index 7e82522872eed8a2adb82b73154c92dfa8326335..b80b0a409065b8b8d382b25124c39c9e5cd7ca16 100644 (file)
@@ -1,5 +1,5 @@
 error: expected `:`, found `{`
-  --> $DIR/where-clauses-no-bounds-or-predicates.rs:13:23
+  --> $DIR/where-clauses-no-bounds-or-predicates.rs:11:23
    |
 LL | fn foo<'a>() where 'a {}
    |                       ^ expected `:`
index 4a1681e4e2b8a83b1a496ca9fe0009698453154a..01b3309fcacb15e92f02dd10f34f2cf606a8842e 100644 (file)
@@ -1,5 +1,3 @@
-// compile-flags: -Z continue-parse-after-error
-
 mod foo {
   struct Self;
   //~^ ERROR expected identifier, found keyword `Self`
index e0df00ffa9299ab818189e00efc3f25a84b31efa..b63de98b8e7021ddd3cd53006f8645712f8dd6bd 100644 (file)
@@ -1,65 +1,65 @@
 error: expected identifier, found keyword `Self`
-  --> $DIR/self_type_keyword.rs:4:10
+  --> $DIR/self_type_keyword.rs:2:10
    |
 LL |   struct Self;
    |          ^^^^ expected identifier, found keyword
 
 error: expected identifier, found keyword `Self`
-  --> $DIR/self_type_keyword.rs:16:13
+  --> $DIR/self_type_keyword.rs:14:13
    |
 LL |         ref Self => (),
    |             ^^^^ expected identifier, found keyword
 
 error: expected identifier, found keyword `Self`
-  --> $DIR/self_type_keyword.rs:18:13
+  --> $DIR/self_type_keyword.rs:16:13
    |
 LL |         mut Self => (),
    |             ^^^^ expected identifier, found keyword
 
 error: expected identifier, found keyword `Self`
-  --> $DIR/self_type_keyword.rs:20:17
+  --> $DIR/self_type_keyword.rs:18:17
    |
 LL |         ref mut Self => (),
    |                 ^^^^ expected identifier, found keyword
 
 error: expected identifier, found keyword `Self`
-  --> $DIR/self_type_keyword.rs:24:15
+  --> $DIR/self_type_keyword.rs:22:15
    |
 LL |         Foo { Self } => (),
    |               ^^^^ expected identifier, found keyword
 
 error: expected identifier, found keyword `Self`
-  --> $DIR/self_type_keyword.rs:30:26
+  --> $DIR/self_type_keyword.rs:28:26
    |
 LL |     extern crate core as Self;
    |                          ^^^^ expected identifier, found keyword
 
 error: expected identifier, found keyword `Self`
-  --> $DIR/self_type_keyword.rs:35:32
+  --> $DIR/self_type_keyword.rs:33:32
    |
 LL |     use std::option::Option as Self;
    |                                ^^^^ expected identifier, found keyword
 
 error: expected identifier, found keyword `Self`
-  --> $DIR/self_type_keyword.rs:40:11
+  --> $DIR/self_type_keyword.rs:38:11
    |
 LL |     trait Self {}
    |           ^^^^ expected identifier, found keyword
 
 error: lifetimes cannot use keyword names
-  --> $DIR/self_type_keyword.rs:8:12
+  --> $DIR/self_type_keyword.rs:6:12
    |
 LL | struct Bar<'Self>;
    |            ^^^^^
 
 error: cannot find macro `Self!` in this scope
-  --> $DIR/self_type_keyword.rs:22:9
+  --> $DIR/self_type_keyword.rs:20:9
    |
 LL |         Self!() => (),
    |         ^^^^
 
 error[E0392]: parameter `'Self` is never used
-  --> $DIR/self_type_keyword.rs:8:12
+  --> $DIR/self_type_keyword.rs:6:12
    |
 LL | struct Bar<'Self>;
    |            ^^^^^ unused parameter
index 0bbe424aa025b99574792a4eb2534d081daaabc0..7fcd2ede31b69b1279d798b61e8da2a5518d1dce 100644 (file)
@@ -1,16 +1,16 @@
-error: symbol-name(_ZN11issue_609253foo36Foo$LT$issue_60925..llv$6d$..Foo$GT$3foo17h059a991a004536adE)
+error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h059a991a004536adE)
   --> $DIR/issue-60925.rs:21:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling(issue_60925::foo::Foo<issue_60925::llv$6d$..Foo$GT$::foo::h059a991a004536ad)
+error: demangling(issue_60925::foo::Foo<issue_60925::llv$u6d$..Foo$GT$::foo::h059a991a004536ad)
   --> $DIR/issue-60925.rs:21:9
    |
 LL |         #[rustc_symbol_name]
    |         ^^^^^^^^^^^^^^^^^^^^
 
-error: demangling-alt(issue_60925::foo::Foo<issue_60925::llv$6d$..Foo$GT$::foo)
+error: demangling-alt(issue_60925::foo::Foo<issue_60925::llv$u6d$..Foo$GT$::foo)
   --> $DIR/issue-60925.rs:21:9
    |
 LL |         #[rustc_symbol_name]
index 09d68eebb950e77377363f24b46cf4fe7386eb57..89de15cc0f3e47d23f0f21eb66a7757606ce7408 100644 (file)
@@ -19,9 +19,9 @@ mod foo {
 
     impl Foo<::llvm::Foo> {
         #[rustc_symbol_name]
-        //[legacy]~^ ERROR symbol-name(_ZN11issue_609253foo36Foo$LT$issue_60925..llv$6d$..Foo$GT$3foo
-        //[legacy]~| ERROR demangling(issue_60925::foo::Foo<issue_60925::llv$6d$..Foo$GT$::foo
-        //[legacy]~| ERROR demangling-alt(issue_60925::foo::Foo<issue_60925::llv$6d$..Foo$GT$::foo)
+        //[legacy]~^ ERROR symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo
+        //[legacy]~| ERROR demangling(issue_60925::foo::Foo<issue_60925::llv$u6d$..Foo$GT$::foo
+        //[legacy]~| ERROR demangling-alt(issue_60925::foo::Foo<issue_60925::llv$u6d$..Foo$GT$::foo)
          //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs4fqI2P2rA04_11issue_609253fooINtB2_3FooNtNtB4_4llvm3FooE3foo)
             //[v0]~| ERROR demangling(<issue_60925[317d481089b8c8fe]::foo::Foo<issue_60925[317d481089b8c8fe]::llvm::Foo>>::foo)
             //[v0]~| ERROR demangling-alt(<issue_60925::foo::Foo<issue_60925::llvm::Foo>>::foo)
index 4d56fcf11e39e1fea08bb8ab4608772c53ac82f7..8a9b8e793487c9f6916c2762a6971a4445bf0cda 100644 (file)
@@ -1,8 +1,6 @@
 // A few contrived examples where lifetime should (or should not) be parsed as an object type.
 // Lifetimes parsed as types are still rejected later by semantic checks.
 
-// compile-flags: -Z continue-parse-after-error
-
 // `'static` is a lifetime, `'static +` is a type, `'a` is a type
 fn g() where
     'static: 'static,
index 24162c920be33701968d014c1a4ed732a44c0304..ef5e2407b9a0e996866d0f23b8a0994c9ecbc7c5 100644 (file)
@@ -1,5 +1,5 @@
 error[E0224]: at least one non-builtin trait is required for an object type
-  --> $DIR/trait-object-vs-lifetime-2.rs:9:5
+  --> $DIR/trait-object-vs-lifetime-2.rs:7:5
    |
 LL |     dyn 'static +: 'static + Copy,
    |     ^^^^^^^^^^^^^
index 2084cbcce4f6253ddd17027f2864c8b7498c288c..4929922c83fe6c0338d333e31f76149e547e3ad0 100644 (file)
@@ -12,7 +12,7 @@ error: expected type, found `0`
 LL |     println!("test"): 0;
    |                       ^ expecting a type here because of type ascription
    |
-   = note: type ascription is a nightly-only feature that lets you annotate an expression with a type: `<expr>: <type>`
+   = note: #![feature(type_ascription)] lets you annotate an expression with a type: `<expr>: <type>`
 note: this expression expects an ascribed type after the colon
   --> $DIR/type-ascription-instead-of-statement-end.rs:9:5
    |
index d2f51228152a139a2a8aaba59b8a4e68f498ff26..f3087c37bf5d8491b72ce007b65a47c2d3c2e733 160000 (submodule)
@@ -1 +1 @@
-Subproject commit d2f51228152a139a2a8aaba59b8a4e68f498ff26
+Subproject commit f3087c37bf5d8491b72ce007b65a47c2d3c2e733
index 0c85dbf3df0f545133dca24eccfc9f0f6107c7f8..e1a0f66373a1a185334a6e3be24e94161e3b4a43 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 0c85dbf3df0f545133dca24eccfc9f0f6107c7f8
+Subproject commit e1a0f66373a1a185334a6e3be24e94161e3b4a43
index ad3ac986c94f6c8f6561ff646e5bde5b1fe9178e..7922cb14eeca8c12c980d30676fccbd1661a8157 100644 (file)
@@ -92,6 +92,7 @@
     Crate("fuchsia-zircon-sys"),
     Crate("getopts"),
     Crate("humantime"),
+    Crate("indexmap"),
     Crate("itertools"),
     Crate("jobserver"),
     Crate("kernel32-sys"),