]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #61499 - varkor:issue-53457, r=oli-obk
authorMazdak Farrokhzad <twingoow@gmail.com>
Tue, 4 Jun 2019 02:48:31 +0000 (04:48 +0200)
committerGitHub <noreply@github.com>
Tue, 4 Jun 2019 02:48:31 +0000 (04:48 +0200)
Add regression test for existential type ICE #53457

Closes #53457.

356 files changed:
.azure-pipelines/steps/install-clang.yml
.azure-pipelines/steps/install-sccache.yml
.azure-pipelines/steps/install-windows-build-deps.yml
.azure-pipelines/steps/run.yml
Cargo.lock
src/bootstrap/config.rs
src/bootstrap/doc.rs
src/ci/docker/scripts/musl-toolchain.sh
src/ci/shared.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/liballoc/rc.rs
src/liballoc/str.rs
src/liballoc/vec.rs
src/libcore/convert.rs
src/libcore/intrinsics.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/dep_graph/dep_node.rs
src/librustc/hir/def.rs
src/librustc/hir/intravisit.rs
src/librustc/hir/lowering.rs
src/librustc/hir/map/def_collector.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/error_reporting/need_type_info.rs
src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs
src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs
src/librustc/infer/mod.rs
src/librustc/infer/region_constraints/mod.rs
src/librustc/lint/context.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/middle/resolve_lifetime.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/mir/mono.rs
src/librustc/query/mod.rs
src/librustc/traits/error_reporting.rs
src/librustc/ty/context.rs
src/librustc/ty/instance.rs
src/librustc/ty/layout.rs
src/librustc/ty/mod.rs
src/librustc/ty/print/mod.rs
src/librustc/ty/print/obsolete.rs [new file with mode: 0644]
src/librustc/ty/print/pretty.rs
src/librustc/ty/query/keys.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/base.rs
src/librustc_codegen_llvm/builder.rs
src/librustc_codegen_llvm/callee.rs
src/librustc_codegen_llvm/common.rs
src/librustc_codegen_llvm/consts.rs
src/librustc_codegen_llvm/context.rs
src/librustc_codegen_llvm/debuginfo/metadata.rs
src/librustc_codegen_llvm/debuginfo/mod.rs
src/librustc_codegen_llvm/debuginfo/namespace.rs
src/librustc_codegen_llvm/intrinsic.rs
src/librustc_codegen_llvm/lib.rs
src/librustc_codegen_llvm/llvm/ffi.rs
src/librustc_codegen_llvm/mono_item.rs
src/librustc_codegen_llvm/type_of.rs
src/librustc_codegen_ssa/Cargo.toml
src/librustc_codegen_ssa/README.md
src/librustc_codegen_ssa/base.rs
src/librustc_codegen_ssa/meth.rs
src/librustc_codegen_ssa/mir/block.rs
src/librustc_codegen_ssa/mir/constant.rs
src/librustc_codegen_ssa/mir/mod.rs
src/librustc_codegen_ssa/mir/operand.rs
src/librustc_codegen_ssa/mir/rvalue.rs
src/librustc_codegen_ssa/mono_item.rs
src/librustc_codegen_ssa/traits/builder.rs
src/librustc_codegen_ssa/traits/debuginfo.rs
src/librustc_codegen_ssa/traits/declare.rs
src/librustc_codegen_ssa/traits/misc.rs
src/librustc_codegen_utils/Cargo.toml
src/librustc_codegen_utils/symbol_names.rs
src/librustc_codegen_utils/symbol_names/legacy.rs
src/librustc_codegen_utils/symbol_names/v0.rs
src/librustc_codegen_utils/symbol_names_test.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_lint/unused.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/borrow_check/used_muts.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/hair/pattern/mod.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/mod.rs
src/librustc_mir/interpret/operand.rs
src/librustc_mir/interpret/place.rs
src/librustc_mir/interpret/terminator.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/monomorphize/item.rs
src/librustc_mir/monomorphize/mod.rs
src/librustc_mir/monomorphize/partitioning.rs
src/librustc_mir/shim.rs
src/librustc_mir/transform/mod.rs
src/librustc_mir/transform/qualify_consts.rs
src/librustc_passes/ast_validation.rs
src/librustc_passes/rvalue_promotion.rs
src/librustc_privacy/lib.rs
src/librustc_resolve/Cargo.toml
src/librustc_resolve/lib.rs
src/librustc_save_analysis/lib.rs
src/librustc_save_analysis/sig.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/intrinsic.rs
src/librustc_typeck/check/method/suggest.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/clean/mod.rs
src/librustdoc/html/format.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/ast.rs
src/libsyntax/attr/builtin.rs
src/libsyntax/ext/build.rs
src/libsyntax/ext/placeholders.rs
src/libsyntax/mut_visit.rs
src/libsyntax/parse/diagnostics.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pprust.rs
src/libsyntax/source_map.rs
src/libsyntax/visit.rs
src/libsyntax_ext/deriving/debug.rs
src/libtest/lib.rs
src/llvm-project
src/test/codegen/unchecked_math.rs [new file with mode: 0644]
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/anon-params-denied-2018.rs
src/test/ui/anon-params-denied-2018.stderr
src/test/ui/async-await/async-await.rs
src/test/ui/async-await/await-macro.rs
src/test/ui/async-await/issues/issue-61187.rs [new file with mode: 0644]
src/test/ui/async-await/issues/issue-61187.stderr [new file with mode: 0644]
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/condition-in-trait-const-arg.rs [new file with mode: 0644]
src/test/ui/const-generics/condition-in-trait-const-arg.stderr [new file with mode: 0644]
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/intrinsics/unchecked_math_unsafe.rs [new file with mode: 0644]
src/test/ui/intrinsics/unchecked_math_unsafe.stderr [new file with mode: 0644]
src/test/ui/intrinsics/unchecked_math_unstable.rs [new file with mode: 0644]
src/test/ui/intrinsics/unchecked_math_unstable.stderr [new file with mode: 0644]
src/test/ui/issues/issue-11192.stderr
src/test/ui/issues/issue-12187-1.rs
src/test/ui/issues/issue-12187-1.stderr
src/test/ui/issues/issue-12187-2.rs
src/test/ui/issues/issue-12187-2.stderr
src/test/ui/issues/issue-17551.stderr
src/test/ui/issues/issue-20261.stderr
src/test/ui/issues/issue-21596.rs [new file with mode: 0644]
src/test/ui/issues/issue-21596.stderr [new file with mode: 0644]
src/test/ui/issues/issue-22644.stderr
src/test/ui/issues/issue-23046.stderr
src/test/ui/issues/issue-25368.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/issue-7813.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/lint/must_use-tuple.rs [new file with mode: 0644]
src/test/ui/lint/must_use-tuple.stderr [new file with mode: 0644]
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/methods/method-ambig-one-trait-unknown-int-type.rs
src/test/ui/methods/method-ambig-one-trait-unknown-int-type.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/nll/issue-61424.rs [new file with mode: 0644]
src/test/ui/nll/issue-61424.stderr [new file with mode: 0644]
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/inverted-parameters.rs
src/test/ui/parser/inverted-parameters.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/omitted-arg-in-item-fn.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/span/issue-34264.stderr
src/test/ui/span/issue-42234-unknown-receiver-type.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/test/ui/type/type-check/cannot_infer_local_or_array.stderr
src/test/ui/type/type-check/cannot_infer_local_or_vec.stderr
src/test/ui/type/type-check/cannot_infer_local_or_vec_in_tuples.stderr
src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-2.stderr
src/test/ui/underscore-lifetime/underscore-lifetime-binders.stderr
src/test/ui/vector-no-ann.rs
src/test/ui/vector-no-ann.stderr
src/tools/clippy
src/tools/miri
src/tools/tidy/src/deps.rs
src/tools/tidy/src/pal.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 e7c6235a50444b59d25b73083b91077270fa466b..cfa28a6a1d70fafdce8eb50be879a3475914cf92 100644 (file)
@@ -118,6 +118,7 @@ steps:
 # bucket.
 - bash: |
     set -e
+    source src/ci/shared.sh
     if [ "$AGENT_OS" = "Linux" ]; then
         rm -rf obj/build/dist/doc
         upload_dir=obj/build/dist
@@ -130,7 +131,7 @@ steps:
     if [ "$DEPLOY_ALT" == "1" ]; then
         deploy_dir=rustc-builds-alt
     fi
-    aws s3 cp --no-progress --recursive --acl public-read ./$upload_dir s3://$DEPLOY_BUCKET/$deploy_dir/$BUILD_SOURCEVERSION
+    retry aws s3 cp --no-progress --recursive --acl public-read ./$upload_dir s3://$DEPLOY_BUCKET/$deploy_dir/$BUILD_SOURCEVERSION
   env:
     AWS_SECRET_ACCESS_KEY: $(AWS_SECRET_ACCESS_KEY)
   condition: and(succeeded(), or(eq(variables.DEPLOY, '1'), eq(variables.DEPLOY_ALT, '1')))
index a13bc0e74760ad30eb4a111677b77c8a525e05fd..d7191743c36f6c50f468f25e76fccb44db1eb01b 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)",
@@ -2678,7 +2684,6 @@ dependencies = [
  "rustc_errors 0.0.0",
  "rustc_fs_util 0.0.0",
  "rustc_incremental 0.0.0",
- "rustc_mir 0.0.0",
  "rustc_target 0.0.0",
  "serialize 0.0.0",
  "syntax 0.0.0",
@@ -2697,7 +2702,6 @@ dependencies = [
  "rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_data_structures 0.0.0",
  "rustc_metadata 0.0.0",
- "rustc_mir 0.0.0",
  "rustc_target 0.0.0",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
@@ -2719,6 +2723,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 +2975,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 +3242,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 +3329,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 +4195,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 +4206,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 d618654b129af844b3a3a1ca6097da7ae6e39d3d..edeb07fda1d59d923dc1f32403568ac927c57806 100644 (file)
@@ -11,7 +11,6 @@
 use std::cmp;
 
 use build_helper::t;
-use num_cpus;
 use toml;
 use serde::Deserialize;
 use crate::cache::{INTERNER, Interned};
@@ -401,7 +400,7 @@ pub fn parse(args: &[String]) -> Config {
         config.rustc_error_format = flags.rustc_error_format;
         config.on_fail = flags.on_fail;
         config.stage = flags.stage;
-        config.jobs = flags.jobs;
+        config.jobs = flags.jobs.map(threads_from_config);
         config.cmd = flags.cmd;
         config.incremental = flags.incremental;
         config.dry_run = flags.dry_run;
@@ -583,13 +582,8 @@ pub fn parse(args: &[String]) -> Config {
 
             set(&mut config.rust_codegen_backends_dir, rust.codegen_backends_dir.clone());
 
-            match rust.codegen_units {
-                Some(0) => config.rust_codegen_units = Some(num_cpus::get() as u32),
-                Some(n) => config.rust_codegen_units = Some(n),
-                None => {}
-            }
-
-            config.rust_codegen_units_std = rust.codegen_units_std;
+            config.rust_codegen_units = rust.codegen_units.map(threads_from_config);
+            config.rust_codegen_units_std = rust.codegen_units_std.map(threads_from_config);
         }
 
         if let Some(ref t) = toml.target {
@@ -688,3 +682,10 @@ fn set<T>(field: &mut T, val: Option<T>) {
         *field = v;
     }
 }
+
+fn threads_from_config(v: u32) -> u32 {
+    match v {
+        0 => num_cpus::get() as u32,
+        n => n,
+    }
+}
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 1e667fca5875afd8b57213211c3cdb63bd1207af..323d53f2bec85d8f1debb4135bf8860ed7d2f911 100644 (file)
@@ -35,6 +35,8 @@ function isOSX {
 function getCIBranch {
   if [ "$TRAVIS" = "true" ]; then
     echo "$TRAVIS_BRANCH"
+  elif [ "$APPVEYOR" = "True" ]; then
+    echo "$APPVEYOR_REPO_BRANCH"
   else
     echo "$BUILD_SOURCEBRANCHNAME"
   fi;
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 1f357a719bb43880725e51309349591dd1777156..c827e218b2fb35f445572993f1fa6c3bd4ea2052 100644 (file)
@@ -580,15 +580,18 @@ pub fn ptr_eq(this: &Self, other: &Self) -> bool {
 impl<T: Clone> Rc<T> {
     /// Makes a mutable reference into the given `Rc`.
     ///
-    /// If there are other `Rc` or [`Weak`][weak] pointers to the same value,
-    /// then `make_mut` will invoke [`clone`][clone] on the inner value to
-    /// ensure unique ownership. This is also referred to as clone-on-write.
+    /// If there are other `Rc` pointers to the same value, then `make_mut` will
+    /// [`clone`] the inner value to ensure unique ownership.  This is also
+    /// referred to as clone-on-write.
     ///
-    /// See also [`get_mut`][get_mut], which will fail rather than cloning.
+    /// If there are no other `Rc` pointers to this value, then [`Weak`]
+    /// pointers to this value will be dissassociated.
     ///
-    /// [weak]: struct.Weak.html
-    /// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone
-    /// [get_mut]: struct.Rc.html#method.get_mut
+    /// See also [`get_mut`], which will fail rather than cloning.
+    ///
+    /// [`Weak`]: struct.Weak.html
+    /// [`clone`]: ../../std/clone/trait.Clone.html#tymethod.clone
+    /// [`get_mut`]: struct.Rc.html#method.get_mut
     ///
     /// # Examples
     ///
@@ -607,6 +610,23 @@ impl<T: Clone> Rc<T> {
     /// assert_eq!(*data, 8);
     /// assert_eq!(*other_data, 12);
     /// ```
+    ///
+    /// [`Weak`] pointers will be dissassociated:
+    ///
+    /// ```
+    /// use std::rc::Rc;
+    ///
+    /// let mut data = Rc::new(75);
+    /// let weak = Rc::downgrade(&data);
+    ///
+    /// assert!(75 == *data);
+    /// assert!(75 == *weak.upgrade().unwrap());
+    ///
+    /// *Rc::make_mut(&mut data) += 1;
+    ///
+    /// assert!(76 == *data);
+    /// assert!(weak.upgrade().is_none());
+    /// ```
     #[inline]
     #[stable(feature = "rc_unique", since = "1.4.0")]
     pub fn make_mut(this: &mut Self) -> &mut T {
index f66ff894ae865c486cf48a4987602c2eaa1e7f55..0c7d2b837a39ac5b9a8537677bec8ee3657f3052 100644 (file)
@@ -431,6 +431,13 @@ fn case_ignoreable_then_cased<I: Iterator<Item = char>>(iter: I) -> bool {
     ///
     /// assert_eq!(new_year, new_year.to_uppercase());
     /// ```
+    ///
+    /// One character can become multiple:
+    /// ```
+    /// let s = "tschüß";
+    ///
+    /// assert_eq!("TSCHÃœSS", s.to_uppercase());
+    /// ```
     #[stable(feature = "unicode_case_mapping", since = "1.2.0")]
     pub fn to_uppercase(&self) -> String {
         let mut s = String::with_capacity(self.len());
index 5cb91395b7bf75cd64cdb81e54392b61ec7140c1..92fe0834dd029bd37225a6ce397bae636f24d7e2 100644 (file)
@@ -2018,16 +2018,14 @@ fn extend_desugared<I: Iterator<Item = T>>(&mut self, mut iterator: I) {
     /// with the given `replace_with` iterator and yields the removed items.
     /// `replace_with` does not need to be the same length as `range`.
     ///
-    /// Note 1: The element range is removed even if the iterator is not
-    /// consumed until the end.
+    /// The element range is removed even if the iterator is not consumed until the end.
     ///
-    /// Note 2: It is unspecified how many elements are removed from the vector,
+    /// It is unspecified how many elements are removed from the vector
     /// if the `Splice` value is leaked.
     ///
-    /// Note 3: The input iterator `replace_with` is only consumed
-    /// when the `Splice` value is dropped.
+    /// The input iterator `replace_with` is only consumed when the `Splice` value is dropped.
     ///
-    /// Note 4: This is optimal if:
+    /// This is optimal if:
     ///
     /// * The tail (elements in the vector after `range`) is empty,
     /// * or `replace_with` yields fewer elements than `range`’s length
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 782a7ba45598455de4b03064c000aeb7bad862ad..31a4e380a3d9b647103a0dd1b653860c1dd3ddfc 100644 (file)
@@ -1240,6 +1240,21 @@ pub fn volatile_copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T,
     /// y < 0 or y >= N, where N is the width of T in bits.
     pub fn unchecked_shr<T>(x: T, y: T) -> T;
 
+    /// Returns the result of an unchecked addition, resulting in
+    /// undefined behavior when `x + y > T::max_value()` or `x + y < T::min_value()`.
+    #[cfg(not(stage0))]
+    pub fn unchecked_add<T>(x: T, y: T) -> T;
+
+    /// Returns the result of an unchecked substraction, resulting in
+    /// undefined behavior when `x - y > T::max_value()` or `x - y < T::min_value()`.
+    #[cfg(not(stage0))]
+    pub fn unchecked_sub<T>(x: T, y: T) -> T;
+
+    /// Returns the result of an unchecked multiplication, resulting in
+    /// undefined behavior when `x * y > T::max_value()` or `x * y < T::min_value()`.
+    #[cfg(not(stage0))]
+    pub fn unchecked_mul<T>(x: T, y: T) -> T;
+
     /// Performs rotate left.
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `rotate_left` method. For example,
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 e5bf9a27ab0500b40d1b5bde87e152e07b72d3ff..a364a6da2e497ff598ae3e60b90e55f567385c2b 100644 (file)
@@ -49,6 +49,7 @@
 //! user of the `DepNode` API of having to know how to compute the expected
 //! fingerprint for a given set of node parameters.
 
+use crate::mir;
 use crate::mir::interpret::GlobalId;
 use crate::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX};
 use crate::hir::map::DefPathHash;
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 8000666044a1aeddeee0dcb9135456365d19cd17..9cf365addca9bb060e3a5c941d1c38d0c3230fd9 100644 (file)
@@ -262,9 +262,6 @@ fn visit_arm(&mut self, a: &'v Arm) {
     fn visit_pat(&mut self, p: &'v Pat) {
         walk_pat(self, p)
     }
-    fn visit_argument_source(&mut self, s: &'v ArgSource) {
-        walk_argument_source(self, s)
-    }
     fn visit_anon_const(&mut self, c: &'v AnonConst) {
         walk_anon_const(self, c)
     }
@@ -402,17 +399,10 @@ pub fn walk_body<'v, V: Visitor<'v>>(visitor: &mut V, body: &'v Body) {
     for argument in &body.arguments {
         visitor.visit_id(argument.hir_id);
         visitor.visit_pat(&argument.pat);
-        visitor.visit_argument_source(&argument.source);
     }
     visitor.visit_expr(&body.value);
 }
 
-pub fn walk_argument_source<'v, V: Visitor<'v>>(visitor: &mut V, source: &'v ArgSource) {
-    if let ArgSource::AsyncFn(pat) = source {
-        visitor.visit_pat(pat);
-    }
-}
-
 pub fn walk_local<'v, V: Visitor<'v>>(visitor: &mut V, local: &'v Local) {
     // Intentionally visiting the expr first - the initialization expr
     // dominates the local's definition.
index 08fbd0d20d74dac3a23818ad7ee4cf5e4fc187aa..14a6e93341e3290c3b988dbcdae837962c2f66a4 100644 (file)
@@ -50,6 +50,7 @@
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_data_structures::thin_vec::ThinVec;
+use rustc_data_structures::sync::Lrc;
 
 use std::collections::{BTreeSet, BTreeMap};
 use std::mem;
 use syntax::ast;
 use syntax::ast::*;
 use syntax::errors;
-use syntax::ext::hygiene::Mark;
+use syntax::ext::hygiene::{Mark, SyntaxContext};
 use syntax::print::pprust;
 use syntax::ptr::P;
-use syntax::source_map::{respan, CompilerDesugaringKind, Spanned};
+use syntax::source_map::{self, respan, CompilerDesugaringKind, Spanned};
 use syntax::source_map::CompilerDesugaringKind::IfTemporary;
 use syntax::std_inject;
 use syntax::symbol::{kw, sym, Symbol};
 use syntax::tokenstream::{TokenStream, TokenTree};
 use syntax::parse::token::Token;
 use syntax::visit::{self, Visitor};
-use syntax_pos::Span;
+use syntax_pos::{edition, Span};
 
 const HIR_ID_COUNTER_LOCKED: u32 = 0xFFFFFFFF;
 
@@ -465,32 +466,6 @@ fn visit_pat(&mut self, p: &'lcx Pat) {
                 visit::walk_pat(self, p)
             }
 
-            fn visit_fn(&mut self, fk: visit::FnKind<'lcx>, fd: &'lcx FnDecl, s: Span, _: NodeId) {
-                if fk.header().map(|h| h.asyncness.node.is_async()).unwrap_or(false) {
-                    // Don't visit the original pattern for async functions as it will be
-                    // replaced.
-                    for arg in &fd.inputs {
-                        if let ArgSource::AsyncFn(pat) = &arg.source { self.visit_pat(pat); }
-                        self.visit_ty(&arg.ty)
-                    }
-                    self.visit_fn_ret_ty(&fd.output);
-
-                    match fk {
-                        visit::FnKind::ItemFn(_, decl, _, body) => {
-                            self.visit_fn_header(decl);
-                            self.visit_block(body)
-                        },
-                        visit::FnKind::Method(_, sig, _, body) => {
-                            self.visit_fn_header(&sig.header);
-                            self.visit_block(body)
-                        },
-                        visit::FnKind::Closure(body) => self.visit_expr(body),
-                    }
-                } else {
-                    visit::walk_fn(self, fk, fd, s)
-                }
-            }
-
             fn visit_item(&mut self, item: &'lcx Item) {
                 let hir_id = self.lctx.allocate_hir_id_counter(item.id);
 
@@ -806,7 +781,7 @@ fn lower_node_id_with_owner(&mut self, ast_node_id: NodeId, owner: NodeId) -> hi
         })
     }
 
-    fn record_body(&mut self, value: hir::Expr, arguments: HirVec<hir::Arg>) -> hir::BodyId {
+    fn record_body(&mut self, arguments: HirVec<hir::Arg>, value: hir::Expr) -> hir::BodyId {
         if self.is_generator && self.is_async_body {
             span_err!(
                 self.sess,
@@ -855,6 +830,27 @@ fn diagnostic(&self) -> &errors::Handler {
         self.sess.diagnostic()
     }
 
+    /// Reuses the span but adds information like the kind of the desugaring and features that are
+    /// allowed inside this span.
+    fn mark_span_with_reason(
+        &self,
+        reason: CompilerDesugaringKind,
+        span: Span,
+        allow_internal_unstable: Option<Lrc<[Symbol]>>,
+    ) -> Span {
+        let mark = Mark::fresh(Mark::root());
+        mark.set_expn_info(source_map::ExpnInfo {
+            call_site: span,
+            def_site: Some(span),
+            format: source_map::CompilerDesugaring(reason),
+            allow_internal_unstable,
+            allow_internal_unsafe: false,
+            local_inner_macros: false,
+            edition: edition::Edition::from_session(),
+        });
+        span.with_ctxt(SyntaxContext::empty().apply_mark(mark))
+    }
+
     fn with_anonymous_lifetime_mode<R>(
         &mut self,
         anonymous_lifetime_mode: AnonymousLifetimeMode,
@@ -1125,27 +1121,21 @@ fn make_async_expr(
         span: Span,
         body: impl FnOnce(&mut LoweringContext<'_>) -> hir::Expr,
     ) -> hir::ExprKind {
-        let prev_is_generator = mem::replace(&mut self.is_generator, false);
-        let prev_is_async_body = mem::replace(&mut self.is_async_body, true);
+        let capture_clause = self.lower_capture_clause(capture_clause);
         let output = match ret_ty {
             Some(ty) => FunctionRetTy::Ty(P(ty.clone())),
             None => FunctionRetTy::Default(span),
         };
-        let decl = FnDecl {
+        let ast_decl = FnDecl {
             inputs: vec![],
             output,
             c_variadic: false
         };
-        // Lower the arguments before the body otherwise the body will call `lower_res` expecting
-        // the argument to have been assigned an id already.
-        let arguments = self.lower_args(Some(&decl));
-        let body_expr = body(self);
-        let body_id = self.record_body(body_expr, arguments);
-        self.is_generator = prev_is_generator;
-        self.is_async_body = prev_is_async_body;
-
-        let capture_clause = self.lower_capture_clause(capture_clause);
-        let decl = self.lower_fn_decl(&decl, None, /* impl trait allowed */ false, None);
+        let decl = self.lower_fn_decl(&ast_decl, None, /* impl trait allowed */ false, None);
+        let body_id = self.lower_fn_body(&ast_decl, |this| {
+            this.is_async_body = true;
+            body(this)
+        });
         let generator = hir::Expr {
             hir_id: self.lower_node_id(closure_node_id),
             node: hir::ExprKind::Closure(capture_clause, decl, body_id, span,
@@ -1154,7 +1144,7 @@ fn make_async_expr(
             attrs: ThinVec::new(),
         };
 
-        let unstable_span = self.sess.source_map().mark_span_with_reason(
+        let unstable_span = self.mark_span_with_reason(
             CompilerDesugaringKind::Async,
             span,
             Some(vec![sym::gen_future].into()),
@@ -1164,18 +1154,32 @@ fn make_async_expr(
         hir::ExprKind::Call(P(gen_future), hir_vec![generator])
     }
 
-    fn lower_body<F>(&mut self, decl: Option<&FnDecl>, f: F) -> hir::BodyId
-    where
-        F: FnOnce(&mut LoweringContext<'_>) -> hir::Expr,
-    {
-        let prev_generator = mem::replace(&mut self.is_generator, false);
-        let prev_async = mem::replace(&mut self.is_async_body, false);
-        let arguments = self.lower_args(decl);
-        let result = f(self);
-        let r = self.record_body(result, arguments);
-        self.is_generator = prev_generator;
-        self.is_async_body = prev_async;
-        return r;
+    fn lower_body(
+        &mut self,
+        f: impl FnOnce(&mut LoweringContext<'_>) -> (HirVec<hir::Arg>, hir::Expr),
+    ) -> hir::BodyId {
+        let prev_is_generator = mem::replace(&mut self.is_generator, false);
+        let prev_is_async_body = mem::replace(&mut self.is_async_body, false);
+        let (arguments, result) = f(self);
+        let body_id = self.record_body(arguments, result);
+        self.is_generator = prev_is_generator;
+        self.is_async_body = prev_is_async_body;
+        body_id
+    }
+
+    fn lower_fn_body(
+        &mut self,
+        decl: &FnDecl,
+        body: impl FnOnce(&mut LoweringContext<'_>) -> hir::Expr,
+    ) -> hir::BodyId {
+        self.lower_body(|this| (
+            decl.inputs.iter().map(|x| this.lower_arg(x)).collect(),
+            body(this),
+        ))
+    }
+
+    fn lower_const_body(&mut self, expr: &Expr) -> hir::BodyId {
+        self.lower_body(|this| (hir_vec![], this.lower_expr(expr)))
     }
 
     fn with_loop_scope<T, F>(&mut self, loop_id: NodeId, f: F) -> T
@@ -1561,7 +1565,7 @@ fn lower_existential_impl_trait(
         // desugaring that explicitly states that we don't want to track that.
         // Not tracking it makes lints in rustc and clippy very fragile as
         // frequently opened issues show.
-        let exist_ty_span = self.sess.source_map().mark_span_with_reason(
+        let exist_ty_span = self.mark_span_with_reason(
             CompilerDesugaringKind::ExistentialReturnType,
             span,
             None,
@@ -2266,17 +2270,10 @@ fn lower_parenthesized_parameter_data(
             init: l.init.as_ref().map(|e| P(self.lower_expr(e))),
             span: l.span,
             attrs: l.attrs.clone(),
-            source: self.lower_local_source(l.source),
+            source: hir::LocalSource::Normal,
         }, ids)
     }
 
-    fn lower_local_source(&mut self, ls: LocalSource) -> hir::LocalSource {
-        match ls {
-            LocalSource::Normal => hir::LocalSource::Normal,
-            LocalSource::AsyncFn => hir::LocalSource::AsyncFn,
-        }
-    }
-
     fn lower_mutability(&mut self, m: Mutability) -> hir::Mutability {
         match m {
             Mutability::Mutable => hir::MutMutable,
@@ -2284,22 +2281,10 @@ fn lower_mutability(&mut self, m: Mutability) -> hir::Mutability {
         }
     }
 
-    fn lower_args(&mut self, decl: Option<&FnDecl>) -> HirVec<hir::Arg> {
-        decl.map_or(hir_vec![], |decl| decl.inputs.iter().map(|x| self.lower_arg(x)).collect())
-    }
-
     fn lower_arg(&mut self, arg: &Arg) -> hir::Arg {
         hir::Arg {
             hir_id: self.lower_node_id(arg.id),
             pat: self.lower_pat(&arg.pat),
-            source: self.lower_arg_source(&arg.source),
-        }
-    }
-
-    fn lower_arg_source(&mut self, source: &ArgSource) -> hir::ArgSource {
-        match source {
-            ArgSource::Normal => hir::ArgSource::Normal,
-            ArgSource::AsyncFn(pat) => hir::ArgSource::AsyncFn(self.lower_pat(pat)),
         }
     }
 
@@ -2435,7 +2420,7 @@ fn lower_async_fn_ret_ty(
     ) -> hir::FunctionRetTy {
         let span = output.span();
 
-        let exist_ty_span = self.sess.source_map().mark_span_with_reason(
+        let exist_ty_span = self.mark_span_with_reason(
             CompilerDesugaringKind::Async,
             span,
             None,
@@ -2998,11 +2983,14 @@ fn lower_param_bounds(&mut self, bounds: &[GenericBound], mut itctx: ImplTraitCo
         bounds.iter().map(|bound| self.lower_param_bound(bound, itctx.reborrow())).collect()
     }
 
-    fn lower_block(&mut self, b: &Block, targeted_by_break: bool) -> P<hir::Block> {
+    fn lower_block_with_stmts(
+        &mut self,
+        b: &Block,
+        targeted_by_break: bool,
+        mut stmts: Vec<hir::Stmt>,
+    ) -> P<hir::Block> {
         let mut expr = None;
 
-        let mut stmts = vec![];
-
         for (index, stmt) in b.stmts.iter().enumerate() {
             if index == b.stmts.len() - 1 {
                 if let StmtKind::Expr(ref e) = stmt.node {
@@ -3025,56 +3013,136 @@ fn lower_block(&mut self, b: &Block, targeted_by_break: bool) -> P<hir::Block> {
         })
     }
 
-    fn lower_async_body(
+    fn lower_block(&mut self, b: &Block, targeted_by_break: bool) -> P<hir::Block> {
+        self.lower_block_with_stmts(b, targeted_by_break, vec![])
+    }
+
+    fn lower_maybe_async_body(
         &mut self,
         decl: &FnDecl,
-        asyncness: &IsAsync,
+        asyncness: IsAsync,
         body: &Block,
     ) -> hir::BodyId {
-        self.lower_body(Some(&decl), |this| {
-            if let IsAsync::Async { closure_id, ref arguments, .. } = asyncness {
-                let mut body = body.clone();
+        let closure_id = match asyncness {
+            IsAsync::Async { closure_id, .. } => closure_id,
+            IsAsync::NotAsync => return self.lower_fn_body(&decl, |this| {
+                let body = this.lower_block(body, false);
+                this.expr_block(body, ThinVec::new())
+            }),
+        };
 
-                // Async function arguments are lowered into the closure body so that they are
-                // captured and so that the drop order matches the equivalent non-async functions.
-                //
-                //     async fn foo(<pattern>: <ty>, <pattern>: <ty>, <pattern>: <ty>) {
-                //       async move {
-                //       }
-                //     }
-                //
-                //     // ...becomes...
-                //     fn foo(__arg0: <ty>, __arg1: <ty>, __arg2: <ty>) {
-                //       async move {
-                //         let __arg2 = __arg2;
-                //         let <pattern> = __arg2;
-                //         let __arg1 = __arg1;
-                //         let <pattern> = __arg1;
-                //         let __arg0 = __arg0;
-                //         let <pattern> = __arg0;
-                //       }
-                //     }
+        self.lower_body(|this| {
+            let mut arguments: Vec<hir::Arg> = Vec::new();
+            let mut statements: Vec<hir::Stmt> = Vec::new();
+
+            // Async function arguments are lowered into the closure body so that they are
+            // captured and so that the drop order matches the equivalent non-async functions.
+            //
+            // from:
+            //
+            //     async fn foo(<pattern>: <ty>, <pattern>: <ty>, <pattern>: <ty>) {
+            //       async move {
+            //       }
+            //     }
+            //
+            // into:
+            //
+            //     fn foo(__arg0: <ty>, __arg1: <ty>, __arg2: <ty>) {
+            //       async move {
+            //         let __arg2 = __arg2;
+            //         let <pattern> = __arg2;
+            //         let __arg1 = __arg1;
+            //         let <pattern> = __arg1;
+            //         let __arg0 = __arg0;
+            //         let <pattern> = __arg0;
+            //       }
+            //     }
+            //
+            // If `<pattern>` is a simple ident, then it is lowered to a single
+            // `let <pattern> = <pattern>;` statement as an optimization.
+            for (index, argument) in decl.inputs.iter().enumerate() {
+                let argument = this.lower_arg(argument);
+                let span = argument.pat.span;
+
+                // Check if this is a binding pattern, if so, we can optimize and avoid adding a
+                // `let <pat> = __argN;` statement. In this case, we do not rename the argument.
+                let (ident, is_simple_argument) = match argument.pat.node {
+                    hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, ident, _) =>
+                        (ident, true),
+                    _ => {
+                        // Replace the ident for bindings that aren't simple.
+                        let name = format!("__arg{}", index);
+                        let ident = Ident::from_str(&name);
+
+                        (ident, false)
+                    },
+                };
+
+                let desugared_span =
+                    this.mark_span_with_reason(CompilerDesugaringKind::Async, span, None);
+
+                // Construct an argument representing `__argN: <ty>` to replace the argument of the
+                // async function.
                 //
-                // If `<pattern>` is a simple ident, then it is lowered to a single
-                // `let <pattern> = <pattern>;` statement as an optimization.
-                for a in arguments.iter().rev() {
-                    if let Some(pat_stmt) = a.pat_stmt.clone() {
-                        body.stmts.insert(0, pat_stmt);
-                    }
-                    body.stmts.insert(0, a.move_stmt.clone());
-                }
+                // If this is the simple case, this argument will end up being the same as the
+                // original argument, but with a different pattern id.
+                let (new_argument_pat, new_argument_id) = this.pat_ident(desugared_span, ident);
+                let new_argument = hir::Arg {
+                    hir_id: argument.hir_id,
+                    pat: new_argument_pat,
+                };
 
-                let async_expr = this.make_async_expr(
-                    CaptureBy::Value, *closure_id, None, body.span,
-                    |this| {
-                        let body = this.lower_block(&body, false);
-                        this.expr_block(body, ThinVec::new())
-                    });
-                this.expr(body.span, async_expr, ThinVec::new())
-            } else {
-                let body = this.lower_block(body, false);
-                this.expr_block(body, ThinVec::new())
+                if is_simple_argument {
+                    // If this is the simple case, then we only insert one statement that is
+                    // `let <pat> = <pat>;`. We re-use the original argument's pattern so that
+                    // `HirId`s are densely assigned.
+                    let expr = this.expr_ident(desugared_span, ident, new_argument_id);
+                    let stmt = this.stmt_let_pat(
+                        desugared_span, Some(P(expr)), argument.pat, hir::LocalSource::AsyncFn);
+                    statements.push(stmt);
+                } else {
+                    // If this is not the simple case, then we construct two statements:
+                    //
+                    // ```
+                    // let __argN = __argN;
+                    // let <pat> = __argN;
+                    // ```
+                    //
+                    // The first statement moves the argument into the closure and thus ensures
+                    // that the drop order is correct.
+                    //
+                    // The second statement creates the bindings that the user wrote.
+
+                    // Construct the `let mut __argN = __argN;` statement. It must be a mut binding
+                    // because the user may have specified a `ref mut` binding in the next
+                    // statement.
+                    let (move_pat, move_id) = this.pat_ident_binding_mode(
+                        desugared_span, ident, hir::BindingAnnotation::Mutable);
+                    let move_expr = this.expr_ident(desugared_span, ident, new_argument_id);
+                    let move_stmt = this.stmt_let_pat(
+                        desugared_span, Some(P(move_expr)), move_pat, hir::LocalSource::AsyncFn);
+
+                    // Construct the `let <pat> = __argN;` statement. We re-use the original
+                    // argument's pattern so that `HirId`s are densely assigned.
+                    let pattern_expr = this.expr_ident(desugared_span, ident, move_id);
+                    let pattern_stmt = this.stmt_let_pat(
+                        desugared_span, Some(P(pattern_expr)), argument.pat,
+                        hir::LocalSource::AsyncFn);
+
+                    statements.push(move_stmt);
+                    statements.push(pattern_stmt);
+                };
+
+                arguments.push(new_argument);
             }
+
+            let async_expr = this.make_async_expr(
+                CaptureBy::Value, closure_id, None, body.span,
+                |this| {
+                    let body = this.lower_block_with_stmts(body, false, statements);
+                    this.expr_block(body, ThinVec::new())
+                });
+            (HirVec::from(arguments), this.expr(body.span, async_expr, ThinVec::new()))
         })
     }
 
@@ -3098,7 +3166,6 @@ fn lower_item_kind(
                 self.lower_use_tree(use_tree, &prefix, id, vis, ident, attrs)
             }
             ItemKind::Static(ref t, m, ref e) => {
-                let value = self.lower_body(None, |this| this.lower_expr(e));
                 hir::ItemKind::Static(
                     self.lower_ty(
                         t,
@@ -3109,11 +3176,10 @@ fn lower_item_kind(
                         }
                     ),
                     self.lower_mutability(m),
-                    value,
+                    self.lower_const_body(e),
                 )
             }
             ItemKind::Const(ref t, ref e) => {
-                let value = self.lower_body(None, |this| this.lower_expr(e));
                 hir::ItemKind::Const(
                     self.lower_ty(
                         t,
@@ -3123,50 +3189,31 @@ fn lower_item_kind(
                             ImplTraitContext::Disallowed(ImplTraitPosition::Binding)
                         }
                     ),
-                    value
+                    self.lower_const_body(e)
                 )
             }
-            ItemKind::Fn(ref decl, ref header, ref generics, ref body) => {
+            ItemKind::Fn(ref decl, header, ref generics, ref body) => {
                 let fn_def_id = self.resolver.definitions().local_def_id(id);
                 self.with_new_scopes(|this| {
                     this.current_item = Some(ident.span);
-                    let mut lower_fn = |decl: &FnDecl| {
-                        // Note: we don't need to change the return type from `T` to
-                        // `impl Future<Output = T>` here because lower_body
-                        // only cares about the input argument patterns in the function
-                        // declaration (decl), not the return types.
-                        let body_id = this.lower_async_body(&decl, &header.asyncness.node, body);
-
-                        let (generics, fn_decl) = this.add_in_band_defs(
-                            generics,
-                            fn_def_id,
-                            AnonymousLifetimeMode::PassThrough,
-                            |this, idty| this.lower_fn_decl(
-                                &decl,
-                                Some((fn_def_id, idty)),
-                                true,
-                                header.asyncness.node.opt_return_id()
-                            ),
-                        );
 
-                        (body_id, generics, fn_decl)
-                    };
+                    // Note: we don't need to change the return type from `T` to
+                    // `impl Future<Output = T>` here because lower_body
+                    // only cares about the input argument patterns in the function
+                    // declaration (decl), not the return types.
+                    let body_id = this.lower_maybe_async_body(&decl, header.asyncness.node, body);
 
-                    let (body_id, generics, fn_decl) = if let IsAsync::Async {
-                        arguments, ..
-                    } = &header.asyncness.node {
-                        let mut decl = decl.clone();
-                        // Replace the arguments of this async function with the generated
-                        // arguments that will be moved into the closure.
-                        for (i, a) in arguments.clone().drain(..).enumerate() {
-                            if let Some(arg) = a.arg {
-                                decl.inputs[i] = arg;
-                            }
-                        }
-                        lower_fn(&decl)
-                    } else {
-                        lower_fn(decl)
-                    };
+                    let (generics, fn_decl) = this.add_in_band_defs(
+                        generics,
+                        fn_def_id,
+                        AnonymousLifetimeMode::PassThrough,
+                        |this, idty| this.lower_fn_decl(
+                            &decl,
+                            Some((fn_def_id, idty)),
+                            true,
+                            header.asyncness.node.opt_return_id()
+                        ),
+                    );
 
                     hir::ItemKind::Fn(
                         fn_decl,
@@ -3548,7 +3595,7 @@ fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem {
                     self.lower_ty(ty, ImplTraitContext::disallowed()),
                     default
                         .as_ref()
-                        .map(|x| self.lower_body(None, |this| this.lower_expr(x))),
+                        .map(|x| self.lower_const_body(x)),
                 ),
             ),
             TraitItemKind::Method(ref sig, None) => {
@@ -3563,7 +3610,7 @@ fn lower_trait_item(&mut self, i: &TraitItem) -> hir::TraitItem {
                 (generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Required(names)))
             }
             TraitItemKind::Method(ref sig, Some(ref body)) => {
-                let body_id = self.lower_body(Some(&sig.decl), |this| {
+                let body_id = self.lower_fn_body(&sig.decl, |this| {
                     let body = this.lower_block(body, false);
                     this.expr_block(body, ThinVec::new())
                 });
@@ -3627,48 +3674,26 @@ fn lower_impl_item(&mut self, i: &ImplItem) -> hir::ImplItem {
         let impl_item_def_id = self.resolver.definitions().local_def_id(i.id);
 
         let (generics, node) = match i.node {
-            ImplItemKind::Const(ref ty, ref expr) => {
-                let body_id = self.lower_body(None, |this| this.lower_expr(expr));
-                (
-                    self.lower_generics(&i.generics, ImplTraitContext::disallowed()),
-                    hir::ImplItemKind::Const(
-                        self.lower_ty(ty, ImplTraitContext::disallowed()),
-                        body_id,
-                    ),
-                )
-            }
+            ImplItemKind::Const(ref ty, ref expr) => (
+                self.lower_generics(&i.generics, ImplTraitContext::disallowed()),
+                hir::ImplItemKind::Const(
+                    self.lower_ty(ty, ImplTraitContext::disallowed()),
+                    self.lower_const_body(expr),
+                ),
+            ),
             ImplItemKind::Method(ref sig, ref body) => {
-                let mut lower_method = |sig: &MethodSig| {
-                    let body_id = self.lower_async_body(
-                        &sig.decl, &sig.header.asyncness.node, body
-                    );
-                    let impl_trait_return_allow = !self.is_in_trait_impl;
-                    let (generics, sig) = self.lower_method_sig(
-                        &i.generics,
-                        sig,
-                        impl_item_def_id,
-                        impl_trait_return_allow,
-                        sig.header.asyncness.node.opt_return_id(),
-                    );
-                    (body_id, generics, sig)
-                };
-
-                let (body_id, generics, sig) = if let IsAsync::Async {
-                    ref arguments, ..
-                } = sig.header.asyncness.node {
-                    let mut sig = sig.clone();
-                    // Replace the arguments of this async function with the generated
-                    // arguments that will be moved into the closure.
-                    for (i, a) in arguments.clone().drain(..).enumerate() {
-                        if let Some(arg) = a.arg {
-                            sig.decl.inputs[i] = arg;
-                        }
-                    }
-                    lower_method(&sig)
-                } else {
-                    lower_method(sig)
-                };
                 self.current_item = Some(i.span);
+                let body_id = self.lower_maybe_async_body(
+                    &sig.decl, sig.header.asyncness.node, body
+                );
+                let impl_trait_return_allow = !self.is_in_trait_impl;
+                let (generics, sig) = self.lower_method_sig(
+                    &i.generics,
+                    sig,
+                    impl_item_def_id,
+                    impl_trait_return_allow,
+                    sig.header.asyncness.node.opt_return_id(),
+                );
 
                 (generics, hir::ImplItemKind::Method(sig, body_id))
             }
@@ -3860,7 +3885,7 @@ fn lower_method_sig(
         impl_trait_return_allow: bool,
         is_async: Option<NodeId>,
     ) -> (hir::Generics, hir::MethodSig) {
-        let header = self.lower_fn_header(&sig.header);
+        let header = self.lower_fn_header(sig.header);
         let (generics, decl) = self.add_in_band_defs(
             generics,
             fn_def_id,
@@ -3882,10 +3907,10 @@ fn lower_is_auto(&mut self, a: IsAuto) -> hir::IsAuto {
         }
     }
 
-    fn lower_fn_header(&mut self, h: &FnHeader) -> hir::FnHeader {
+    fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader {
         hir::FnHeader {
             unsafety: self.lower_unsafety(h.unsafety),
-            asyncness: self.lower_asyncness(&h.asyncness.node),
+            asyncness: self.lower_asyncness(h.asyncness.node),
             constness: self.lower_constness(h.constness),
             abi: h.abi,
         }
@@ -3905,7 +3930,7 @@ fn lower_constness(&mut self, c: Spanned<Constness>) -> hir::Constness {
         }
     }
 
-    fn lower_asyncness(&mut self, a: &IsAsync) -> hir::IsAsync {
+    fn lower_asyncness(&mut self, a: IsAsync) -> hir::IsAsync {
         match a {
             IsAsync::Async { .. } => hir::IsAsync::Async,
             IsAsync::NotAsync => hir::IsAsync::NotAsync,
@@ -4064,7 +4089,7 @@ fn lower_anon_const(&mut self, c: &AnonConst) -> hir::AnonConst {
         self.with_new_scopes(|this| {
             hir::AnonConst {
                 hir_id: this.lower_node_id(c.id),
-                body: this.lower_body(None, |this| this.lower_expr(&c.value)),
+                body: this.lower_const_body(&c.value),
             }
         })
     }
@@ -4151,10 +4176,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                 let else_arm = self.arm(hir_vec![else_pat], P(else_expr));
 
                 // Lower condition:
-                let span_block = self
-                    .sess
-                    .source_map()
-                    .mark_span_with_reason(IfTemporary, cond.span, None);
+                let span_block = self.mark_span_with_reason(IfTemporary, cond.span, None);
                 let cond = self.lower_expr(cond);
                 // Wrap in a construct equivalent to `{ let _t = $cond; _t }` to preserve drop
                 // semantics since `if cond { ... }` don't let temporaries live outside of `cond`.
@@ -4184,7 +4206,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
             }),
             ExprKind::TryBlock(ref body) => {
                 self.with_catch_scope(body.id, |this| {
-                    let unstable_span = this.sess.source_map().mark_span_with_reason(
+                    let unstable_span = this.mark_span_with_reason(
                         CompilerDesugaringKind::TryBlock,
                         body.span,
                         Some(vec![sym::try_trait].into()),
@@ -4222,7 +4244,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
             }
             ExprKind::Await(_origin, ref expr) => self.lower_await(e.span, expr),
             ExprKind::Closure(
-                capture_clause, ref asyncness, movability, ref decl, ref body, fn_decl_span
+                capture_clause, asyncness, movability, ref decl, ref body, fn_decl_span
             ) => {
                 if let IsAsync::Async { closure_id, .. } = asyncness {
                     let outer_decl = FnDecl {
@@ -4255,12 +4277,12 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
 
                         // Transform `async |x: u8| -> X { ... }` into
                         // `|x: u8| future_from_generator(|| -> X { ... })`.
-                        let body_id = this.lower_body(Some(&outer_decl), |this| {
+                        let body_id = this.lower_fn_body(&outer_decl, |this| {
                             let async_ret_ty = if let FunctionRetTy::Ty(ty) = &decl.output {
                                 Some(&**ty)
                             } else { None };
                             let async_body = this.make_async_expr(
-                                capture_clause, *closure_id, async_ret_ty, body.span,
+                                capture_clause, closure_id, async_ret_ty, body.span,
                                 |this| {
                                     this.with_new_scopes(|this| this.lower_expr(body))
                                 });
@@ -4281,7 +4303,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                     self.with_new_scopes(|this| {
                         this.current_item = Some(fn_decl_span);
                         let mut is_generator = false;
-                        let body_id = this.lower_body(Some(decl), |this| {
+                        let body_id = this.lower_fn_body(decl, |this| {
                             let e = this.lower_expr(body);
                             is_generator = this.is_generator;
                             e
@@ -4616,7 +4638,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                 // expand <head>
                 let mut head = self.lower_expr(head);
                 let head_sp = head.span;
-                let desugared_span = self.sess.source_map().mark_span_with_reason(
+                let desugared_span = self.mark_span_with_reason(
                     CompilerDesugaringKind::ForLoop,
                     head_sp,
                     None,
@@ -4770,13 +4792,13 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                 //                 return Try::from_error(From::from(err)),
                 // }
 
-                let unstable_span = self.sess.source_map().mark_span_with_reason(
+                let unstable_span = self.mark_span_with_reason(
                     CompilerDesugaringKind::QuestionMark,
                     e.span,
                     Some(vec![sym::try_trait].into()),
                 );
                 let try_span = self.sess.source_map().end_point(e.span);
-                let try_span = self.sess.source_map().mark_span_with_reason(
+                let try_span = self.mark_span_with_reason(
                     CompilerDesugaringKind::QuestionMark,
                     try_span,
                     Some(vec![sym::try_trait].into()),
@@ -5573,12 +5595,12 @@ fn lower_await(
             err.emit();
             return hir::ExprKind::Err;
         }
-        let span = self.sess.source_map().mark_span_with_reason(
+        let span = self.mark_span_with_reason(
             CompilerDesugaringKind::Await,
             await_span,
             None,
         );
-        let gen_future_span = self.sess.source_map().mark_span_with_reason(
+        let gen_future_span = self.mark_span_with_reason(
             CompilerDesugaringKind::Await,
             await_span,
             Some(vec![sym::gen_future].into()),
index bde27c71f9a6d242f68bcd5f8c4c2b08b912ac85..a4484c81738983c53d434ec3be8086d6c5f78ec4 100644 (file)
@@ -64,17 +64,16 @@ fn visit_async_fn(
         id: NodeId,
         name: Name,
         span: Span,
-        header: &'a FnHeader,
+        header: &FnHeader,
         generics: &'a Generics,
         decl: &'a FnDecl,
         body: &'a Block,
     ) {
-        let (closure_id, return_impl_trait_id, arguments) = match &header.asyncness.node {
+        let (closure_id, return_impl_trait_id) = match header.asyncness.node {
             IsAsync::Async {
                 closure_id,
                 return_impl_trait_id,
-                arguments,
-            } => (closure_id, return_impl_trait_id, arguments),
+            } => (closure_id, return_impl_trait_id),
             _ => unreachable!(),
         };
 
@@ -83,38 +82,16 @@ fn visit_async_fn(
         let fn_def_data = DefPathData::ValueNs(name.as_interned_str());
         let fn_def = self.create_def(id, fn_def_data, span);
         return self.with_parent(fn_def, |this| {
-            this.create_def(*return_impl_trait_id, DefPathData::ImplTrait, span);
+            this.create_def(return_impl_trait_id, DefPathData::ImplTrait, span);
 
             visit::walk_generics(this, generics);
-
-            // Walk the generated arguments for the `async fn`.
-            for (i, a) in arguments.iter().enumerate() {
-                use visit::Visitor;
-                if let Some(arg) = &a.arg {
-                    this.visit_ty(&arg.ty);
-                } else {
-                    this.visit_ty(&decl.inputs[i].ty);
-                }
-            }
-
-            // We do not invoke `walk_fn_decl` as this will walk the arguments that are being
-            // replaced.
-            visit::walk_fn_ret_ty(this, &decl.output);
+            visit::walk_fn_decl(this, decl);
 
             let closure_def = this.create_def(
-                *closure_id, DefPathData::ClosureExpr, span,
+                closure_id, DefPathData::ClosureExpr, span,
             );
             this.with_parent(closure_def, |this| {
-                use visit::Visitor;
-                // Walk each of the generated statements before the regular block body.
-                for a in arguments {
-                    this.visit_stmt(&a.move_stmt);
-                    if let Some(pat_stmt) = &a.pat_stmt {
-                        this.visit_stmt(&pat_stmt);
-                    }
-                }
-
-                visit::walk_block(this, &body);
+                visit::walk_block(this, body);
             })
         })
     }
@@ -302,7 +279,7 @@ fn visit_expr(&mut self, expr: &'a Expr) {
 
         match expr.node {
             ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id),
-            ExprKind::Closure(_, ref asyncness, ..) => {
+            ExprKind::Closure(_, asyncness, ..) => {
                 let closure_def = self.create_def(expr.id,
                                           DefPathData::ClosureExpr,
                                           expr.span);
@@ -311,7 +288,7 @@ fn visit_expr(&mut self, expr: &'a Expr) {
                 // Async closures desugar to closures inside of closures, so
                 // we must create two defs.
                 if let IsAsync::Async { closure_id, .. } = asyncness {
-                    let async_def = self.create_def(*closure_id,
+                    let async_def = self.create_def(closure_id,
                                                     DefPathData::ClosureExpr,
                                                     expr.span);
                     self.parent_def = Some(async_def);
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..65fc56f2c48787e8d1747f4aa912d549bd214888 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,
@@ -1921,26 +1929,6 @@ pub struct InlineAsm {
 pub struct Arg {
     pub pat: P<Pat>,
     pub hir_id: HirId,
-    pub source: ArgSource,
-}
-
-impl Arg {
-    /// Returns the pattern representing the original binding for this argument.
-    pub fn original_pat(&self) -> &P<Pat> {
-        match &self.source {
-            ArgSource::Normal => &self.pat,
-            ArgSource::AsyncFn(pat) => &pat,
-        }
-    }
-}
-
-/// Represents the source of an argument in a function header.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable)]
-pub enum ArgSource {
-    /// Argument as specified by the user.
-    Normal,
-    /// Generated argument from `async fn` lowering, contains the original binding pattern.
-    AsyncFn(P<Pat>),
 }
 
 /// Represents the header (not the body) of a function declaration.
@@ -2493,32 +2481,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 +2504,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 972ffbe1820a5569ee59ae336b4f89652e4dcce2..b3ff25a695f2fd9e1218f207bb999126abeb3293 100644 (file)
@@ -15,17 +15,18 @@ struct FindLocalByTypeVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
     hir_map: &'a hir::map::Map<'gcx>,
     found_local_pattern: Option<&'gcx Pat>,
     found_arg_pattern: Option<&'gcx Pat>,
+    found_ty: Option<Ty<'tcx>>,
 }
 
 impl<'a, 'gcx, 'tcx> FindLocalByTypeVisitor<'a, 'gcx, 'tcx> {
-    fn node_matches_type(&mut self, hir_id: HirId) -> bool {
+    fn node_matches_type(&mut self, hir_id: HirId) -> Option<Ty<'tcx>> {
         let ty_opt = self.infcx.in_progress_tables.and_then(|tables| {
             tables.borrow().node_type_opt(hir_id)
         });
         match ty_opt {
             Some(ty) => {
                 let ty = self.infcx.resolve_vars_if_possible(&ty);
-                ty.walk().any(|inner_ty| {
+                if ty.walk().any(|inner_ty| {
                     inner_ty == self.target_ty || match (&inner_ty.sty, &self.target_ty.sty) {
                         (&Infer(TyVar(a_vid)), &Infer(TyVar(b_vid))) => {
                             self.infcx
@@ -35,9 +36,13 @@ fn node_matches_type(&mut self, hir_id: HirId) -> bool {
                         }
                         _ => false,
                     }
-                })
+                }) {
+                    Some(ty)
+                } else {
+                    None
+                }
             }
-            None => false,
+            None => None,
         }
     }
 }
@@ -48,16 +53,21 @@ fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'gcx> {
     }
 
     fn visit_local(&mut self, local: &'gcx Local) {
-        if self.found_local_pattern.is_none() && self.node_matches_type(local.hir_id) {
+        if let (None, Some(ty)) = (self.found_local_pattern, self.node_matches_type(local.hir_id)) {
             self.found_local_pattern = Some(&*local.pat);
+            self.found_ty = Some(ty);
         }
         intravisit::walk_local(self, local);
     }
 
     fn visit_body(&mut self, body: &'gcx Body) {
         for argument in &body.arguments {
-            if self.found_arg_pattern.is_none() && self.node_matches_type(argument.hir_id) {
+            if let (None, Some(ty)) = (
+                self.found_arg_pattern,
+                self.node_matches_type(argument.hir_id),
+            ) {
                 self.found_arg_pattern = Some(&*argument.pat);
+                self.found_ty = Some(ty);
             }
         }
         intravisit::walk_body(self, body);
@@ -98,7 +108,6 @@ pub fn need_type_info_err(
         let name = self.extract_type_name(&ty, None);
 
         let mut err_span = span;
-        let mut labels = vec![(span, InferCtxt::missing_type_msg(&name))];
 
         let mut local_visitor = FindLocalByTypeVisitor {
             infcx: &self,
@@ -106,6 +115,22 @@ pub fn need_type_info_err(
             hir_map: &self.tcx.hir(),
             found_local_pattern: None,
             found_arg_pattern: None,
+            found_ty: None,
+        };
+        let ty_to_string = |ty: Ty<'tcx>| -> String {
+            let mut s = String::new();
+            let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS);
+            let ty_vars = self.type_variables.borrow();
+            let getter = move |ty_vid| {
+                if let TypeVariableOrigin::TypeParameterDefinition(_, name) =
+                    *ty_vars.var_origin(ty_vid) {
+                    return Some(name.to_string());
+                }
+                None
+            };
+            printer.name_resolver = Some(Box::new(&getter));
+            let _ = ty.print(printer);
+            s
         };
 
         if let Some(body_id) = body_id {
@@ -113,6 +138,38 @@ pub fn need_type_info_err(
             local_visitor.visit_expr(expr);
         }
 
+        // When `name` corresponds to a type argument, show the path of the full type we're
+        // trying to infer. In the following example, `ty_msg` contains
+        // " in `std::result::Result<i32, E>`":
+        // ```
+        // error[E0282]: type annotations needed for `std::result::Result<i32, E>`
+        //  --> file.rs:L:CC
+        //   |
+        // L |     let b = Ok(4);
+        //   |         -   ^^ cannot infer type for `E` in `std::result::Result<i32, E>`
+        //   |         |
+        //   |         consider giving `b` the explicit type `std::result::Result<i32, E>`, where
+        //   |         the type parameter `E` is specified
+        // ```
+        let (ty_msg, suffix) = match &local_visitor.found_ty {
+            Some(ty) if &ty.to_string() != "_" && name == "_" => {
+                let ty = ty_to_string(ty);
+                (format!(" for `{}`", ty),
+                 format!("the explicit type `{}`, with the type parameters specified", ty))
+            }
+            Some(ty) if &ty.to_string() != "_" && ty.to_string() != name => {
+                let ty = ty_to_string(ty);
+                (format!(" for `{}`", ty),
+                 format!(
+                     "the explicit type `{}`, where the type parameter `{}` is specified",
+                    ty,
+                    name,
+                 ))
+            }
+            _ => (String::new(), "a type".to_owned()),
+        };
+        let mut labels = vec![(span, InferCtxt::missing_type_msg(&name))];
+
         if let Some(pattern) = local_visitor.found_arg_pattern {
             err_span = pattern.span;
             // We don't want to show the default label for closures.
@@ -128,16 +185,21 @@ pub fn need_type_info_err(
             // After clearing, it looks something like this:
             // ```
             // let x = |_| {  };
-            //          ^ consider giving this closure parameter a type
+            //          ^ consider giving this closure parameter the type `[_; 0]`
+            //            with the type parameter `_` specified
             // ```
             labels.clear();
-            labels.push(
-                (pattern.span, "consider giving this closure parameter a type".to_owned()));
+            labels.push((
+                pattern.span,
+                format!("consider giving this closure parameter {}", suffix),
+            ));
         } else if let Some(pattern) = local_visitor.found_local_pattern {
             if let Some(simple_ident) = pattern.simple_ident() {
                 match pattern.span.compiler_desugaring_kind() {
-                    None => labels.push((pattern.span,
-                                         format!("consider giving `{}` a type", simple_ident))),
+                    None => labels.push((
+                        pattern.span,
+                        format!("consider giving `{}` {}", simple_ident, suffix),
+                    )),
                     Some(CompilerDesugaringKind::ForLoop) => labels.push((
                         pattern.span,
                         "the element type for this iterator is not specified".to_owned(),
@@ -145,14 +207,17 @@ pub fn need_type_info_err(
                     _ => {}
                 }
             } else {
-                labels.push((pattern.span, "consider giving the pattern a type".to_owned()));
+                labels.push((pattern.span, format!("consider giving this pattern {}", suffix)));
             }
-        }
+        };
 
-        let mut err = struct_span_err!(self.tcx.sess,
-                                       err_span,
-                                       E0282,
-                                       "type annotations needed");
+        let mut err = struct_span_err!(
+            self.tcx.sess,
+            err_span,
+            E0282,
+            "type annotations needed{}",
+            ty_msg,
+        );
 
         for (target_span, label_message) in labels {
             err.span_label(target_span, label_message);
index 944cc8a8b1999b0112ca47b95ea4ede49cb825fc..ecdcb4bbf114a44de9a37f4c530c3d4ef42748b8 100644 (file)
@@ -86,12 +86,12 @@ pub(super) fn try_report_anon_anon_conflict(&self) -> Option<ErrorReported> {
         let sub_is_ret_type =
             self.is_return_type_anon(scope_def_id_sub, bregion_sub, ty_fndecl_sub);
 
-        let span_label_var1 = match anon_arg_sup.original_pat().simple_ident() {
+        let span_label_var1 = match anon_arg_sup.pat.simple_ident() {
             Some(simple_ident) => format!(" from `{}`", simple_ident),
             None => String::new(),
         };
 
-        let span_label_var2 = match anon_arg_sub.original_pat().simple_ident() {
+        let span_label_var2 = match anon_arg_sub.pat.simple_ident() {
             Some(simple_ident) => format!(" into `{}`", simple_ident),
             None => String::new(),
         };
index 2d7587b11b6f8e51ea905ddc5c3f0cedfcf9fd2d..0efc124e31fee10350238d7be32f935ef6639813 100644 (file)
@@ -95,7 +95,7 @@ pub(super) fn try_report_named_anon_conflict(&self) -> Option<DiagnosticBuilder<
             }
         }
 
-        let (error_var, span_label_var) = match arg.original_pat().simple_ident() {
+        let (error_var, span_label_var) = match arg.pat.simple_ident() {
             Some(simple_ident) => (
                 format!("the type of `{}`", simple_ident),
                 format!("the type of `{}`", simple_ident),
index a4a7efdbc9e3e204d9687b9afeffba6b46dae0fa..4414e677fb5b758adb599c7299d1ae81e39ff6ef 100644 (file)
 use crate::ty::fold::{TypeFolder, TypeFoldable};
 use crate::ty::relate::RelateResult;
 use crate::ty::subst::{Kind, InternalSubsts, SubstsRef};
-use crate::ty::{self, GenericParamDefKind, Ty, TyCtxt, CtxtInterners, InferConst};
+use crate::ty::{self, GenericParamDefKind, Ty, TyCtxt, InferConst};
 use crate::ty::{FloatVid, IntVid, TyVid, ConstVid};
 use crate::util::nodemap::FxHashMap;
 
-use arena::SyncDroplessArena;
 use errors::DiagnosticBuilder;
 use rustc_data_structures::unify as ut;
 use std::cell::{Cell, Ref, RefCell, RefMut};
@@ -468,8 +467,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 /// `F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(InferCtxt<'b, 'gcx, 'tcx>)`.
 pub struct InferCtxtBuilder<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
     global_tcx: TyCtxt<'a, 'gcx, 'gcx>,
-    arena: SyncDroplessArena,
-    interners: Option<CtxtInterners<'tcx>>,
     fresh_tables: Option<RefCell<ty::TypeckTables<'tcx>>>,
 }
 
@@ -477,8 +474,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
     pub fn infer_ctxt(self) -> InferCtxtBuilder<'a, 'gcx, 'tcx> {
         InferCtxtBuilder {
             global_tcx: self,
-            arena: SyncDroplessArena::default(),
-            interners: None,
             fresh_tables: None,
         }
     }
@@ -518,14 +513,10 @@ pub fn enter_with_canonical<T, R>(
     pub fn enter<R>(&'tcx mut self, f: impl for<'b> FnOnce(InferCtxt<'b, 'gcx, 'tcx>) -> R) -> R {
         let InferCtxtBuilder {
             global_tcx,
-            ref arena,
-            ref mut interners,
             ref fresh_tables,
         } = *self;
         let in_progress_tables = fresh_tables.as_ref();
-        // Check that we haven't entered before
-        assert!(interners.is_none());
-        global_tcx.enter_local(arena, interners, |tcx| {
+        global_tcx.enter_local(|tcx| {
             f(InferCtxt {
                 tcx,
                 in_progress_tables,
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 c6583dd7a27b707cd1057dc24b9804f6a96ade1c..c5c6c4b944700c0fdef79fb6a6a9debda17d9528 100644 (file)
@@ -1335,30 +1335,6 @@ fn visit_mac(&mut self, mac: &'a ast::Mac) {
 
         run_early_pass!(self, check_mac, mac);
     }
-
-    fn visit_fn_header(&mut self, header: &'a ast::FnHeader) {
-        // Unlike in HIR lowering and name resolution, the `AsyncArgument` statements are not added
-        // to the function body and the arguments do not replace those in the declaration. They are
-        // still visited manually here so that buffered lints can be emitted.
-        if let ast::IsAsync::Async { ref arguments, .. } = header.asyncness.node {
-            for a in arguments {
-                // Visit the argument..
-                if let Some(arg) = &a.arg {
-                    self.visit_pat(&arg.pat);
-                    if let ast::ArgSource::AsyncFn(pat) = &arg.source {
-                        self.visit_pat(pat);
-                    }
-                    self.visit_ty(&arg.ty);
-                }
-
-                // ..and the statement.
-                self.visit_stmt(&a.move_stmt);
-                if let Some(pat_stmt) = &a.pat_stmt {
-                    self.visit_stmt(&pat_stmt);
-                }
-            }
-        }
-    }
 }
 
 struct LateLintPassObjects<'a> {
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 593a09b6866dbb8335b58c42b5be149941b1bf64..7c57c50595bc8db00ac47645db65b10a0a97c325 100644 (file)
@@ -2414,9 +2414,10 @@ fn report_elision_failure(
                 have_bound_regions,
             } = info;
 
-            let help_name = if let Some(body) = parent {
-                let arg = &self.tcx.hir().body(body).arguments[index];
-                format!("`{}`", self.tcx.hir().hir_to_pretty_string(arg.original_pat().hir_id))
+            let help_name = if let Some(ident) = parent.and_then(|body| {
+                self.tcx.hir().body(body).arguments[index].pat.simple_ident()
+            }) {
+                format!("`{}`", ident)
             } else {
                 format!("argument {}", index + 1)
             };
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 ca79bc15358c500fb6f3216af3933ddf43af2e87..79228a5c56f2d3fa016c5a114526b8b95a474e36 100644 (file)
@@ -1,15 +1,45 @@
 use crate::hir::def_id::{DefId, CrateNum, LOCAL_CRATE};
 use crate::hir::HirId;
 use syntax::symbol::InternedString;
-use crate::ty::{Instance, TyCtxt};
+use syntax::attr::InlineAttr;
+use syntax::source_map::Span;
+use crate::ty::{Instance, InstanceDef, TyCtxt, SymbolName, subst::InternalSubsts};
 use crate::util::nodemap::FxHashMap;
+use crate::ty::print::obsolete::DefPathBasedNames;
+use crate::dep_graph::{WorkProductId, DepNode, WorkProduct, DepConstructor};
 use rustc_data_structures::base_n;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasherResult,
                                            StableHasher};
 use crate::ich::{Fingerprint, StableHashingContext, NodeIdHashingMode};
+use crate::session::config::OptLevel;
 use std::fmt;
 use std::hash::Hash;
 
+/// Describes how a monomorphization will be instantiated in object files.
+#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
+pub enum InstantiationMode {
+    /// There will be exactly one instance of the given MonoItem. It will have
+    /// external linkage so that it can be linked to from other codegen units.
+    GloballyShared {
+        /// In some compilation scenarios we may decide to take functions that
+        /// are typically `LocalCopy` and instead move them to `GloballyShared`
+        /// to avoid codegenning them a bunch of times. In this situation,
+        /// however, our local copy may conflict with other crates also
+        /// inlining the same function.
+        ///
+        /// This flag indicates that this situation is occurring, and informs
+        /// symbol name calculation that some extra mangling is needed to
+        /// avoid conflicts. Note that this may eventually go away entirely if
+        /// ThinLTO enables us to *always* have a globally shared instance of a
+        /// function within one crate's compilation.
+        may_conflict: bool,
+    },
+
+    /// Each codegen unit containing a reference to the given MonoItem will
+    /// have its own private copy of the function (with internal linkage).
+    LocalCopy,
+}
+
 #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
 pub enum MonoItem<'tcx> {
     Fn(Instance<'tcx>),
@@ -31,6 +61,166 @@ pub fn size_estimate<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> usize {
             MonoItem::GlobalAsm(_) => 1,
         }
     }
+
+    pub fn is_generic_fn(&self) -> bool {
+        match *self {
+            MonoItem::Fn(ref instance) => {
+                instance.substs.non_erasable_generics().next().is_some()
+            }
+            MonoItem::Static(..) |
+            MonoItem::GlobalAsm(..) => false,
+        }
+    }
+
+    pub fn symbol_name(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> SymbolName {
+        match *self {
+            MonoItem::Fn(instance) => tcx.symbol_name(instance),
+            MonoItem::Static(def_id) => {
+                tcx.symbol_name(Instance::mono(tcx, def_id))
+            }
+            MonoItem::GlobalAsm(hir_id) => {
+                let def_id = tcx.hir().local_def_id_from_hir_id(hir_id);
+                SymbolName {
+                    name: InternedString::intern(&format!("global_asm_{:?}", def_id))
+                }
+            }
+        }
+    }
+
+    pub fn instantiation_mode(&self,
+                          tcx: TyCtxt<'a, 'tcx, 'tcx>)
+                          -> InstantiationMode {
+        let inline_in_all_cgus =
+            tcx.sess.opts.debugging_opts.inline_in_all_cgus.unwrap_or_else(|| {
+                tcx.sess.opts.optimize != OptLevel::No
+            }) && !tcx.sess.opts.cg.link_dead_code;
+
+        match *self {
+            MonoItem::Fn(ref instance) => {
+                let entry_def_id = tcx.entry_fn(LOCAL_CRATE).map(|(id, _)| id);
+                // If this function isn't inlined or otherwise has explicit
+                // linkage, then we'll be creating a globally shared version.
+                if self.explicit_linkage(tcx).is_some() ||
+                    !instance.def.requires_local(tcx) ||
+                    Some(instance.def_id()) == entry_def_id
+                {
+                    return InstantiationMode::GloballyShared  { may_conflict: false }
+                }
+
+                // At this point we don't have explicit linkage and we're an
+                // inlined function. If we're inlining into all CGUs then we'll
+                // be creating a local copy per CGU
+                if inline_in_all_cgus {
+                    return InstantiationMode::LocalCopy
+                }
+
+                // Finally, if this is `#[inline(always)]` we're sure to respect
+                // that with an inline copy per CGU, but otherwise we'll be
+                // creating one copy of this `#[inline]` function which may
+                // conflict with upstream crates as it could be an exported
+                // symbol.
+                match tcx.codegen_fn_attrs(instance.def_id()).inline {
+                    InlineAttr::Always => InstantiationMode::LocalCopy,
+                    _ => {
+                        InstantiationMode::GloballyShared  { may_conflict: true }
+                    }
+                }
+            }
+            MonoItem::Static(..) |
+            MonoItem::GlobalAsm(..) => {
+                InstantiationMode::GloballyShared { may_conflict: false }
+            }
+        }
+    }
+
+    pub fn explicit_linkage(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<Linkage> {
+        let def_id = match *self {
+            MonoItem::Fn(ref instance) => instance.def_id(),
+            MonoItem::Static(def_id) => def_id,
+            MonoItem::GlobalAsm(..) => return None,
+        };
+
+        let codegen_fn_attrs = tcx.codegen_fn_attrs(def_id);
+        codegen_fn_attrs.linkage
+    }
+
+    /// Returns `true` if this instance is instantiable - whether it has no unsatisfied
+    /// predicates.
+    ///
+    /// In order to codegen an item, all of its predicates must hold, because
+    /// otherwise the item does not make sense. Type-checking ensures that
+    /// the predicates of every item that is *used by* a valid item *do*
+    /// hold, so we can rely on that.
+    ///
+    /// However, we codegen collector roots (reachable items) and functions
+    /// in vtables when they are seen, even if they are not used, and so they
+    /// might not be instantiable. For example, a programmer can define this
+    /// public function:
+    ///
+    ///     pub fn foo<'a>(s: &'a mut ()) where &'a mut (): Clone {
+    ///         <&mut () as Clone>::clone(&s);
+    ///     }
+    ///
+    /// That function can't be codegened, because the method `<&mut () as Clone>::clone`
+    /// does not exist. Luckily for us, that function can't ever be used,
+    /// because that would require for `&'a mut (): Clone` to hold, so we
+    /// can just not emit any code, or even a linker reference for it.
+    ///
+    /// Similarly, if a vtable method has such a signature, and therefore can't
+    /// be used, we can just not emit it and have a placeholder (a null pointer,
+    /// which will never be accessed) in its place.
+    pub fn is_instantiable(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool {
+        debug!("is_instantiable({:?})", self);
+        let (def_id, substs) = match *self {
+            MonoItem::Fn(ref instance) => (instance.def_id(), instance.substs),
+            MonoItem::Static(def_id) => (def_id, InternalSubsts::empty()),
+            // global asm never has predicates
+            MonoItem::GlobalAsm(..) => return true
+        };
+
+        tcx.substitute_normalize_and_test_predicates((def_id, &substs))
+    }
+
+    pub fn to_string(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, debug: bool) -> String {
+        return match *self {
+            MonoItem::Fn(instance) => {
+                to_string_internal(tcx, "fn ", instance, debug)
+            },
+            MonoItem::Static(def_id) => {
+                let instance = Instance::new(def_id, tcx.intern_substs(&[]));
+                to_string_internal(tcx, "static ", instance, debug)
+            },
+            MonoItem::GlobalAsm(..) => {
+                "global_asm".to_string()
+            }
+        };
+
+        fn to_string_internal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                        prefix: &str,
+                                        instance: Instance<'tcx>,
+                                        debug: bool)
+                                        -> String {
+            let mut result = String::with_capacity(32);
+            result.push_str(prefix);
+            let printer = DefPathBasedNames::new(tcx, false, false);
+            printer.push_instance_as_string(instance, &mut result, debug);
+            result
+        }
+    }
+
+    pub fn local_span(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<Span> {
+        match *self {
+            MonoItem::Fn(Instance { def, .. }) => {
+                tcx.hir().as_local_hir_id(def.def_id())
+            }
+            MonoItem::Static(def_id) => {
+                tcx.hir().as_local_hir_id(def_id)
+            }
+            MonoItem::GlobalAsm(hir_id) => {
+                Some(hir_id)
+            }
+        }.map(|hir_id| tcx.hir().span_by_hir_id(hir_id))
+    }
 }
 
 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for MonoItem<'tcx> {
@@ -161,6 +351,73 @@ pub fn modify_size_estimate(&mut self, delta: usize) {
             self.size_estimate = Some(size_estimate + delta);
         }
     }
+
+    pub fn contains_item(&self, item: &MonoItem<'tcx>) -> bool {
+        self.items().contains_key(item)
+    }
+
+    pub fn work_product_id(&self) -> WorkProductId {
+        WorkProductId::from_cgu_name(&self.name().as_str())
+    }
+
+    pub fn work_product(&self, tcx: TyCtxt<'_, '_, '_>) -> WorkProduct {
+        let work_product_id = self.work_product_id();
+        tcx.dep_graph
+           .previous_work_product(&work_product_id)
+           .unwrap_or_else(|| {
+                panic!("Could not find work-product for CGU `{}`", self.name())
+            })
+    }
+
+    pub fn items_in_deterministic_order<'a>(&self,
+                                        tcx: TyCtxt<'a, 'tcx, 'tcx>)
+                                        -> Vec<(MonoItem<'tcx>,
+                                                (Linkage, Visibility))> {
+        // The codegen tests rely on items being process in the same order as
+        // they appear in the file, so for local items, we sort by node_id first
+        #[derive(PartialEq, Eq, PartialOrd, Ord)]
+        pub struct ItemSortKey(Option<HirId>, SymbolName);
+
+        fn item_sort_key<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                   item: MonoItem<'tcx>) -> ItemSortKey {
+            ItemSortKey(match item {
+                MonoItem::Fn(ref instance) => {
+                    match instance.def {
+                        // We only want to take HirIds of user-defined
+                        // instances into account. The others don't matter for
+                        // the codegen tests and can even make item order
+                        // unstable.
+                        InstanceDef::Item(def_id) => {
+                            tcx.hir().as_local_hir_id(def_id)
+                        }
+                        InstanceDef::VtableShim(..) |
+                        InstanceDef::Intrinsic(..) |
+                        InstanceDef::FnPtrShim(..) |
+                        InstanceDef::Virtual(..) |
+                        InstanceDef::ClosureOnceShim { .. } |
+                        InstanceDef::DropGlue(..) |
+                        InstanceDef::CloneShim(..) => {
+                            None
+                        }
+                    }
+                }
+                MonoItem::Static(def_id) => {
+                    tcx.hir().as_local_hir_id(def_id)
+                }
+                MonoItem::GlobalAsm(hir_id) => {
+                    Some(hir_id)
+                }
+            }, item.symbol_name(tcx))
+        }
+
+        let mut items: Vec<_> = self.items().iter().map(|(&i, &l)| (i, l)).collect();
+        items.sort_by_cached_key(|&(i, _)| item_sort_key(tcx, i));
+        items
+    }
+
+    pub fn codegen_dep_node(&self, tcx: TyCtxt<'_, 'tcx, 'tcx>) -> DepNode {
+        DepNode::new(tcx, DepConstructor::CompileCodegenUnit(self.name().clone()))
+    }
 }
 
 impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for CodegenUnit<'tcx> {
index f61677fa594993d3061a90068de6ca4dad70cec1..10efef54526a6d49a905927f24de082a9169d40f 100644 (file)
@@ -4,6 +4,7 @@
 use crate::ty::subst::SubstsRef;
 use crate::dep_graph::SerializedDepNodeIndex;
 use crate::hir::def_id::{CrateNum, DefId, DefIndex};
+use crate::mir;
 use crate::mir::interpret::GlobalId;
 use crate::traits;
 use crate::traits::query::{
@@ -42,7 +43,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))
             }
         }
     }
                 tcx.queries.on_disk_cache.try_load_query_result(tcx, id).map(Ok)
             }
         }
+
+        /// Extracts a field of a (variant of a) const.
+        query const_field(
+            key: ty::ParamEnvAnd<'tcx, (&'tcx ty::Const<'tcx>, mir::Field)>
+        ) -> &'tcx ty::Const<'tcx> {
+            eval_always
+            no_force
+            desc { "extract field of const" }
+        }
+
+        /// Produces an absolute path representation of the given type. See also the documentation
+        /// on `std::any::type_name`.
+        query type_name(key: Ty<'tcx>) -> &'tcx ty::Const<'tcx> {
+            eval_always
+            no_force
+            desc { "get absolute path of type" }
+        }
+
     }
 
     TypeChecking {
             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..2599b8fbf6ff14a51acf6736c2d6e1a7b7de40c5 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,
+    pub local_interner: SyncDroplessArena,
 }
 
-impl<'tcx> AllArenas<'tcx> {
+impl AllArenas {
     pub fn new() -> Self {
         AllArenas {
-            global: WorkerLocal::new(|_| GlobalArenas::default()),
             interner: SyncDroplessArena::default(),
+            local_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> {
@@ -154,7 +137,7 @@ fn new(arena: &'tcx SyncDroplessArena) -> CtxtInterners<'tcx> {
     /// Intern a type
     #[inline(never)]
     fn intern_ty(
-        local: &CtxtInterners<'tcx>,
+        local: &CtxtInterners<'gcx>,
         global: &CtxtInterners<'gcx>,
         st: TyKind<'tcx>
     ) -> Ty<'tcx> {
@@ -179,6 +162,12 @@ fn intern_ty(
                         &ty_struct);
                 }
 
+                // This is safe because all the types the ty_struct can point to
+                // already is in the local arena or the global arena
+                let ty_struct: TyS<'gcx> = unsafe {
+                    mem::transmute(ty_struct)
+                };
+
                 Interned(local.arena.alloc(ty_struct))
             }).0
         } else {
@@ -1029,8 +1018,8 @@ pub struct FreeRegionInfo {
 #[derive(Copy, Clone)]
 pub struct TyCtxt<'a, 'gcx: 'tcx, 'tcx: 'a> {
     gcx: &'gcx GlobalCtxt<'gcx>,
-    interners: &'tcx CtxtInterners<'tcx>,
-    dummy: PhantomData<&'a ()>,
+    interners: &'gcx CtxtInterners<'gcx>,
+    dummy: PhantomData<(&'a (), &'tcx ())>,
 }
 
 impl<'gcx> Deref for TyCtxt<'_, 'gcx, '_> {
@@ -1043,8 +1032,9 @@ fn deref(&self) -> &Self::Target {
 
 pub struct GlobalCtxt<'tcx> {
     pub arena: WorkerLocal<Arena<'tcx>>,
-    global_arenas: &'tcx WorkerLocal<GlobalArenas<'tcx>>,
+
     global_interners: CtxtInterners<'tcx>,
+    local_interners: CtxtInterners<'tcx>,
 
     cstore: &'tcx CrateStoreDyn,
 
@@ -1081,11 +1071,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 +1135,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 +1146,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 +1219,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>,
@@ -1262,6 +1231,7 @@ pub fn create_global_ctxt(
             s.fatal(&err);
         });
         let interners = CtxtInterners::new(&arenas.interner);
+        let local_interners = CtxtInterners::new(&arenas.local_interner);
         let common = Common {
             empty_predicates: ty::GenericPredicates {
                 parent: None,
@@ -1319,8 +1289,8 @@ pub fn create_global_ctxt(
             sess: s,
             cstore,
             arena: WorkerLocal::new(|_| Arena::default()),
-            global_arenas: &arenas.global,
             global_interners: interners,
+            local_interners: local_interners,
             dep_graph,
             common,
             types: common_types,
@@ -1333,12 +1303,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()
@@ -1716,18 +1680,15 @@ impl<'gcx> GlobalCtxt<'gcx> {
     /// with the same lifetime as `arena`.
     pub fn enter_local<'tcx, F, R>(
         &'gcx self,
-        arena: &'tcx SyncDroplessArena,
-        interners: &'tcx mut Option<CtxtInterners<'tcx>>,
         f: F
     ) -> R
     where
         F: FnOnce(TyCtxt<'tcx, 'gcx, 'tcx>) -> R,
         'gcx: 'tcx,
     {
-        *interners = Some(CtxtInterners::new(&arena));
         let tcx = TyCtxt {
             gcx: self,
-            interners: interners.as_ref().unwrap(),
+            interners: &self.local_interners,
             dummy: PhantomData,
         };
         ty::tls::with_related_context(tcx.global_tcx(), |icx| {
@@ -2333,6 +2294,17 @@ impl<'a, 'gcx, $lt_tcx> TyCtxt<'a, 'gcx, $lt_tcx> {
             pub fn $method(self, v: $alloc) -> &$lt_tcx $ty {
                 let key = ($alloc_to_key)(&v);
 
+                let alloc = |v, interners: &'gcx CtxtInterners<'gcx>| {
+                    // This transmutes $alloc<'tcx> to $alloc<'gcx>
+                    let v = unsafe {
+                        mem::transmute(v)
+                    };
+                    let i: &$lt_tcx $ty = $alloc_method(&interners.arena, v);
+                    // Cast to 'gcx
+                    let i = unsafe { mem::transmute(i) };
+                    Interned(i)
+                };
+
                 // HACK(eddyb) Depend on flags being accurate to
                 // determine that all contents are in the global tcx.
                 // See comments on Lift for why we can't use that.
@@ -2346,18 +2318,11 @@ pub fn $method(self, v: $alloc) -> &$lt_tcx $ty {
                                 v);
                         }
 
-                        Interned($alloc_method(&self.interners.arena, v))
+                        alloc(v, &self.interners)
                     }).0
                 } else {
                     self.global_interners.$name.borrow_mut().intern_ref(key, || {
-                        // This transmutes $alloc<'tcx> to $alloc<'gcx>
-                        let v = unsafe {
-                            mem::transmute(v)
-                        };
-                        let i: &$lt_tcx $ty = $alloc_method(&self.global_interners.arena, v);
-                        // Cast to 'gcx
-                        let i = unsafe { mem::transmute(i) };
-                        Interned(i)
+                        alloc(v, &self.global_interners)
                     }).0
                 }
             }
@@ -3059,7 +3024,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 be15b1e3cc9e4c930831354a2c3d300f61e1166c..f0251917074d44f6ec5c4f30240c5721349a1249 100644 (file)
@@ -4,6 +4,7 @@
 use crate::ty::{self, Ty, PolyFnSig, TypeFoldable, SubstsRef, TyCtxt};
 use crate::ty::print::{FmtPrinter, Printer};
 use crate::traits;
+use crate::middle::lang_items::DropInPlaceFnLangItem;
 use rustc_target::spec::abi::Abi;
 use rustc_macros::HashStable;
 
@@ -325,11 +326,47 @@ pub fn resolve_closure(
         let actual_kind = substs.closure_kind(def_id, tcx);
 
         match needs_fn_once_adapter_shim(actual_kind, requested_kind) {
-            Ok(true) => fn_once_adapter_instance(tcx, def_id, substs),
+            Ok(true) => Instance::fn_once_adapter_instance(tcx, def_id, substs),
             _ => Instance::new(def_id, substs.substs)
         }
     }
 
+    pub fn resolve_drop_in_place(
+        tcx: TyCtxt<'a, 'tcx, 'tcx>,
+        ty: Ty<'tcx>)
+        -> ty::Instance<'tcx>
+    {
+        let def_id = tcx.require_lang_item(DropInPlaceFnLangItem);
+        let substs = tcx.intern_substs(&[ty.into()]);
+        Instance::resolve(tcx, ty::ParamEnv::reveal_all(), def_id, substs).unwrap()
+    }
+
+    pub fn fn_once_adapter_instance(
+        tcx: TyCtxt<'a, 'tcx, 'tcx>,
+        closure_did: DefId,
+        substs: ty::ClosureSubsts<'tcx>)
+        -> Instance<'tcx>
+    {
+        debug!("fn_once_adapter_shim({:?}, {:?})",
+               closure_did,
+               substs);
+        let fn_once = tcx.lang_items().fn_once_trait().unwrap();
+        let call_once = tcx.associated_items(fn_once)
+            .find(|it| it.kind == ty::AssocKind::Method)
+            .unwrap().def_id;
+        let def = ty::InstanceDef::ClosureOnceShim { call_once };
+
+        let self_ty = tcx.mk_closure(closure_did, substs);
+
+        let sig = substs.closure_sig(closure_did, tcx);
+        let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
+        assert_eq!(sig.inputs().len(), 1);
+        let substs = tcx.mk_substs_trait(self_ty, &[sig.inputs()[0].into()]);
+
+        debug!("fn_once_adapter_shim: self_ty={:?} sig={:?}", self_ty, sig);
+        Instance { def, substs }
+    }
+
     pub fn is_vtable_shim(&self) -> bool {
         if let InstanceDef::VtableShim(..) = self.def {
             true
@@ -438,29 +475,3 @@ fn needs_fn_once_adapter_shim<'a, 'tcx>(actual_closure_kind: ty::ClosureKind,
         (ty::ClosureKind::FnOnce, _) => Err(())
     }
 }
-
-fn fn_once_adapter_instance<'a, 'tcx>(
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    closure_did: DefId,
-    substs: ty::ClosureSubsts<'tcx>)
-    -> Instance<'tcx>
-{
-    debug!("fn_once_adapter_shim({:?}, {:?})",
-           closure_did,
-           substs);
-    let fn_once = tcx.lang_items().fn_once_trait().unwrap();
-    let call_once = tcx.associated_items(fn_once)
-        .find(|it| it.kind == ty::AssocKind::Method)
-        .unwrap().def_id;
-    let def = ty::InstanceDef::ClosureOnceShim { call_once };
-
-    let self_ty = tcx.mk_closure(closure_did, substs);
-
-    let sig = substs.closure_sig(closure_did, tcx);
-    let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
-    assert_eq!(sig.inputs().len(), 1);
-    let substs = tcx.mk_substs_trait(self_ty, &[sig.inputs()[0].into()]);
-
-    debug!("fn_once_adapter_shim: self_ty={:?} sig={:?}", self_ty, sig);
-    Instance { def, substs }
-}
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 53d4466cfef684d8007e4b4c569ba64e15cfe634..a7cb7bd3956f00457b30c76b636bc204fe40d574 100644 (file)
@@ -9,6 +9,8 @@
 mod pretty;
 pub use self::pretty::*;
 
+pub mod obsolete;
+
 pub trait Print<'gcx, 'tcx, P> {
     type Output;
     type Error;
diff --git a/src/librustc/ty/print/obsolete.rs b/src/librustc/ty/print/obsolete.rs
new file mode 100644 (file)
index 0000000..85d3386
--- /dev/null
@@ -0,0 +1,286 @@
+//! Allows for producing a unique string key for a mono item.
+//! These keys are used by the handwritten auto-tests, so they need to be
+//! predictable and human-readable.
+//!
+//! Note: A lot of this could looks very similar to what's already in `ty::print`.
+//! FIXME(eddyb) implement a custom `PrettyPrinter` for this.
+
+use rustc::hir::def_id::DefId;
+use rustc::mir::interpret::ConstValue;
+use rustc::ty::subst::SubstsRef;
+use rustc::ty::{self, ClosureSubsts, Const, GeneratorSubsts, Instance, Ty, TyCtxt};
+use rustc::{bug, hir};
+use std::fmt::Write;
+use std::iter;
+use syntax::ast;
+
+/// Same as `unique_type_name()` but with the result pushed onto the given
+/// `output` parameter.
+pub struct DefPathBasedNames<'a, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    omit_disambiguators: bool,
+    omit_local_crate_name: bool,
+}
+
+impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
+    pub fn new(
+        tcx: TyCtxt<'a, 'tcx, 'tcx>,
+        omit_disambiguators: bool,
+        omit_local_crate_name: bool,
+    ) -> Self {
+        DefPathBasedNames { tcx, omit_disambiguators, omit_local_crate_name }
+    }
+
+    // Pushes the type name of the specified type to the provided string.
+    // If `debug` is true, printing normally unprintable types is allowed
+    // (e.g. `ty::GeneratorWitness`). This parameter should only be set when
+    // this method is being used for logging purposes (e.g. with `debug!` or `info!`)
+    // When being used for codegen purposes, `debug` should be set to `false`
+    // in order to catch unexpected types that should never end up in a type name.
+    pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String, debug: bool) {
+        match t.sty {
+            ty::Bool => output.push_str("bool"),
+            ty::Char => output.push_str("char"),
+            ty::Str => output.push_str("str"),
+            ty::Never => output.push_str("!"),
+            ty::Int(ast::IntTy::Isize) => output.push_str("isize"),
+            ty::Int(ast::IntTy::I8) => output.push_str("i8"),
+            ty::Int(ast::IntTy::I16) => output.push_str("i16"),
+            ty::Int(ast::IntTy::I32) => output.push_str("i32"),
+            ty::Int(ast::IntTy::I64) => output.push_str("i64"),
+            ty::Int(ast::IntTy::I128) => output.push_str("i128"),
+            ty::Uint(ast::UintTy::Usize) => output.push_str("usize"),
+            ty::Uint(ast::UintTy::U8) => output.push_str("u8"),
+            ty::Uint(ast::UintTy::U16) => output.push_str("u16"),
+            ty::Uint(ast::UintTy::U32) => output.push_str("u32"),
+            ty::Uint(ast::UintTy::U64) => output.push_str("u64"),
+            ty::Uint(ast::UintTy::U128) => output.push_str("u128"),
+            ty::Float(ast::FloatTy::F32) => output.push_str("f32"),
+            ty::Float(ast::FloatTy::F64) => output.push_str("f64"),
+            ty::Adt(adt_def, substs) => {
+                self.push_def_path(adt_def.did, output);
+                self.push_generic_params(substs, iter::empty(), output, debug);
+            }
+            ty::Tuple(component_types) => {
+                output.push('(');
+                for &component_type in component_types {
+                    self.push_type_name(component_type.expect_ty(), output, debug);
+                    output.push_str(", ");
+                }
+                if !component_types.is_empty() {
+                    output.pop();
+                    output.pop();
+                }
+                output.push(')');
+            }
+            ty::RawPtr(ty::TypeAndMut { ty: inner_type, mutbl }) => {
+                output.push('*');
+                match mutbl {
+                    hir::MutImmutable => output.push_str("const "),
+                    hir::MutMutable => output.push_str("mut "),
+                }
+
+                self.push_type_name(inner_type, output, debug);
+            }
+            ty::Ref(_, inner_type, mutbl) => {
+                output.push('&');
+                if mutbl == hir::MutMutable {
+                    output.push_str("mut ");
+                }
+
+                self.push_type_name(inner_type, output, debug);
+            }
+            ty::Array(inner_type, len) => {
+                output.push('[');
+                self.push_type_name(inner_type, output, debug);
+                write!(output, "; {}", len.unwrap_usize(self.tcx)).unwrap();
+                output.push(']');
+            }
+            ty::Slice(inner_type) => {
+                output.push('[');
+                self.push_type_name(inner_type, output, debug);
+                output.push(']');
+            }
+            ty::Dynamic(ref trait_data, ..) => {
+                if let Some(principal) = trait_data.principal() {
+                    self.push_def_path(principal.def_id(), output);
+                    self.push_generic_params(
+                        principal.skip_binder().substs,
+                        trait_data.projection_bounds(),
+                        output,
+                        debug,
+                    );
+                } else {
+                    output.push_str("dyn '_");
+                }
+            }
+            ty::Foreign(did) => self.push_def_path(did, output),
+            ty::FnDef(..) | ty::FnPtr(_) => {
+                let sig = t.fn_sig(self.tcx);
+                if sig.unsafety() == hir::Unsafety::Unsafe {
+                    output.push_str("unsafe ");
+                }
+
+                let abi = sig.abi();
+                if abi != ::rustc_target::spec::abi::Abi::Rust {
+                    output.push_str("extern \"");
+                    output.push_str(abi.name());
+                    output.push_str("\" ");
+                }
+
+                output.push_str("fn(");
+
+                let sig =
+                    self.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
+
+                if !sig.inputs().is_empty() {
+                    for &parameter_type in sig.inputs() {
+                        self.push_type_name(parameter_type, output, debug);
+                        output.push_str(", ");
+                    }
+                    output.pop();
+                    output.pop();
+                }
+
+                if sig.c_variadic {
+                    if !sig.inputs().is_empty() {
+                        output.push_str(", ...");
+                    } else {
+                        output.push_str("...");
+                    }
+                }
+
+                output.push(')');
+
+                if !sig.output().is_unit() {
+                    output.push_str(" -> ");
+                    self.push_type_name(sig.output(), output, debug);
+                }
+            }
+            ty::Generator(def_id, GeneratorSubsts { ref substs }, _)
+            | ty::Closure(def_id, ClosureSubsts { ref substs }) => {
+                self.push_def_path(def_id, output);
+                let generics = self.tcx.generics_of(self.tcx.closure_base_def_id(def_id));
+                let substs = substs.truncate_to(self.tcx, generics);
+                self.push_generic_params(substs, iter::empty(), output, debug);
+            }
+            ty::Error
+            | ty::Bound(..)
+            | ty::Infer(_)
+            | ty::Placeholder(..)
+            | ty::UnnormalizedProjection(..)
+            | ty::Projection(..)
+            | ty::Param(_)
+            | ty::GeneratorWitness(_)
+            | ty::Opaque(..) => {
+                if debug {
+                    output.push_str(&format!("`{:?}`", t));
+                } else {
+                    bug!(
+                        "DefPathBasedNames: trying to create type name for unexpected type: {:?}",
+                        t,
+                    );
+                }
+            }
+        }
+    }
+
+    // Pushes the the name of the specified const to the provided string.
+    // If `debug` is true, usually-unprintable consts (such as `Infer`) will be printed,
+    // as well as the unprintable types of constants (see `push_type_name` for more details).
+    pub fn push_const_name(&self, c: &Const<'tcx>, output: &mut String, debug: bool) {
+        match c.val {
+            ConstValue::Scalar(..) | ConstValue::Slice { .. } | ConstValue::ByRef(..) => {
+                // FIXME(const_generics): we could probably do a better job here.
+                write!(output, "{:?}", c).unwrap()
+            }
+            _ => {
+                if debug {
+                    write!(output, "{:?}", c).unwrap()
+                } else {
+                    bug!(
+                        "DefPathBasedNames: trying to create const name for unexpected const: {:?}",
+                        c,
+                    );
+                }
+            }
+        }
+        output.push_str(": ");
+        self.push_type_name(c.ty, output, debug);
+    }
+
+    pub fn push_def_path(&self, def_id: DefId, output: &mut String) {
+        let def_path = self.tcx.def_path(def_id);
+
+        // some_crate::
+        if !(self.omit_local_crate_name && def_id.is_local()) {
+            output.push_str(&self.tcx.crate_name(def_path.krate).as_str());
+            output.push_str("::");
+        }
+
+        // foo::bar::ItemName::
+        for part in self.tcx.def_path(def_id).data {
+            if self.omit_disambiguators {
+                write!(output, "{}::", part.data.as_interned_str()).unwrap();
+            } else {
+                write!(output, "{}[{}]::", part.data.as_interned_str(), part.disambiguator)
+                    .unwrap();
+            }
+        }
+
+        // remove final "::"
+        output.pop();
+        output.pop();
+    }
+
+    fn push_generic_params<I>(
+        &self,
+        substs: SubstsRef<'tcx>,
+        projections: I,
+        output: &mut String,
+        debug: bool,
+    ) where
+        I: Iterator<Item = ty::PolyExistentialProjection<'tcx>>,
+    {
+        let mut projections = projections.peekable();
+        if substs.non_erasable_generics().next().is_none() && projections.peek().is_none() {
+            return;
+        }
+
+        output.push('<');
+
+        for type_parameter in substs.types() {
+            self.push_type_name(type_parameter, output, debug);
+            output.push_str(", ");
+        }
+
+        for projection in projections {
+            let projection = projection.skip_binder();
+            let name = &self.tcx.associated_item(projection.item_def_id).ident.as_str();
+            output.push_str(name);
+            output.push_str("=");
+            self.push_type_name(projection.ty, output, debug);
+            output.push_str(", ");
+        }
+
+        for const_parameter in substs.consts() {
+            self.push_const_name(const_parameter, output, debug);
+            output.push_str(", ");
+        }
+
+        output.pop();
+        output.pop();
+
+        output.push('>');
+    }
+
+    pub fn push_instance_as_string(
+        &self,
+        instance: Instance<'tcx>,
+        output: &mut String,
+        debug: bool,
+    ) {
+        self.push_def_path(instance.def_id(), output);
+        self.push_generic_params(instance.substs, iter::empty(), output, debug);
+    }
+}
index a246d9652f2f045ef3b1c9667b736c191e0d2d62..513ffd69ccaadfc58309b79de33da5cb3ec21e16 100644 (file)
@@ -483,7 +483,17 @@ fn pretty_print_type(
             ty::FnPtr(ref bare_fn) => {
                 p!(print(bare_fn))
             }
-            ty::Infer(infer_ty) => p!(write("{}", infer_ty)),
+            ty::Infer(infer_ty) => {
+                if let ty::TyVar(ty_vid) = infer_ty {
+                    if let Some(name) = self.infer_ty_name(ty_vid) {
+                        p!(write("{}", name))
+                    } else {
+                        p!(write("{}", infer_ty))
+                    }
+                } else {
+                    p!(write("{}", infer_ty))
+                }
+            },
             ty::Error => p!(write("[type error]")),
             ty::Param(ref param_ty) => p!(write("{}", param_ty)),
             ty::Bound(debruijn, bound_ty) => {
@@ -585,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 = ", ";
                     }
@@ -628,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 = ", ";
                     }
@@ -681,6 +691,10 @@ fn pretty_print_type(
         Ok(self)
     }
 
+    fn infer_ty_name(&self, _: ty::TyVid) -> Option<String> {
+        None
+    }
+
     fn pretty_print_dyn_existential(
         mut self,
         predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
@@ -931,6 +945,8 @@ pub struct FmtPrinterData<'a, 'gcx, 'tcx, F> {
     binder_depth: usize,
 
     pub region_highlight_mode: RegionHighlightMode,
+
+    pub name_resolver: Option<Box<&'a dyn Fn(ty::sty::TyVid) -> Option<String>>>,
 }
 
 impl<F> Deref for FmtPrinter<'a, 'gcx, 'tcx, F> {
@@ -957,6 +973,7 @@ pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, fmt: F, ns: Namespace) -> Self {
             region_index: 0,
             binder_depth: 0,
             region_highlight_mode: RegionHighlightMode::default(),
+            name_resolver: None,
         }))
     }
 }
@@ -1206,6 +1223,10 @@ fn path_generic_args(
 }
 
 impl<F: fmt::Write> PrettyPrinter<'gcx, 'tcx> for FmtPrinter<'_, 'gcx, 'tcx, F> {
+    fn infer_ty_name(&self, id: ty::TyVid) -> Option<String> {
+        self.0.name_resolver.as_ref().and_then(|func| func(id))
+    }
+
     fn print_value_path(
         mut self,
         def_id: DefId,
@@ -1441,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 d353da801778d5999f6426caa0665af8da36bb6b..27b0e8e881df9b3700d482c775c5814ed9c28347 100644 (file)
@@ -127,6 +127,15 @@ fn default_span(&self, tcx: TyCtxt<'_, '_, '_>) -> Span {
     }
 }
 
+impl<'tcx> Key for (&'tcx ty::Const<'tcx>, mir::Field) {
+    fn query_crate(&self) -> CrateNum {
+        LOCAL_CRATE
+    }
+    fn default_span(&self, _: TyCtxt<'_, '_, '_>) -> Span {
+        DUMMY_SP
+    }
+}
+
 impl<'tcx> Key for ty::PolyTraitRef<'tcx>{
     fn query_crate(&self) -> CrateNum {
         self.def_id().krate
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 f8c6087373f1eb9218bd24c475e22bb6a8d417b6..62374eb21039ad4d6397a39a18f56f016af1c153 100644 (file)
@@ -22,7 +22,6 @@
 use crate::builder::Builder;
 use crate::common;
 use crate::context::CodegenCx;
-use crate::monomorphize::partitioning::CodegenUnitExt;
 use rustc::dep_graph;
 use rustc::mir::mono::{Linkage, Visibility};
 use rustc::middle::cstore::{EncodedMetadata};
index 42e7a72c43b217cffdcd9615347bd7a3f0772722..102e9e38612e065e227f73d36588be9a2249fcf7 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,78 @@ 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,
+        unchecked_sadd(x, y) => LLVMBuildNSWAdd,
+        unchecked_uadd(x, y) => LLVMBuildNUWAdd,
+        unchecked_ssub(x, y) => LLVMBuildNSWSub,
+        unchecked_usub(x, y) => LLVMBuildNUWSub,
+        unchecked_smul(x, y) => LLVMBuildNSWMul,
+        unchecked_umul(x, y) => LLVMBuildNUWMul,
     }
 
     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 +398,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 +416,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 +429,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 +437,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 +453,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 +656,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 +750,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 +758,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 +832,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 +862,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 +871,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 +879,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 +1049,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 +1138,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 +1149,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 +1291,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 +1314,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 2d732adcb91381650d7114fd298098fb75e04cfb..2c0a6f631b73948622249f3a46efacf9af782474 100644 (file)
@@ -6,12 +6,11 @@
 
 use crate::attributes;
 use crate::llvm;
-use crate::monomorphize::Instance;
 use crate::context::CodegenCx;
 use crate::value::Value;
 use rustc_codegen_ssa::traits::*;
 
-use rustc::ty::TypeFoldable;
+use rustc::ty::{TypeFoldable, Instance};
 use rustc::ty::layout::{LayoutOf, HasTyCtxt};
 
 /// Codegens a reference to a fn/method item, monomorphizing and
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 99b5cf42551faff6d56c991e7174c3180c905d7d..eb059ac453c3d8319ca5b8c2a81463f250acfb25 100644 (file)
@@ -1,8 +1,6 @@
 use crate::llvm::{self, SetUnnamedAddr, True};
 use crate::debuginfo;
-use crate::monomorphize::MonoItem;
 use crate::common::CodegenCx;
-use crate::monomorphize::Instance;
 use crate::base;
 use crate::type_::Type;
 use crate::type_of::LayoutLlvmExt;
 use rustc::hir::def_id::DefId;
 use rustc::mir::interpret::{ConstValue, Allocation, read_target_uint,
     Pointer, ErrorHandled, GlobalId};
+use rustc::mir::mono::MonoItem;
 use rustc::hir::Node;
 use syntax_pos::Span;
 use rustc_target::abi::HasDataLayout;
 use syntax::symbol::sym;
 use syntax_pos::symbol::LocalInternedString;
-use rustc::ty::{self, Ty};
+use rustc::ty::{self, Ty, Instance};
 use rustc_codegen_ssa::traits::*;
 
 use rustc::ty::layout::{self, Size, Align, LayoutOf};
index b6b47d047c8b1023e8c7ef843167ff0b3d502257..ead9bad656db5605d2138cdcc8ae2ba97bc1bcca 100644 (file)
@@ -1,23 +1,22 @@
 use crate::attributes;
 use crate::llvm;
 use crate::debuginfo;
-use crate::monomorphize::Instance;
 use crate::value::Value;
 use rustc::dep_graph::DepGraphSafe;
 use rustc::hir;
 
-use crate::monomorphize::partitioning::CodegenUnit;
 use crate::type_::Type;
 use rustc_codegen_ssa::traits::*;
 
 use rustc_data_structures::base_n;
 use rustc_data_structures::small_c_str::SmallCStr;
+use rustc::mir::mono::CodegenUnit;
 use rustc::session::config::{self, DebugInfo};
 use rustc::session::Session;
 use rustc::ty::layout::{
     LayoutError, LayoutOf, PointeeInfo, Size, TyLayout, VariantIdx, HasParamEnv
 };
-use rustc::ty::{self, Ty, TyCtxt};
+use rustc::ty::{self, Ty, TyCtxt, Instance};
 use rustc::util::nodemap::FxHashMap;
 use rustc_target::spec::{HasTargetSpec, Target};
 use rustc_codegen_ssa::callee::resolve_and_get_fn;
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 6fa594d44530004bbd7a1df51d0d4fb73db1795a..548ea0b1036e0e564e6e96c009c8bda5ff9b0e31 100644 (file)
@@ -20,9 +20,8 @@
 use crate::abi::Abi;
 use crate::common::CodegenCx;
 use crate::builder::Builder;
-use crate::monomorphize::Instance;
 use crate::value::Value;
-use rustc::ty::{self, ParamEnv, Ty, InstanceDef};
+use rustc::ty::{self, ParamEnv, Ty, InstanceDef, Instance};
 use rustc::mir;
 use rustc::session::config::{self, DebugInfo};
 use rustc::util::nodemap::{DefIdMap, FxHashMap, FxHashSet};
index f7c377adf35297297904ec609c794678a3485eec..889984749fdf7aa94558e8344e1d781776ae2371 100644 (file)
@@ -2,8 +2,7 @@
 
 use super::metadata::{unknown_file_metadata, UNKNOWN_LINE_NUMBER};
 use super::utils::{DIB, debug_context};
-use crate::monomorphize::Instance;
-use rustc::ty;
+use rustc::ty::{self, Instance};
 
 use crate::llvm;
 use crate::llvm::debuginfo::DIScope;
index 060c295eb7af19b13664aea56355b193626481d8..42aa9989346fca3a4547ada64084dcf1d1860ded 100644 (file)
@@ -212,7 +212,7 @@ fn codegen_intrinsic_call(
             }
             "type_name" => {
                 let tp_ty = substs.type_at(0);
-                let ty_name = rustc_mir::interpret::type_name(self.tcx, tp_ty);
+                let ty_name = self.tcx.type_name(tp_ty);
                 OperandRef::from_const(self, ty_name).immediate_or_packed_pair(self)
             }
             "type_id" => {
@@ -334,7 +334,8 @@ fn codegen_intrinsic_call(
             "ctlz" | "ctlz_nonzero" | "cttz" | "cttz_nonzero" | "ctpop" | "bswap" |
             "bitreverse" | "add_with_overflow" | "sub_with_overflow" |
             "mul_with_overflow" | "overflowing_add" | "overflowing_sub" | "overflowing_mul" |
-            "unchecked_div" | "unchecked_rem" | "unchecked_shl" | "unchecked_shr" | "exact_div" |
+            "unchecked_div" | "unchecked_rem" | "unchecked_shl" | "unchecked_shr" |
+            "unchecked_add" | "unchecked_sub" | "unchecked_mul" | "exact_div" |
             "rotate_left" | "rotate_right" | "saturating_add" | "saturating_sub" => {
                 let ty = arg_tys[0];
                 match int_type_width_signed(ty, self) {
@@ -430,6 +431,27 @@ fn codegen_intrinsic_call(
                                 } else {
                                     self.lshr(args[0].immediate(), args[1].immediate())
                                 },
+                            "unchecked_add" => {
+                                if signed {
+                                    self.unchecked_sadd(args[0].immediate(), args[1].immediate())
+                                } else {
+                                    self.unchecked_uadd(args[0].immediate(), args[1].immediate())
+                                }
+                            },
+                            "unchecked_sub" => {
+                                if signed {
+                                    self.unchecked_ssub(args[0].immediate(), args[1].immediate())
+                                } else {
+                                    self.unchecked_usub(args[0].immediate(), args[1].immediate())
+                                }
+                            },
+                            "unchecked_mul" => {
+                                if signed {
+                                    self.unchecked_smul(args[0].immediate(), args[1].immediate())
+                                } else {
+                                    self.unchecked_umul(args[0].immediate(), args[1].immediate())
+                                }
+                            },
                             "rotate_left" | "rotate_right" => {
                                 let is_left = name == "rotate_left";
                                 let val = args[0].immediate();
index 57cffa48163e1d6506a857c38776cb9b4d87d21a..0fdd326a1882e667fb681bd4147a36c2d09b01d1 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)]
@@ -31,7 +32,6 @@
 #[macro_use] extern crate bitflags;
 extern crate libc;
 #[macro_use] extern crate rustc;
-extern crate rustc_mir;
 extern crate rustc_allocator;
 extern crate rustc_target;
 #[macro_use] extern crate rustc_data_structures;
@@ -63,7 +63,6 @@
 use rustc::session::config::{OutputFilenames, OutputType, PrintRequest, OptLevel};
 use rustc::ty::{self, TyCtxt};
 use rustc::util::common::ErrorReported;
-use rustc_mir::monomorphize;
 use rustc_codegen_ssa::ModuleCodegen;
 use rustc_codegen_utils::codegen_backend::CodegenBackend;
 
index f88923fc9f1c5dc54e94062c6e68f51363f288ad..a71243c7c826b9e6361814f376de9bcb7f377269 100644 (file)
@@ -1002,6 +1002,36 @@ pub fn LLVMBuildAShr(B: &Builder<'a>,
                          RHS: &'a Value,
                          Name: *const c_char)
                          -> &'a Value;
+    pub fn LLVMBuildNSWAdd(B: &Builder<'a>,
+                           LHS: &'a Value,
+                           RHS: &'a Value,
+                           Name: *const c_char)
+                           -> &'a Value;
+    pub fn LLVMBuildNUWAdd(B: &Builder<'a>,
+                           LHS: &'a Value,
+                           RHS: &'a Value,
+                           Name: *const c_char)
+                           -> &'a Value;
+    pub fn LLVMBuildNSWSub(B: &Builder<'a>,
+                           LHS: &'a Value,
+                           RHS: &'a Value,
+                           Name: *const c_char)
+                           -> &'a Value;
+    pub fn LLVMBuildNUWSub(B: &Builder<'a>,
+                           LHS: &'a Value,
+                           RHS: &'a Value,
+                           Name: *const c_char)
+                           -> &'a Value;
+    pub fn LLVMBuildNSWMul(B: &Builder<'a>,
+                           LHS: &'a Value,
+                           RHS: &'a Value,
+                           Name: *const c_char)
+                           -> &'a Value;
+    pub fn LLVMBuildNUWMul(B: &Builder<'a>,
+                           LHS: &'a Value,
+                           RHS: &'a Value,
+                           Name: *const c_char)
+                           -> &'a Value;
     pub fn LLVMBuildAnd(B: &Builder<'a>,
                         LHS: &'a Value,
                         RHS: &'a Value,
index 7f0cdb9f580088b1b49f0e0ee1d08596f42afcb7..c1703ffd0c753524ab53284ec78320349ab1cfa3 100644 (file)
@@ -2,11 +2,10 @@
 use crate::base;
 use crate::context::CodegenCx;
 use crate::llvm;
-use crate::monomorphize::Instance;
 use crate::type_of::LayoutLlvmExt;
 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::mir::mono::{Linkage, Visibility};
-use rustc::ty::TypeFoldable;
+use rustc::ty::{TypeFoldable, Instance};
 use rustc::ty::layout::{LayoutOf, HasTyCtxt};
 use rustc_codegen_ssa::traits::*;
 
index 800bf505125d677842d88e8023848b91edb342fa..7a82fd731f60483d1fdb5df533eea33faf0e675f 100644 (file)
@@ -4,7 +4,7 @@
 use rustc::ty::{self, Ty, TypeFoldable};
 use rustc::ty::layout::{self, Align, LayoutOf, FnTypeExt, PointeeInfo, Size, TyLayout};
 use rustc_target::abi::{FloatTy, TyLayoutMethods};
-use rustc_mir::monomorphize::item::DefPathBasedNames;
+use rustc::ty::print::obsolete::DefPathBasedNames;
 use rustc_codegen_ssa::traits::*;
 
 use std::fmt::Write;
index 0b34ec8e8bc1cb857e12637510d717ac4cf3e3ce..a4cb517fafed6af5327b9b0237dec80c7ea94915 100644 (file)
@@ -33,5 +33,4 @@ rustc_data_structures = { path = "../librustc_data_structures"}
 rustc_errors = { path = "../librustc_errors" }
 rustc_fs_util = { path = "../librustc_fs_util" }
 rustc_incremental = { path = "../librustc_incremental" }
-rustc_mir = { path = "../librustc_mir" }
 rustc_target = { path = "../librustc_target" }
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 172b5b39987d43247f137f5039361318c3ebe749..0cd29e0213ee7b2ca73ba20b9ca5ce862ce5cf54 100644 (file)
 use rustc::middle::cstore::EncodedMetadata;
 use rustc::middle::lang_items::StartFnLangItem;
 use rustc::middle::weak_lang_items;
-use rustc::mir::mono::CodegenUnitNameBuilder;
-use rustc::ty::{self, Ty, TyCtxt};
+use rustc::mir::mono::{CodegenUnitNameBuilder, CodegenUnit, MonoItem};
+use rustc::ty::{self, Ty, TyCtxt, Instance};
 use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, VariantIdx, HasTyCtxt};
 use rustc::ty::query::Providers;
 use rustc::middle::cstore::{self, LinkagePreference};
 use rustc::util::common::{time, print_time_passes_entry};
 use rustc::session::config::{self, EntryFnType, Lto};
 use rustc::session::Session;
-use rustc_mir::monomorphize::Instance;
-use rustc_mir::monomorphize::partitioning::{CodegenUnit, CodegenUnitExt};
 use rustc::util::nodemap::FxHashMap;
 use rustc_data_structures::indexed_vec::Idx;
 use rustc_codegen_utils::{symbol_names_test, check_for_rustc_errors_attr};
@@ -42,7 +40,6 @@
 use crate::common::{RealPredicate, TypeKind, IntPredicate};
 use crate::meth;
 use crate::mir;
-use crate::mono_item::MonoItem;
 
 use crate::traits::*;
 
index 49f3c87ee2d9dc8de0eb13820a7d9b2c27a2dcf2..d38e434d98ce81cfc4ba73002dcb463b293b7d92 100644 (file)
@@ -1,10 +1,9 @@
 use rustc_target::abi::call::FnType;
-use rustc_mir::monomorphize;
 
 use crate::callee;
 use crate::traits::*;
 
-use rustc::ty::{self, Ty};
+use rustc::ty::{self, Ty, Instance};
 
 #[derive(Copy, Clone, Debug)]
 pub struct VirtualIndex(u64);
@@ -103,7 +102,7 @@ pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>(
     // `get_vtable` in rust_mir/interpret/traits.rs
     // /////////////////////////////////////////////////////////////////////////////////////////////
     let components: Vec<_> = [
-        cx.get_fn(monomorphize::resolve_drop_in_place(cx.tcx(), ty)),
+        cx.get_fn(Instance::resolve_drop_in_place(cx.tcx(), ty)),
         cx.const_usize(layout.size.bytes()),
         cx.const_usize(layout.align.abi.bytes())
     ].iter().cloned().chain(methods).collect();
index c7dd019fc3eb8abb464c0bcca87e15059a312c76..4c9313a3309210387780431d6146768874ddba52 100644 (file)
@@ -1,11 +1,10 @@
 use rustc::middle::lang_items;
-use rustc::ty::{self, Ty, TypeFoldable};
+use rustc::ty::{self, Ty, TypeFoldable, Instance};
 use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, FnTypeExt};
 use rustc::mir::{self, Place, PlaceBase, Static, StaticKind};
 use rustc::mir::interpret::InterpError;
 use rustc_target::abi::call::{ArgType, FnType, PassMode, IgnoreMode};
 use rustc_target::spec::abi::Abi;
-use rustc_mir::monomorphize;
 use crate::base;
 use crate::MemFlags;
 use crate::common::{self, IntPredicate};
@@ -310,7 +309,7 @@ fn codegen_drop_terminator<'b>(
     ) {
         let ty = location.ty(self.mir, bx.tcx()).ty;
         let ty = self.monomorphize(&ty);
-        let drop_fn = monomorphize::resolve_drop_in_place(bx.tcx(), ty);
+        let drop_fn = Instance::resolve_drop_in_place(bx.tcx(), ty);
 
         if let ty::InstanceDef::DropGlue(_, None) = drop_fn.def {
             // we don't actually need to drop anything.
index eaa1dd186a536c39667e4bd3120a36f5719dba99..78c22206ab7a54d24d48a3fc080d1528b9b85f7c 100644 (file)
@@ -1,5 +1,4 @@
 use rustc::mir::interpret::ErrorHandled;
-use rustc_mir::const_eval::const_field;
 use rustc::mir;
 use rustc_data_structures::indexed_vec::Idx;
 use rustc::ty::{self, Ty};
@@ -46,12 +45,8 @@ pub fn simd_shuffle_indices(
                     _ => bug!("invalid simd shuffle type: {}", c.ty),
                 };
                 let values: Vec<_> = (0..fields).map(|field| {
-                    let field = const_field(
-                        bx.tcx(),
-                        ty::ParamEnv::reveal_all(),
-                        None,
-                        mir::Field::new(field as usize),
-                        c,
+                    let field = bx.tcx().const_field(
+                        ty::ParamEnv::reveal_all().and((&c, mir::Field::new(field as usize)))
                     );
                     if let Some(prim) = field.val.try_to_scalar() {
                         let layout = bx.layout_of(field_ty);
index 5d6f7036c3e29cf4fabb7fad3b8bc4e6e98db697..1d40d004e2ddcfcd08b20898270c32af7dc60f5b 100644 (file)
@@ -1,8 +1,7 @@
-use rustc::ty::{self, Ty, TypeFoldable, UpvarSubsts};
+use rustc::ty::{self, Ty, TypeFoldable, UpvarSubsts, Instance};
 use rustc::ty::layout::{TyLayout, HasTyCtxt, FnTypeExt};
 use rustc::mir::{self, Body};
 use rustc::session::config::DebugInfo;
-use rustc_mir::monomorphize::Instance;
 use rustc_target::abi::call::{FnType, PassMode, IgnoreMode};
 use rustc_target::abi::{Variants, VariantIdx};
 use crate::base;
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 586db5cfabea44c83c1e4bafdeffca034818b86d..7a2bd18df4ec9a67dac551df2f42a48d100242c9 100644 (file)
@@ -1,4 +1,4 @@
-use rustc::ty::{self, Ty, adjustment::{PointerCast}};
+use rustc::ty::{self, Ty, adjustment::{PointerCast}, Instance};
 use rustc::ty::cast::{CastTy, IntTy};
 use rustc::ty::layout::{self, LayoutOf, HasTyCtxt};
 use rustc::mir;
@@ -11,7 +11,6 @@
 use crate::MemFlags;
 use crate::callee;
 use crate::common::{self, RealPredicate, IntPredicate};
-use rustc_mir::monomorphize;
 
 use crate::traits::*;
 
@@ -196,7 +195,7 @@ pub fn codegen_rvalue_operand(
                     mir::CastKind::Pointer(PointerCast::ClosureFnPointer(_)) => {
                         match operand.layout.ty.sty {
                             ty::Closure(def_id, substs) => {
-                                let instance = monomorphize::resolve_closure(
+                                let instance = Instance::resolve_closure(
                                     bx.cx().tcx(), def_id, substs, ty::ClosureKind::FnOnce);
                                 OperandValue::Immediate(bx.cx().get_fn(instance))
                             }
index 60d75480e61a65365dc5129f5e6f58b4534406fd..11e9a48133d9a2aff18b6b54fcdd60e0d26aedd3 100644 (file)
@@ -1,22 +1,30 @@
 use rustc::hir;
 use rustc::mir::mono::{Linkage, Visibility};
 use rustc::ty::layout::HasTyCtxt;
-use std::fmt;
 use crate::base;
 use crate::traits::*;
 
-pub use rustc::mir::mono::MonoItem;
+use rustc::mir::mono::MonoItem;
 
-pub use rustc_mir::monomorphize::item::MonoItemExt as BaseMonoItemExt;
+pub trait MonoItemExt<'a, 'tcx: 'a> {
+    fn define<Bx: BuilderMethods<'a, 'tcx>>(&self, cx: &'a Bx::CodegenCx);
+    fn predefine<Bx: BuilderMethods<'a, 'tcx>>(
+        &self,
+        cx: &'a Bx::CodegenCx,
+        linkage: Linkage,
+        visibility: Visibility
+    );
+    fn to_raw_string(&self) -> String;
+}
 
-pub trait MonoItemExt<'a, 'tcx: 'a>: fmt::Debug + BaseMonoItemExt<'a, 'tcx> {
+impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {
     fn define<Bx: BuilderMethods<'a, 'tcx>>(&self, cx: &'a Bx::CodegenCx) {
         debug!("BEGIN IMPLEMENTING '{} ({})' in cgu {}",
                self.to_string(cx.tcx(), true),
                self.to_raw_string(),
                cx.codegen_unit().name());
 
-        match *self.as_mono_item() {
+        match *self {
             MonoItem::Static(def_id) => {
                 cx.codegen_static(def_id, cx.tcx().is_mutable_static(def_id));
             }
@@ -54,7 +62,7 @@ fn predefine<Bx: BuilderMethods<'a, 'tcx>>(
 
         debug!("symbol {}", &symbol_name);
 
-        match *self.as_mono_item() {
+        match *self {
             MonoItem::Static(def_id) => {
                 cx.predefine_static(def_id, linkage, visibility, &symbol_name);
             }
@@ -71,7 +79,7 @@ fn predefine<Bx: BuilderMethods<'a, 'tcx>>(
     }
 
     fn to_raw_string(&self) -> String {
-        match *self.as_mono_item() {
+        match *self {
             MonoItem::Fn(instance) => {
                 format!("Fn({:?}, {})",
                         instance.def,
@@ -86,5 +94,3 @@ fn to_raw_string(&self) -> String {
         }
     }
 }
-
-impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {}
index 0c4c4547a7955a1f0ad3ffdd391ea11d678509b4..a11d1ba9231cc52dbd72949656b8db240cbe7ca9 100644 (file)
@@ -88,6 +88,12 @@ fn invoke(
     fn shl(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
     fn lshr(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
     fn ashr(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
+    fn unchecked_sadd(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
+    fn unchecked_uadd(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
+    fn unchecked_ssub(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
+    fn unchecked_usub(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
+    fn unchecked_smul(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
+    fn unchecked_umul(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
     fn and(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
     fn or(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
     fn xor(&mut self, lhs: Self::Value, rhs: Self::Value) -> Self::Value;
index 37b7a15e2ba5e3331ea4da590cf17d02bdee7e35..be2fa7279aa7cbec2dfa853a39a238b92afaef96 100644 (file)
@@ -2,9 +2,8 @@
 use crate::debuginfo::{FunctionDebugContext, MirDebugScope, VariableAccess, VariableKind};
 use rustc::hir::def_id::CrateNum;
 use rustc::mir;
-use rustc::ty::{self, Ty};
+use rustc::ty::{self, Ty, Instance};
 use rustc_data_structures::indexed_vec::IndexVec;
-use rustc_mir::monomorphize::Instance;
 use syntax::ast::Name;
 use syntax_pos::{SourceFile, Span};
 
index 6a400a7d7a45d80835aea14c6d568eeffb4f7f32..624a982b619ee7b2d26f298779897df95c444b39 100644 (file)
@@ -1,8 +1,7 @@
 use super::BackendTypes;
 use rustc::hir::def_id::DefId;
 use rustc::mir::mono::{Linkage, Visibility};
-use rustc::ty;
-use rustc_mir::monomorphize::Instance;
+use rustc::ty::{self, Instance};
 
 pub trait DeclareMethods<'tcx>: BackendTypes {
     /// Declare a global value.
index 5ea86df6e9459cc76fcb3e0c5dfb007b65003b84..46c88a6113ebe486e853728ea09fefd6605749cd 100644 (file)
@@ -1,8 +1,8 @@
 use super::BackendTypes;
+use rustc::mir::mono::CodegenUnit;
 use rustc::session::Session;
 use rustc::ty::{self, Instance, Ty};
 use rustc::util::nodemap::FxHashMap;
-use rustc_mir::monomorphize::partitioning::CodegenUnit;
 use std::cell::RefCell;
 use std::sync::Arc;
 
index 268be2b109114d764fee9e60bb1b107ca8eb073e..b218d18a06ba73824166f9bed06e5a3e7796be6a 100644 (file)
@@ -22,4 +22,3 @@ rustc = { path = "../librustc" }
 rustc_target = { path = "../librustc_target" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_metadata = { path = "../librustc_metadata" }
-rustc_mir = { path = "../librustc_mir" }
index 37847b1b0988f681dd16d77388deb0899500daef..47dc4e5b2cafe231448b162600b712d6ee4b2c20 100644 (file)
@@ -92,9 +92,8 @@
 use rustc::hir::CodegenFnAttrFlags;
 use rustc::session::config::SymbolManglingVersion;
 use rustc::ty::query::Providers;
-use rustc::ty::{self, TyCtxt};
-use rustc_mir::monomorphize::item::{InstantiationMode, MonoItem, MonoItemExt};
-use rustc_mir::monomorphize::Instance;
+use rustc::ty::{self, TyCtxt, Instance};
+use rustc::mir::mono::{MonoItem, InstantiationMode};
 
 use syntax_pos::symbol::InternedString;
 
index 53682b9bdc2c8ef47605270d39bfb8b1f754de00..b6ece06fa6c5d592eb5699fda1173575fb99103c 100644 (file)
@@ -4,10 +4,9 @@
 use rustc::mir::interpret::{ConstValue, Scalar};
 use rustc::ty::print::{PrettyPrinter, Printer, Print};
 use rustc::ty::subst::{Kind, UnpackedKind};
-use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
+use rustc::ty::{self, Ty, TyCtxt, TypeFoldable, Instance};
 use rustc::util::common::record_time;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_mir::monomorphize::Instance;
 
 use log::debug;
 
@@ -440,7 +439,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 1615a097b3bf9e0938f86af47ad9844d2ad80f88..d83d7e5244e6570a90a4f47f7e379f9ee45c3362 100644 (file)
@@ -1,12 +1,11 @@
 use rustc::hir;
 use rustc::hir::def_id::{CrateNum, DefId};
 use rustc::hir::map::{DefPathData, DisambiguatedDefPathData};
-use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
+use rustc::ty::{self, Ty, TyCtxt, TypeFoldable, Instance};
 use rustc::ty::print::{Printer, Print};
 use rustc::ty::subst::{Kind, Subst, UnpackedKind};
 use rustc_data_structures::base_n;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_mir::monomorphize::Instance;
 use rustc_target::spec::abi::Abi;
 use syntax::ast::{IntTy, UintTy, FloatTy};
 
index b935ccb7398e23e33407343ffa7a991bffbaa1fb..9f7e483395244c6641234719f7ef5df7ca23f116 100644 (file)
@@ -5,8 +5,7 @@
 //! paths etc in all kinds of annoying scenarios.
 
 use rustc::hir;
-use rustc::ty::TyCtxt;
-use rustc_mir::monomorphize::Instance;
+use rustc::ty::{TyCtxt, Instance};
 use syntax::symbol::{Symbol, sym};
 
 const SYMBOL_NAME: Symbol = sym::rustc_symbol_name;
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 036820c6d7fa1386d30ba69fb1720990fec71eef..d540b3f7e40a3c38ea251897a07ad11ab10e1a89 100644 (file)
@@ -1,7 +1,7 @@
 use rustc::hir::def::{Res, DefKind};
 use rustc::hir::def_id::DefId;
 use rustc::lint;
-use rustc::ty;
+use rustc::ty::{self, Ty};
 use rustc::ty::adjustment;
 use rustc_data_structures::fx::FxHashMap;
 use lint::{LateContext, EarlyContext, LintContext, LintArray};
@@ -47,43 +47,8 @@ fn check_stmt(&mut self, cx: &LateContext<'_, '_>, s: &hir::Stmt) {
             return;
         }
 
-        let t = cx.tables.expr_ty(&expr);
-        let type_permits_lack_of_use = if t.is_unit()
-            || cx.tcx.is_ty_uninhabited_from(
-                cx.tcx.hir().get_module_parent_by_hir_id(expr.hir_id), t)
-        {
-            true
-        } else {
-            match t.sty {
-                ty::Adt(def, _) => check_must_use(cx, def.did, s.span, "", ""),
-                ty::Opaque(def, _) => {
-                    let mut must_use = false;
-                    for (predicate, _) in &cx.tcx.predicates_of(def).predicates {
-                        if let ty::Predicate::Trait(ref poly_trait_predicate) = predicate {
-                            let trait_ref = poly_trait_predicate.skip_binder().trait_ref;
-                            if check_must_use(cx, trait_ref.def_id, s.span, "implementer of ", "") {
-                                must_use = true;
-                                break;
-                            }
-                        }
-                    }
-                    must_use
-                }
-                ty::Dynamic(binder, _) => {
-                    let mut must_use = false;
-                    for predicate in binder.skip_binder().iter() {
-                        if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate {
-                            if check_must_use(cx, trait_ref.def_id, s.span, "", " trait object") {
-                                must_use = true;
-                                break;
-                            }
-                        }
-                    }
-                    must_use
-                }
-                _ => false,
-            }
-        };
+        let ty = cx.tables.expr_ty(&expr);
+        let type_permits_lack_of_use = check_must_use_ty(cx, ty, &expr, s.span, "");
 
         let mut fn_warned = false;
         let mut op_warned = false;
@@ -108,7 +73,7 @@ fn check_stmt(&mut self, cx: &LateContext<'_, '_>, s: &hir::Stmt) {
             _ => None
         };
         if let Some(def_id) = maybe_def_id {
-            fn_warned = check_must_use(cx, def_id, s.span, "return value of ", "");
+            fn_warned = check_must_use_def(cx, def_id, s.span, "return value of ", "");
         } else if type_permits_lack_of_use {
             // We don't warn about unused unit or uninhabited types.
             // (See https://github.com/rust-lang/rust/issues/43806 for details.)
@@ -162,10 +127,75 @@ fn check_stmt(&mut self, cx: &LateContext<'_, '_>, s: &hir::Stmt) {
             cx.span_lint(UNUSED_RESULTS, s.span, "unused result");
         }
 
-        fn check_must_use(
+        // Returns whether an error has been emitted (and thus another does not need to be later).
+        fn check_must_use_ty<'tcx>(
+            cx: &LateContext<'_, 'tcx>,
+            ty: Ty<'tcx>,
+            expr: &hir::Expr,
+            span: Span,
+            descr_post_path: &str,
+        ) -> bool {
+            if ty.is_unit() || cx.tcx.is_ty_uninhabited_from(
+                cx.tcx.hir().get_module_parent_by_hir_id(expr.hir_id), ty)
+            {
+                return true;
+            }
+
+            match ty.sty {
+                ty::Adt(def, _) => check_must_use_def(cx, def.did, span, "", descr_post_path),
+                ty::Opaque(def, _) => {
+                    let mut has_emitted = false;
+                    for (predicate, _) in &cx.tcx.predicates_of(def).predicates {
+                        if let ty::Predicate::Trait(ref poly_trait_predicate) = predicate {
+                            let trait_ref = poly_trait_predicate.skip_binder().trait_ref;
+                            let def_id = trait_ref.def_id;
+                            if check_must_use_def(cx, def_id, span, "implementer of ", "") {
+                                has_emitted = true;
+                                break;
+                            }
+                        }
+                    }
+                    has_emitted
+                }
+                ty::Dynamic(binder, _) => {
+                    let mut has_emitted = false;
+                    for predicate in binder.skip_binder().iter() {
+                        if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate {
+                            let def_id = trait_ref.def_id;
+                            if check_must_use_def(cx, def_id, span, "", " trait object") {
+                                has_emitted = true;
+                                break;
+                            }
+                        }
+                    }
+                    has_emitted
+                }
+                ty::Tuple(ref tys) => {
+                    let mut has_emitted = false;
+                    let spans = if let hir::ExprKind::Tup(comps) = &expr.node {
+                        debug_assert_eq!(comps.len(), tys.len());
+                        comps.iter().map(|e| e.span).collect()
+                    } else {
+                        vec![]
+                    };
+                    for (i, ty) in tys.iter().map(|k| k.expect_ty()).enumerate() {
+                        let descr_post_path = &format!(" in tuple element {}", i);
+                        let span = *spans.get(i).unwrap_or(&span);
+                        if check_must_use_ty(cx, ty, expr, span, descr_post_path) {
+                            has_emitted = true;
+                        }
+                    }
+                    has_emitted
+                }
+                _ => false,
+            }
+        }
+
+        // Returns whether an error has been emitted (and thus another does not need to be later).
+        fn check_must_use_def(
             cx: &LateContext<'_, '_>,
             def_id: DefId,
-            sp: Span,
+            span: Span,
             descr_pre_path: &str,
             descr_post_path: &str,
         ) -> bool {
@@ -173,7 +203,7 @@ fn check_must_use(
                 if attr.check_name(sym::must_use) {
                     let msg = format!("unused {}`{}`{} that must be used",
                         descr_pre_path, cx.tcx.def_path_str(def_id), descr_post_path);
-                    let mut err = cx.struct_span_lint(UNUSED_MUST_USE, sp, &msg);
+                    let mut err = cx.struct_span_lint(UNUSED_MUST_USE, span, &msg);
                     // check for #[must_use = "..."]
                     if let Some(note) = attr.value_str() {
                         err.note(&note.as_str());
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 abfc2f9466c8ed74aca33687e7b421ec51aff0cc..4a4787337ab582d92b2fffc82fafc21d0c22a59a 100644 (file)
@@ -52,6 +52,19 @@ struct GatherUsedMutsVisitor<'visit, 'cx: 'visit, 'gcx: 'tcx, 'tcx: 'cx> {
     mbcx: &'visit mut MirBorrowckCtxt<'cx, 'gcx, 'tcx>,
 }
 
+impl GatherUsedMutsVisitor<'_, '_, '_, '_> {
+    fn remove_never_initialized_mut_locals(&mut self, into: &Place<'_>) {
+        // Remove any locals that we found were initialized from the
+        // `never_initialized_mut_locals` set. At the end, the only remaining locals will
+        // be those that were never initialized - we will consider those as being used as
+        // they will either have been removed by unreachable code optimizations; or linted
+        // as unused variables.
+        if let Some(local) = into.base_local() {
+            let _ = self.never_initialized_mut_locals.remove(&local);
+        }
+    }
+}
+
 impl<'visit, 'cx, 'gcx, 'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'visit, 'cx, 'gcx, 'tcx> {
     fn visit_terminator_kind(
         &mut self,
@@ -61,14 +74,10 @@ fn visit_terminator_kind(
         debug!("visit_terminator_kind: kind={:?}", kind);
         match &kind {
             TerminatorKind::Call { destination: Some((into, _)), .. } => {
-                if let Some(local) = into.base_local() {
-                    debug!(
-                        "visit_terminator_kind: kind={:?} local={:?} \
-                         never_initialized_mut_locals={:?}",
-                        kind, local, self.never_initialized_mut_locals
-                    );
-                    let _ = self.never_initialized_mut_locals.remove(&local);
-                }
+                self.remove_never_initialized_mut_locals(&into);
+            },
+            TerminatorKind::DropAndReplace { location, .. } => {
+                self.remove_never_initialized_mut_locals(&location);
             },
             _ => {},
         }
@@ -81,19 +90,14 @@ fn visit_statement(
     ) {
         match &statement.kind {
             StatementKind::Assign(into, _) => {
-                // Remove any locals that we found were initialized from the
-                // `never_initialized_mut_locals` set. At the end, the only remaining locals will
-                // be those that were never initialized - we will consider those as being used as
-                // they will either have been removed by unreachable code optimizations; or linted
-                // as unused variables.
                 if let Some(local) = into.base_local() {
                     debug!(
                         "visit_statement: statement={:?} local={:?} \
                          never_initialized_mut_locals={:?}",
                         statement, local, self.never_initialized_mut_locals
                     );
-                    let _ = self.never_initialized_mut_locals.remove(&local);
                 }
+                self.remove_never_initialized_mut_locals(into);
             },
             _ => {},
         }
index 5797f9c34786617d01d834d833da6768e8212f74..91106ebd77e070d63ac9c6d3ff8bc5b1c922edb4 100644 (file)
@@ -126,6 +126,7 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Body<'
                             opt_ty_info = None;
                             self_arg = None;
                         }
+
                         ArgInfo(fn_sig.inputs()[index], opt_ty_info, Some(&*arg.pat), self_arg)
                     });
 
@@ -614,10 +615,7 @@ fn should_abort_on_panic<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
 ///////////////////////////////////////////////////////////////////////////
 /// the main entry point for building MIR for a function
 
-struct ArgInfo<'gcx>(Ty<'gcx>,
-                     Option<Span>,
-                     Option<&'gcx hir::Pat>,
-                     Option<ImplicitSelfKind>);
+struct ArgInfo<'gcx>(Ty<'gcx>, Option<Span>, Option<&'gcx hir::Pat>, Option<ImplicitSelfKind>);
 
 fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
                                    fn_id: hir::HirId,
@@ -651,10 +649,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,
@@ -884,21 +881,13 @@ fn args_and_body(&mut self,
             // debuginfo and so that error reporting knows that this is a user
             // variable. For any other pattern the pattern introduces new
             // variables which will be named instead.
-            let mut name = None;
-            if let Some(pat) = pattern {
-                match pat.node {
-                    hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, ident, _)
-                    | hir::PatKind::Binding(hir::BindingAnnotation::Mutable, _, ident, _) => {
-                        name = Some(ident.name);
-                    }
-                    _ => (),
-                }
-            }
-
-            let source_info = SourceInfo {
-                scope: OUTERMOST_SOURCE_SCOPE,
-                span: pattern.map_or(self.fn_span, |pat| pat.span)
+            let (name, span) = if let Some(pat) = pattern {
+                (pat.simple_ident().map(|ident| ident.name), pat.span)
+            } else {
+                (None, self.fn_span)
             };
+
+            let source_info = SourceInfo { scope: OUTERMOST_SOURCE_SCOPE, span, };
             self.local_decls.push(LocalDecl {
                 mutability: Mutability::Mut,
                 ty,
@@ -933,7 +922,13 @@ fn args_and_body(&mut self,
 
                 match *pattern.kind {
                     // Don't introduce extra copies for simple bindings
-                    PatternKind::Binding { mutability, var, mode: BindingMode::ByValue, .. } => {
+                    PatternKind::Binding {
+                        mutability,
+                        var,
+                        mode: BindingMode::ByValue,
+                        subpattern: None,
+                        ..
+                    } => {
                         self.local_decls[local].mutability = mutability;
                         self.local_decls[local].is_user_variable =
                             if let Some(kind) = self_binding {
index 2c68ed58d50d40edbd0ae5649b14c2678e6240dd..d118a61bcc6ce06f03b9776f9f3cafea56b08218 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(
@@ -470,7 +470,7 @@ fn stack_pop(
     }
 }
 
-/// Projects to a field of a (variant of a) const.
+/// Extracts a field of a (variant of a) const.
 // this function uses `unwrap` copiously, because an already validated constant must have valid
 // fields and can thus never fail outside of compiler bugs
 pub fn const_field<'a, 'tcx>(
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 d5cee871810f50a614c54f75762db6dc0e9752f5..716838b4fc597c4078641bd013371122d13c098a 100644 (file)
@@ -5,7 +5,7 @@
 
 pub(crate) use self::check_match::check_match;
 
-use crate::const_eval::{const_field, const_variant_index};
+use crate::const_eval::const_variant_index;
 
 use crate::hair::util::UserAnnotatedTyHelpers;
 use crate::hair::constant::*;
@@ -949,7 +949,9 @@ fn const_to_pat(
         debug!("const_to_pat: cv={:#?} id={:?}", cv, id);
         let adt_subpattern = |i, variant_opt| {
             let field = Field::new(i);
-            let val = const_field(self.tcx, self.param_env, variant_opt, field, cv);
+            let val = crate::const_eval::const_field(
+                self.tcx, self.param_env, variant_opt, field, cv
+            );
             self.const_to_pat(instance, val, id, span)
         };
         let adt_subpatterns = |n, variant_opt| {
index 76b11ac2fe6463a4515782d743e1a2b30dc018ee..ff7a9984da4ee164d11a58741a5dd3b67b591fba 100644 (file)
@@ -11,7 +11,7 @@
 use rustc::mir::CastKind;
 use rustc_apfloat::Float;
 
-use super::{InterpretCx, Machine, PlaceTy, OpTy, ImmTy, Immediate};
+use super::{InterpretCx, Machine, PlaceTy, OpTy, Immediate};
 
 impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> {
     fn type_is_fat_ptr(&self, ty: Ty<'tcx>) -> bool {
@@ -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)?;
                     }
@@ -306,6 +306,7 @@ fn unsize_into(
         src: OpTy<'tcx, M::PointerTag>,
         dest: PlaceTy<'tcx, M::PointerTag>,
     ) -> EvalResult<'tcx> {
+        trace!("Unsizing {:?} into {:?}", src, dest);
         match (&src.layout.ty.sty, &dest.layout.ty.sty) {
             (&ty::Ref(_, s, _), &ty::Ref(_, d, _)) |
             (&ty::Ref(_, s, _), &ty::RawPtr(TypeAndMut { ty: d, .. })) |
@@ -335,20 +336,7 @@ fn unsize_into(
                     if dst_field.layout.is_zst() {
                         continue;
                     }
-                    let src_field = match src.try_as_mplace() {
-                        Ok(mplace) => {
-                            let src_field = self.mplace_field(mplace, i as u64)?;
-                            src_field.into()
-                        }
-                        Err(..) => {
-                            let src_field_layout = src.layout.field(self, i)?;
-                            // this must be a field covering the entire thing
-                            assert_eq!(src.layout.fields.offset(i).bytes(), 0);
-                            assert_eq!(src_field_layout.size, src.layout.size);
-                            // just sawp out the layout
-                            OpTy::from(ImmTy { imm: src.to_immediate(), layout: src_field_layout })
-                        }
-                    };
+                    let src_field = self.operand_field(src, i as u64)?;
                     if src_field.layout.ty == dst_field.layout.ty {
                         self.copy_op(src_field, dst_field)?;
                     } else {
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 ed389a8df94abaa9a164b266a1c2caa15533161d..d59bee6943a51fa45a0b0e2a91e9c7ddf9345b73 100644 (file)
@@ -33,4 +33,4 @@
 
 pub use self::validity::RefTracking;
 
-pub use self::intrinsics::type_name;
+pub(super) use self::intrinsics::type_name;
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 ba48a28fc83159d2b6b58243ca4202ab9a1c55c3..a39af9640ac343bd6254de6692fc2a8863c99aa4 100644 (file)
@@ -1,6 +1,7 @@
 use std::borrow::Cow;
 
 use rustc::{mir, ty};
+use rustc::ty::Instance;
 use rustc::ty::layout::{self, TyLayout, LayoutOf};
 use syntax::source_map::Span;
 use rustc_target::spec::abi::Abi;
@@ -112,7 +113,7 @@ pub(super) fn eval_terminator(
                 let ty = place.layout.ty;
                 trace!("TerminatorKind::drop: {:?}, type {}", location, ty);
 
-                let instance = crate::monomorphize::resolve_drop_in_place(*self.tcx, ty);
+                let instance = Instance::resolve_drop_in_place(*self.tcx, ty);
                 self.drop_in_place(
                     place,
                     instance,
index 4eb79cf56fcf2a764f1ba9a4d4ae3f08a7c7a708..33cb1a097175d5df2755c16c98a34e8349c907a0 100644 (file)
@@ -1,4 +1,4 @@
-use rustc::ty::{self, Ty};
+use rustc::ty::{self, Ty, Instance};
 use rustc::ty::layout::{Size, Align, LayoutOf};
 use rustc::mir::interpret::{Scalar, Pointer, EvalResult, PointerArithmetic};
 
@@ -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 {
@@ -55,8 +55,9 @@ 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 = Instance::resolve_drop_in_place(*tcx, ty);
+        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 +84,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 +93,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..9213a009ea740374641900fa189a332c0c2b5f1e 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"]
@@ -64,6 +63,11 @@ pub fn provide(providers: &mut Providers<'_>) {
     providers.const_eval = const_eval::const_eval_provider;
     providers.const_eval_raw = const_eval::const_eval_raw_provider;
     providers.check_match = hair::pattern::check_match;
+    providers.const_field = |tcx, param_env_and_value| {
+        let (param_env, (value, field)) = param_env_and_value.into_parts();
+        const_eval::const_field(tcx, param_env, None, field, value)
+    };
+    providers.type_name = interpret::type_name;
 }
 
 __build_diagnostic_array! { librustc_mir, DIAGNOSTICS }
index c1131336f3636a08606c48c619eba604eaec4464..eed051449e155637663f2a581bb3712d97e156d2 100644 (file)
 use rustc::mir::interpret::{AllocId, ConstValue};
 use rustc::middle::lang_items::{ExchangeMallocFnLangItem, StartFnLangItem};
 use rustc::ty::subst::{InternalSubsts, SubstsRef};
-use rustc::ty::{self, TypeFoldable, Ty, TyCtxt, GenericParamDefKind};
+use rustc::ty::{self, TypeFoldable, Ty, TyCtxt, GenericParamDefKind, Instance};
+use rustc::ty::print::obsolete::DefPathBasedNames;
 use rustc::ty::adjustment::{CustomCoerceUnsized, PointerCast};
 use rustc::session::config::EntryFnType;
 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::mono::{MonoItem, InstantiationMode};
+use rustc::mir::interpret::{Scalar, GlobalId, GlobalAlloc, ErrorHandled};
 
-use crate::monomorphize::{self, Instance};
+use crate::monomorphize;
 use rustc::util::nodemap::{FxHashSet, FxHashMap, DefIdMap};
 use rustc::util::common::time;
 
-use crate::monomorphize::item::{MonoItemExt, DefPathBasedNames, InstantiationMode};
-
 use rustc_data_structures::bit_set::GrowableBitSet;
 use rustc_data_structures::sync::{MTRef, MTLock, ParallelIterator, par_iter};
 
@@ -580,7 +579,7 @@ fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) {
                 );
                 match source_ty.sty {
                     ty::Closure(def_id, substs) => {
-                        let instance = monomorphize::resolve_closure(
+                        let instance = Instance::resolve_closure(
                             self.tcx, def_id, substs, ty::ClosureKind::FnOnce);
                         if should_monomorphize_locally(self.tcx, &instance) {
                             self.output.push(create_fn_mono_item(instance));
@@ -684,7 +683,7 @@ fn visit_drop_use<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                             is_direct_call: bool,
                             output: &mut Vec<MonoItem<'tcx>>)
 {
-    let instance = monomorphize::resolve_drop_in_place(tcx, ty);
+    let instance = Instance::resolve_drop_in_place(tcx, ty);
     visit_instance_use(tcx, instance, is_direct_call, output);
 }
 
@@ -1183,20 +1182,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 +1262,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 +1271,7 @@ fn collect_const<'a, 'tcx>(
             );
             let instance = ty::Instance::resolve(tcx,
                                                 param_env,
-                                                did,
+                                                def_id,
                                                 substs).unwrap();
 
             let cid = GlobalId {
@@ -1283,7 +1282,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 8b44f148facf6dd9608fbe88f8677a64bf08dfad..d60d0fe9114d36de15bd88058d1f03956cb0b146 100644 (file)
@@ -1,18 +1,14 @@
-use crate::monomorphize::Instance;
-use rustc::hir;
-use rustc::hir::def_id::{DefId, LOCAL_CRATE};
-use rustc::mir::interpret::ConstValue;
+use rustc::hir::def_id::LOCAL_CRATE;
+use rustc::mir::mono::MonoItem;
 use rustc::session::config::OptLevel;
-use rustc::ty::{self, Ty, TyCtxt, Const, ClosureSubsts, GeneratorSubsts};
-use rustc::ty::subst::{SubstsRef, InternalSubsts};
-use syntax::ast;
+use rustc::ty::{self, TyCtxt, Instance};
+use rustc::ty::subst::InternalSubsts;
+use rustc::ty::print::obsolete::DefPathBasedNames;
 use syntax::attr::InlineAttr;
-use std::fmt::{self, Write};
-use std::iter;
+use std::fmt;
 use rustc::mir::mono::Linkage;
 use syntax_pos::symbol::InternedString;
 use syntax::source_map::Span;
-pub use rustc::mir::mono::MonoItem;
 
 /// Describes how a monomorphization will be instantiated in object files.
 #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]
@@ -207,290 +203,3 @@ fn as_mono_item(&self) -> &MonoItem<'tcx> {
         self
     }
 }
-
-//=-----------------------------------------------------------------------------
-// MonoItem String Keys
-//=-----------------------------------------------------------------------------
-
-// The code below allows for producing a unique string key for a mono item.
-// These keys are used by the handwritten auto-tests, so they need to be
-// predictable and human-readable.
-//
-// Note: A lot of this could looks very similar to what's already in `ty::print`.
-// FIXME(eddyb) implement a custom `PrettyPrinter` for this.
-
-/// Same as `unique_type_name()` but with the result pushed onto the given
-/// `output` parameter.
-pub struct DefPathBasedNames<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    omit_disambiguators: bool,
-    omit_local_crate_name: bool,
-}
-
-impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
-    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-               omit_disambiguators: bool,
-               omit_local_crate_name: bool)
-               -> Self {
-        DefPathBasedNames {
-            tcx,
-            omit_disambiguators,
-            omit_local_crate_name,
-        }
-    }
-
-    // Pushes the type name of the specified type to the provided string.
-    // If `debug` is true, printing normally unprintable types is allowed
-    // (e.g. `ty::GeneratorWitness`). This parameter should only be set when
-    // this method is being used for logging purposes (e.g. with `debug!` or `info!`)
-    // When being used for codegen purposes, `debug` should be set to `false`
-    // in order to catch unexpected types that should never end up in a type name.
-    pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String, debug: bool) {
-        match t.sty {
-            ty::Bool              => output.push_str("bool"),
-            ty::Char              => output.push_str("char"),
-            ty::Str               => output.push_str("str"),
-            ty::Never             => output.push_str("!"),
-            ty::Int(ast::IntTy::Isize)    => output.push_str("isize"),
-            ty::Int(ast::IntTy::I8)    => output.push_str("i8"),
-            ty::Int(ast::IntTy::I16)   => output.push_str("i16"),
-            ty::Int(ast::IntTy::I32)   => output.push_str("i32"),
-            ty::Int(ast::IntTy::I64)   => output.push_str("i64"),
-            ty::Int(ast::IntTy::I128)   => output.push_str("i128"),
-            ty::Uint(ast::UintTy::Usize)   => output.push_str("usize"),
-            ty::Uint(ast::UintTy::U8)   => output.push_str("u8"),
-            ty::Uint(ast::UintTy::U16)  => output.push_str("u16"),
-            ty::Uint(ast::UintTy::U32)  => output.push_str("u32"),
-            ty::Uint(ast::UintTy::U64)  => output.push_str("u64"),
-            ty::Uint(ast::UintTy::U128)  => output.push_str("u128"),
-            ty::Float(ast::FloatTy::F32) => output.push_str("f32"),
-            ty::Float(ast::FloatTy::F64) => output.push_str("f64"),
-            ty::Adt(adt_def, substs) => {
-                self.push_def_path(adt_def.did, output);
-                self.push_generic_params(substs, iter::empty(), output, debug);
-            },
-            ty::Tuple(component_types) => {
-                output.push('(');
-                for &component_type in component_types {
-                    self.push_type_name(component_type.expect_ty(), output, debug);
-                    output.push_str(", ");
-                }
-                if !component_types.is_empty() {
-                    output.pop();
-                    output.pop();
-                }
-                output.push(')');
-            },
-            ty::RawPtr(ty::TypeAndMut { ty: inner_type, mutbl } ) => {
-                output.push('*');
-                match mutbl {
-                    hir::MutImmutable => output.push_str("const "),
-                    hir::MutMutable => output.push_str("mut "),
-                }
-
-                self.push_type_name(inner_type, output, debug);
-            },
-            ty::Ref(_, inner_type, mutbl) => {
-                output.push('&');
-                if mutbl == hir::MutMutable {
-                    output.push_str("mut ");
-                }
-
-                self.push_type_name(inner_type, output, debug);
-            },
-            ty::Array(inner_type, len) => {
-                output.push('[');
-                self.push_type_name(inner_type, output, debug);
-                write!(output, "; {}", len.unwrap_usize(self.tcx)).unwrap();
-                output.push(']');
-            },
-            ty::Slice(inner_type) => {
-                output.push('[');
-                self.push_type_name(inner_type, output, debug);
-                output.push(']');
-            },
-            ty::Dynamic(ref trait_data, ..) => {
-                if let Some(principal) = trait_data.principal() {
-                    self.push_def_path(principal.def_id(), output);
-                    self.push_generic_params(
-                        principal.skip_binder().substs,
-                        trait_data.projection_bounds(),
-                        output,
-                        debug
-                    );
-                } else {
-                    output.push_str("dyn '_");
-                }
-            },
-            ty::Foreign(did) => self.push_def_path(did, output),
-            ty::FnDef(..) |
-            ty::FnPtr(_) => {
-                let sig = t.fn_sig(self.tcx);
-                if sig.unsafety() == hir::Unsafety::Unsafe {
-                    output.push_str("unsafe ");
-                }
-
-                let abi = sig.abi();
-                if abi != ::rustc_target::spec::abi::Abi::Rust {
-                    output.push_str("extern \"");
-                    output.push_str(abi.name());
-                    output.push_str("\" ");
-                }
-
-                output.push_str("fn(");
-
-                let sig = self.tcx.normalize_erasing_late_bound_regions(
-                    ty::ParamEnv::reveal_all(),
-                    &sig,
-                );
-
-                if !sig.inputs().is_empty() {
-                    for &parameter_type in sig.inputs() {
-                        self.push_type_name(parameter_type, output, debug);
-                        output.push_str(", ");
-                    }
-                    output.pop();
-                    output.pop();
-                }
-
-                if sig.c_variadic {
-                    if !sig.inputs().is_empty() {
-                        output.push_str(", ...");
-                    } else {
-                        output.push_str("...");
-                    }
-                }
-
-                output.push(')');
-
-                if !sig.output().is_unit() {
-                    output.push_str(" -> ");
-                    self.push_type_name(sig.output(), output, debug);
-                }
-            },
-            ty::Generator(def_id, GeneratorSubsts { ref substs }, _) |
-            ty::Closure(def_id, ClosureSubsts { ref substs }) => {
-                self.push_def_path(def_id, output);
-                let generics = self.tcx.generics_of(self.tcx.closure_base_def_id(def_id));
-                let substs = substs.truncate_to(self.tcx, generics);
-                self.push_generic_params(substs, iter::empty(), output, debug);
-            }
-            ty::Error |
-            ty::Bound(..) |
-            ty::Infer(_) |
-            ty::Placeholder(..) |
-            ty::UnnormalizedProjection(..) |
-            ty::Projection(..) |
-            ty::Param(_) |
-            ty::GeneratorWitness(_) |
-            ty::Opaque(..) => {
-                if debug {
-                    output.push_str(&format!("`{:?}`", t));
-                } else {
-                    bug!(
-                        "DefPathBasedNames: trying to create type name for unexpected type: {:?}",
-                        t,
-                    );
-                }
-            }
-        }
-    }
-
-    // Pushes the the name of the specified const to the provided string.
-    // If `debug` is true, usually-unprintable consts (such as `Infer`) will be printed,
-    // as well as the unprintable types of constants (see `push_type_name` for more details).
-    pub fn push_const_name(&self, c: &Const<'tcx>, output: &mut String, debug: bool) {
-        match c.val {
-            ConstValue::Scalar(..) | ConstValue::Slice { .. } | ConstValue::ByRef(..) => {
-                // FIXME(const_generics): we could probably do a better job here.
-                write!(output, "{:?}", c).unwrap()
-            }
-            _ => {
-                if debug {
-                    write!(output, "{:?}", c).unwrap()
-                } else {
-                    bug!(
-                        "DefPathBasedNames: trying to create const name for unexpected const: {:?}",
-                        c,
-                    );
-                }
-            }
-        }
-        output.push_str(": ");
-        self.push_type_name(c.ty, output, debug);
-    }
-
-    pub fn push_def_path(&self,
-                         def_id: DefId,
-                         output: &mut String) {
-        let def_path = self.tcx.def_path(def_id);
-
-        // some_crate::
-        if !(self.omit_local_crate_name && def_id.is_local()) {
-            output.push_str(&self.tcx.crate_name(def_path.krate).as_str());
-            output.push_str("::");
-        }
-
-        // foo::bar::ItemName::
-        for part in self.tcx.def_path(def_id).data {
-            if self.omit_disambiguators {
-                write!(output, "{}::", part.data.as_interned_str()).unwrap();
-            } else {
-                write!(output, "{}[{}]::",
-                       part.data.as_interned_str(),
-                       part.disambiguator).unwrap();
-            }
-        }
-
-        // remove final "::"
-        output.pop();
-        output.pop();
-    }
-
-    fn push_generic_params<I>(
-        &self,
-        substs: SubstsRef<'tcx>,
-        projections: I,
-        output: &mut String,
-        debug: bool,
-    ) where I: Iterator<Item=ty::PolyExistentialProjection<'tcx>> {
-        let mut projections = projections.peekable();
-        if substs.non_erasable_generics().next().is_none() && projections.peek().is_none() {
-            return;
-        }
-
-        output.push('<');
-
-        for type_parameter in substs.types() {
-            self.push_type_name(type_parameter, output, debug);
-            output.push_str(", ");
-        }
-
-        for projection in projections {
-            let projection = projection.skip_binder();
-            let name = &self.tcx.associated_item(projection.item_def_id).ident.as_str();
-            output.push_str(name);
-            output.push_str("=");
-            self.push_type_name(projection.ty, output, debug);
-            output.push_str(", ");
-        }
-
-        for const_parameter in substs.consts() {
-            self.push_const_name(const_parameter, output, debug);
-            output.push_str(", ");
-        }
-
-        output.pop();
-        output.pop();
-
-        output.push('>');
-    }
-
-    pub fn push_instance_as_string(&self,
-                                   instance: Instance<'tcx>,
-                                   output: &mut String,
-                                   debug: bool) {
-        self.push_def_path(instance.def_id(), output);
-        self.push_generic_params(instance.substs, iter::empty(), output, debug);
-    }
-}
index ff48c86817b49ef89b96f86d5d8acdecd432b4e1..51bcbff7f3236472e95dc955b6f7e0d2cc971a2c 100644 (file)
-use rustc::hir::def_id::DefId;
-use rustc::middle::lang_items::DropInPlaceFnLangItem;
 use rustc::traits;
 use rustc::ty::adjustment::CustomCoerceUnsized;
 use rustc::ty::{self, Ty, TyCtxt};
 
-pub use rustc::ty::Instance;
-pub use self::item::{MonoItem, MonoItemExt};
-
 pub mod collector;
-pub mod item;
 pub mod partitioning;
 
-#[inline(never)] // give this a place in the profiler
-pub fn assert_symbols_are_distinct<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mono_items: I)
-    where I: Iterator<Item=&'a MonoItem<'tcx>>
-{
-    let mut symbols: Vec<_> = mono_items.map(|mono_item| {
-        (mono_item, mono_item.symbol_name(tcx))
-    }).collect();
-
-    symbols.sort_by_key(|sym| sym.1);
-
-    for pair in symbols.windows(2) {
-        let sym1 = &pair[0].1;
-        let sym2 = &pair[1].1;
-
-        if sym1 == sym2 {
-            let mono_item1 = pair[0].0;
-            let mono_item2 = pair[1].0;
-
-            let span1 = mono_item1.local_span(tcx);
-            let span2 = mono_item2.local_span(tcx);
-
-            // Deterministically select one of the spans for error reporting
-            let span = match (span1, span2) {
-                (Some(span1), Some(span2)) => {
-                    Some(if span1.lo().0 > span2.lo().0 {
-                        span1
-                    } else {
-                        span2
-                    })
-                }
-                (span1, span2) => span1.or(span2),
-            };
-
-            let error_message = format!("symbol `{}` is already defined", sym1);
-
-            if let Some(span) = span {
-                tcx.sess.span_fatal(span, &error_message)
-            } else {
-                tcx.sess.fatal(&error_message)
-            }
-        }
-    }
-}
-
-fn fn_once_adapter_instance<'a, 'tcx>(
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    closure_did: DefId,
-    substs: ty::ClosureSubsts<'tcx>,
-    ) -> Instance<'tcx> {
-    debug!("fn_once_adapter_shim({:?}, {:?})",
-           closure_did,
-           substs);
-    let fn_once = tcx.lang_items().fn_once_trait().unwrap();
-    let call_once = tcx.associated_items(fn_once)
-        .find(|it| it.kind == ty::AssocKind::Method)
-        .unwrap().def_id;
-    let def = ty::InstanceDef::ClosureOnceShim { call_once };
-
-    let self_ty = tcx.mk_closure(closure_did, substs);
-
-    let sig = substs.closure_sig(closure_did, tcx);
-    let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
-    assert_eq!(sig.inputs().len(), 1);
-    let substs = tcx.mk_substs_trait(self_ty, &[sig.inputs()[0].into()]);
-
-    debug!("fn_once_adapter_shim: self_ty={:?} sig={:?}", self_ty, sig);
-    Instance { def, substs }
-}
-
-fn needs_fn_once_adapter_shim(actual_closure_kind: ty::ClosureKind,
-                              trait_closure_kind: ty::ClosureKind)
-                              -> Result<bool, ()>
-{
-    match (actual_closure_kind, trait_closure_kind) {
-        (ty::ClosureKind::Fn, ty::ClosureKind::Fn) |
-        (ty::ClosureKind::FnMut, ty::ClosureKind::FnMut) |
-        (ty::ClosureKind::FnOnce, ty::ClosureKind::FnOnce) => {
-            // No adapter needed.
-           Ok(false)
-        }
-        (ty::ClosureKind::Fn, ty::ClosureKind::FnMut) => {
-            // The closure fn `llfn` is a `fn(&self, ...)`.  We want a
-            // `fn(&mut self, ...)`. In fact, at codegen time, these are
-            // basically the same thing, so we can just return llfn.
-            Ok(false)
-        }
-        (ty::ClosureKind::Fn, ty::ClosureKind::FnOnce) |
-        (ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
-            // The closure fn `llfn` is a `fn(&self, ...)` or `fn(&mut
-            // self, ...)`.  We want a `fn(self, ...)`. We can produce
-            // this by doing something like:
-            //
-            //     fn call_once(self, ...) { call_mut(&self, ...) }
-            //     fn call_once(mut self, ...) { call_mut(&mut self, ...) }
-            //
-            // These are both the same at codegen time.
-            Ok(true)
-        }
-        _ => Err(()),
-    }
-}
-
-pub fn resolve_closure<'a, 'tcx> (
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    def_id: DefId,
-    substs: ty::ClosureSubsts<'tcx>,
-    requested_kind: ty::ClosureKind)
-    -> Instance<'tcx>
-{
-    let actual_kind = substs.closure_kind(def_id, tcx);
-
-    match needs_fn_once_adapter_shim(actual_kind, requested_kind) {
-        Ok(true) => fn_once_adapter_instance(tcx, def_id, substs),
-        _ => Instance::new(def_id, substs.substs)
-    }
-}
-
-pub fn resolve_drop_in_place<'a, 'tcx>(
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    ty: Ty<'tcx>)
-    -> ty::Instance<'tcx>
-{
-    let def_id = tcx.require_lang_item(DropInPlaceFnLangItem);
-    let substs = tcx.intern_substs(&[ty.into()]);
-    Instance::resolve(tcx, ty::ParamEnv::reveal_all(), def_id, substs).unwrap()
-}
-
 pub fn custom_coerce_unsize_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                            source_ty: Ty<'tcx>,
                                            target_ty: Ty<'tcx>)
index f321e05d68115120b68be82aacbdd743d962b388..1895d4871552e2dd4d32a3cb9fc6815dc9dad39a 100644 (file)
 use std::sync::Arc;
 
 use syntax::symbol::InternedString;
-use rustc::dep_graph::{WorkProductId, WorkProduct, DepNode, DepConstructor};
-use rustc::hir::{CodegenFnAttrFlags, HirId};
+use rustc::hir::CodegenFnAttrFlags;
 use rustc::hir::def::DefKind;
 use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE, CRATE_DEF_INDEX};
-use rustc::mir::mono::{Linkage, Visibility, CodegenUnitNameBuilder};
+use rustc::mir::mono::{Linkage, Visibility, CodegenUnitNameBuilder, CodegenUnit};
 use rustc::middle::exported_symbols::SymbolExportLevel;
 use rustc::ty::{self, DefIdTree, TyCtxt, InstanceDef};
 use rustc::ty::print::characteristic_def_id_of_type;
 use rustc::ty::query::Providers;
 use rustc::util::common::time;
 use rustc::util::nodemap::{DefIdSet, FxHashMap, FxHashSet};
-use rustc::mir::mono::MonoItem;
+use rustc::mir::mono::{MonoItem, InstantiationMode};
 
 use crate::monomorphize::collector::InliningMap;
 use crate::monomorphize::collector::{self, MonoItemCollectionMode};
-use crate::monomorphize::item::{MonoItemExt, InstantiationMode};
-
-pub use rustc::mir::mono::CodegenUnit;
 
 pub enum PartitioningStrategy {
     /// Generates one codegen unit per source-level module.
@@ -124,93 +120,6 @@ pub enum PartitioningStrategy {
     FixedUnitCount(usize)
 }
 
-pub trait CodegenUnitExt<'tcx> {
-    fn as_codegen_unit(&self) -> &CodegenUnit<'tcx>;
-
-    fn contains_item(&self, item: &MonoItem<'tcx>) -> bool {
-        self.items().contains_key(item)
-    }
-
-    fn name<'a>(&'a self) -> &'a InternedString
-        where 'tcx: 'a,
-    {
-        &self.as_codegen_unit().name()
-    }
-
-    fn items(&self) -> &FxHashMap<MonoItem<'tcx>, (Linkage, Visibility)> {
-        &self.as_codegen_unit().items()
-    }
-
-    fn work_product_id(&self) -> WorkProductId {
-        WorkProductId::from_cgu_name(&self.name().as_str())
-    }
-
-    fn work_product(&self, tcx: TyCtxt<'_, '_, '_>) -> WorkProduct {
-        let work_product_id = self.work_product_id();
-        tcx.dep_graph
-           .previous_work_product(&work_product_id)
-           .unwrap_or_else(|| {
-                panic!("Could not find work-product for CGU `{}`", self.name())
-            })
-    }
-
-    fn items_in_deterministic_order<'a>(&self,
-                                        tcx: TyCtxt<'a, 'tcx, 'tcx>)
-                                        -> Vec<(MonoItem<'tcx>,
-                                                (Linkage, Visibility))> {
-        // The codegen tests rely on items being process in the same order as
-        // they appear in the file, so for local items, we sort by node_id first
-        #[derive(PartialEq, Eq, PartialOrd, Ord)]
-        pub struct ItemSortKey(Option<HirId>, ty::SymbolName);
-
-        fn item_sort_key<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                   item: MonoItem<'tcx>) -> ItemSortKey {
-            ItemSortKey(match item {
-                MonoItem::Fn(ref instance) => {
-                    match instance.def {
-                        // We only want to take HirIds of user-defined
-                        // instances into account. The others don't matter for
-                        // the codegen tests and can even make item order
-                        // unstable.
-                        InstanceDef::Item(def_id) => {
-                            tcx.hir().as_local_hir_id(def_id)
-                        }
-                        InstanceDef::VtableShim(..) |
-                        InstanceDef::Intrinsic(..) |
-                        InstanceDef::FnPtrShim(..) |
-                        InstanceDef::Virtual(..) |
-                        InstanceDef::ClosureOnceShim { .. } |
-                        InstanceDef::DropGlue(..) |
-                        InstanceDef::CloneShim(..) => {
-                            None
-                        }
-                    }
-                }
-                MonoItem::Static(def_id) => {
-                    tcx.hir().as_local_hir_id(def_id)
-                }
-                MonoItem::GlobalAsm(hir_id) => {
-                    Some(hir_id)
-                }
-            }, item.symbol_name(tcx))
-        }
-
-        let mut items: Vec<_> = self.items().iter().map(|(&i, &l)| (i, l)).collect();
-        items.sort_by_cached_key(|&(i, _)| item_sort_key(tcx, i));
-        items
-    }
-
-    fn codegen_dep_node(&self, tcx: TyCtxt<'_, 'tcx, 'tcx>) -> DepNode {
-        DepNode::new(tcx, DepConstructor::CompileCodegenUnit(self.name().clone()))
-    }
-}
-
-impl<'tcx> CodegenUnitExt<'tcx> for CodegenUnit<'tcx> {
-    fn as_codegen_unit(&self) -> &CodegenUnit<'tcx> {
-        self
-    }
-}
-
 // Anything we can't find a proper codegen unit for goes into this.
 fn fallback_cgu_name(name_builder: &mut CodegenUnitNameBuilder<'_, '_, '_>) -> InternedString {
     name_builder.build_cgu_name(LOCAL_CRATE, &["fallback"], Some("cgu"))
@@ -882,6 +791,50 @@ fn debug_dump<'a, 'b, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 }
 
+#[inline(never)] // give this a place in the profiler
+fn assert_symbols_are_distinct<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mono_items: I)
+    where I: Iterator<Item=&'a MonoItem<'tcx>>
+{
+    let mut symbols: Vec<_> = mono_items.map(|mono_item| {
+        (mono_item, mono_item.symbol_name(tcx))
+    }).collect();
+
+    symbols.sort_by_key(|sym| sym.1);
+
+    for pair in symbols.windows(2) {
+        let sym1 = &pair[0].1;
+        let sym2 = &pair[1].1;
+
+        if sym1 == sym2 {
+            let mono_item1 = pair[0].0;
+            let mono_item2 = pair[1].0;
+
+            let span1 = mono_item1.local_span(tcx);
+            let span2 = mono_item2.local_span(tcx);
+
+            // Deterministically select one of the spans for error reporting
+            let span = match (span1, span2) {
+                (Some(span1), Some(span2)) => {
+                    Some(if span1.lo().0 > span2.lo().0 {
+                        span1
+                    } else {
+                        span2
+                    })
+                }
+                (span1, span2) => span1.or(span2),
+            };
+
+            let error_message = format!("symbol `{}` is already defined", sym1);
+
+            if let Some(span) = span {
+                tcx.sess.span_fatal(span, &error_message)
+            } else {
+                tcx.sess.fatal(&error_message)
+            }
+        }
+    }
+}
+
 fn collect_and_partition_mono_items<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     cnum: CrateNum,
@@ -922,7 +875,7 @@ fn collect_and_partition_mono_items<'a, 'tcx>(
 
     tcx.sess.abort_if_errors();
 
-    crate::monomorphize::assert_symbols_are_distinct(tcx, items.iter());
+    assert_symbols_are_distinct(tcx, items.iter());
 
     let strategy = if tcx.sess.opts.incremental.is_some() {
         PartitioningStrategy::PerModule
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 2afcbe8a151373bbc6ca64ae8c155e9d8c554c53..89c4a9106a4773a7dbc593b8d2842b87b58a74b6 100644 (file)
@@ -222,7 +222,7 @@ fn check_decl_no_pat<ReportFn: Fn(Span, bool)>(&self, decl: &FnDecl, report_err:
         }
     }
 
-    fn check_trait_fn_not_async(&self, span: Span, asyncness: &IsAsync) {
+    fn check_trait_fn_not_async(&self, span: Span, asyncness: IsAsync) {
         if asyncness.is_async() {
             struct_span_err!(self.session, span, E0706,
                              "trait fns cannot be declared `async`").emit()
@@ -561,7 +561,7 @@ fn visit_item(&mut self, item: &'a Item) {
                     self.invalid_visibility(&impl_item.vis, None);
                     if let ImplItemKind::Method(ref sig, _) = impl_item.node {
                         self.check_trait_fn_not_const(sig.header.constness);
-                        self.check_trait_fn_not_async(impl_item.span, &sig.header.asyncness.node);
+                        self.check_trait_fn_not_async(impl_item.span, sig.header.asyncness.node);
                     }
                 }
             }
@@ -633,7 +633,7 @@ fn visit_item(&mut self, item: &'a Item) {
                 self.no_questions_in_bounds(bounds, "supertraits", true);
                 for trait_item in trait_items {
                     if let TraitItemKind::Method(ref sig, ref block) = trait_item.node {
-                        self.check_trait_fn_not_async(trait_item.span, &sig.header.asyncness.node);
+                        self.check_trait_fn_not_async(trait_item.span, sig.header.asyncness.node);
                         self.check_trait_fn_not_const(sig.header.constness);
                         if block.is_none() {
                             self.check_decl_no_pat(&sig.decl, |span, mut_ident| {
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 20e18d60f076b43e36fbb762c0f281eac43c096b..f084d3b9f28c3a4c8c7dae9793f215a4fd24cf58 100644 (file)
@@ -948,16 +948,6 @@ fn visit_pat(&mut self, pat: &'tcx hir::Pat) {
 
         intravisit::walk_pat(self, pat);
     }
-
-    fn visit_argument_source(&mut self, s: &'tcx hir::ArgSource) {
-        match s {
-            // Don't visit the pattern in `ArgSource::AsyncFn`, it contains a pattern which has
-            // a `NodeId` w/out a type, as it is only used for getting the name of the original
-            // pattern for diagnostics where only an `hir::Arg` is present.
-            hir::ArgSource::AsyncFn(..) => {},
-            _ => intravisit::walk_argument_source(self, s),
-        }
-    }
 }
 
 ////////////////////////////////////////////////////////////////////////////////////////////
@@ -1147,16 +1137,6 @@ fn visit_pat(&mut self, pattern: &'tcx hir::Pat) {
         intravisit::walk_pat(self, pattern);
     }
 
-    fn visit_argument_source(&mut self, s: &'tcx hir::ArgSource) {
-        match s {
-            // Don't visit the pattern in `ArgSource::AsyncFn`, it contains a pattern which has
-            // a `NodeId` w/out a type, as it is only used for getting the name of the original
-            // pattern for diagnostics where only an `hir::Arg` is present.
-            hir::ArgSource::AsyncFn(..) => {},
-            _ => intravisit::walk_argument_source(self, s),
-        }
-    }
-
     fn visit_local(&mut self, local: &'tcx hir::Local) {
         if let Some(ref init) = local.init {
             if self.check_expr_pat_type(init.hir_id, init.span) {
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..99abe69017da729245d96620c4576ded94a23c87 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,18 +852,13 @@ 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 {
-            FnKind::ItemFn(_, ref header, ..) =>
-                (FnItemRibKind, &header.asyncness.node),
-            FnKind::Method(_, ref sig, _, _) =>
-                (AssocItemRibKind, &sig.header.asyncness.node),
-            FnKind::Closure(_) =>
-                // Async closures aren't resolved through `visit_fn`-- they're
-                // processed separately
-                (ClosureRibKind(node_id), &IsAsync::NotAsync),
+        let rib_kind = match function_kind {
+            FnKind::ItemFn(..) => FnItemRibKind,
+            FnKind::Method(..) => AssocItemRibKind,
+            FnKind::Closure(_) => NormalRibKind,
         };
 
         // Create a value rib for the function.
@@ -875,63 +869,26 @@ fn visit_fn(&mut self,
 
         // Add each argument to the rib.
         let mut bindings_list = FxHashMap::default();
-        let mut add_argument = |argument: &ast::Arg| {
+        for argument in &declaration.inputs {
             self.resolve_pattern(&argument.pat, PatternSource::FnParam, &mut bindings_list);
+
             self.visit_ty(&argument.ty);
-            debug!("(resolving function) recorded argument");
-        };
 
-        // Walk the generated async arguments if this is an `async fn`, otherwise walk the
-        // normal arguments.
-        if let IsAsync::Async { ref arguments, .. } = asyncness {
-            for (i, a) in arguments.iter().enumerate() {
-                if let Some(arg) = &a.arg {
-                    add_argument(&arg);
-                } else {
-                    add_argument(&declaration.inputs[i]);
-                }
-            }
-        } else {
-            for a in &declaration.inputs { add_argument(a); }
+            debug!("(resolving function) recorded argument");
         }
-
         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 {
-                    let mut body = body.clone();
-                    // Insert the generated statements into the body before attempting to
-                    // resolve names.
-                    for a in arguments.iter().rev() {
-                        if let Some(pat_stmt) = a.pat_stmt.clone() {
-                            body.stmts.insert(0, pat_stmt);
-                        }
-                        body.stmts.insert(0, a.move_stmt.clone());
-                    }
-                    self.visit_block(&body);
-                } else {
-                    self.visit_block(body);
-                }
+            FnKind::ItemFn(.., body) |
+            FnKind::Method(.., body) => {
+                self.visit_block(body);
             }
             FnKind::Closure(body) => {
                 self.visit_expr(body);
             }
         };
 
-        // 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 +975,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 +1621,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 +1983,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 +2155,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 +3957,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 +3988,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 +3998,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 +4027,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.
@@ -4224,7 +4148,7 @@ fn lookup_typo_candidate<FilterFn>(
         let add_module_candidates = |module: Module<'_>, names: &mut Vec<TypoSuggestion>| {
             for (&(ident, _), resolution) in module.resolutions.borrow().iter() {
                 if let Some(binding) = resolution.borrow().binding {
-                    if !ident.is_gensymed() && filter_fn(binding.res()) {
+                    if filter_fn(binding.res()) {
                         names.push(TypoSuggestion {
                             candidate: ident.name,
                             article: binding.res().article(),
@@ -4242,7 +4166,7 @@ fn lookup_typo_candidate<FilterFn>(
             for rib in self.ribs[ns].iter().rev() {
                 // Locals and type parameters
                 for (ident, &res) in &rib.bindings {
-                    if !ident.is_gensymed() && filter_fn(res) {
+                    if filter_fn(res) {
                         names.push(TypoSuggestion {
                             candidate: ident.name,
                             article: res.article(),
@@ -4272,7 +4196,7 @@ fn lookup_typo_candidate<FilterFn>(
                                             },
                                         );
 
-                                        if !ident.is_gensymed() && filter_fn(crate_mod) {
+                                        if filter_fn(crate_mod) {
                                             Some(TypoSuggestion {
                                                 candidate: ident.name,
                                                 article: "a",
@@ -4295,15 +4219,13 @@ fn lookup_typo_candidate<FilterFn>(
             // Add primitive types to the mix
             if filter_fn(Res::PrimTy(Bool)) {
                 names.extend(
-                    self.primitive_type_table.primitive_types
-                        .iter()
-                        .map(|(name, _)| {
-                            TypoSuggestion {
-                                candidate: *name,
-                                article: "a",
-                                kind: "primitive type",
-                            }
-                        })
+                    self.primitive_type_table.primitive_types.iter().map(|(name, _)| {
+                        TypoSuggestion {
+                            candidate: *name,
+                            article: "a",
+                            kind: "primitive type",
+                        }
+                    })
                 )
             }
         } else {
@@ -4483,25 +4405,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 +4425,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 109863f8a56b2798e06ed2207b453c639f0f64f5..db8b5eacd94d9321f2f7e7b9b1175f927590e693 100644 (file)
@@ -374,7 +374,7 @@ fn make(&self, offset: usize, _parent_id: Option<NodeId>, scx: &SaveContext<'_,
 
                 Ok(extend_sig(ty, text, defs, vec![]))
             }
-            ast::ItemKind::Fn(ref decl, ref header, ref generics, _) => {
+            ast::ItemKind::Fn(ref decl, header, ref generics, _) => {
                 let mut text = String::new();
                 if header.constness.node == ast::Constness::Const {
                     text.push_str("const ");
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 c6191e6b579ce45c036876db9c47656585997c97..0b14ff1db59d460d580c21b49e387ac4e1bce1ae 100644 (file)
@@ -305,7 +305,8 @@ pub fn check_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             "unchecked_shl" | "unchecked_shr" |
             "rotate_left" | "rotate_right" =>
                 (1, vec![param(0), param(0)], param(0)),
-
+            "unchecked_add" | "unchecked_sub" | "unchecked_mul" =>
+                (1, vec![param(0), param(0)], param(0)),
             "overflowing_add" | "overflowing_sub" | "overflowing_mul" =>
                 (1, vec![param(0), param(0)], param(0)),
             "saturating_add" | "saturating_sub" =>
index 9ef6112a94591f5f4ff3b2cecd9f09a21b2def43..f05e0d31582fa20cd3204446ba63c2c77fc96096 100644 (file)
@@ -324,6 +324,11 @@ pub fn report_method_error<'b>(
                                 );
                             }
                         }
+                        if let ty::RawPtr(_) = &actual.sty {
+                            err.note("try using `<*const T>::as_ref()` to get a reference to the \
+                                      type behind the pointer: https://doc.rust-lang.org/std/\
+                                      primitive.pointer.html#method.as_ref");
+                        }
                         err
                     }
                 } else {
index 7a6d02cc33b210cc3e93d06fa624f1e921d9059b..3ada80b3e8b7015e03df59364917ae815ec77cbd 100644 (file)
@@ -1009,16 +1009,6 @@ fn visit_pat(&mut self, p: &'gcx hir::Pat) {
     // Don't descend into the bodies of nested closures
     fn visit_fn(&mut self, _: intravisit::FnKind<'gcx>, _: &'gcx hir::FnDecl,
                 _: hir::BodyId, _: Span, _: hir::HirId) { }
-
-    fn visit_argument_source(&mut self, s: &'gcx hir::ArgSource) {
-        match s {
-            // Don't visit the pattern in `ArgSource::AsyncFn`, it contains a pattern which has
-            // a `NodeId` w/out a type, as it is only used for getting the name of the original
-            // pattern for diagnostics where only an `hir::Arg` is present.
-            hir::ArgSource::AsyncFn(..) => {},
-            _ => intravisit::walk_argument_source(self, s),
-        }
-    }
 }
 
 /// When `check_fn` is invoked on a generator (i.e., a body that
@@ -5264,7 +5254,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 +5315,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..6f8682e64671c3fb4afe381816858d7c0f7c907d 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)
     }
 }
 
@@ -307,16 +311,6 @@ fn visit_ty(&mut self, hir_ty: &'gcx hir::Ty) {
         let ty = self.resolve(&ty, &hir_ty.span);
         self.write_ty_to_tables(hir_ty.hir_id, ty);
     }
-
-    fn visit_argument_source(&mut self, s: &'gcx hir::ArgSource) {
-        match s {
-            // Don't visit the pattern in `ArgSource::AsyncFn`, it contains a pattern which has
-            // a `NodeId` w/out a type, as it is only used for getting the name of the original
-            // pattern for diagnostics where only an `hir::Arg` is present.
-            hir::ArgSource::AsyncFn(..) => {},
-            _ => intravisit::walk_argument_source(self, s),
-        }
-    }
 }
 
 impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
@@ -343,21 +337,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..3034cacf6253f966a98d1971db00de78995358ba 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,
@@ -1335,88 +1335,97 @@ pub fn checked_type_of<'a, 'tcx>(
 
                 Node::Ty(&hir::Ty { node: hir::TyKind::Path(_), .. }) |
                 Node::Expr(&hir::Expr { node: ExprKind::Struct(..), .. }) |
-                Node::Expr(&hir::Expr { node: ExprKind::Path(_), .. }) => {
+                Node::Expr(&hir::Expr { node: ExprKind::Path(_), .. }) |
+                Node::TraitRef(..) => {
                     let path = match parent_node {
-                        Node::Ty(&hir::Ty { node: hir::TyKind::Path(ref path), .. }) |
-                        Node::Expr(&hir::Expr { node: ExprKind::Path(ref path), .. }) => {
-                            path
+                        Node::Ty(&hir::Ty {
+                            node: hir::TyKind::Path(QPath::Resolved(_, ref path)),
+                            ..
+                        })
+                        | Node::Expr(&hir::Expr {
+                            node: ExprKind::Path(QPath::Resolved(_, ref path)),
+                            ..
+                        }) => {
+                            Some(&**path)
                         }
                         Node::Expr(&hir::Expr { node: ExprKind::Struct(ref path, ..), .. }) => {
-                            &*path
+                            if let QPath::Resolved(_, ref path) = **path {
+                                Some(&**path)
+                            } else {
+                                None
+                            }
                         }
-                        _ => unreachable!(),
+                        Node::TraitRef(&hir::TraitRef { ref path, .. }) => Some(path),
+                        _ => None,
                     };
 
-                    match path {
-                        QPath::Resolved(_, ref path) => {
-                            let arg_index = path.segments.iter()
-                                .filter_map(|seg| seg.args.as_ref())
-                                .map(|generic_args| generic_args.args.as_ref())
-                                .find_map(|args| {
-                                    args.iter()
-                                        .filter(|arg| arg.is_const())
-                                        .enumerate()
-                                        .filter(|(_, arg)| arg.id() == hir_id)
-                                        .map(|(index, _)| index)
-                                        .next()
-                                })
-                                .or_else(|| {
-                                    if !fail {
-                                        None
-                                    } else {
-                                        bug!("no arg matching AnonConst in path")
-                                    }
-                                })?;
-
-                            // We've encountered an `AnonConst` in some path, so we need to
-                            // figure out which generic parameter it corresponds to and return
-                            // the relevant type.
-                            let generics = match path.res {
-                                Res::Def(DefKind::Ctor(..), def_id) =>
-                                    tcx.generics_of(tcx.parent(def_id).unwrap()),
-                                Res::Def(_, def_id) =>
-                                    tcx.generics_of(def_id),
-                                Res::Err =>
-                                    return Some(tcx.types.err),
-                                _ if !fail =>
-                                    return None,
-                                x => {
-                                    tcx.sess.delay_span_bug(
-                                        DUMMY_SP,
-                                        &format!(
-                                            "unexpected const parent path def {:?}", x
-                                        ),
-                                    );
-                                    return Some(tcx.types.err);
+                    if let Some(path) = path {
+                        let arg_index = path.segments.iter()
+                            .filter_map(|seg| seg.args.as_ref())
+                            .map(|generic_args| generic_args.args.as_ref())
+                            .find_map(|args| {
+                                args.iter()
+                                    .filter(|arg| arg.is_const())
+                                    .enumerate()
+                                    .filter(|(_, arg)| arg.id() == hir_id)
+                                    .map(|(index, _)| index)
+                                    .next()
+                            })
+                            .or_else(|| {
+                                if !fail {
+                                    None
+                                } else {
+                                    bug!("no arg matching AnonConst in path")
                                 }
-                            };
-
-                            generics.params.iter()
-                                .filter(|param| {
-                                    if let ty::GenericParamDefKind::Const = param.kind {
-                                        true
-                                    } else {
-                                        false
-                                    }
-                                })
-                                .nth(arg_index)
-                                .map(|param| tcx.type_of(param.def_id))
-                                // This is no generic parameter associated with the arg. This is
-                                // probably from an extra arg where one is not needed.
-                                .unwrap_or(tcx.types.err)
-                        }
-                        x => {
-                            if !fail {
-                                return None;
+                            })?;
+
+                        // We've encountered an `AnonConst` in some path, so we need to
+                        // figure out which generic parameter it corresponds to and return
+                        // the relevant type.
+                        let generics = match path.res {
+                            Res::Def(DefKind::Ctor(..), def_id) => {
+                                tcx.generics_of(tcx.parent(def_id).unwrap())
                             }
-                            tcx.sess.delay_span_bug(
-                                DUMMY_SP,
-                                &format!(
-                                    "unexpected const parent path {:?}", x
-                                ),
-                            );
-                            tcx.types.err
+                            Res::Def(_, def_id) => tcx.generics_of(def_id),
+                            Res::Err => return Some(tcx.types.err),
+                            _ if !fail => return None,
+                            res => {
+                                tcx.sess.delay_span_bug(
+                                    DUMMY_SP,
+                                    &format!(
+                                        "unexpected const parent path def {:?}",
+                                        res,
+                                    ),
+                                );
+                                return Some(tcx.types.err);
+                            }
+                        };
+
+                        generics.params.iter()
+                            .filter(|param| {
+                                if let ty::GenericParamDefKind::Const = param.kind {
+                                    true
+                                } else {
+                                    false
+                                }
+                            })
+                            .nth(arg_index)
+                            .map(|param| tcx.type_of(param.def_id))
+                            // This is no generic parameter associated with the arg. This is
+                            // probably from an extra arg where one is not needed.
+                            .unwrap_or(tcx.types.err)
+                    } else {
+                        if !fail {
+                            return None;
                         }
+                        tcx.sess.delay_span_bug(
+                            DUMMY_SP,
+                            &format!(
+                                "unexpected const parent path {:?}",
+                                parent_node,
+                            ),
+                        );
+                        return Some(tcx.types.err);
                     }
                 }
 
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 e68ad6a7c3b4bc375c6e5a8f7db6c0298cd67aaa..0c00b3b20b5b3f36c8391580f64206e67b6960f7 100644 (file)
@@ -2019,7 +2019,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Arguments {
         Arguments {
             values: self.0.iter().enumerate().map(|(i, ty)| {
                 Argument {
-                    name: name_from_pat(&body.arguments[i].original_pat()),
+                    name: name_from_pat(&body.arguments[i].pat),
                     type_: ty.clean(cx),
                 }
             }).collect()
index 58e55d570a4f3336df942f258d7ed065fc812454..1b38d4879050e0458f2a897270c7ddecf5822c82 100644 (file)
@@ -9,6 +9,7 @@
 use std::fmt;
 
 use rustc::hir::def_id::DefId;
+use rustc::util::nodemap::FxHashSet;
 use rustc_target::spec::abi::Abi;
 use rustc::hir;
 
@@ -107,8 +108,10 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 
 impl<'a> fmt::Display for GenericBounds<'a> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let mut bounds_dup = FxHashSet::default();
         let &GenericBounds(bounds) = self;
-        for (i, bound) in bounds.iter().enumerate() {
+
+        for (i, bound) in bounds.iter().filter(|b| bounds_dup.insert(b.to_string())).enumerate() {
             if i > 0 {
                 f.write_str(" + ")?;
             }
@@ -206,16 +209,13 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                         clause.push_str(&format!("{}: {}", ty, GenericBounds(bounds)));
                     }
                 }
-                &clean::WherePredicate::RegionPredicate { ref lifetime,
-                                                          ref bounds } => {
-                    clause.push_str(&format!("{}: ", lifetime));
-                    for (i, lifetime) in bounds.iter().enumerate() {
-                        if i > 0 {
-                            clause.push_str(" + ");
-                        }
-
-                        clause.push_str(&lifetime.to_string());
-                    }
+                &clean::WherePredicate::RegionPredicate { ref lifetime, ref bounds } => {
+                    clause.push_str(&format!("{}: {}",
+                                             lifetime,
+                                             bounds.iter()
+                                                   .map(|b| b.to_string())
+                                                   .collect::<Vec<_>>()
+                                                   .join(" + ")));
                 }
                 &clean::WherePredicate::EqPredicate { ref lhs, ref rhs } => {
                     if f.alternate() {
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 75e83bd9f9c74db2f0b606452781f3e389da361e..b8a10d90c3c0afe10974137fa06b5238d4a5e05a 100644 (file)
@@ -879,17 +879,6 @@ pub struct Local {
     pub id: NodeId,
     pub span: Span,
     pub attrs: ThinVec<Attribute>,
-    /// Origin of this local variable.
-    pub source: LocalSource,
-}
-
-#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
-pub enum LocalSource {
-    /// Local was parsed from source.
-    Normal,
-    /// Within `ast::IsAsync::Async`, a local is generated that will contain the moved arguments
-    /// of an `async fn`.
-    AsyncFn,
 }
 
 /// An arm of a 'match'.
@@ -1770,16 +1759,6 @@ pub struct Arg {
     pub ty: P<Ty>,
     pub pat: P<Pat>,
     pub id: NodeId,
-    pub source: ArgSource,
-}
-
-/// The source of an argument in a function header.
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
-pub enum ArgSource {
-    /// Argument as written by the user.
-    Normal,
-    /// Argument from `async fn` lowering, contains the original binding pattern.
-    AsyncFn(P<Pat>),
 }
 
 /// Alternative representation for `Arg`s describing `self` parameter of methods.
@@ -1839,7 +1818,6 @@ pub fn from_self(eself: ExplicitSelf, eself_ident: Ident) -> Arg {
             }),
             ty,
             id: DUMMY_NODE_ID,
-            source: ArgSource::Normal,
         };
         match eself.node {
             SelfKind::Explicit(ty, mutbl) => arg(mutbl, ty),
@@ -1894,39 +1872,18 @@ pub enum Unsafety {
     Normal,
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
-pub struct AsyncArgument {
-    /// `__arg0`
-    pub ident: Ident,
-    /// `__arg0: <ty>` argument to replace existing function argument `<pat>: <ty>`. Only if
-    /// argument is not a simple binding.
-    pub arg: Option<Arg>,
-    /// `let __arg0 = __arg0;` statement to be inserted at the start of the block.
-    pub move_stmt: Stmt,
-    /// `let <pat> = __arg0;` statement to be inserted at the start of the block, after matching
-    /// move statement. Only if argument is not a simple binding.
-    pub pat_stmt: Option<Stmt>,
-}
-
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)]
 pub enum IsAsync {
     Async {
         closure_id: NodeId,
         return_impl_trait_id: NodeId,
-        /// This field stores the arguments and statements that are used in HIR lowering to
-        /// ensure that `async fn` arguments are dropped at the correct time.
-        ///
-        /// The argument and statements here are generated at parse time as they are required in
-        /// both the hir lowering, def collection and name resolution and this stops them needing
-        /// to be created in each place.
-        arguments: Vec<AsyncArgument>,
     },
     NotAsync,
 }
 
 impl IsAsync {
-    pub fn is_async(&self) -> bool {
-        if let IsAsync::Async { .. } = *self {
+    pub fn is_async(self) -> bool {
+        if let IsAsync::Async { .. } = self {
             true
         } else {
             false
@@ -1934,12 +1891,12 @@ pub fn is_async(&self) -> bool {
     }
 
     /// In ths case this is an `async` return, the `NodeId` for the generated `impl Trait` item.
-    pub fn opt_return_id(&self) -> Option<NodeId> {
+    pub fn opt_return_id(self) -> Option<NodeId> {
         match self {
             IsAsync::Async {
                 return_impl_trait_id,
                 ..
-            } => Some(*return_impl_trait_id),
+            } => Some(return_impl_trait_id),
             IsAsync::NotAsync => None,
         }
     }
@@ -2279,7 +2236,7 @@ pub fn span_with_attributes(&self) -> Span {
 ///
 /// All the information between the visibility and the name of the function is
 /// included in this struct (e.g., `async unsafe fn` or `const extern "C" fn`).
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
 pub struct FnHeader {
     pub unsafety: Unsafety,
     pub asyncness: Spanned<IsAsync>,
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 9c0ffc1f6e8cb39174077c0ffcacbe465d6fd510..47c79f8466a95c486983fc5f1b33a4409865a562 100644 (file)
@@ -516,7 +516,6 @@ fn stmt_let(&self, sp: Span, mutbl: bool, ident: ast::Ident,
             id: ast::DUMMY_NODE_ID,
             span: sp,
             attrs: ThinVec::new(),
-            source: ast::LocalSource::Normal,
         });
         ast::Stmt {
             id: ast::DUMMY_NODE_ID,
@@ -545,7 +544,6 @@ fn stmt_let_typed(&self,
             id: ast::DUMMY_NODE_ID,
             span: sp,
             attrs: ThinVec::new(),
-            source: ast::LocalSource::Normal,
         });
         ast::Stmt {
             id: ast::DUMMY_NODE_ID,
@@ -563,7 +561,6 @@ fn stmt_let_type_only(&self, span: Span, ty: P<ast::Ty>) -> ast::Stmt {
             id: ast::DUMMY_NODE_ID,
             span,
             attrs: ThinVec::new(),
-            source: ast::LocalSource::Normal,
         });
         ast::Stmt {
             id: ast::DUMMY_NODE_ID,
@@ -971,8 +968,7 @@ fn arg(&self, span: Span, ident: ast::Ident, ty: P<ast::Ty>) -> ast::Arg {
         ast::Arg {
             ty,
             pat: arg_pat,
-            id: ast::DUMMY_NODE_ID,
-            source: ast::ArgSource::Normal,
+            id: ast::DUMMY_NODE_ID
         }
     }
 
index 8f24d11cfd5b0696da080a9cd55211c757086f6c..c56c156182bd66089c3202bc7aa72d41003ae508 100644 (file)
@@ -101,13 +101,6 @@ pub fn add(&mut self, id: ast::NodeId, mut fragment: AstFragment, derives: Vec<M
     fn remove(&mut self, id: ast::NodeId) -> AstFragment {
         self.expanded_fragments.remove(&id).unwrap()
     }
-
-    fn next_id(&mut self, id: &mut ast::NodeId) {
-        if self.monotonic {
-            assert_eq!(*id, ast::DUMMY_NODE_ID);
-            *id = self.cx.resolver.next_node_id()
-        }
-    }
 }
 
 impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> {
@@ -189,19 +182,9 @@ fn visit_block(&mut self, block: &mut P<ast::Block>) {
         noop_visit_block(block, self);
 
         for stmt in block.stmts.iter_mut() {
-            self.next_id(&mut stmt.id);
-        }
-    }
-
-    fn visit_asyncness(&mut self, a: &mut ast::IsAsync) {
-        noop_visit_asyncness(a, self);
-
-        if let ast::IsAsync::Async { ref mut arguments, .. } = a {
-            for argument in arguments.iter_mut() {
-                self.next_id(&mut argument.move_stmt.id);
-                if let Some(ref mut pat_stmt) = &mut argument.pat_stmt {
-                    self.next_id(&mut pat_stmt.id);
-                }
+            if self.monotonic {
+                assert_eq!(stmt.id, ast::DUMMY_NODE_ID);
+                stmt.id = self.cx.resolver.next_node_id();
             }
         }
     }
index 0016c0d4d7e2b26ade57deeecdd568b5fb016c53..757513098995be60379061d73adeb29c129ba635 100644 (file)
@@ -207,10 +207,6 @@ fn visit_local(&mut self, l: &mut P<Local>) {
         noop_visit_local(l, self);
     }
 
-    fn visit_local_source(&mut self, l: &mut LocalSource) {
-        noop_visit_local_source(l, self);
-    }
-
     fn visit_mac(&mut self, _mac: &mut Mac) {
         panic!("visit_mac disabled by default");
         // N.B., see note about macros above. If you really want a visitor that
@@ -234,10 +230,6 @@ fn visit_arg(&mut self, a: &mut Arg) {
         noop_visit_arg(a, self);
     }
 
-    fn visit_arg_source(&mut self, a: &mut ArgSource) {
-        noop_visit_arg_source(a, self);
-    }
-
     fn visit_generics(&mut self, generics: &mut Generics) {
         noop_visit_generics(generics, self);
     }
@@ -522,17 +514,13 @@ pub fn noop_visit_parenthesized_parameter_data<T: MutVisitor>(args: &mut Parenth
 }
 
 pub fn noop_visit_local<T: MutVisitor>(local: &mut P<Local>, vis: &mut T) {
-    let Local { id, pat, ty, init, span, attrs, source } = local.deref_mut();
+    let Local { id, pat, ty, init, span, attrs } = local.deref_mut();
     vis.visit_id(id);
     vis.visit_pat(pat);
     visit_opt(ty, |ty| vis.visit_ty(ty));
     visit_opt(init, |init| vis.visit_expr(init));
     vis.visit_span(span);
     visit_thin_attrs(attrs, vis);
-    vis.visit_local_source(source);
-}
-
-pub fn noop_visit_local_source<T: MutVisitor>(_local_source: &mut LocalSource, _vis: &mut T) {
 }
 
 pub fn noop_visit_attribute<T: MutVisitor>(attr: &mut Attribute, vis: &mut T) {
@@ -571,18 +559,10 @@ pub fn noop_visit_meta_item<T: MutVisitor>(mi: &mut MetaItem, vis: &mut T) {
     vis.visit_span(span);
 }
 
-pub fn noop_visit_arg<T: MutVisitor>(Arg { id, pat, ty, source }: &mut Arg, vis: &mut T) {
+pub fn noop_visit_arg<T: MutVisitor>(Arg { id, pat, ty }: &mut Arg, vis: &mut T) {
     vis.visit_id(id);
     vis.visit_pat(pat);
     vis.visit_ty(ty);
-    vis.visit_arg_source(source);
-}
-
-pub fn noop_visit_arg_source<T: MutVisitor>(source: &mut ArgSource, vis: &mut T) {
-    match source {
-        ArgSource::Normal => {},
-        ArgSource::AsyncFn(pat) => vis.visit_pat(pat),
-    }
 }
 
 pub fn noop_visit_tt<T: MutVisitor>(tt: &mut TokenTree, vis: &mut T) {
@@ -690,25 +670,9 @@ pub fn noop_visit_interpolated<T: MutVisitor>(nt: &mut token::Nonterminal, vis:
 
 pub fn noop_visit_asyncness<T: MutVisitor>(asyncness: &mut IsAsync, vis: &mut T) {
     match asyncness {
-        IsAsync::Async { closure_id, return_impl_trait_id, ref mut arguments } => {
+        IsAsync::Async { closure_id, return_impl_trait_id } => {
             vis.visit_id(closure_id);
             vis.visit_id(return_impl_trait_id);
-            for AsyncArgument { ident, arg, pat_stmt, move_stmt } in arguments.iter_mut() {
-                vis.visit_ident(ident);
-                if let Some(arg) = arg {
-                    vis.visit_arg(arg);
-                }
-                visit_clobber(move_stmt, |stmt| {
-                    vis.flat_map_stmt(stmt)
-                        .expect_one("expected visitor to produce exactly one item")
-                });
-                visit_opt(pat_stmt, |stmt| {
-                    visit_clobber(stmt, |stmt| {
-                        vis.flat_map_stmt(stmt)
-                            .expect_one("expected visitor to produce exactly one item")
-                    })
-                });
-            }
         }
         IsAsync::NotAsync => {}
     }
index b3d49524d7668599e9d37ed6d46907db65981776..5df22f28797a4813a49d7530e517e1f2f123de3d 100644 (file)
@@ -1,7 +1,6 @@
-use crate::ast;
 use crate::ast::{
-    BlockCheckMode, BinOpKind, Expr, ExprKind, Item, ItemKind, Pat, PatKind, PathSegment, QSelf,
-    Ty, TyKind, VariantData,
+    self, Arg, BinOpKind, BindingMode, BlockCheckMode, Expr, ExprKind, Ident, Item, ItemKind,
+    Mutability, Pat, PatKind, PathSegment, QSelf, Ty, TyKind, VariantData,
 };
 use crate::parse::{SeqSep, token, PResult, Parser};
 use crate::parse::parser::{BlockMode, PathStyle, SemiColonMode, TokenType, TokenExpectType};
 use crate::ThinVec;
 use crate::util::parser::AssocOp;
 use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
+use rustc_data_structures::fx::FxHashSet;
 use syntax_pos::{Span, DUMMY_SP, MultiSpan};
 use log::{debug, trace};
 
+/// Creates a placeholder argument.
+crate fn dummy_arg(ident: Ident) -> Arg {
+    let pat = P(Pat {
+        id: ast::DUMMY_NODE_ID,
+        node: PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), ident, None),
+        span: ident.span,
+    });
+    let ty = Ty {
+        node: TyKind::Err,
+        span: ident.span,
+        id: ast::DUMMY_NODE_ID
+    };
+    Arg { ty: P(ty), pat: pat, id: ast::DUMMY_NODE_ID }
+}
+
 pub enum Error {
     FileNotFoundForModule {
         mod_name: String,
@@ -858,8 +873,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",
@@ -1092,12 +1107,12 @@ pub fn unexpected_try_recover(
         pat: P<ast::Pat>,
         require_name: bool,
         is_trait_item: bool,
-    ) {
+    ) -> Option<Ident> {
         // If we find a pattern followed by an identifier, it could be an (incorrect)
         // C-style parameter declaration.
         if self.check_ident() && self.look_ahead(1, |t| {
             *t == token::Comma || *t == token::CloseDelim(token::Paren)
-        }) {
+        }) { // `fn foo(String s) {}`
             let ident = self.parse_ident().unwrap();
             let span = pat.span.with_hi(ident.span.hi());
 
@@ -1107,18 +1122,30 @@ pub fn unexpected_try_recover(
                 String::from("<identifier>: <type>"),
                 Applicability::HasPlaceholders,
             );
-        } else if require_name && is_trait_item {
-            if let PatKind::Ident(_, ident, _) = pat.node {
+            return Some(ident);
+        } else if let PatKind::Ident(_, ident, _) = pat.node {
+            if require_name && (
+                is_trait_item ||
+                self.token == token::Comma ||
+                self.token == token::CloseDelim(token::Paren)
+            ) { // `fn foo(a, b) {}` or `fn foo(usize, usize) {}`
                 err.span_suggestion(
                     pat.span,
-                    "explicitly ignore parameter",
+                    "if this was a parameter name, give it a type",
+                    format!("{}: TypeName", ident),
+                    Applicability::HasPlaceholders,
+                );
+                err.span_suggestion(
+                    pat.span,
+                    "if this is a type, explicitly ignore the parameter name",
                     format!("_: {}", ident),
                     Applicability::MachineApplicable,
                 );
+                err.note("anonymous parameters are removed in the 2018 edition (see RFC 1685)");
+                return Some(ident);
             }
-
-            err.note("anonymous parameters are removed in the 2018 edition (see RFC 1685)");
         }
+        None
     }
 
     crate fn recover_arg_parse(&mut self) -> PResult<'a, (P<ast::Pat>, P<ast::Ty>)> {
@@ -1205,4 +1232,31 @@ pub fn unexpected_try_recover(
         err.span_label(span, "expected expression");
         err
     }
+
+    /// Replace duplicated recovered arguments with `_` pattern to avoid unecessary errors.
+    ///
+    /// This is necessary because at this point we don't know whether we parsed a function with
+    /// anonymous arguments or a function with names but no types. In order to minimize
+    /// unecessary errors, we assume the arguments are in the shape of `fn foo(a, b, c)` where
+    /// the arguments are *names* (so we don't emit errors about not being able to find `b` in
+    /// the local scope), but if we find the same name multiple times, like in `fn foo(i8, i8)`,
+    /// we deduplicate them to not complain about duplicated argument names.
+    crate fn deduplicate_recovered_arg_names(&self, fn_inputs: &mut Vec<Arg>) {
+        let mut seen_inputs = FxHashSet::default();
+        for input in fn_inputs.iter_mut() {
+            let opt_ident = if let (PatKind::Ident(_, ident, _), TyKind::Err) = (
+                &input.pat.node, &input.ty.node,
+            ) {
+                Some(*ident)
+            } else {
+                None
+            };
+            if let Some(ident) = opt_ident {
+                if seen_inputs.contains(&ident) {
+                    input.pat.node = PatKind::Wild;
+                }
+                seen_inputs.insert(ident);
+            }
+        }
+    }
 }
index 746e9cad4962ca4057e9214ef433aedaedade7f2..ae1e5116c676e884847f1715be28fc1cd2ac15e2 100644 (file)
@@ -1,9 +1,9 @@
 // ignore-tidy-filelength
 
-use crate::ast::{AngleBracketedArgs, AsyncArgument, ParenthesizedArgs, AttrStyle, BareFnTy};
+use crate::ast::{AngleBracketedArgs, ParenthesizedArgs, AttrStyle, BareFnTy};
 use crate::ast::{GenericBound, TraitBoundModifier};
 use crate::ast::Unsafety;
-use crate::ast::{Mod, AnonConst, Arg, ArgSource, Arm, Guard, Attribute, BindingMode, TraitItemKind};
+use crate::ast::{Mod, AnonConst, Arg, Arm, Guard, Attribute, BindingMode, TraitItemKind};
 use crate::ast::Block;
 use crate::ast::{BlockCheckMode, CaptureBy, Movability};
 use crate::ast::{Constness, Crate};
@@ -16,7 +16,7 @@
 use crate::ast::GenericArg;
 use crate::ast::{Ident, ImplItem, IsAsync, IsAuto, Item, ItemKind};
 use crate::ast::{Label, Lifetime};
-use crate::ast::{Local, LocalSource};
+use crate::ast::Local;
 use crate::ast::MacStmtStyle;
 use crate::ast::{Mac, Mac_, MacDelimiter};
 use crate::ast::{MutTy, Mutability};
 use crate::ThinVec;
 use crate::tokenstream::{self, DelimSpan, TokenTree, TokenStream, TreeAndJoint};
 use crate::symbol::{kw, sym, Symbol};
-use crate::parse::diagnostics::Error;
+use crate::parse::diagnostics::{Error, dummy_arg};
 
 use errors::{Applicability, DiagnosticBuilder, DiagnosticId, FatalError};
 use rustc_target::spec::abi::{self, Abi};
-use syntax_pos::{Span, BytePos, DUMMY_SP, FileName, hygiene::CompilerDesugaringKind};
+use syntax_pos::{Span, BytePos, DUMMY_SP, FileName};
 use log::debug;
 
 use std::borrow::Cow;
@@ -451,22 +451,6 @@ fn from(expr: P<Expr>) -> Self {
     }
 }
 
-/// Creates a placeholder argument.
-fn dummy_arg(span: Span) -> Arg {
-    let ident = Ident::new(kw::Invalid, span);
-    let pat = P(Pat {
-        id: ast::DUMMY_NODE_ID,
-        node: PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), ident, None),
-        span,
-    });
-    let ty = Ty {
-        node: TyKind::Err,
-        span,
-        id: ast::DUMMY_NODE_ID
-    };
-    Arg { ty: P(ty), pat: pat, id: ast::DUMMY_NODE_ID, source: ast::ArgSource::Normal }
-}
-
 #[derive(Copy, Clone, Debug)]
 crate enum TokenExpectType {
     Expect,
@@ -1142,7 +1126,6 @@ fn parse_asyncness(&mut self) -> IsAsync {
             IsAsync::Async {
                 closure_id: ast::DUMMY_NODE_ID,
                 return_impl_trait_id: ast::DUMMY_NODE_ID,
-                arguments: Vec::new(),
             }
         } else {
             IsAsync::NotAsync
@@ -1201,12 +1184,12 @@ fn parse_trait_item_(&mut self,
             // trait item macro.
             (Ident::invalid(), ast::TraitItemKind::Macro(mac), ast::Generics::default())
         } else {
-            let (constness, unsafety, mut asyncness, abi) = self.parse_fn_front_matter()?;
+            let (constness, unsafety, asyncness, abi) = self.parse_fn_front_matter()?;
 
             let ident = self.parse_ident()?;
             let mut generics = self.parse_generics()?;
 
-            let mut decl = self.parse_fn_decl_with_self(|p: &mut Parser<'a>| {
+            let decl = self.parse_fn_decl_with_self(|p: &mut Parser<'a>| {
                 // This is somewhat dubious; We don't want to allow
                 // argument names to be left off if there is a
                 // definition...
@@ -1215,7 +1198,6 @@ fn parse_trait_item_(&mut self,
                 p.parse_arg_general(p.span.rust_2018(), true, false)
             })?;
             generics.where_clause = self.parse_where_clause()?;
-            self.construct_async_arguments(&mut asyncness, &mut decl);
 
             let sig = ast::MethodSig {
                 header: FnHeader {
@@ -1528,8 +1510,17 @@ fn parse_arg_general(
             let pat = self.parse_pat(Some("argument name"))?;
 
             if let Err(mut err) = self.expect(&token::Colon) {
-                self.argument_without_type(&mut err, pat, require_name, is_trait_item);
-                return Err(err);
+                if let Some(ident) = self.argument_without_type(
+                    &mut err,
+                    pat,
+                    require_name,
+                    is_trait_item,
+                ) {
+                    err.emit();
+                    return Ok(dummy_arg(ident));
+                } else {
+                    return Err(err);
+                }
             }
 
             self.eat_incorrect_doc_comment("a method argument's type");
@@ -1570,7 +1561,7 @@ fn parse_arg_general(
             }
         };
 
-        Ok(Arg { ty, pat, id: ast::DUMMY_NODE_ID, source: ast::ArgSource::Normal })
+        Ok(Arg { ty, pat, id: ast::DUMMY_NODE_ID })
     }
 
     /// Parses an argument in a lambda header (e.g., `|arg, arg|`).
@@ -1588,8 +1579,7 @@ fn parse_fn_block_arg(&mut self) -> PResult<'a, Arg> {
         Ok(Arg {
             ty: t,
             pat,
-            id: ast::DUMMY_NODE_ID,
-            source: ast::ArgSource::Normal,
+            id: ast::DUMMY_NODE_ID
         })
     }
 
@@ -4220,7 +4210,6 @@ fn parse_local(&mut self, attrs: ThinVec<Attribute>) -> PResult<'a, P<Local>> {
             id: ast::DUMMY_NODE_ID,
             span: lo.to(hi),
             attrs,
-            source: LocalSource::Normal,
         }))
     }
 
@@ -5050,21 +5039,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.
@@ -5250,9 +5240,13 @@ fn parse_generic_args(&mut self) -> PResult<'a, (Vec<GenericArg>, Vec<TypeBindin
                     // FIXME(const_generics): to distinguish between idents for types and consts,
                     // we should introduce a GenericArg::Ident in the AST and distinguish when
                     // lowering to the HIR. For now, idents for const args are not permitted.
-                    return Err(
-                        self.fatal("identifiers may currently not be used for const generics")
-                    );
+                    if self.token.is_keyword(kw::True) || self.token.is_keyword(kw::False) {
+                        self.parse_literal_maybe_minus()?
+                    } else {
+                        return Err(
+                            self.fatal("identifiers may currently not be used for const generics")
+                        );
+                    }
                 } else {
                     self.parse_literal_maybe_minus()?
                 };
@@ -5431,7 +5425,7 @@ fn parse_fn_args(&mut self, named_args: bool, allow_c_variadic: bool)
                             p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(token::Paren)]);
                             // Create a placeholder argument for proper arg count (issue #34264).
                             let span = lo.to(p.prev_span);
-                            Ok(Some(dummy_arg(span)))
+                            Ok(Some(dummy_arg(Ident::new(kw::Invalid, span))))
                         }
                     }
                 }
@@ -5584,7 +5578,7 @@ fn parse_fn_decl_with_self<F>(&mut self, parse_arg_fn: F) -> PResult<'a, P<FnDec
 
         // Parse the rest of the function parameter list.
         let sep = SeqSep::trailing_allowed(token::Comma);
-        let (fn_inputs, recovered) = if let Some(self_arg) = self_arg {
+        let (mut fn_inputs, recovered) = if let Some(self_arg) = self_arg {
             if self.check(&token::CloseDelim(token::Paren)) {
                 (vec![self_arg], false)
             } else if self.eat(&token::Comma) {
@@ -5607,6 +5601,9 @@ fn parse_fn_decl_with_self<F>(&mut self, parse_arg_fn: F) -> PResult<'a, P<FnDec
             // Parse closing paren and return type.
             self.expect(&token::CloseDelim(token::Paren))?;
         }
+        // Replace duplicated recovered arguments with `_` pattern to avoid unecessary errors.
+        self.deduplicate_recovered_arg_names(&mut fn_inputs);
+
         Ok(P(FnDecl {
             inputs: fn_inputs,
             output: self.parse_ret_ty(true)?,
@@ -5663,16 +5660,15 @@ fn mk_item(&self, span: Span, ident: Ident, node: ItemKind, vis: Visibility,
     /// Parses an item-position function declaration.
     fn parse_item_fn(&mut self,
                      unsafety: Unsafety,
-                     mut asyncness: Spanned<IsAsync>,
+                     asyncness: Spanned<IsAsync>,
                      constness: Spanned<Constness>,
                      abi: Abi)
                      -> PResult<'a, ItemInfo> {
         let (ident, mut generics) = self.parse_fn_header()?;
         let allow_c_variadic = abi == Abi::C && unsafety == Unsafety::Unsafe;
-        let mut decl = self.parse_fn_decl(allow_c_variadic)?;
+        let decl = self.parse_fn_decl(allow_c_variadic)?;
         generics.where_clause = self.parse_where_clause()?;
         let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
-        self.construct_async_arguments(&mut asyncness, &mut decl);
         let header = FnHeader { unsafety, asyncness, constness, abi };
         Ok((ident, ItemKind::Fn(decl, header, generics, body), Some(inner_attrs)))
     }
@@ -5852,14 +5848,13 @@ fn parse_impl_method(&mut self, vis: &Visibility, at_end: &mut bool)
             Ok((Ident::invalid(), vec![], ast::Generics::default(),
                 ast::ImplItemKind::Macro(mac)))
         } else {
-            let (constness, unsafety, mut asyncness, abi) = self.parse_fn_front_matter()?;
+            let (constness, unsafety, asyncness, abi) = self.parse_fn_front_matter()?;
             let ident = self.parse_ident()?;
             let mut generics = self.parse_generics()?;
-            let mut decl = self.parse_fn_decl_with_self(|p| {
+            let decl = self.parse_fn_decl_with_self(|p| {
                 p.parse_arg_general(true, true, false)
             })?;
             generics.where_clause = self.parse_where_clause()?;
-            self.construct_async_arguments(&mut asyncness, &mut decl);
             *at_end = true;
             let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
             let header = ast::FnHeader { abi, unsafety, constness, asyncness };
@@ -7205,44 +7200,40 @@ 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,
+                                    }),
+                                    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])
@@ -7855,116 +7846,6 @@ fn report_invalid_macro_expansion_item(&self) {
             Applicability::MaybeIncorrect,
         ).emit();
     }
-
-    /// When lowering a `async fn` to the HIR, we need to move all of the arguments of the function
-    /// into the generated closure so that they are dropped when the future is polled and not when
-    /// it is created.
-    ///
-    /// The arguments of the function are replaced in HIR lowering with the arguments created by
-    /// this function and the statements created here are inserted at the top of the closure body.
-    fn construct_async_arguments(&mut self, asyncness: &mut Spanned<IsAsync>, decl: &mut FnDecl) {
-        // FIXME(davidtwco): This function should really live in the HIR lowering but because
-        // the types constructed here need to be used in parts of resolve so that the correct
-        // locals are considered upvars, it is currently easier for it to live here in the parser,
-        // where it can be constructed once.
-        if let IsAsync::Async { ref mut arguments, .. } = asyncness.node {
-            for (index, input) in decl.inputs.iter_mut().enumerate() {
-                let id = ast::DUMMY_NODE_ID;
-                let span = input.pat.span;
-                let desugared_span = self.sess.source_map()
-                    .mark_span_with_reason(CompilerDesugaringKind::Async, span, None);
-
-                // Construct a name for our temporary argument.
-                let name = format!("__arg{}", index);
-                let ident = Ident::from_str(&name).gensym();
-
-                // Check if this is a ident pattern, if so, we can optimize and avoid adding a
-                // `let <pat> = __argN;` statement, instead just adding a `let <pat> = <pat>;`
-                // statement.
-                let (binding_mode, ident, is_simple_pattern) = match input.pat.node {
-                    PatKind::Ident(binding_mode @ BindingMode::ByValue(_), ident, _) => {
-                        // Simple patterns like this don't have a generated argument, but they are
-                        // moved into the closure with a statement, so any `mut` bindings on the
-                        // argument will be unused. This binding mode can't be removed, because
-                        // this would affect the input to procedural macros, but they can have
-                        // their span marked as being the result of a compiler desugaring so
-                        // that they aren't linted against.
-                        input.pat.span = desugared_span;
-
-                        (binding_mode, ident, true)
-                    }
-                    _ => (BindingMode::ByValue(Mutability::Mutable), ident, false),
-                };
-
-                // Construct an argument representing `__argN: <ty>` to replace the argument of the
-                // async function if it isn't a simple pattern.
-                let arg = if is_simple_pattern {
-                    None
-                } else {
-                    Some(Arg {
-                        ty: input.ty.clone(),
-                        id,
-                        pat: P(Pat {
-                            id,
-                            node: PatKind::Ident(
-                                BindingMode::ByValue(Mutability::Immutable), ident, None,
-                            ),
-                            span: desugared_span,
-                        }),
-                        source: ArgSource::AsyncFn(input.pat.clone()),
-                    })
-                };
-
-                // Construct a `let __argN = __argN;` statement to insert at the top of the
-                // async closure. This makes sure that the argument is captured by the closure and
-                // that the drop order is correct.
-                let move_local = Local {
-                    pat: P(Pat {
-                        id,
-                        node: PatKind::Ident(binding_mode, ident, None),
-                        span: desugared_span,
-                    }),
-                    // We explicitly do not specify the type for this statement. When the user's
-                    // argument type is `impl Trait` then this would require the
-                    // `impl_trait_in_bindings` feature to also be present for that same type to
-                    // be valid in this binding. At the time of writing (13 Mar 19),
-                    // `impl_trait_in_bindings` is not stable.
-                    ty: None,
-                    init: Some(P(Expr {
-                        id,
-                        node: ExprKind::Path(None, ast::Path {
-                            span,
-                            segments: vec![PathSegment { ident, id, args: None }],
-                        }),
-                        span,
-                        attrs: ThinVec::new(),
-                    })),
-                    id,
-                    span,
-                    attrs: ThinVec::new(),
-                    source: LocalSource::AsyncFn,
-                };
-
-                // Construct a `let <pat> = __argN;` statement to insert at the top of the
-                // async closure if this isn't a simple pattern.
-                let pat_stmt = if is_simple_pattern {
-                    None
-                } else {
-                    Some(Stmt {
-                        id,
-                        node: StmtKind::Local(P(Local {
-                            pat: input.pat.clone(),
-                            ..move_local.clone()
-                        })),
-                        span,
-                    })
-                };
-
-                let move_stmt = Stmt { id, node: StmtKind::Local(P(move_local)), span };
-                arguments.push(AsyncArgument { ident, arg, pat_stmt, move_stmt });
-            }
-        }
-    }
 }
 
 pub fn emit_unclosed_delims(unclosed_delims: &mut Vec<UnmatchedBrace>, handler: &errors::Handler) {
index cf546332c2c9dde920ef7b292a05df82cc3c8b45..b81dc53ef6836061b2a5b107b4da3cf994e00534 100644 (file)
@@ -357,7 +357,7 @@ pub fn vis_to_string(v: &ast::Visibility) -> String {
 }
 
 pub fn fun_to_string(decl: &ast::FnDecl,
-                     header: &ast::FnHeader,
+                     header: ast::FnHeader,
                      name: ast::Ident,
                      generics: &ast::Generics)
                      -> String {
@@ -1040,7 +1040,7 @@ pub fn print_foreign_item(&mut self,
         match item.node {
             ast::ForeignItemKind::Fn(ref decl, ref generics) => {
                 self.head("")?;
-                self.print_fn(decl, &ast::FnHeader::default(),
+                self.print_fn(decl, ast::FnHeader::default(),
                               Some(item.ident),
                               generics, &item.vis)?;
                 self.end()?; // end head-ibox
@@ -1170,7 +1170,7 @@ pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
                 self.s.word(";")?;
                 self.end()?; // end the outer cbox
             }
-            ast::ItemKind::Fn(ref decl, ref header, ref param_names, ref body) => {
+            ast::ItemKind::Fn(ref decl, header, ref param_names, ref body) => {
                 self.head("")?;
                 self.print_fn(
                     decl,
@@ -1522,7 +1522,7 @@ pub fn print_method_sig(&mut self,
                             vis: &ast::Visibility)
                             -> io::Result<()> {
         self.print_fn(&m.decl,
-                      &m.header,
+                      m.header,
                       Some(ident),
                       &generics,
                       vis)
@@ -2113,7 +2113,7 @@ fn print_expr_outer_attr_style(&mut self,
                 self.bclose_(expr.span, INDENT_UNIT)?;
             }
             ast::ExprKind::Closure(
-                capture_clause, ref asyncness, movability, ref decl, ref body, _) => {
+                capture_clause, asyncness, movability, ref decl, ref body, _) => {
                 self.print_movability(movability)?;
                 self.print_asyncness(asyncness)?;
                 self.print_capture_clause(capture_clause)?;
@@ -2710,7 +2710,7 @@ fn print_explicit_self(&mut self, explicit_self: &ast::ExplicitSelf) -> io::Resu
 
     pub fn print_fn(&mut self,
                     decl: &ast::FnDecl,
-                    header: &ast::FnHeader,
+                    header: ast::FnHeader,
                     name: Option<ast::Ident>,
                     generics: &ast::Generics,
                     vis: &ast::Visibility) -> io::Result<()> {
@@ -2765,7 +2765,8 @@ pub fn print_movability(&mut self, movability: ast::Movability)
         }
     }
 
-    pub fn print_asyncness(&mut self, asyncness: &ast::IsAsync) -> io::Result<()> {
+    pub fn print_asyncness(&mut self, asyncness: ast::IsAsync)
+                                -> io::Result<()> {
         if asyncness.is_async() {
             self.word_nbsp("async")?;
         }
@@ -3037,7 +3038,7 @@ pub fn print_ty_fn(&mut self,
             span: syntax_pos::DUMMY_SP,
         };
         self.print_fn(decl,
-                      &ast::FnHeader { unsafety, abi, ..ast::FnHeader::default() },
+                      ast::FnHeader { unsafety, abi, ..ast::FnHeader::default() },
                       name,
                       &generics,
                       &source_map::dummy_spanned(ast::VisibilityKind::Inherited))?;
@@ -3100,7 +3101,7 @@ pub fn print_extern_opt_abi(&mut self,
     }
 
     pub fn print_fn_header_info(&mut self,
-                                header: &ast::FnHeader,
+                                header: ast::FnHeader,
                                 vis: &ast::Visibility) -> io::Result<()> {
         self.s.word(visibility_qualified(vis, ""))?;
 
@@ -3109,7 +3110,7 @@ pub fn print_fn_header_info(&mut self,
             ast::Constness::Const => self.word_nbsp("const")?
         }
 
-        self.print_asyncness(&header.asyncness.node)?;
+        self.print_asyncness(header.asyncness.node)?;
         self.print_unsafety(header.unsafety)?;
 
         if header.abi != Abi::Rust {
@@ -3158,7 +3159,7 @@ fn test_fun_to_string() {
             assert_eq!(
                 fun_to_string(
                     &decl,
-                    &ast::FnHeader {
+                    ast::FnHeader {
                         unsafety: ast::Unsafety::Normal,
                         constness: source_map::dummy_spanned(ast::Constness::NotConst),
                         asyncness: source_map::dummy_spanned(ast::IsAsync::NotAsync),
index 4b6893b242337d03cf6f929c90aa2a2bbee0c16a..a21d2df416206fc3c44534800ea3d2ff79d7a070 100644 (file)
@@ -935,27 +935,6 @@ pub fn generate_local_type_param_snippet(&self, span: Span) -> Option<(Span, Str
 
         None
     }
-
-    /// Reuses the span but adds information like the kind of the desugaring and features that are
-    /// allowed inside this span.
-    pub fn mark_span_with_reason(
-        &self,
-        reason: hygiene::CompilerDesugaringKind,
-        span: Span,
-        allow_internal_unstable: Option<Lrc<[symbol::Symbol]>>,
-    ) -> Span {
-        let mark = Mark::fresh(Mark::root());
-        mark.set_expn_info(ExpnInfo {
-            call_site: span,
-            def_site: Some(span),
-            format: CompilerDesugaring(reason),
-            allow_internal_unstable,
-            allow_internal_unsafe: false,
-            local_inner_macros: false,
-            edition: edition::Edition::from_session(),
-        });
-        span.with_ctxt(SyntaxContext::empty().apply_mark(mark))
-    }
 }
 
 impl SourceMapper for SourceMap {
index 4e096d68235b5c35c9823fc82b1dc0fa7a497731..eb516b5c7c62fd7e5e07fcb865a1a206187ca509 100644 (file)
@@ -544,9 +544,6 @@ pub fn walk_fn_ret_ty<'a, V: Visitor<'a>>(visitor: &mut V, ret_ty: &'a FunctionR
 pub fn walk_fn_decl<'a, V: Visitor<'a>>(visitor: &mut V, function_declaration: &'a FnDecl) {
     for argument in &function_declaration.inputs {
         visitor.visit_pat(&argument.pat);
-        if let ArgSource::AsyncFn(pat) = &argument.source {
-            visitor.visit_pat(pat);
-        }
         visitor.visit_ty(&argument.ty)
     }
     visitor.visit_fn_ret_ty(&function_declaration.output)
index dec4c2dfc3b5eb50ccfdf05b8a84d6540bbf8df8..44ddbb98809b4f0d217bc234df31b15071520e35 100644 (file)
@@ -129,7 +129,6 @@ fn stmt_let_undescore(cx: &mut ExtCtxt<'_>, sp: Span, expr: P<ast::Expr>) -> ast
         id: ast::DUMMY_NODE_ID,
         span: sp,
         attrs: ThinVec::new(),
-        source: ast::LocalSource::Normal,
     });
     ast::Stmt {
         id: ast::DUMMY_NODE_ID,
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
diff --git a/src/test/codegen/unchecked_math.rs b/src/test/codegen/unchecked_math.rs
new file mode 100644 (file)
index 0000000..419c120
--- /dev/null
@@ -0,0 +1,46 @@
+#![crate_type = "lib"]
+#![feature(core_intrinsics)]
+
+use std::intrinsics::*;
+
+// CHECK-LABEL: @unchecked_add_signed
+#[no_mangle]
+pub unsafe fn unchecked_add_signed(a: i32, b: i32) -> i32 {
+    // CHECK: add nsw
+    unchecked_add(a, b)
+}
+
+// CHECK-LABEL: @unchecked_add_unsigned
+#[no_mangle]
+pub unsafe fn unchecked_add_unsigned(a: u32, b: u32) -> u32 {
+    // CHECK: add nuw
+    unchecked_add(a, b)
+}
+
+// CHECK-LABEL: @unchecked_sub_signed
+#[no_mangle]
+pub unsafe fn unchecked_sub_signed(a: i32, b: i32) -> i32 {
+    // CHECK: sub nsw
+    unchecked_sub(a, b)
+}
+
+// CHECK-LABEL: @unchecked_sub_unsigned
+#[no_mangle]
+pub unsafe fn unchecked_sub_unsigned(a: u32, b: u32) -> u32 {
+    // CHECK: sub nuw
+    unchecked_sub(a, b)
+}
+
+// CHECK-LABEL: @unchecked_mul_signed
+#[no_mangle]
+pub unsafe fn unchecked_mul_signed(a: i32, b: i32) -> i32 {
+    // CHECK: mul nsw
+    unchecked_mul(a, b)
+}
+
+// CHECK-LABEL: @unchecked_mul_unsigned
+#[no_mangle]
+pub unsafe fn unchecked_mul_unsigned(a: u32, b: u32) -> u32 {
+    // CHECK: mul nuw
+    unchecked_mul(a, b)
+}
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 5e77aa8fbb923fdf17dcdbc6985e5a947fc2d1a6..abff8275064e24dfd8d922a003feab905deaa06a 100644 (file)
@@ -6,7 +6,13 @@ trait T {
     fn foo(i32); //~ expected one of `:` or `@`, found `)`
 
     fn bar_with_default_impl(String, String) {}
-    //~^ ERROR expected one of `:` or `@`, found `,`
+    //~^ ERROR expected one of `:`
+    //~| ERROR expected one of `:`
+
+    // do not complain about missing `b`
+    fn baz(a:usize, b, c: usize) -> usize { //~ ERROR expected one of `:`
+        a + b + c
+    }
 }
 
 fn main() {}
index 1ec0cf323e9960798b21f96b7cc9b46c0ed982d8..438bcf4274daaf0ab6e0c1dca14f6633b93ee5ef 100644 (file)
@@ -2,21 +2,65 @@ error: expected one of `:` or `@`, found `)`
   --> $DIR/anon-params-denied-2018.rs:6:15
    |
 LL |     fn foo(i32);
-   |            ---^ expected one of `:` or `@` here
-   |            |
-   |            help: explicitly ignore parameter: `_: i32`
+   |               ^ expected one of `:` or `@` here
    |
    = note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
+help: if this was a parameter name, give it a type
+   |
+LL |     fn foo(i32: TypeName);
+   |            ^^^^^^^^^^^^^
+help: if this is a type, explicitly ignore the parameter name
+   |
+LL |     fn foo(_: i32);
+   |            ^^^^^^
 
 error: expected one of `:` or `@`, found `,`
   --> $DIR/anon-params-denied-2018.rs:8:36
    |
 LL |     fn bar_with_default_impl(String, String) {}
-   |                              ------^ expected one of `:` or `@` here
-   |                              |
-   |                              help: explicitly ignore parameter: `_: String`
+   |                                    ^ expected one of `:` or `@` here
+   |
+   = note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
+help: if this was a parameter name, give it a type
+   |
+LL |     fn bar_with_default_impl(String: TypeName, String) {}
+   |                              ^^^^^^^^^^^^^^^^
+help: if this is a type, explicitly ignore the parameter name
+   |
+LL |     fn bar_with_default_impl(_: String, String) {}
+   |                              ^^^^^^^^^
+
+error: expected one of `:` or `@`, found `)`
+  --> $DIR/anon-params-denied-2018.rs:8:44
+   |
+LL |     fn bar_with_default_impl(String, String) {}
+   |                                            ^ expected one of `:` or `@` here
    |
    = note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
+help: if this was a parameter name, give it a type
+   |
+LL |     fn bar_with_default_impl(String, String: TypeName) {}
+   |                                      ^^^^^^^^^^^^^^^^
+help: if this is a type, explicitly ignore the parameter name
+   |
+LL |     fn bar_with_default_impl(String, _: String) {}
+   |                                      ^^^^^^^^^
+
+error: expected one of `:` or `@`, found `,`
+  --> $DIR/anon-params-denied-2018.rs:13:22
+   |
+LL |     fn baz(a:usize, b, c: usize) -> usize {
+   |                      ^ expected one of `:` or `@` here
+   |
+   = note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
+help: if this was a parameter name, give it a type
+   |
+LL |     fn baz(a:usize, b: TypeName, c: usize) -> usize {
+   |                     ^^^^^^^^^^^
+help: if this is a type, explicitly ignore the parameter name
+   |
+LL |     fn baz(a:usize, _: b, c: usize) -> usize {
+   |                     ^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to 4 previous errors
 
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
 }
diff --git a/src/test/ui/async-await/issues/issue-61187.rs b/src/test/ui/async-await/issues/issue-61187.rs
new file mode 100644 (file)
index 0000000..8b939b4
--- /dev/null
@@ -0,0 +1,9 @@
+// edition:2018
+#![feature(async_await)]
+
+fn main() {
+}
+
+async fn response(data: Vec<u8>) {
+    data.reverse(); //~ ERROR E0596
+}
diff --git a/src/test/ui/async-await/issues/issue-61187.stderr b/src/test/ui/async-await/issues/issue-61187.stderr
new file mode 100644 (file)
index 0000000..a031422
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0596]: cannot borrow `data` as mutable, as it is not declared as mutable
+  --> $DIR/issue-61187.rs:8:5
+   |
+LL | async fn response(data: Vec<u8>) {
+   |                   ---- help: consider changing this to be mutable: `mut data`
+LL |     data.reverse();
+   |     ^^^^ cannot borrow as mutable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0596`.
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/condition-in-trait-const-arg.rs b/src/test/ui/const-generics/condition-in-trait-const-arg.rs
new file mode 100644 (file)
index 0000000..091fe90
--- /dev/null
@@ -0,0 +1,12 @@
+// run-pass
+
+#![feature(const_generics)]
+//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
+
+trait IsZeroTrait<const IS_ZERO: bool>{}
+
+impl IsZeroTrait<{0u8 == 0u8}> for () {}
+
+impl IsZeroTrait<true> for ((),) {}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/condition-in-trait-const-arg.stderr b/src/test/ui/const-generics/condition-in-trait-const-arg.stderr
new file mode 100644 (file)
index 0000000..7c85651
--- /dev/null
@@ -0,0 +1,6 @@
+warning: the feature `const_generics` is incomplete and may cause the compiler to crash
+  --> $DIR/condition-in-trait-const-arg.rs:3:12
+   |
+LL | #![feature(const_generics)]
+   |            ^^^^^^^^^^^^^^
+
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
diff --git a/src/test/ui/intrinsics/unchecked_math_unsafe.rs b/src/test/ui/intrinsics/unchecked_math_unsafe.rs
new file mode 100644 (file)
index 0000000..a034b45
--- /dev/null
@@ -0,0 +1,8 @@
+#![feature(core_intrinsics)]
+
+fn main() {
+    let (x, y) = (1u32, 2u32);
+    let add = std::intrinsics::unchecked_add(x, y); //~ ERROR call to unsafe function
+    let sub = std::intrinsics::unchecked_sub(x, y); //~ ERROR call to unsafe function
+    let mul = std::intrinsics::unchecked_mul(x, y); //~ ERROR call to unsafe function
+}
diff --git a/src/test/ui/intrinsics/unchecked_math_unsafe.stderr b/src/test/ui/intrinsics/unchecked_math_unsafe.stderr
new file mode 100644 (file)
index 0000000..4066cf8
--- /dev/null
@@ -0,0 +1,27 @@
+error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
+  --> $DIR/unchecked_math_unsafe.rs:5:15
+   |
+LL |     let add = std::intrinsics::unchecked_add(x, y);
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
+  --> $DIR/unchecked_math_unsafe.rs:6:15
+   |
+LL |     let sub = std::intrinsics::unchecked_sub(x, y);
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
+  --> $DIR/unchecked_math_unsafe.rs:7:15
+   |
+LL |     let mul = std::intrinsics::unchecked_mul(x, y);
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/intrinsics/unchecked_math_unstable.rs b/src/test/ui/intrinsics/unchecked_math_unstable.rs
new file mode 100644 (file)
index 0000000..8869063
--- /dev/null
@@ -0,0 +1,8 @@
+fn main() {
+    let (x, y) = (1u32, 2u32);
+    unsafe {
+        let add = std::intrinsics::unchecked_add(x, y); //~ ERROR use of unstable library feature
+        let sub = std::intrinsics::unchecked_sub(x, y); //~ ERROR use of unstable library feature
+        let mul = std::intrinsics::unchecked_mul(x, y); //~ ERROR use of unstable library feature
+    }
+}
diff --git a/src/test/ui/intrinsics/unchecked_math_unstable.stderr b/src/test/ui/intrinsics/unchecked_math_unstable.stderr
new file mode 100644 (file)
index 0000000..6f54291
--- /dev/null
@@ -0,0 +1,27 @@
+error[E0658]: use of unstable library feature 'core_intrinsics': intrinsics are unlikely to ever be stabilized, instead they should be used through stabilized interfaces in the rest of the standard library
+  --> $DIR/unchecked_math_unstable.rs:4:19
+   |
+LL |         let add = std::intrinsics::unchecked_add(x, y);
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(core_intrinsics)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'core_intrinsics': intrinsics are unlikely to ever be stabilized, instead they should be used through stabilized interfaces in the rest of the standard library
+  --> $DIR/unchecked_math_unstable.rs:5:19
+   |
+LL |         let sub = std::intrinsics::unchecked_sub(x, y);
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(core_intrinsics)] to the crate attributes to enable
+
+error[E0658]: use of unstable library feature 'core_intrinsics': intrinsics are unlikely to ever be stabilized, instead they should be used through stabilized interfaces in the rest of the standard library
+  --> $DIR/unchecked_math_unstable.rs:6:19
+   |
+LL |         let mul = std::intrinsics::unchecked_mul(x, y);
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(core_intrinsics)] to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
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 37ff468e032050492258e20fd41d76ee94694bab..86128ed94bd71f5d90ea8029714152b239143682 100644 (file)
@@ -4,5 +4,5 @@ fn new<T>() -> &'static T {
 
 fn main() {
     let &v = new();
-    //~^ ERROR type annotations needed [E0282]
+    //~^ ERROR type annotations needed
 }
index f8df4f82e7efd7ce2bc5813f9dd10f43a2455347..3ea15439df25a69276b8239ea62fe125587282e2 100644 (file)
@@ -1,11 +1,11 @@
-error[E0282]: type annotations needed
+error[E0282]: type annotations needed for `&T`
   --> $DIR/issue-12187-1.rs:6:10
    |
 LL |     let &v = new();
    |         -^
    |         ||
    |         |cannot infer type
-   |         consider giving the pattern a type
+   |         consider giving this pattern the explicit type `&T`, with the type parameters specified
 
 error: aborting due to previous error
 
index a1cdb84977907940e71fe749d288e0ea79c047e6..080a6206be76df188986bb11f8c12b367e2f7ebf 100644 (file)
@@ -4,5 +4,5 @@ fn new<'r, T>() -> &'r T {
 
 fn main() {
     let &v = new();
-    //~^ ERROR type annotations needed [E0282]
+    //~^ ERROR type annotations needed
 }
index c40ae0461ec033356c73b71c8a811ebca7abf4f9..a5e65c65beb2fe6b059a635330bea9468d0bf030 100644 (file)
@@ -1,11 +1,11 @@
-error[E0282]: type annotations needed
+error[E0282]: type annotations needed for `&T`
   --> $DIR/issue-12187-2.rs:6:10
    |
 LL |     let &v = new();
    |         -^
    |         ||
    |         |cannot infer type
-   |         consider giving the pattern a type
+   |         consider giving this pattern the explicit type `&T`, with the type parameters specified
 
 error: aborting due to previous error
 
index 40e7727752b76d9b529e3e9145d125d1316708f7..ce16f0f58eaf0cacff150cf9b4c1a18237cfa26a 100644 (file)
@@ -1,10 +1,10 @@
-error[E0282]: type annotations needed
+error[E0282]: type annotations needed for `B<T>`
   --> $DIR/issue-17551.rs:6:15
    |
 LL |     let foo = B(marker::PhantomData);
    |         ---   ^ cannot infer type for `T`
    |         |
-   |         consider giving `foo` a type
+   |         consider giving `foo` the explicit type `B<T>`, where the type parameter `T` is specified
 
 error: aborting due to previous error
 
index 5665f5893f428a94fdbb841c7b266b49e72e2221..c6c3f32dfe7d8f3a8a8f8fe6a578dd16acc9bb24 100644 (file)
@@ -1,4 +1,4 @@
-error[E0282]: type annotations needed
+error[E0282]: type annotations needed for `&(_,)`
   --> $DIR/issue-20261.rs:4:11
    |
 LL |     for (ref i,) in [].iter() {
diff --git a/src/test/ui/issues/issue-21596.rs b/src/test/ui/issues/issue-21596.rs
new file mode 100644 (file)
index 0000000..79f6c91
--- /dev/null
@@ -0,0 +1,5 @@
+fn main() {
+    let x = 8u8;
+    let z: *const u8 = &x;
+    println!("{}", z.to_string());  //~ ERROR E0599
+}
diff --git a/src/test/ui/issues/issue-21596.stderr b/src/test/ui/issues/issue-21596.stderr
new file mode 100644 (file)
index 0000000..07d29f3
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0599]: no method named `to_string` found for type `*const u8` in the current scope
+  --> $DIR/issue-21596.rs:4:22
+   |
+LL |     println!("{}", z.to_string());
+   |                      ^^^^^^^^^
+   |
+   = note: try using `<*const T>::as_ref()` to get a reference to the type behind the pointer: https://doc.rust-lang.org/std/primitive.pointer.html#method.as_ref
+   = note: the method `to_string` exists but the following trait bounds were not satisfied:
+           `*const u8 : std::string::ToString`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
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 aab90a9d4403af43c33259fef6044a171305996b..12b2eb48e7eaa2987d341590f80595f040d88ba6 100644 (file)
@@ -1,8 +1,8 @@
-error[E0282]: type annotations needed
+error[E0282]: type annotations needed for `Expr<'_, VAR>`
   --> $DIR/issue-23046.rs:17:15
    |
 LL |     let ex = |x| {
-   |               ^ consider giving this closure parameter a type
+   |               ^ consider giving this closure parameter the explicit type `Expr<'_, VAR>`, where the type parameter `VAR` is specified
 
 error: aborting due to previous error
 
index 3ad6a2569be451b35ce4d3f9395f77b349677b96..0b890b573da131ad77cba13b3d3642f82b8fee92 100644 (file)
@@ -1,8 +1,8 @@
-error[E0282]: type annotations needed
+error[E0282]: type annotations needed for `(std::sync::mpsc::Sender<Foo<T>>, std::sync::mpsc::Receiver<Foo<T>>)`
   --> $DIR/issue-25368.rs:11:17
    |
 LL |     let (tx, rx) = channel();
-   |         -------- consider giving the pattern a type
+   |         -------- consider giving this pattern the explicit type `(std::sync::mpsc::Sender<Foo<T>>, std::sync::mpsc::Receiver<Foo<T>>)`, where the type parameter `T` is specified
 ...
 LL |         tx.send(Foo{ foo: PhantomData });
    |                 ^^^ cannot infer type for `T`
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 45b9c915885b4afc87bed4e79cff75d137fb7142..59be0f3be11e6a2d3a408778bbb3af3a6e9b0999 100644 (file)
@@ -1,10 +1,10 @@
-error[E0282]: type annotations needed
+error[E0282]: type annotations needed for `&[_; 0]`
   --> $DIR/issue-7813.rs:2:13
    |
 LL |     let v = &[];
    |         -   ^^^ cannot infer type
    |         |
-   |         consider giving `v` a type
+   |         consider giving `v` the explicit type `&[_; 0]`, with the type parameters specified
 
 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
diff --git a/src/test/ui/lint/must_use-tuple.rs b/src/test/ui/lint/must_use-tuple.rs
new file mode 100644 (file)
index 0000000..f6b579a
--- /dev/null
@@ -0,0 +1,17 @@
+#![deny(unused_must_use)]
+
+fn foo() -> (Result<(), ()>, ()) {
+    (Ok::<(), ()>(()), ())
+}
+
+fn main() {
+    (Ok::<(), ()>(()),); //~ ERROR unused `std::result::Result`
+
+    (Ok::<(), ()>(()), 0, Ok::<(), ()>(()), 5);
+    //~^ ERROR unused `std::result::Result`
+    //~^^ ERROR unused `std::result::Result`
+
+    foo(); //~ ERROR unused `std::result::Result`
+
+    ((Err::<(), ()>(()), ()), ()); //~ ERROR unused `std::result::Result`
+}
diff --git a/src/test/ui/lint/must_use-tuple.stderr b/src/test/ui/lint/must_use-tuple.stderr
new file mode 100644 (file)
index 0000000..45d2a43
--- /dev/null
@@ -0,0 +1,47 @@
+error: unused `std::result::Result` in tuple element 0 that must be used
+  --> $DIR/must_use-tuple.rs:8:6
+   |
+LL |     (Ok::<(), ()>(()),);
+   |      ^^^^^^^^^^^^^^^^
+   |
+note: lint level defined here
+  --> $DIR/must_use-tuple.rs:1:9
+   |
+LL | #![deny(unused_must_use)]
+   |         ^^^^^^^^^^^^^^^
+   = note: this `Result` may be an `Err` variant, which should be handled
+
+error: unused `std::result::Result` in tuple element 0 that must be used
+  --> $DIR/must_use-tuple.rs:10:6
+   |
+LL |     (Ok::<(), ()>(()), 0, Ok::<(), ()>(()), 5);
+   |      ^^^^^^^^^^^^^^^^
+   |
+   = note: this `Result` may be an `Err` variant, which should be handled
+
+error: unused `std::result::Result` in tuple element 2 that must be used
+  --> $DIR/must_use-tuple.rs:10:27
+   |
+LL |     (Ok::<(), ()>(()), 0, Ok::<(), ()>(()), 5);
+   |                           ^^^^^^^^^^^^^^^^
+   |
+   = note: this `Result` may be an `Err` variant, which should be handled
+
+error: unused `std::result::Result` in tuple element 0 that must be used
+  --> $DIR/must_use-tuple.rs:14:5
+   |
+LL |     foo();
+   |     ^^^^^^
+   |
+   = note: this `Result` may be an `Err` variant, which should be handled
+
+error: unused `std::result::Result` in tuple element 0 that must be used
+  --> $DIR/must_use-tuple.rs:16:6
+   |
+LL |     ((Err::<(), ()>(()), ()), ());
+   |      ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this `Result` may be an `Err` variant, which should be handled
+
+error: aborting due to 5 previous errors
+
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 590e98dc35365ef97ccdbe43cd899c12becf2a2f..e33f23c64dbe14a33fcea4afa6d6236bb07d1ca4 100644 (file)
@@ -22,7 +22,7 @@ fn foo(&self) -> isize {2}
 fn m1() {
     // we couldn't infer the type of the vector just based on calling foo()...
     let mut x = Vec::new();
-    //~^ ERROR type annotations needed [E0282]
+    //~^ ERROR type annotations needed
     x.foo();
 }
 
index 063a4865b1987db22a50bb319e0bd7c01b0823e7..b1bd749bef4a254e9f121ffcfcd27e61e4ce8f30 100644 (file)
@@ -1,10 +1,10 @@
-error[E0282]: type annotations needed
+error[E0282]: type annotations needed for `std::vec::Vec<T>`
   --> $DIR/method-ambig-one-trait-unknown-int-type.rs:24:17
    |
 LL |     let mut x = Vec::new();
    |         -----   ^^^^^^^^ cannot infer type for `T`
    |         |
-   |         consider giving `x` a type
+   |         consider giving `x` the explicit type `std::vec::Vec<T>`, where the type parameter `T` is specified
 
 error[E0308]: mismatched types
   --> $DIR/method-ambig-one-trait-unknown-int-type.rs:33:20
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!(),
     }
 }
diff --git a/src/test/ui/nll/issue-61424.rs b/src/test/ui/nll/issue-61424.rs
new file mode 100644 (file)
index 0000000..44c8e9f
--- /dev/null
@@ -0,0 +1,7 @@
+#![deny(unused_mut)]
+
+fn main() {
+    let mut x; //~ ERROR: variable does not need to be mutable
+    x = String::new();
+    dbg!(x);
+}
diff --git a/src/test/ui/nll/issue-61424.stderr b/src/test/ui/nll/issue-61424.stderr
new file mode 100644 (file)
index 0000000..ae336b2
--- /dev/null
@@ -0,0 +1,16 @@
+error: variable does not need to be mutable
+  --> $DIR/issue-61424.rs:4:9
+   |
+LL |     let mut x;
+   |         ----^
+   |         |
+   |         help: remove this `mut`
+   |
+note: lint level defined here
+  --> $DIR/issue-61424.rs:1:9
+   |
+LL | #![deny(unused_mut)]
+   |         ^^^^^^^^^^
+
+error: aborting due to previous error
+
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 42430278c7267f6b2274d2269dc60c855a61e65c..f06b9510417310ba616f0651b6986a080ad08900 100644 (file)
@@ -20,6 +20,8 @@ fn pattern((i32, i32) (a, b)) {}
 
 fn fizz(i32) {}
 //~^ ERROR expected one of `:` or `@`
+//~| HELP if this was a parameter name, give it a type
+//~| HELP if this is a type, explicitly ignore the parameter name
 
 fn missing_colon(quux S) {}
 //~^ ERROR expected one of `:` or `@`
index bdb8faa6c6593975ad0dfd09db6fa7ed04362fcd..fb48bd1fe9383625660ab5150f43c7efef6d494d 100644 (file)
@@ -33,9 +33,19 @@ error: expected one of `:` or `@`, found `)`
    |
 LL | fn fizz(i32) {}
    |            ^ expected one of `:` or `@` here
+   |
+   = note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
+help: if this was a parameter name, give it a type
+   |
+LL | fn fizz(i32: TypeName) {}
+   |         ^^^^^^^^^^^^^
+help: if this is a type, explicitly ignore the parameter name
+   |
+LL | fn fizz(_: i32) {}
+   |         ^^^^^^
 
 error: expected one of `:` or `@`, found `S`
-  --> $DIR/inverted-parameters.rs:24:23
+  --> $DIR/inverted-parameters.rs:26:23
    |
 LL | fn missing_colon(quux S) {}
    |                  -----^
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 4f2a76d2d25627db8ebabe3dbc70dd504e45779c..e501f235d6d3b6fce85d1e2858810e455d9771c6 100644 (file)
@@ -3,6 +3,16 @@ error: expected one of `:` or `@`, found `)`
    |
 LL | fn foo(x) {
    |         ^ expected one of `:` or `@` here
+   |
+   = note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
+help: if this was a parameter name, give it a type
+   |
+LL | fn foo(x: TypeName) {
+   |        ^^^^^^^^^^^
+help: if this is a type, explicitly ignore the parameter name
+   |
+LL | fn foo(_: x) {
+   |        ^^^^
 
 error: aborting due to previous error
 
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 295b8c6f67f357758b2ee27fdb667d8ef3b6ed9e..5dd9895c6e4f45f141292a27afd0eeaaf78afd42 100644 (file)
@@ -9,12 +9,32 @@ error: expected one of `:` or `@`, found `)`
    |
 LL | fn foo(Option<i32>, String) {}
    |                           ^ expected one of `:` or `@` here
+   |
+   = note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
+help: if this was a parameter name, give it a type
+   |
+LL | fn foo(Option<i32>, String: TypeName) {}
+   |                     ^^^^^^^^^^^^^^^^
+help: if this is a type, explicitly ignore the parameter name
+   |
+LL | fn foo(Option<i32>, _: String) {}
+   |                     ^^^^^^^^^
 
 error: expected one of `:` or `@`, found `,`
   --> $DIR/issue-34264.rs:3:9
    |
 LL | fn bar(x, y: usize) {}
    |         ^ expected one of `:` or `@` here
+   |
+   = note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
+help: if this was a parameter name, give it a type
+   |
+LL | fn bar(x: TypeName, y: usize) {}
+   |        ^^^^^^^^^^^
+help: if this is a type, explicitly ignore the parameter name
+   |
+LL | fn bar(_: x, y: usize) {}
+   |        ^^^^
 
 error[E0061]: this function takes 2 parameters but 3 parameters were supplied
   --> $DIR/issue-34264.rs:7:5
index 8923de5705b18c0f06e15c1601b7c5de08685757..04c2870d8329740c841dcfda86e97ce2eb01f8ac 100644 (file)
@@ -1,8 +1,8 @@
-error[E0282]: type annotations needed
+error[E0282]: type annotations needed for `std::option::Option<_>`
   --> $DIR/issue-42234-unknown-receiver-type.rs:7:5
    |
 LL |     let x: Option<_> = None;
-   |         - consider giving `x` a type
+   |         - consider giving `x` the explicit type `std::option::Option<_>`, where the type parameter `T` is specified
 LL |     x.unwrap().method_that_could_exist_on_some_type();
    |     ^^^^^^^^^^ cannot infer type for `T`
    |
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 17be67c6c3a0dc02553d795b2b78943cffc99a00..8edec6e0ea3fd0a662a705e601d15ffae563f783 100644 (file)
@@ -1,10 +1,10 @@
-error[E0282]: type annotations needed
+error[E0282]: type annotations needed for `[_; 0]`
   --> $DIR/cannot_infer_local_or_array.rs:2:13
    |
 LL |     let x = [];
    |         -   ^^ cannot infer type
    |         |
-   |         consider giving `x` a type
+   |         consider giving `x` the explicit type `[_; 0]`, with the type parameters specified
 
 error: aborting due to previous error
 
index 8215947d49cdd5a558f5f197592492b5aeea826e..6524bf5dd2bc52c81b4481cafd6179fc17e8f269 100644 (file)
@@ -1,10 +1,10 @@
-error[E0282]: type annotations needed
+error[E0282]: type annotations needed for `std::vec::Vec<T>`
   --> $DIR/cannot_infer_local_or_vec.rs:2:13
    |
 LL |     let x = vec![];
    |         -   ^^^^^^ cannot infer type for `T`
    |         |
-   |         consider giving `x` a type
+   |         consider giving `x` the explicit type `std::vec::Vec<T>`, where the type parameter `T` is specified
    |
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
index 1065d49c26b2dd2cd6395a2bc2f2bdc5a2c9cc8d..6d1ef240da60c03cb3461fa84deab1c7646cf603 100644 (file)
@@ -1,10 +1,10 @@
-error[E0282]: type annotations needed
+error[E0282]: type annotations needed for `(std::vec::Vec<T>,)`
   --> $DIR/cannot_infer_local_or_vec_in_tuples.rs:2:18
    |
 LL |     let (x, ) = (vec![], );
    |         -----    ^^^^^^ cannot infer type for `T`
    |         |
-   |         consider giving the pattern a type
+   |         consider giving this pattern the explicit type `(std::vec::Vec<T>,)`, where the type parameter `T` is specified
    |
    = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
 
index bd58e241f0cb00e40d73fe5f831034555ee199b7..18af3dc640d1c9108d00ec31812d15992c1b2d41 100644 (file)
@@ -1,8 +1,8 @@
-error[E0282]: type annotations needed
+error[E0282]: type annotations needed for `std::option::Option<T>`
   --> $DIR/unboxed-closures-failed-recursive-fn-2.rs:16:32
    |
 LL |     let mut closure0 = None;
-   |         ------------ consider giving `closure0` a type
+   |         ------------ consider giving `closure0` the explicit type `std::option::Option<T>`, with the type parameters specified
 ...
 LL |                         return c();
    |                                ^^^ cannot infer type
index 654f4285f655f90e88192c3dc8701f1ce423cefc..ef9e7e39df0bcf593918664cb827b08c55c35ec2 100644 (file)
@@ -30,7 +30,7 @@ error[E0106]: missing lifetime specifier
 LL | fn foo2(_: &'_ u8, y: &'_ u8) -> &'_ u8 { y }
    |                                   ^^ expected lifetime parameter
    |
-   = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `_` or `y`
+   = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or `y`
 
 error: aborting due to 5 previous errors
 
index 200364a5d937ee755c560ca97c7c89601c9029c1..1f11d9c8dffc7e044eecf357059b4b7b77c8a744 100644 (file)
@@ -1,4 +1,4 @@
 fn main() {
     let _foo = Vec::new();
-    //~^ ERROR type annotations needed [E0282]
+    //~^ ERROR type annotations needed
 }
index 01b569f97f91073b83ecdc8a3d5bd55eb79c6544..28100d7c89e71e6e8e091e5617a272846bd29d2b 100644 (file)
@@ -1,10 +1,10 @@
-error[E0282]: type annotations needed
+error[E0282]: type annotations needed for `std::vec::Vec<T>`
   --> $DIR/vector-no-ann.rs:2:16
    |
 LL |     let _foo = Vec::new();
    |         ----   ^^^^^^^^ cannot infer type for `T`
    |         |
-   |         consider giving `_foo` a type
+   |         consider giving `_foo` the explicit type `std::vec::Vec<T>`, where the type parameter `T` is specified
 
 error: aborting due to previous error
 
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"),
index 837be69f7caddff7834166ed1eaf7bfee410f659..d4a6cf73bf98c2cae7ab5bb4dbcd8779cc965a7d 100644 (file)
@@ -204,7 +204,7 @@ fn parse_cfgs<'a>(contents: &'a str) -> Vec<(usize, &'a str)> {
         succeeds_non_ident && preceeds_whitespace_and_paren
     });
 
-    cfgs.map(|i| {
+    cfgs.flat_map(|i| {
         let mut depth = 0;
         let contents_from = &contents[i..];
         for (j, byte) in contents_from.bytes().enumerate() {
@@ -215,13 +215,15 @@ fn parse_cfgs<'a>(contents: &'a str) -> Vec<(usize, &'a str)> {
                 b')' => {
                     depth -= 1;
                     if depth == 0 {
-                        return (i, &contents_from[..=j]);
+                        return Some((i, &contents_from[..=j]));
                     }
                 }
                 _ => { }
             }
         }
 
-        unreachable!()
+        // if the parentheses are unbalanced just ignore this cfg -- it'll be caught when attempting
+        // to run the compiler, and there's no real reason to lint it separately here
+        None
     }).collect()
 }