]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #54813 - petrochenkov:uilocale, r=alexcrichton
authorbors <bors@rust-lang.org>
Sun, 7 Oct 2018 11:10:39 +0000 (11:10 +0000)
committerbors <bors@rust-lang.org>
Sun, 7 Oct 2018 11:10:39 +0000 (11:10 +0000)
Fix two UI tests with locale-dependent output

Closes https://github.com/rust-lang/rust/issues/54719

379 files changed:
CONTRIBUTING.md
src/Cargo.lock
src/doc/unstable-book/src/language-features/lang-items.md
src/liballoc/collections/vec_deque.rs
src/liballoc/rc.rs
src/liballoc/sync.rs
src/liballoc/vec.rs
src/libcore/lib.rs
src/libcore/sync/atomic.rs
src/libfmt_macros/lib.rs
src/libpanic_abort/lib.rs
src/librustc/hir/def.rs
src/librustc/hir/intravisit.rs
src/librustc/hir/lowering.rs
src/librustc/hir/mod.rs
src/librustc/hir/print.rs
src/librustc/ich/impls_hir.rs
src/librustc/ich/impls_mir.rs
src/librustc/ich/impls_ty.rs
src/librustc/infer/canonical/canonicalizer.rs
src/librustc/infer/combine.rs
src/librustc/infer/error_reporting/mod.rs
src/librustc/infer/freshen.rs
src/librustc/infer/higher_ranked/README.md
src/librustc/infer/higher_ranked/mod.rs
src/librustc/infer/lexical_region_resolve/mod.rs
src/librustc/infer/mod.rs
src/librustc/infer/region_constraints/mod.rs
src/librustc/middle/dead.rs
src/librustc/middle/dependency_format.rs
src/librustc/middle/entry.rs
src/librustc/middle/exported_symbols.rs
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/intrinsicck.rs
src/librustc/middle/lang_items.rs
src/librustc/middle/lib_features.rs
src/librustc/middle/liveness.rs
src/librustc/middle/mem_categorization.rs
src/librustc/middle/reachable.rs
src/librustc/middle/region.rs
src/librustc/middle/resolve_lifetime.rs
src/librustc/middle/stability.rs
src/librustc/middle/weak_lang_items.rs
src/librustc/mir/interpret/value.rs
src/librustc/mir/mod.rs
src/librustc/mir/mono.rs
src/librustc/mir/tcx.rs
src/librustc/mir/visit.rs
src/librustc/traits/coherence.rs
src/librustc/traits/error_reporting.rs
src/librustc/traits/project.rs
src/librustc/traits/query/dropck_outlives.rs
src/librustc/traits/select.rs
src/librustc/traits/specialize/mod.rs
src/librustc/ty/codec.rs
src/librustc/ty/context.rs
src/librustc/ty/error.rs
src/librustc/ty/fast_reject.rs
src/librustc/ty/flags.rs
src/librustc/ty/fold.rs
src/librustc/ty/inhabitedness/def_id_forest.rs
src/librustc/ty/instance.rs
src/librustc/ty/item_path.rs
src/librustc/ty/layout.rs
src/librustc/ty/mod.rs
src/librustc/ty/outlives.rs
src/librustc/ty/query/config.rs
src/librustc/ty/query/job.rs
src/librustc/ty/query/mod.rs
src/librustc/ty/query/on_disk_cache.rs
src/librustc/ty/query/plumbing.rs
src/librustc/ty/relate.rs
src/librustc/ty/structural_impls.rs
src/librustc/ty/sty.rs
src/librustc/ty/subst.rs
src/librustc/ty/trait_def.rs
src/librustc/ty/util.rs
src/librustc/ty/walk.rs
src/librustc/ty/wf.rs
src/librustc/util/ppaux.rs
src/librustc_borrowck/borrowck/check_loans.rs
src/librustc_borrowck/borrowck/gather_loans/mod.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_borrowck/borrowck/unused.rs
src/librustc_codegen_llvm/back/linker.rs
src/librustc_codegen_llvm/debuginfo/type_names.rs
src/librustc_codegen_llvm/mir/block.rs
src/librustc_lint/builtin.rs
src/librustc_lint/lib.rs
src/librustc_lint/types.rs
src/librustc_lint/unused.rs
src/librustc_mir/borrow_check/error_reporting.rs
src/librustc_mir/borrow_check/mod.rs
src/librustc_mir/borrow_check/move_errors.rs
src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
src/librustc_mir/borrow_check/nll/invalidation.rs
src/librustc_mir/borrow_check/nll/mod.rs
src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs
src/librustc_mir/borrow_check/nll/region_infer/mod.rs
src/librustc_mir/borrow_check/nll/region_infer/values.rs
src/librustc_mir/borrow_check/nll/type_check/mod.rs
src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs
src/librustc_mir/build/block.rs
src/librustc_mir/build/expr/as_temp.rs
src/librustc_mir/build/expr/into.rs
src/librustc_mir/build/expr/stmt.rs
src/librustc_mir/build/matches/mod.rs
src/librustc_mir/build/matches/test.rs
src/librustc_mir/build/mod.rs
src/librustc_mir/dataflow/mod.rs
src/librustc_mir/dataflow/move_paths/builder.rs
src/librustc_mir/hair/cx/expr.rs
src/librustc_mir/hair/mod.rs
src/librustc_mir/interpret/memory.rs
src/librustc_mir/monomorphize/item.rs
src/librustc_mir/shim.rs
src/librustc_mir/transform/generator.rs
src/librustc_mir/transform/lower_128bit.rs
src/librustc_mir/transform/promote_consts.rs
src/librustc_mir/transform/qualify_min_const_fn.rs
src/librustc_mir/util/elaborate_drops.rs
src/librustc_resolve/Cargo.toml
src/librustc_resolve/lib.rs
src/librustc_resolve/macros.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_traits/dropck_outlives.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/cast.rs
src/librustc_typeck/check/compare_method.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/outlives/utils.rs
src/librustc_typeck/variance/constraints.rs
src/librustdoc/clean/mod.rs
src/librustdoc/html/static/rustdoc.css
src/libstd/error.rs
src/libstd/lib.rs
src/libstd/panicking.rs
src/libstd/sync/mod.rs
src/libstd/sys/wasm/condvar_atomics.rs [new file with mode: 0644]
src/libstd/sys/wasm/mod.rs
src/libstd/sys/wasm/mutex_atomics.rs [new file with mode: 0644]
src/libstd/sys/wasm/rwlock_atomics.rs [new file with mode: 0644]
src/libstd/sys/wasm/thread.rs
src/libstd/sys/wasm/thread_local_atomics.rs [new file with mode: 0644]
src/libsyntax/ext/expand.rs
src/libsyntax/feature_gate.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pprust.rs
src/libsyntax_ext/test.rs
src/stdsimd
src/test/codegen/export-no-mangle.rs [new file with mode: 0644]
src/test/codegen/external-no-mangle-fns.rs [new file with mode: 0644]
src/test/codegen/external-no-mangle-statics.rs [new file with mode: 0644]
src/test/codegen/issue-44056-macos-tls-align.rs
src/test/codegen/lto-removes-invokes.rs
src/test/compile-fail-fulldeps/proc-macro/attr-invalid-exprs.rs
src/test/compile-fail-fulldeps/proc-macro/attr-stmt-expr.rs
src/test/compile-fail-fulldeps/proc-macro/lints_in_proc_macros.rs
src/test/compile-fail-fulldeps/proc-macro/proc-macro-gates.rs
src/test/parse-fail/duplicate-visibility.rs
src/test/pretty/issue-54752-async-block.rs [new file with mode: 0644]
src/test/run-make-fulldeps/extern-fn-reachable/main.rs
src/test/run-make/thumb-none-cortex-m/Makefile
src/test/run-make/wasm-export-all-symbols/Makefile [new file with mode: 0644]
src/test/run-make/wasm-export-all-symbols/bar.rs [new file with mode: 0644]
src/test/run-make/wasm-export-all-symbols/foo.rs [new file with mode: 0644]
src/test/run-make/wasm-export-all-symbols/verify.js [new file with mode: 0644]
src/test/run-pass-fulldeps/auxiliary/cond_plugin.rs
src/test/run-pass-fulldeps/auxiliary/hello_macro.rs
src/test/run-pass-fulldeps/auxiliary/linkage-visibility.rs
src/test/run-pass-fulldeps/auxiliary/proc_macro_def.rs
src/test/run-pass-fulldeps/macro-crate.rs
src/test/run-pass-fulldeps/macro-quote-cond.rs
src/test/run-pass-fulldeps/macro-quote-test.rs
src/test/run-pass-fulldeps/proc-macro/attr-stmt-expr.rs
src/test/run-pass-fulldeps/proc-macro/auxiliary/count_compound_ops.rs
src/test/run-pass-fulldeps/proc-macro/auxiliary/hygiene_example_codegen.rs
src/test/run-pass-fulldeps/proc-macro/bang-macro.rs
src/test/run-pass-fulldeps/proc-macro/call-site.rs
src/test/run-pass-fulldeps/proc-macro/count_compound_ops.rs
src/test/run-pass-fulldeps/proc-macro/hygiene_example.rs
src/test/run-pass-fulldeps/proc-macro/negative-token.rs
src/test/run-pass-fulldeps/proc_macro.rs
src/test/run-pass/issues/issue-33992.rs
src/test/run-pass/project-cache-issue-37154.rs
src/test/ui-fulldeps/attribute-order-restricted.rs
src/test/ui-fulldeps/attribute-order-restricted.stderr
src/test/ui-fulldeps/lifetimes.rs
src/test/ui-fulldeps/proc-macro/macro-use-bang.rs
src/test/ui-fulldeps/proc-macro/multispan.rs
src/test/ui-fulldeps/proc-macro/parent-source-spans.rs
src/test/ui-fulldeps/proc-macro/three-equals.rs
src/test/ui/E0501.ast.nll.stderr
src/test/ui/E0501.mir.stderr
src/test/ui/binop/binop-move-semantics.nll.stderr
src/test/ui/borrowck/borrow-tuple-fields.nll.stderr
src/test/ui/borrowck/borrowck-anon-fields-struct.nll.stderr
src/test/ui/borrowck/borrowck-anon-fields-tuple.nll.stderr
src/test/ui/borrowck/borrowck-anon-fields-variant.nll.stderr
src/test/ui/borrowck/borrowck-assign-comp-idx.nll.stderr
src/test/ui/borrowck/borrowck-autoref-3261.nll.stderr
src/test/ui/borrowck/borrowck-bad-nested-calls-free.nll.stderr
src/test/ui/borrowck/borrowck-bad-nested-calls-move.nll.stderr
src/test/ui/borrowck/borrowck-borrow-from-owned-ptr.nll.stderr
src/test/ui/borrowck/borrowck-borrow-from-stack-variable.nll.stderr
src/test/ui/borrowck/borrowck-borrow-mut-base-ptr-in-aliasable-loc.nll.stderr
src/test/ui/borrowck/borrowck-borrow-mut-object-twice.nll.stderr
src/test/ui/borrowck/borrowck-closures-mut-and-imm.ast.nll.stderr
src/test/ui/borrowck/borrowck-closures-mut-and-imm.mir.stderr
src/test/ui/borrowck/borrowck-closures-two-mut-fail.nll.stderr
src/test/ui/borrowck/borrowck-closures-two-mut.stderr
src/test/ui/borrowck/borrowck-closures-unique-imm.nll.stderr
src/test/ui/borrowck/borrowck-closures-unique.nll.stderr
src/test/ui/borrowck/borrowck-closures-use-after-free.nll.stderr
src/test/ui/borrowck/borrowck-describe-lvalue.ast.nll.stderr
src/test/ui/borrowck/borrowck-describe-lvalue.mir.stderr
src/test/ui/borrowck/borrowck-field-sensitivity.nll.stderr
src/test/ui/borrowck/borrowck-for-loop-head-linkage.nll.stderr
src/test/ui/borrowck/borrowck-insert-during-each.nll.stderr
src/test/ui/borrowck/borrowck-lend-flow-if.nll.stderr
src/test/ui/borrowck/borrowck-lend-flow-loop.nll.stderr
src/test/ui/borrowck/borrowck-lend-flow.nll.stderr
src/test/ui/borrowck/borrowck-loan-blocks-mut-uniq.nll.stderr
src/test/ui/borrowck/borrowck-loan-rcvr-overloaded-op.nll.stderr
src/test/ui/borrowck/borrowck-loan-rcvr.nll.stderr
src/test/ui/borrowck/borrowck-loan-vec-content.nll.stderr
src/test/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.ast.nll.stderr [new file with mode: 0644]
src/test/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.mir.stderr
src/test/ui/borrowck/borrowck-move-out-of-overloaded-deref.nll.stderr
src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.ast.nll.stderr
src/test/ui/borrowck/borrowck-mut-borrow-linear-errors.mir.stderr
src/test/ui/borrowck/borrowck-mut-borrow-of-mut-base-ptr.nll.stderr
src/test/ui/borrowck/borrowck-object-lifetime.nll.stderr
src/test/ui/borrowck/borrowck-overloaded-index-autoderef.nll.stderr
src/test/ui/borrowck/borrowck-overloaded-index-ref-index.ast.nll.stderr
src/test/ui/borrowck/borrowck-overloaded-index-ref-index.mir.stderr
src/test/ui/borrowck/borrowck-report-with-custom-diagnostic.nll.stderr
src/test/ui/borrowck/borrowck-slice-pattern-element-loan.stderr
src/test/ui/borrowck/borrowck-swap-mut-base-ptr.nll.stderr
src/test/ui/borrowck/borrowck-union-borrow.ast.nll.stderr
src/test/ui/borrowck/borrowck-union-borrow.mir.stderr
src/test/ui/borrowck/borrowck-uniq-via-lend.nll.stderr
src/test/ui/borrowck/borrowck-vec-pattern-loan-from-mut.nll.stderr
src/test/ui/borrowck/issue-51117.nll.stderr
src/test/ui/borrowck/mut-borrow-in-loop.nll.stderr
src/test/ui/borrowck/mut-borrow-outside-loop.nll.stderr
src/test/ui/borrowck/two-phase-activation-sharing-interference.nll_target.stderr
src/test/ui/borrowck/two-phase-cannot-nest-mut-self-calls.stderr
src/test/ui/borrowck/two-phase-multi-mut.stderr
src/test/ui/borrowck/two-phase-nonrecv-autoref.ast.nll.stderr
src/test/ui/borrowck/two-phase-nonrecv-autoref.nll.stderr
src/test/ui/borrowck/two-phase-reservation-sharing-interference.nll_target.stderr
src/test/ui/borrowck/two-phase-sneaky.nll.stderr
src/test/ui/borrowck/two-phase-surprise-no-conflict.nll.stderr
src/test/ui/borrowck/two-phase-surprise-no-conflict.no2pb.stderr
src/test/ui/chalkify/lower_env1.stderr
src/test/ui/codemap_tests/issue-11715.nll.stderr
src/test/ui/codemap_tests/one_line.nll.stderr
src/test/ui/coercion/coerce-overloaded-autoderef.ast.nll.stderr
src/test/ui/coercion/coerce-overloaded-autoderef.mir.nll.stderr
src/test/ui/coercion/coerce-overloaded-autoderef.mir.stderr
src/test/ui/did_you_mean/issue-34126.nll.stderr
src/test/ui/dropck/dropck-eyepatch-extern-crate.nll.stderr
src/test/ui/dropck/dropck-eyepatch-reorder.nll.stderr
src/test/ui/dropck/dropck-eyepatch.nll.stderr
src/test/ui/dropck/dropck-union.nll.stderr
src/test/ui/error-codes/E0499.nll.stderr
src/test/ui/error-codes/E0502.nll.stderr
src/test/ui/error-codes/E0597.nll.stderr
src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.rs
src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr
src/test/ui/generator/borrowing.nll.stderr
src/test/ui/generator/dropck.nll.stderr
src/test/ui/generator/yield-while-iterating.nll.stderr
src/test/ui/generator/yield-while-ref-reborrowed.nll.stderr
src/test/ui/hashmap-iter-value-lifetime.nll.stderr
src/test/ui/hashmap-lifetimes.nll.stderr
src/test/ui/hrtb/hrtb-debruijn-in-receiver.nll.stderr
src/test/ui/hygiene/fields-numeric-borrowck.nll.stderr
src/test/ui/if/ifmt-bad-arg.rs
src/test/ui/if/ifmt-bad-arg.stderr
src/test/ui/impl-trait/deprecated_annotation.rs [new file with mode: 0644]
src/test/ui/imports/shadow_builtin_macros.stderr
src/test/ui/issues/issue-11192.nll.stderr
src/test/ui/issues/issue-13058.nll.stderr
src/test/ui/issues/issue-13058.rs
src/test/ui/issues/issue-13058.stderr
src/test/ui/issues/issue-18566.nll.stderr
src/test/ui/issues/issue-18783.nll.stderr
src/test/ui/issues/issue-24338.rs [new file with mode: 0644]
src/test/ui/issues/issue-25793.nll.stderr
src/test/ui/issues/issue-28134.rs [new file with mode: 0644]
src/test/ui/issues/issue-28134.stderr [new file with mode: 0644]
src/test/ui/issues/issue-29743.rs [new file with mode: 0644]
src/test/ui/issues/issue-42106.nll.stderr
src/test/ui/issues/issue-45157.stderr
src/test/ui/issues/issue-47646.stderr
src/test/ui/lint/lint-unexported-no-mangle.rs
src/test/ui/lint/lint-unexported-no-mangle.stderr
src/test/ui/lint/suggestions.rs
src/test/ui/lint/suggestions.stderr
src/test/ui/macros/issue-54441.rs [new file with mode: 0644]
src/test/ui/macros/issue-54441.stderr [new file with mode: 0644]
src/test/ui/methods/method-self-arg-2.nll.stderr
src/test/ui/moves/moves-based-on-type-no-recursive-stack-closure.nll.stderr
src/test/ui/mut/mut-cant-alias.nll.stderr
src/test/ui/mut/no-mut-lint-for-desugared-mut.rs [new file with mode: 0644]
src/test/ui/nll/borrowed-local-error.stderr
src/test/ui/nll/borrowed-referent-issue-38899.stderr
src/test/ui/nll/closure-access-spans.stderr
src/test/ui/nll/closure-borrow-spans.stderr
src/test/ui/nll/drop-no-may-dangle.stderr
src/test/ui/nll/get_default.nll.stderr
src/test/ui/nll/get_default.stderr
src/test/ui/nll/issue-21114-ebfull.rs [new file with mode: 0644]
src/test/ui/nll/issue-21114-kixunil.rs [new file with mode: 0644]
src/test/ui/nll/issue-32382-index-assoc-type-with-lifetime.rs [new file with mode: 0644]
src/test/ui/nll/issue-51268.stderr
src/test/ui/nll/issue-52086.rs [new file with mode: 0644]
src/test/ui/nll/issue-52086.stderr [new file with mode: 0644]
src/test/ui/nll/issue-54556-niconii.nll.stderr [new file with mode: 0644]
src/test/ui/nll/issue-54556-niconii.rs [new file with mode: 0644]
src/test/ui/nll/issue-54556-niconii.stderr [new file with mode: 0644]
src/test/ui/nll/issue-54556-stephaneyfx.nll.stderr [new file with mode: 0644]
src/test/ui/nll/issue-54556-stephaneyfx.rs [new file with mode: 0644]
src/test/ui/nll/issue-54556-stephaneyfx.stderr [new file with mode: 0644]
src/test/ui/nll/issue-54556-temps-in-tail-diagnostic.nll.stderr [new file with mode: 0644]
src/test/ui/nll/issue-54556-temps-in-tail-diagnostic.rs [new file with mode: 0644]
src/test/ui/nll/issue-54556-temps-in-tail-diagnostic.stderr [new file with mode: 0644]
src/test/ui/nll/issue-54556-used-vs-unused-tails.nll.stderr [new file with mode: 0644]
src/test/ui/nll/issue-54556-used-vs-unused-tails.rs [new file with mode: 0644]
src/test/ui/nll/issue-54556-used-vs-unused-tails.stderr [new file with mode: 0644]
src/test/ui/nll/issue-54556-wrap-it-up.nll.stderr [new file with mode: 0644]
src/test/ui/nll/issue-54556-wrap-it-up.rs [new file with mode: 0644]
src/test/ui/nll/issue-54556-wrap-it-up.stderr [new file with mode: 0644]
src/test/ui/nll/loan_ends_mid_block_vec.stderr
src/test/ui/nll/maybe-initialized-drop-implicit-fragment-drop.stderr
src/test/ui/nll/maybe-initialized-drop-with-fragment.stderr
src/test/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.stderr
src/test/ui/nll/maybe-initialized-drop.stderr
src/test/ui/nll/move-errors.stderr
src/test/ui/nll/region-ends-after-if-condition.nll.stderr
src/test/ui/nll/region-ends-after-if-condition.stderr
src/test/ui/nll/return_from_loop.stderr
src/test/ui/parser/inverted-parameters.rs [new file with mode: 0644]
src/test/ui/parser/inverted-parameters.stderr [new file with mode: 0644]
src/test/ui/privacy/private-type-in-interface.rs
src/test/ui/privacy/private-type-in-interface.stderr
src/test/ui/regions/region-bound-on-closure-outlives-call.nll.stderr
src/test/ui/regions/regions-adjusted-lvalue-op.nll.stderr
src/test/ui/rfc-2005-default-binding-mode/borrowck-issue-49631.nll.stderr
src/test/ui/span/borrowck-call-is-borrow-issue-12224.nll.stderr
src/test/ui/span/destructor-restrictions.nll.stderr
src/test/ui/span/dropck-object-cycle.nll.stderr
src/test/ui/span/dropck_arr_cycle_checked.nll.stderr
src/test/ui/span/dropck_direct_cycle_with_drop.nll.stderr
src/test/ui/span/dropck_misc_variants.nll.stderr
src/test/ui/span/dropck_vec_cycle_checked.nll.stderr
src/test/ui/span/issue-23338-locals-die-before-temps-of-body.nll.stderr
src/test/ui/span/issue-24805-dropck-child-has-items-via-parent.nll.stderr
src/test/ui/span/issue-24805-dropck-trait-has-items.nll.stderr
src/test/ui/span/issue-24895-copy-clone-dropck.nll.stderr
src/test/ui/span/issue-25199.nll.stderr
src/test/ui/span/issue-26656.nll.stderr
src/test/ui/span/issue-29106.nll.stderr
src/test/ui/span/issue28498-reject-ex1.nll.stderr
src/test/ui/span/issue28498-reject-lifetime-param.nll.stderr
src/test/ui/span/issue28498-reject-passed-to-fn.nll.stderr
src/test/ui/span/issue28498-reject-trait-bound.nll.stderr
src/test/ui/span/regions-close-over-borrowed-ref-in-obj.nll.stderr
src/test/ui/span/send-is-not-static-std-sync.nll.stderr
src/test/ui/span/vec-must-not-hide-type-from-dropck.nll.stderr
src/test/ui/span/vec_refs_data_with_early_death.nll.stderr
src/test/ui/unboxed-closures/unboxed-closures-failed-recursive-fn-1.nll.stderr
src/test/ui/unboxed-closures/unboxed-closures-recursive-fn-using-fn-mut.nll.stderr
src/test/ui/vec/vec-mut-iter-borrow.nll.stderr
src/tools/cargotest/main.rs
src/tools/clippy
src/tools/rustc-workspace-hack/Cargo.toml

index 2e51a786f46826a52e936179dd612fad91357657..49961d02ddab7731d835b059ed7459b75bb52e3e 100644 (file)
@@ -566,7 +566,7 @@ labels to triage issues:
   to fix the issue.
 
 * The dark blue **final-comment-period** label marks bugs that are using the
-  RFC signoff functionality of [rfcbot][rfcbot] and are currenty in the final
+  RFC signoff functionality of [rfcbot][rfcbot] and are currently in the final
   comment period.
 
 * Red, **I**-prefixed labels indicate the **importance** of the issue. The
index 926016e5f02628208b47c88ed395757d3efeb8a3..6a9488226b1bdc61a35479268dcce8fee9cfaf16 100644 (file)
@@ -2074,6 +2074,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 name = "rustc-workspace-hack"
 version = "1.0.0"
 dependencies = [
+ "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.31 (registry+https://github.com/rust-lang/crates.io-index)",
  "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
@@ -2386,6 +2388,7 @@ name = "rustc_resolve"
 version = "0.0.0"
 dependencies = [
  "arena 0.0.0",
+ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc 0.0.0",
  "rustc_data_structures 0.0.0",
index bac619fd4a30d2c17e50d45415d55d1ef42600d6..b16739b4743a9ebb0070527216419f6388da4fb3 100644 (file)
@@ -311,3 +311,5 @@ the source code.
   - `freeze`: `libcore/marker.rs`
   - `debug_trait`: `libcore/fmt/mod.rs`
   - `non_zero`: `libcore/nonzero.rs`
+  - `arc`: `liballoc/sync.rs`
+  - `rc`: `liballoc/rc.rs`
index c53549ab85d6d5aa075e9f0e168f0d4e512ae206..571f35a2031d2a0b9e1eb57ac1f9728ca2fb245f 100644 (file)
@@ -19,7 +19,6 @@
 
 use core::cmp::Ordering;
 use core::fmt;
-use core::isize;
 use core::iter::{repeat, FromIterator, FusedIterator};
 use core::mem;
 use core::ops::Bound::{Excluded, Included, Unbounded};
@@ -203,33 +202,6 @@ unsafe fn copy_nonoverlapping(&self, dst: usize, src: usize, len: usize) {
                                  len);
     }
 
-    /// Copies all values from `src` to the back of `self`, wrapping around if needed.
-    ///
-    /// # Safety
-    ///
-    /// The capacity must be sufficient to hold self.len() + src.len() elements.
-    /// If so, this function never panics.
-    #[inline]
-    unsafe fn copy_slice(&mut self, src: &[T]) {
-        /// This is guaranteed by `RawVec`.
-        debug_assert!(self.capacity() <= isize::MAX as usize);
-
-        let expected_new_len = self.len() + src.len();
-        debug_assert!(self.capacity() >= expected_new_len);
-
-        let dst_high_ptr = self.ptr().add(self.head);
-        let dst_high_len = self.cap() - self.head;
-
-        let split = cmp::min(src.len(), dst_high_len);
-        let (src_high, src_low) = src.split_at(split);
-
-        ptr::copy_nonoverlapping(src_high.as_ptr(), dst_high_ptr, src_high.len());
-        ptr::copy_nonoverlapping(src_low.as_ptr(), self.ptr(), src_low.len());
-
-        self.head = self.wrap_add(self.head, src.len());
-        debug_assert!(self.len() == expected_new_len);
-    }
-
     /// Copies a potentially wrapping block of memory len long from src to dest.
     /// (abs(dst - src) + len) must be no larger than cap() (There must be at
     /// most one continuous overlapping region between src and dest).
@@ -1052,7 +1024,7 @@ pub fn drain<R>(&mut self, range: R) -> Drain<T>
             iter: Iter {
                 tail: drain_tail,
                 head: drain_head,
-                ring: unsafe { self.buffer_as_slice() },
+                ring: unsafe { self.buffer_as_mut_slice() },
             },
         }
     }
@@ -1862,22 +1834,8 @@ pub fn split_off(&mut self, at: usize) -> Self {
     #[inline]
     #[stable(feature = "append", since = "1.4.0")]
     pub fn append(&mut self, other: &mut Self) {
-        unsafe {
-            // Guarantees there is space in `self` for `other`.
-            self.reserve(other.len());
-
-            {
-                let (src_high, src_low) = other.as_slices();
-
-                // This is only safe because copy_slice never panics when capacity is sufficient.
-                self.copy_slice(src_low);
-                self.copy_slice(src_high);
-            }
-
-            // Some values now exist in both `other` and `self` but are made inaccessible
-            // in`other`.
-            other.tail = other.head;
-        }
+        // naive impl
+        self.extend(other.drain(..));
     }
 
     /// Retains only the elements specified by the predicate.
@@ -2635,8 +2593,8 @@ fn from(other: VecDeque<T>) -> Self {
                         let mut right_offset = 0;
                         for i in left_edge..right_edge {
                             right_offset = (i - left_edge) % (cap - right_edge);
-                            let src = right_edge + right_offset;
-                            ptr::swap(buf.add(i), buf.add(src));
+                            let src: isize = (right_edge + right_offset) as isize;
+                            ptr::swap(buf.add(i), buf.offset(src));
                         }
                         let n_ops = right_edge - left_edge;
                         left_edge += n_ops;
index 9d951691a34e76b4847498e18649ee5cb0746159..915b8e7787e998d0d12fb19147172675cda8a236 100644 (file)
@@ -282,6 +282,7 @@ struct RcBox<T: ?Sized> {
 /// type `T`.
 ///
 /// [get_mut]: #method.get_mut
+#[cfg_attr(all(not(stage0), not(test)), lang = "rc")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Rc<T: ?Sized> {
     ptr: NonNull<RcBox<T>>,
index 116393bdad195b54375dcba6e8266af802bc4386..9e245fbd7bbe563595a72054a70f69ed72a5dffe 100644 (file)
 /// counting in general.
 ///
 /// [rc_examples]: ../../std/rc/index.html#examples
+#[cfg_attr(all(not(stage0), not(test)), lang = "arc")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Arc<T: ?Sized> {
     ptr: NonNull<ArcInner<T>>,
index e845438c0a836972d56a39c72cd7f897e6a1e626..2bc037e3fee126343715212911c8b62e1d28867e 100644 (file)
@@ -1822,12 +1822,12 @@ impl<T, I> SpecExtend<T, I> for Vec<T>
             unsafe {
                 let mut ptr = self.as_mut_ptr().add(self.len());
                 let mut local_len = SetLenOnDrop::new(&mut self.len);
-                for element in iterator {
+                iterator.for_each(move |element| {
                     ptr::write(ptr, element);
                     ptr = ptr.offset(1);
                     // NB can't overflow since we would have had to alloc the address space
                     local_len.increment_len(1);
-                }
+                });
             }
         } else {
             self.extend_desugared(iterator)
index 184ed19da952477062ec3f1ca514139518e1b71c..59cc312bee5fcc4064751bca256ed75592fa31ea 100644 (file)
 #![feature(powerpc_target_feature)]
 #![feature(mips_target_feature)]
 #![feature(aarch64_target_feature)]
+#![feature(wasm_target_feature)]
 #![feature(const_slice_len)]
 #![feature(const_str_as_bytes)]
 #![feature(const_str_len)]
index 69c524925fc546e9d82f9f1a9aab80cba7e504bc..f130dbfb0e3dfea57259d2f89df93f6be11c00ab 100644 (file)
@@ -2251,7 +2251,15 @@ unsafe fn atomic_umin<T>(dst: *mut T, val: T, order: Ordering) -> T {
 /// [`Relaxed`]: enum.Ordering.html#variant.Relaxed
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(target_arch = "wasm32", allow(unused_variables))]
 pub fn fence(order: Ordering) {
+    // On wasm32 it looks like fences aren't implemented in LLVM yet in that
+    // they will cause LLVM to abort. The wasm instruction set doesn't have
+    // fences right now. There's discussion online about the best way for tools
+    // to conventionally implement fences at
+    // https://github.com/WebAssembly/tool-conventions/issues/59. We should
+    // follow that discussion and implement a solution when one comes about!
+    #[cfg(not(target_arch = "wasm32"))]
     unsafe {
         match order {
             Acquire => intrinsics::atomic_fence_acq(),
index 2a38464d7c1ee3ca742888d52669641cd5b567b3..7d87c1839d78c7059e9fe49d8dacb404964d2efe 100644 (file)
@@ -288,7 +288,7 @@ fn must_consume(&mut self, c: char) -> Option<usize> {
                 self.cur.next();
                 Some(pos)
             } else {
-                let pos = pos + padding + 1;
+                let pos = pos + raw + 1;
                 self.err(format!("expected `{:?}`, found `{:?}`", c, maybe),
                          format!("expected `{}`", c),
                          pos,
index cf05e56e53c8464e4e9a1c5dc11b824d7e234d06..b86928534cb244f79ccc09202963576208bf17fc 100644 (file)
@@ -96,9 +96,14 @@ unsafe fn abort() -> ! {
 // runtime at all.
 pub mod personalities {
     #[no_mangle]
-    #[cfg(not(all(target_os = "windows",
-                  target_env = "gnu",
-                  target_arch = "x86_64")))]
+    #[cfg(not(any(
+        target_arch = "wasm32",
+        all(
+            target_os = "windows",
+            target_env = "gnu",
+            target_arch = "x86_64",
+        ),
+    )))]
     pub extern fn rust_eh_personality() {}
 
     // On x86_64-pc-windows-gnu we use our own personality function that needs
index 4286b0628f5fff76f7054e69d74650287483850e..5d9d4deb0abc9e95793aa303ce1a621980cc0b1c 100644 (file)
@@ -36,6 +36,8 @@ pub enum NonMacroAttrKind {
     Tool,
     /// Single-segment custom attribute registered by a derive macro (`#[serde(default)]`).
     DeriveHelper,
+    /// Single-segment custom attriubte registered by a legacy plugin (`register_attribute`).
+    LegacyPluginHelper,
     /// Single-segment custom attribute not registered in any way (`#[my_attr]`).
     Custom,
 }
@@ -259,6 +261,7 @@ fn descr(self) -> &'static str {
             NonMacroAttrKind::Builtin => "built-in attribute",
             NonMacroAttrKind::Tool => "tool attribute",
             NonMacroAttrKind::DeriveHelper => "derive helper attribute",
+            NonMacroAttrKind::LegacyPluginHelper => "legacy plugin helper attribute",
             NonMacroAttrKind::Custom => "custom attribute",
         }
     }
index 76c2ebc0e4a0e36ab5265924e527fdee83bbb329..942f1cbd6651b63c2c6df2cd6482270bb83a218a 100644 (file)
@@ -603,6 +603,10 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
         TyKind::Path(ref qpath) => {
             visitor.visit_qpath(qpath, typ.hir_id, typ.span);
         }
+        TyKind::Def(item_id, ref lifetimes) => {
+            visitor.visit_nested_item(item_id);
+            walk_list!(visitor, visit_generic_arg, lifetimes);
+        }
         TyKind::Array(ref ty, ref length) => {
             visitor.visit_ty(ty);
             visitor.visit_anon_const(length)
index cd2e34ec78b10ec6e4b4dc11c4cb491c3b0197ca..7309358091056e32bc512e7536d5b0d05b6681fe 100644 (file)
@@ -1378,20 +1378,7 @@ fn lower_existential_impl_trait(
             lctx.items.insert(exist_ty_id.node_id, exist_ty_item);
 
             // `impl Trait` now just becomes `Foo<'a, 'b, ..>`
-            let path = P(hir::Path {
-                span: exist_ty_span,
-                def: Def::Existential(DefId::local(exist_ty_def_index)),
-                segments: hir_vec![hir::PathSegment {
-                    infer_types: false,
-                    ident: Ident::new(keywords::Invalid.name(), exist_ty_span),
-                    args: Some(P(hir::GenericArgs {
-                        parenthesized: false,
-                        bindings: HirVec::new(),
-                        args: lifetimes,
-                    }))
-                }],
-            });
-            hir::TyKind::Path(hir::QPath::Resolved(None, path))
+            hir::TyKind::Def(hir::ItemId { id: exist_ty_id.node_id }, lifetimes)
         })
     }
 
@@ -3262,23 +3249,6 @@ fn lower_mod(&mut self, m: &Mod) -> hir::Mod {
         }
     }
 
-    /// Lowers `impl Trait` items for a function and appends them to the list
-    fn lower_fn_impl_trait_ids(
-        &mut self,
-        decl: &FnDecl,
-        header: &FnHeader,
-        ids: &mut SmallVec<[hir::ItemId; 1]>,
-    ) {
-        if let Some(id) = header.asyncness.opt_return_id() {
-            ids.push(hir::ItemId { id });
-        }
-        let mut visitor = ImplTraitTypeIdVisitor { ids };
-        match decl.output {
-            FunctionRetTy::Default(_) => {},
-            FunctionRetTy::Ty(ref ty) => visitor.visit_ty(ty),
-        }
-    }
-
     fn lower_item_id(&mut self, i: &Item) -> SmallVec<[hir::ItemId; 1]> {
         match i.node {
             ItemKind::Use(ref use_tree) => {
@@ -3287,20 +3257,8 @@ fn lower_fn_impl_trait_ids(
                 vec
             }
             ItemKind::MacroDef(..) => SmallVec::new(),
-            ItemKind::Fn(ref decl, ref header, ..) => {
-                let mut ids = smallvec![hir::ItemId { id: i.id }];
-                self.lower_fn_impl_trait_ids(decl, header, &mut ids);
-                ids
-            },
-            ItemKind::Impl(.., None, _, ref items) => {
-                let mut ids = smallvec![hir::ItemId { id: i.id }];
-                for item in items {
-                    if let ImplItemKind::Method(ref sig, _) = item.node {
-                        self.lower_fn_impl_trait_ids(&sig.decl, &sig.header, &mut ids);
-                    }
-                }
-                ids
-            },
+            ItemKind::Fn(..) |
+            ItemKind::Impl(.., None, _, _) => smallvec![hir::ItemId { id: i.id }],
             ItemKind::Static(ref ty, ..) => {
                 let mut ids = smallvec![hir::ItemId { id: i.id }];
                 if self.sess.features_untracked().impl_trait_in_bindings {
@@ -4174,16 +4132,16 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                 // expand <head>
                 let head = self.lower_expr(head);
                 let head_sp = head.span;
+                let desugared_span = self.allow_internal_unstable(
+                    CompilerDesugaringKind::ForLoop,
+                    head_sp,
+                );
 
                 let iter = self.str_to_ident("iter");
 
                 let next_ident = self.str_to_ident("__next");
-                let next_sp = self.allow_internal_unstable(
-                    CompilerDesugaringKind::ForLoop,
-                    head_sp,
-                );
                 let next_pat = self.pat_ident_binding_mode(
-                    next_sp,
+                    desugared_span,
                     next_ident,
                     hir::BindingAnnotation::Mutable,
                 );
@@ -4212,8 +4170,11 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                 };
 
                 // `mut iter`
-                let iter_pat =
-                    self.pat_ident_binding_mode(head_sp, iter, hir::BindingAnnotation::Mutable);
+                let iter_pat = self.pat_ident_binding_mode(
+                    desugared_span,
+                    iter,
+                    hir::BindingAnnotation::Mutable
+                );
 
                 // `match ::std::iter::Iterator::next(&mut iter) { ... }`
                 let match_expr = {
@@ -4242,8 +4203,12 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                 let next_expr = P(self.expr_ident(head_sp, next_ident, next_pat.id));
 
                 // `let mut __next`
-                let next_let =
-                    self.stmt_let_pat(head_sp, None, next_pat, hir::LocalSource::ForLoopDesugar);
+                let next_let = self.stmt_let_pat(
+                    desugared_span,
+                    None,
+                    next_pat,
+                    hir::LocalSource::ForLoopDesugar,
+                );
 
                 // `let <pat> = __next`
                 let pat = self.lower_pat(pat);
index e2a9fd078a522acfbe0af29b5667c2971e236b37..c57c26434e32af38012a12d1554b05de6e93f83d 100644 (file)
@@ -1789,6 +1789,12 @@ pub enum TyKind {
     ///
     /// Type parameters may be stored in each `PathSegment`.
     Path(QPath),
+    /// A type definition itself. This is currently only used for the `existential type`
+    /// item that `impl Trait` in return position desugars to.
+    ///
+    /// The generic arg list are the lifetimes (and in the future possibly parameters) that are
+    /// actually bound on the `impl Trait`.
+    Def(ItemId, HirVec<GenericArg>),
     /// A trait object type `Bound1 + Bound2 + Bound3`
     /// where `Bound` is a trait or a lifetime.
     TraitObject(HirVec<PolyTraitRef>, Lifetime),
@@ -2461,9 +2467,22 @@ pub fn requests_inline(&self) -> bool {
         }
     }
 
-    /// True if `#[no_mangle]` or `#[export_name(...)]` is present.
+    /// True if it looks like this symbol needs to be exported, for example:
+    ///
+    /// * `#[no_mangle]` is present
+    /// * `#[export_name(...)]` is present
+    /// * `#[linkage]` is present
     pub fn contains_extern_indicator(&self) -> bool {
-        self.flags.contains(CodegenFnAttrFlags::NO_MANGLE) || self.export_name.is_some()
+        self.flags.contains(CodegenFnAttrFlags::NO_MANGLE) ||
+            self.export_name.is_some() ||
+            match self.linkage {
+                // these are private, make sure we don't try to consider
+                // them external
+                None |
+                Some(Linkage::Internal) |
+                Some(Linkage::Private) => false,
+                Some(_) => true,
+            }
     }
 }
 
index 69699d2e4acd35f9f5dd3e8fb2678f096730902d..08d46793d97bf60da9beb59ad3717b378deb98bb 100644 (file)
@@ -401,6 +401,7 @@ pub fn print_type(&mut self, ty: &hir::Ty) -> io::Result<()> {
                 self.print_ty_fn(f.abi, f.unsafety, &f.decl, None, &f.generic_params,
                                  &f.arg_names[..])?;
             }
+            hir::TyKind::Def(..) => {},
             hir::TyKind::Path(ref qpath) => {
                 self.print_qpath(qpath, false)?
             }
index 23533b7a4c3901f9f38587d7b36d2dd7e410af67..da9604702dfa38ac91545a898231deb40b08a95c 100644 (file)
@@ -345,6 +345,7 @@ fn hash_stable<W: StableHasherResult>(&self,
     Never,
     Tup(ts),
     Path(qpath),
+    Def(it, lt),
     TraitObject(trait_refs, lifetime),
     Typeof(body_id),
     Err,
@@ -1012,6 +1013,7 @@ fn to_stable_hash_key(&self,
     Builtin,
     Tool,
     DeriveHelper,
+    LegacyPluginHelper,
     Custom,
 });
 
index ec54613d1dbacfd41871ab4a6166e298549e561f..9312349ee405528d6db4a5fad114f29a5841e4c3 100644 (file)
@@ -29,6 +29,7 @@
     source_info,
     visibility_scope,
     internal,
+    is_block_tail,
     is_user_variable
 });
 impl_stable_hash_for!(struct mir::UpvarDecl { debug_name, var_hir_id, by_ref, mutability });
@@ -194,11 +195,13 @@ fn hash_stable<W: StableHasherResult>(&self,
             mir::TerminatorKind::Call { ref func,
                                         ref args,
                                         ref destination,
-                                        cleanup } => {
+                                        cleanup,
+                                        from_hir_call, } => {
                 func.hash_stable(hcx, hasher);
                 args.hash_stable(hcx, hasher);
                 destination.hash_stable(hcx, hasher);
                 cleanup.hash_stable(hcx, hasher);
+                from_hir_call.hash_stable(hcx, hasher);
             }
             mir::TerminatorKind::Assert { ref cond,
                                           expected,
index 9c4e995e24d01fe3dd6fd2dd8171a525d0386276..3ff0034fbbee7d850988e443c87c9922861c36e0 100644 (file)
@@ -131,7 +131,7 @@ fn hash_stable<W: StableHasherResult>(&self,
             }
             ty::ReLateBound(..) |
             ty::ReVar(..) |
-            ty::ReSkolemized(..) => {
+            ty::RePlaceholder(..) => {
                 bug!("StableHasher: unexpected region {:?}", *self)
             }
         }
@@ -873,8 +873,8 @@ fn hash_stable<W: StableHasherResult>(&self,
             Tuple(inner_tys) => {
                 inner_tys.hash_stable(hcx, hasher);
             }
-            Projection(ref projection_ty) => {
-                projection_ty.hash_stable(hcx, hasher);
+            Projection(ref data) | UnnormalizedProjection(ref data) => {
+                data.hash_stable(hcx, hasher);
             }
             Opaque(def_id, substs) => {
                 def_id.hash_stable(hcx, hasher);
index b30ccb5976c98c9cf46f2d85a320ae06d08adb0e..1119c928a89aeaf557b0e843909f116f1325d44e 100644 (file)
@@ -224,7 +224,7 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
             ty::ReEarlyBound(..)
             | ty::ReFree(_)
             | ty::ReScope(_)
-            | ty::ReSkolemized(..)
+            | ty::RePlaceholder(..)
             | ty::ReEmpty
             | ty::ReErased => {
                 if self.canonicalize_region_mode.other_free_regions {
@@ -283,6 +283,7 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
             | ty::Never
             | ty::Tuple(..)
             | ty::Projection(..)
+            | ty::UnnormalizedProjection(..)
             | ty::Foreign(..)
             | ty::Param(..)
             | ty::Opaque(..) => {
index 4738a03cbd3ec4177f2ecf1a7905b6a334aaf5b1..de8f57ee796661446670dad90ec2804b6663e0f3 100644 (file)
@@ -458,9 +458,10 @@ fn regions(&mut self, r: ty::Region<'tcx>, r2: ty::Region<'tcx>)
                 return Ok(r);
             }
 
-            // Always make a fresh region variable for skolemized regions;
-            // the higher-ranked decision procedures rely on this.
-            ty::ReSkolemized(..) => { }
+            // Always make a fresh region variable for placeholder
+            // regions; the higher-ranked decision procedures rely on
+            // this.
+            ty::RePlaceholder(..) => { }
 
             // For anything else, we make a region variable, unless we
             // are *equating*, in which case it's just wasteful.
index a68241ff2c0201c761894a3736e9d4c72aa44f2d..8b4669c89fe83598161d4114d72d6f7465f17f23 100644 (file)
@@ -142,12 +142,12 @@ pub fn note_and_explain_region(
 
             ty::ReEmpty => ("the empty lifetime".to_owned(), None),
 
-            // FIXME(#13998) ReSkolemized should probably print like
+            // FIXME(#13998) RePlaceholder should probably print like
             // ReFree rather than dumping Debug output on the user.
             //
             // We shouldn't really be having unification failures with ReVar
             // and ReLateBound though.
-            ty::ReSkolemized(..) | ty::ReVar(_) | ty::ReLateBound(..) | ty::ReErased => {
+            ty::RePlaceholder(..) | ty::ReVar(_) | ty::ReLateBound(..) | ty::ReErased => {
                 (format!("lifetime {:?}", region), None)
             }
 
index 1cb813c39e68ce6fbb94f85362b1a94982c4021a..969d260d97e218d2989717c604682c9f9234e438 100644 (file)
@@ -107,7 +107,7 @@ fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
             ty::ReFree(_) |
             ty::ReScope(_) |
             ty::ReVar(_) |
-            ty::ReSkolemized(..) |
+            ty::RePlaceholder(..) |
             ty::ReEmpty |
             ty::ReErased => {
                 // replace all free regions with 'erased
@@ -193,6 +193,7 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
             ty::Never |
             ty::Tuple(..) |
             ty::Projection(..) |
+            ty::UnnormalizedProjection(..) |
             ty::Foreign(..) |
             ty::Param(..) |
             ty::Closure(..) |
index 57665b6d9392348833f973f4502273dc1d448608..b1ac8bae4fb986bbbfd8239c7d8173a542e95a82 100644 (file)
@@ -72,11 +72,11 @@ the same lifetime, but not the reverse.
 Here is the algorithm we use to perform the subtyping check:
 
 1. Replace all bound regions in the subtype with new variables
-2. Replace all bound regions in the supertype with skolemized
-   equivalents. A "skolemized" region is just a new fresh region
+2. Replace all bound regions in the supertype with placeholder
+   equivalents. A "placeholder" region is just a new fresh region
    name.
 3. Check that the parameter and return types match as normal
-4. Ensure that no skolemized regions 'leak' into region variables
+4. Ensure that no placeholder regions 'leak' into region variables
    visible from "the outside"
 
 Let's walk through some examples and see how this algorithm plays out.
@@ -95,7 +95,7 @@ like so:
 Here the upper case `&A` indicates a *region variable*, that is, a
 region whose value is being inferred by the system. I also replaced
 `&b` with `&x`---I'll use letters late in the alphabet (`x`, `y`, `z`)
-to indicate skolemized region names. We can assume they don't appear
+to indicate placeholder region names. We can assume they don't appear
 elsewhere. Note that neither the sub- nor the supertype bind any
 region names anymore (as indicated by the absence of `<` and `>`).
 
@@ -133,7 +133,7 @@ match. This will ultimately require (as before) that `'a` <= `&x`
 must hold: but this does not hold. `self` and `x` are both distinct
 free regions. So the subtype check fails.
 
-#### Checking for skolemization leaks
+#### Checking for placeholder leaks
 
 You may be wondering about that mysterious last step in the algorithm.
 So far it has not been relevant. The purpose of that last step is to
@@ -159,7 +159,7 @@ Now we compare the return types, which are covariant, and hence we have:
 
     fn(&'A T) <: for<'b> fn(&'b T)?
 
-Here we skolemize the bound region in the supertype to yield:
+Here we replace the bound region in the supertype with a placeholder to yield:
 
     fn(&'A T) <: fn(&'x T)?
 
@@ -175,23 +175,23 @@ region `x` and think that everything is happy. In fact, this behavior
 is *necessary*, it was key to the first example we walked through.
 
 The difference between this example and the first one is that the variable
-`A` already existed at the point where the skolemization occurred. In
+`A` already existed at the point where the placeholders were added. In
 the first example, you had two functions:
 
     for<'a> fn(&'a T) <: for<'b> fn(&'b T)
 
 and hence `&A` and `&x` were created "together". In general, the
-intention of the skolemized names is that they are supposed to be
+intention of the placeholder names is that they are supposed to be
 fresh names that could never be equal to anything from the outside.
 But when inference comes into play, we might not be respecting this
 rule.
 
 So the way we solve this is to add a fourth step that examines the
-constraints that refer to skolemized names. Basically, consider a
+constraints that refer to placeholder names. Basically, consider a
 non-directed version of the constraint graph. Let `Tainted(x)` be the
-set of all things reachable from a skolemized variable `x`.
+set of all things reachable from a placeholder variable `x`.
 `Tainted(x)` should not contain any regions that existed before the
-step at which the skolemization was performed. So this case here
+step at which the placeholders were created. So this case here
 would fail because `&x` was created alone, but is relatable to `&A`.
 
 ## Computing the LUB and GLB
index fae48325371562fabd0adf7eb6b6e9c59445ccbd..e77d20665bf3bd7b510f3138624bbd4ffee2bbc2 100644 (file)
@@ -15,7 +15,7 @@
             InferCtxt,
             HigherRankedType,
             SubregionOrigin,
-            SkolemizationMap};
+            PlaceholderMap};
 use super::combine::CombineFields;
 use super::region_constraints::{TaintDirections};
 
@@ -51,19 +51,21 @@ pub fn higher_ranked_sub<T>(&mut self, a: &Binder<T>, b: &Binder<T>, a_is_expect
         return self.infcx.commit_if_ok(|snapshot| {
             let span = self.trace.cause.span;
 
-            // First, we instantiate each bound region in the subtype with a fresh
-            // region variable.
+            // First, we instantiate each bound region in the supertype with a
+            // fresh placeholder region.
+            let (b_prime, placeholder_map) =
+                self.infcx.replace_late_bound_regions_with_placeholders(b);
+
+            // Next, we instantiate each bound region in the subtype
+            // with a fresh region variable. These region variables --
+            // but no other pre-existing region variables -- can name
+            // the placeholders.
             let (a_prime, _) =
                 self.infcx.replace_late_bound_regions_with_fresh_var(
                     span,
                     HigherRankedType,
                     a);
 
-            // Second, we instantiate each bound region in the supertype with a
-            // fresh concrete region.
-            let (b_prime, skol_map) =
-                self.infcx.skolemize_late_bound_regions(b);
-
             debug!("a_prime={:?}", a_prime);
             debug!("b_prime={:?}", b_prime);
 
@@ -71,12 +73,12 @@ pub fn higher_ranked_sub<T>(&mut self, a: &Binder<T>, b: &Binder<T>, a_is_expect
             let result = self.sub(a_is_expected).relate(&a_prime, &b_prime)?;
 
             // Presuming type comparison succeeds, we need to check
-            // that the skolemized regions do not "leak".
-            self.infcx.leak_check(!a_is_expected, span, &skol_map, snapshot)?;
+            // that the placeholder regions do not "leak".
+            self.infcx.leak_check(!a_is_expected, span, &placeholder_map, snapshot)?;
 
-            // We are finished with the skolemized regions now so pop
+            // We are finished with the placeholder regions now so pop
             // them off.
-            self.infcx.pop_skolemized(skol_map, snapshot);
+            self.infcx.pop_placeholders(placeholder_map, snapshot);
 
             debug!("higher_ranked_sub: OK result={:?}", result);
 
@@ -112,68 +114,68 @@ pub fn higher_ranked_match<T, U>(&mut self,
         // created as part of this type comparison".
         return self.infcx.commit_if_ok(|snapshot| {
             // First, we instantiate each bound region in the matcher
-            // with a skolemized region.
-            let ((a_match, a_value), skol_map) =
-                self.infcx.skolemize_late_bound_regions(a_pair);
+            // with a placeholder region.
+            let ((a_match, a_value), placeholder_map) =
+                self.infcx.replace_late_bound_regions_with_placeholders(a_pair);
 
             debug!("higher_ranked_match: a_match={:?}", a_match);
-            debug!("higher_ranked_match: skol_map={:?}", skol_map);
+            debug!("higher_ranked_match: placeholder_map={:?}", placeholder_map);
 
             // Equate types now that bound regions have been replaced.
             self.equate(a_is_expected).relate(&a_match, &b_match)?;
 
-            // Map each skolemized region to a vector of other regions that it
+            // Map each placeholder region to a vector of other regions that it
             // must be equated with. (Note that this vector may include other
-            // skolemized regions from `skol_map`.)
-            let skol_resolution_map: FxHashMap<_, _> =
-                skol_map
+            // placeholder regions from `placeholder_map`.)
+            let placeholder_resolution_map: FxHashMap<_, _> =
+                placeholder_map
                 .iter()
-                .map(|(&br, &skol)| {
+                .map(|(&br, &placeholder)| {
                     let tainted_regions =
                         self.infcx.tainted_regions(snapshot,
-                                                   skol,
+                                                   placeholder,
                                                    TaintDirections::incoming()); // [1]
 
-                    // [1] this routine executes after the skolemized
+                    // [1] this routine executes after the placeholder
                     // regions have been *equated* with something
                     // else, so examining the incoming edges ought to
                     // be enough to collect all constraints
 
-                    (skol, (br, tainted_regions))
+                    (placeholder, (br, tainted_regions))
                 })
                 .collect();
 
-            // For each skolemized region, pick a representative -- which can
+            // For each placeholder region, pick a representative -- which can
             // be any region from the sets above, except for other members of
-            // `skol_map`. There should always be a representative if things
+            // `placeholder_map`. There should always be a representative if things
             // are properly well-formed.
-            let skol_representatives: FxHashMap<_, _> =
-                skol_resolution_map
+            let placeholder_representatives: FxHashMap<_, _> =
+                placeholder_resolution_map
                 .iter()
-                .map(|(&skol, &(_, ref regions))| {
+                .map(|(&placeholder, &(_, ref regions))| {
                     let representative =
                         regions.iter()
-                               .filter(|&&r| !skol_resolution_map.contains_key(r))
+                               .filter(|&&r| !placeholder_resolution_map.contains_key(r))
                                .cloned()
                                .next()
                                .unwrap_or_else(|| {
                                    bug!("no representative region for `{:?}` in `{:?}`",
-                                        skol, regions)
+                                        placeholder, regions)
                                });
 
-                    (skol, representative)
+                    (placeholder, representative)
                 })
                 .collect();
 
-            // Equate all the members of each skolemization set with the
+            // Equate all the members of each placeholder set with the
             // representative.
-            for (skol, &(_br, ref regions)) in &skol_resolution_map {
-                let representative = &skol_representatives[skol];
+            for (placeholder, &(_br, ref regions)) in &placeholder_resolution_map {
+                let representative = &placeholder_representatives[placeholder];
                 debug!("higher_ranked_match: \
-                        skol={:?} representative={:?} regions={:?}",
-                       skol, representative, regions);
+                        placeholder={:?} representative={:?} regions={:?}",
+                       placeholder, representative, regions);
                 for region in regions.iter()
-                                     .filter(|&r| !skol_resolution_map.contains_key(r))
+                                     .filter(|&r| !placeholder_resolution_map.contains_key(r))
                                      .filter(|&r| r != representative)
                 {
                     let origin = SubregionOrigin::Subtype(self.trace.clone());
@@ -184,18 +186,18 @@ pub fn higher_ranked_match<T, U>(&mut self,
                 }
             }
 
-            // Replace the skolemized regions appearing in value with
+            // Replace the placeholder regions appearing in value with
             // their representatives
             let a_value =
                 fold_regions_in(
                     self.tcx(),
                     &a_value,
-                    |r, _| skol_representatives.get(&r).cloned().unwrap_or(r));
+                    |r, _| placeholder_representatives.get(&r).cloned().unwrap_or(r));
 
             debug!("higher_ranked_match: value={:?}", a_value);
 
-            // We are now done with these skolemized variables.
-            self.infcx.pop_skolemized(skol_map, snapshot);
+            // We are now done with these placeholder variables.
+            self.infcx.pop_placeholders(placeholder_map, snapshot);
 
             Ok(HrMatchResult { value: a_value })
         });
@@ -500,7 +502,7 @@ fn region_vars_confined_to_snapshot(&self,
          * started. This is used in the sub/lub/glb computations. The
          * idea here is that when we are computing lub/glb of two
          * regions, we sometimes create intermediate region variables.
-         * Those region variables may touch some of the skolemized or
+         * Those region variables may touch some of the placeholder or
          * other "forbidden" regions we created to replace bound
          * regions, but they don't really represent an "external"
          * constraint.
@@ -527,10 +529,10 @@ fn region_vars_confined_to_snapshot(&self,
          * we're not careful, it will succeed.
          *
          * The reason is that when we walk through the subtyping
-         * algorithm, we begin by replacing `'a` with a skolemized
+         * algorithm, we begin by replacing `'a` with a placeholder
          * variable `'1`. We then have `fn(_#0t) <: fn(&'1 int)`. This
          * can be made true by unifying `_#0t` with `&'1 int`. In the
-         * process, we create a fresh variable for the skolemized
+         * process, we create a fresh variable for the placeholder
          * region, `'$2`, and hence we have that `_#0t == &'$2
          * int`. However, because `'$2` was created during the sub
          * computation, if we're not careful we will erroneously
@@ -568,33 +570,39 @@ fn region_vars_confined_to_snapshot(&self,
         region_vars
     }
 
-    /// Replace all regions bound by `binder` with skolemized regions and
+    /// Replace all regions bound by `binder` with placeholder regions and
     /// return a map indicating which bound-region was replaced with what
-    /// skolemized region. This is the first step of checking subtyping
+    /// placeholder region. This is the first step of checking subtyping
     /// when higher-ranked things are involved.
     ///
     /// **Important:** you must call this function from within a snapshot.
     /// Moreover, before committing the snapshot, you must eventually call
-    /// either `plug_leaks` or `pop_skolemized` to remove the skolemized
+    /// either `plug_leaks` or `pop_placeholders` to remove the placeholder
     /// regions. If you rollback the snapshot (or are using a probe), then
     /// the pop occurs as part of the rollback, so an explicit call is not
     /// needed (but is also permitted).
     ///
-    /// For more information about how skolemization for HRTBs works, see
+    /// For more information about how placeholders and HRTBs work, see
     /// the [rustc guide].
     ///
     /// [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/traits/hrtb.html
-    pub fn skolemize_late_bound_regions<T>(&self,
-                                           binder: &ty::Binder<T>)
-                                           -> (T, SkolemizationMap<'tcx>)
-        where T : TypeFoldable<'tcx>
+    pub fn replace_late_bound_regions_with_placeholders<T>(
+        &self,
+        binder: &ty::Binder<T>,
+    ) -> (T, PlaceholderMap<'tcx>)
+    where
+        T : TypeFoldable<'tcx>,
     {
+        let new_universe = self.create_subuniverse();
+
         let (result, map) = self.tcx.replace_late_bound_regions(binder, |br| {
-            self.universe.set(self.universe().subuniverse());
-            self.tcx.mk_region(ty::ReSkolemized(self.universe(), br))
+            self.tcx.mk_region(ty::RePlaceholder(ty::Placeholder {
+                universe: new_universe,
+                name: br,
+            }))
         });
 
-        debug!("skolemize_bound_regions(binder={:?}, result={:?}, map={:?})",
+        debug!("replace_late_bound_regions_with_placeholders(binder={:?}, result={:?}, map={:?})",
                binder,
                result,
                map);
@@ -603,19 +611,19 @@ pub fn skolemize_late_bound_regions<T>(&self,
     }
 
     /// Searches the region constraints created since `snapshot` was started
-    /// and checks to determine whether any of the skolemized regions created
-    /// in `skol_map` would "escape" -- meaning that they are related to
+    /// and checks to determine whether any of the placeholder regions created
+    /// in `placeholder_map` would "escape" -- meaning that they are related to
     /// other regions in some way. If so, the higher-ranked subtyping doesn't
     /// hold. See `README.md` for more details.
     pub fn leak_check(&self,
                       overly_polymorphic: bool,
                       _span: Span,
-                      skol_map: &SkolemizationMap<'tcx>,
+                      placeholder_map: &PlaceholderMap<'tcx>,
                       snapshot: &CombinedSnapshot<'a, 'tcx>)
                       -> RelateResult<'tcx, ()>
     {
-        debug!("leak_check: skol_map={:?}",
-               skol_map);
+        debug!("leak_check: placeholder_map={:?}",
+               placeholder_map);
 
         // If the user gave `-Zno-leak-check`, then skip the leak
         // check completely. This is wildly unsound and also not
@@ -630,14 +638,14 @@ pub fn leak_check(&self,
         }
 
         let new_vars = self.region_vars_confined_to_snapshot(snapshot);
-        for (&skol_br, &skol) in skol_map {
-            // The inputs to a skolemized variable can only
+        for (&placeholder_br, &placeholder) in placeholder_map {
+            // The inputs to a placeholder variable can only
             // be itself or other new variables.
             let incoming_taints = self.tainted_regions(snapshot,
-                                                       skol,
+                                                       placeholder,
                                                        TaintDirections::both());
             for &tainted_region in &incoming_taints {
-                // Each skolemized should only be relatable to itself
+                // Each placeholder should only be relatable to itself
                 // or new variables:
                 match *tainted_region {
                     ty::ReVar(vid) => {
@@ -646,21 +654,21 @@ pub fn leak_check(&self,
                         }
                     }
                     _ => {
-                        if tainted_region == skol { continue; }
+                        if tainted_region == placeholder { continue; }
                     }
                 };
 
                 debug!("{:?} (which replaced {:?}) is tainted by {:?}",
-                       skol,
-                       skol_br,
+                       placeholder,
+                       placeholder_br,
                        tainted_region);
 
                 return Err(if overly_polymorphic {
                     debug!("Overly polymorphic!");
-                    TypeError::RegionsOverlyPolymorphic(skol_br, tainted_region)
+                    TypeError::RegionsOverlyPolymorphic(placeholder_br, tainted_region)
                 } else {
                     debug!("Not as polymorphic!");
-                    TypeError::RegionsInsufficientlyPolymorphic(skol_br, tainted_region)
+                    TypeError::RegionsInsufficientlyPolymorphic(placeholder_br, tainted_region)
                 })
             }
         }
@@ -668,9 +676,9 @@ pub fn leak_check(&self,
         Ok(())
     }
 
-    /// This code converts from skolemized regions back to late-bound
+    /// This code converts from placeholder regions back to late-bound
     /// regions. It works by replacing each region in the taint set of a
-    /// skolemized region with a bound-region. The bound region will be bound
+    /// placeholder region with a bound-region. The bound region will be bound
     /// by the outer-most binder in `value`; the caller must ensure that there is
     /// such a binder and it is the right place.
     ///
@@ -687,7 +695,7 @@ pub fn leak_check(&self,
     ///         where A : Clone
     ///     { ... }
     ///
-    /// Here we will have replaced `'a` with a skolemized region
+    /// Here we will have replaced `'a` with a placeholder region
     /// `'0`. This means that our substitution will be `{A=>&'0
     /// int, R=>&'0 int}`.
     ///
@@ -697,65 +705,65 @@ pub fn leak_check(&self,
     /// to the depth of the predicate, in this case 1, so that the final
     /// predicate is `for<'a> &'a int : Clone`.
     pub fn plug_leaks<T>(&self,
-                         skol_map: SkolemizationMap<'tcx>,
+                         placeholder_map: PlaceholderMap<'tcx>,
                          snapshot: &CombinedSnapshot<'a, 'tcx>,
                          value: T) -> T
         where T : TypeFoldable<'tcx>
     {
-        debug!("plug_leaks(skol_map={:?}, value={:?})",
-               skol_map,
+        debug!("plug_leaks(placeholder_map={:?}, value={:?})",
+               placeholder_map,
                value);
 
-        if skol_map.is_empty() {
+        if placeholder_map.is_empty() {
             return value;
         }
 
-        // Compute a mapping from the "taint set" of each skolemized
+        // Compute a mapping from the "taint set" of each placeholder
         // region back to the `ty::BoundRegion` that it originally
         // represented. Because `leak_check` passed, we know that
         // these taint sets are mutually disjoint.
-        let inv_skol_map: FxHashMap<ty::Region<'tcx>, ty::BoundRegion> =
-            skol_map
+        let inv_placeholder_map: FxHashMap<ty::Region<'tcx>, ty::BoundRegion> =
+            placeholder_map
             .iter()
-            .flat_map(|(&skol_br, &skol)| {
-                self.tainted_regions(snapshot, skol, TaintDirections::both())
+            .flat_map(|(&placeholder_br, &placeholder)| {
+                self.tainted_regions(snapshot, placeholder, TaintDirections::both())
                     .into_iter()
-                    .map(move |tainted_region| (tainted_region, skol_br))
+                    .map(move |tainted_region| (tainted_region, placeholder_br))
             })
             .collect();
 
-        debug!("plug_leaks: inv_skol_map={:?}",
-               inv_skol_map);
+        debug!("plug_leaks: inv_placeholder_map={:?}",
+               inv_placeholder_map);
 
         // Remove any instantiated type variables from `value`; those can hide
         // references to regions from the `fold_regions` code below.
         let value = self.resolve_type_vars_if_possible(&value);
 
-        // Map any skolemization byproducts back to a late-bound
+        // Map any placeholder byproducts back to a late-bound
         // region. Put that late-bound region at whatever the outermost
         // binder is that we encountered in `value`. The caller is
         // responsible for ensuring that (a) `value` contains at least one
         // binder and (b) that binder is the one we want to use.
         let result = self.tcx.fold_regions(&value, &mut false, |r, current_depth| {
-            match inv_skol_map.get(&r) {
+            match inv_placeholder_map.get(&r) {
                 None => r,
                 Some(br) => {
                     // It is the responsibility of the caller to ensure
-                    // that each skolemized region appears within a
+                    // that each placeholder region appears within a
                     // binder. In practice, this routine is only used by
-                    // trait checking, and all of the skolemized regions
+                    // trait checking, and all of the placeholder regions
                     // appear inside predicates, which always have
                     // binders, so this assert is satisfied.
                     assert!(current_depth > ty::INNERMOST);
 
-                    // since leak-check passed, this skolemized region
+                    // since leak-check passed, this placeholder region
                     // should only have incoming edges from variables
                     // (which ought not to escape the snapshot, but we
                     // don't check that) or itself
                     assert!(
                         match *r {
                             ty::ReVar(_) => true,
-                            ty::ReSkolemized(_, ref br1) => br == br1,
+                            ty::RePlaceholder(index) => index.name == *br,
                             _ => false,
                         },
                         "leak-check would have us replace {:?} with {:?}",
@@ -769,31 +777,36 @@ pub fn plug_leaks<T>(&self,
             }
         });
 
-        self.pop_skolemized(skol_map, snapshot);
+        self.pop_placeholders(placeholder_map, snapshot);
 
         debug!("plug_leaks: result={:?}", result);
 
         result
     }
 
-    /// Pops the skolemized regions found in `skol_map` from the region
-    /// inference context. Whenever you create skolemized regions via
-    /// `skolemize_late_bound_regions`, they must be popped before you
+    /// Pops the placeholder regions found in `placeholder_map` from the region
+    /// inference context. Whenever you create placeholder regions via
+    /// `replace_late_bound_regions_with_placeholders`, they must be popped before you
     /// commit the enclosing snapshot (if you do not commit, e.g. within a
     /// probe or as a result of an error, then this is not necessary, as
     /// popping happens as part of the rollback).
     ///
     /// Note: popping also occurs implicitly as part of `leak_check`.
-    pub fn pop_skolemized(&self,
-                          skol_map: SkolemizationMap<'tcx>,
-                          snapshot: &CombinedSnapshot<'a, 'tcx>) {
-        debug!("pop_skolemized({:?})", skol_map);
-        let skol_regions: FxHashSet<_> = skol_map.values().cloned().collect();
+    pub fn pop_placeholders(
+        &self,
+        placeholder_map: PlaceholderMap<'tcx>,
+        snapshot: &CombinedSnapshot<'a, 'tcx>,
+    ) {
+        debug!("pop_placeholders({:?})", placeholder_map);
+        let placeholder_regions: FxHashSet<_> = placeholder_map.values().cloned().collect();
         self.borrow_region_constraints()
-            .pop_skolemized(self.universe(), &skol_regions, &snapshot.region_constraints_snapshot);
+            .pop_placeholders(
+                &placeholder_regions,
+                &snapshot.region_constraints_snapshot,
+            );
         self.universe.set(snapshot.universe);
-        if !skol_map.is_empty() {
-            self.projection_cache.borrow_mut().rollback_skolemized(
+        if !placeholder_map.is_empty() {
+            self.projection_cache.borrow_mut().rollback_placeholder(
                 &snapshot.projection_cache_snapshot);
         }
     }
index ca49d053210c7c0026ada442afc0ca14f55bed34..caba8b514f7972498bf54aa3623312ae2d374840 100644 (file)
@@ -28,7 +28,7 @@
 use ty::fold::TypeFoldable;
 use ty::{self, Ty, TyCtxt};
 use ty::{ReEarlyBound, ReEmpty, ReErased, ReFree, ReStatic};
-use ty::{ReLateBound, ReScope, ReSkolemized, ReVar};
+use ty::{ReLateBound, ReScope, RePlaceholder, ReVar};
 use ty::{Region, RegionVid};
 
 mod graphviz;
@@ -341,7 +341,7 @@ fn lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'tcx>
 
             // For these types, we cannot define any additional
             // relationship:
-            (&ReSkolemized(..), _) | (_, &ReSkolemized(..)) => if a == b {
+            (&RePlaceholder(..), _) | (_, &RePlaceholder(..)) => if a == b {
                 a
             } else {
                 tcx.types.re_static
index 7722896b6eb4a8263d2c6ac8fb6c8c80d2187520..291b46edccfb2342b6b9f981fd4865d1d95ba4b7 100644 (file)
@@ -229,9 +229,10 @@ pub struct InferCtxt<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
     universe: Cell<ty::UniverseIndex>,
 }
 
-/// A map returned by `skolemize_late_bound_regions()` indicating the skolemized
-/// region that each late-bound region was replaced with.
-pub type SkolemizationMap<'tcx> = BTreeMap<ty::BoundRegion, ty::Region<'tcx>>;
+/// A map returned by `replace_late_bound_regions_with_placeholders()`
+/// indicating the placeholder region that each late-bound region was
+/// replaced with.
+pub type PlaceholderMap<'tcx> = BTreeMap<ty::BoundRegion, ty::Region<'tcx>>;
 
 /// See `error_reporting` module for more details
 #[derive(Clone, Debug)]
@@ -405,12 +406,14 @@ pub enum RegionVariableOrigin {
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
 pub enum NLLRegionVariableOrigin {
-    // During NLL region processing, we create variables for free
-    // regions that we encounter in the function signature and
-    // elsewhere. This origin indices we've got one of those.
+    /// During NLL region processing, we create variables for free
+    /// regions that we encounter in the function signature and
+    /// elsewhere. This origin indices we've got one of those.
     FreeRegion,
 
-    BoundRegion(ty::UniverseIndex),
+    /// "Universal" instantiation of a higher-ranked region (e.g.,
+    /// from a `for<'a> T` binder). Meant to represent "any region".
+    Placeholder(ty::Placeholder),
 
     Existential,
 }
@@ -419,7 +422,7 @@ impl NLLRegionVariableOrigin {
     pub fn is_universal(self) -> bool {
         match self {
             NLLRegionVariableOrigin::FreeRegion => true,
-            NLLRegionVariableOrigin::BoundRegion(..) => true,
+            NLLRegionVariableOrigin::Placeholder(..) => true,
             NLLRegionVariableOrigin::Existential => false,
         }
     }
@@ -913,13 +916,13 @@ pub fn subtype_predicate(
                     a,
                     b,
                 },
-                skol_map,
-            ) = self.skolemize_late_bound_regions(predicate);
+                placeholder_map,
+            ) = self.replace_late_bound_regions_with_placeholders(predicate);
 
             let cause_span = cause.span;
             let ok = self.at(cause, param_env).sub_exp(a_is_expected, a, b)?;
-            self.leak_check(false, cause_span, &skol_map, snapshot)?;
-            self.pop_skolemized(skol_map, snapshot);
+            self.leak_check(false, cause_span, &placeholder_map, snapshot)?;
+            self.pop_placeholders(placeholder_map, snapshot);
             Ok(ok.unit())
         }))
     }
@@ -930,14 +933,14 @@ pub fn region_outlives_predicate(
         predicate: &ty::PolyRegionOutlivesPredicate<'tcx>,
     ) -> UnitResult<'tcx> {
         self.commit_if_ok(|snapshot| {
-            let (ty::OutlivesPredicate(r_a, r_b), skol_map) =
-                self.skolemize_late_bound_regions(predicate);
+            let (ty::OutlivesPredicate(r_a, r_b), placeholder_map) =
+                self.replace_late_bound_regions_with_placeholders(predicate);
             let origin = SubregionOrigin::from_obligation_cause(cause, || {
                 RelateRegionParamBound(cause.span)
             });
             self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b`
-            self.leak_check(false, cause.span, &skol_map, snapshot)?;
-            Ok(self.pop_skolemized(skol_map, snapshot))
+            self.leak_check(false, cause.span, &placeholder_map, snapshot)?;
+            Ok(self.pop_placeholders(placeholder_map, snapshot))
         })
     }
 
index 87bfbaef54c4e7748bf3cb6dee249b4fcf2b3ea2..525ae03dfaf934eca8931a5ff93353fd5efa90f4 100644 (file)
 
 //! See README.md
 
-use self::UndoLogEntry::*;
 use self::CombineMapType::*;
+use self::UndoLogEntry::*;
 
-use super::{MiscVariable, RegionVariableOrigin, SubregionOrigin};
 use super::unify_key;
+use super::{MiscVariable, RegionVariableOrigin, SubregionOrigin};
 
-use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_data_structures::unify as ut;
-use ty::{self, Ty, TyCtxt};
-use ty::{Region, RegionVid};
 use ty::ReStatic;
+use ty::{self, Ty, TyCtxt};
 use ty::{BrFresh, ReLateBound, ReVar};
+use ty::{Region, RegionVid};
 
 use std::collections::BTreeMap;
 use std::{cmp, fmt, mem, u32};
@@ -306,10 +306,10 @@ pub struct RegionSnapshot {
     any_unifications: bool,
 }
 
-/// When working with skolemized regions, we often wish to find all of
-/// the regions that are either reachable from a skolemized region, or
-/// which can reach a skolemized region, or both. We call such regions
-/// *tained* regions.  This struct allows you to decide what set of
+/// When working with placeholder regions, we often wish to find all of
+/// the regions that are either reachable from a placeholder region, or
+/// which can reach a placeholder region, or both. We call such regions
+/// *tainted* regions.  This struct allows you to decide what set of
 /// tainted regions you want.
 #[derive(Debug)]
 pub struct TaintDirections {
@@ -495,13 +495,12 @@ fn rollback_undo_entry(&mut self, undo_entry: UndoLogEntry<'tcx>) {
         }
     }
 
-    pub fn new_region_var(&mut self,
-                          universe: ty::UniverseIndex,
-                          origin: RegionVariableOrigin) -> RegionVid {
-        let vid = self.var_infos.push(RegionVariableInfo {
-            origin,
-            universe,
-        });
+    pub fn new_region_var(
+        &mut self,
+        universe: ty::UniverseIndex,
+        origin: RegionVariableOrigin,
+    ) -> RegionVid {
+        let vid = self.var_infos.push(RegionVariableInfo { origin, universe });
 
         let u_vid = self.unification_table
             .new_key(unify_key::RegionVidKey { min_vid: vid });
@@ -511,8 +510,7 @@ pub fn new_region_var(&mut self,
         }
         debug!(
             "created new region variable {:?} with origin {:?}",
-            vid,
-            origin
+            vid, origin
         );
         return vid;
     }
@@ -527,51 +525,25 @@ pub fn var_origin(&self, vid: RegionVid) -> RegionVariableOrigin {
         self.var_infos[vid].origin
     }
 
-    /// Removes all the edges to/from the skolemized regions that are
+    /// Removes all the edges to/from the placeholder regions that are
     /// in `skols`. This is used after a higher-ranked operation
-    /// completes to remove all trace of the skolemized regions
+    /// completes to remove all trace of the placeholder regions
     /// created in that time.
-    pub fn pop_skolemized(
+    pub fn pop_placeholders(
         &mut self,
-        skolemization_count: ty::UniverseIndex,
-        skols: &FxHashSet<ty::Region<'tcx>>,
+        placeholders: &FxHashSet<ty::Region<'tcx>>,
         snapshot: &RegionSnapshot,
     ) {
-        debug!("pop_skolemized_regions(skols={:?})", skols);
+        debug!("pop_placeholders(placeholders={:?})", placeholders);
 
         assert!(self.in_snapshot());
         assert!(self.undo_log[snapshot.length] == OpenSnapshot);
-        assert!(
-            skolemization_count.as_usize() >= skols.len(),
-            "popping more skolemized variables than actually exist, \
-             sc now = {:?}, skols.len = {:?}",
-            skolemization_count,
-            skols.len()
-        );
-
-        let last_to_pop = skolemization_count.subuniverse();
-        let first_to_pop = ty::UniverseIndex::from(last_to_pop.as_u32() - skols.len() as u32);
-
-        debug_assert! {
-            skols.iter()
-                 .all(|&k| match *k {
-                     ty::ReSkolemized(universe, _) =>
-                         universe >= first_to_pop &&
-                         universe < last_to_pop,
-                     _ =>
-                         false
-                 }),
-            "invalid skolemization keys or keys out of range ({:?}..{:?}): {:?}",
-            first_to_pop,
-            last_to_pop,
-            skols
-        }
 
         let constraints_to_kill: Vec<usize> = self.undo_log
             .iter()
             .enumerate()
             .rev()
-            .filter(|&(_, undo_entry)| kill_constraint(skols, undo_entry))
+            .filter(|&(_, undo_entry)| kill_constraint(placeholders, undo_entry))
             .map(|(index, _)| index)
             .collect();
 
@@ -583,20 +555,20 @@ pub fn pop_skolemized(
         return;
 
         fn kill_constraint<'tcx>(
-            skols: &FxHashSet<ty::Region<'tcx>>,
+            placeholders: &FxHashSet<ty::Region<'tcx>>,
             undo_entry: &UndoLogEntry<'tcx>,
         ) -> bool {
             match undo_entry {
                 &AddConstraint(Constraint::VarSubVar(..)) => false,
-                &AddConstraint(Constraint::RegSubVar(a, _)) => skols.contains(&a),
-                &AddConstraint(Constraint::VarSubReg(_, b)) => skols.contains(&b),
+                &AddConstraint(Constraint::RegSubVar(a, _)) => placeholders.contains(&a),
+                &AddConstraint(Constraint::VarSubReg(_, b)) => placeholders.contains(&b),
                 &AddConstraint(Constraint::RegSubReg(a, b)) => {
-                    skols.contains(&a) || skols.contains(&b)
+                    placeholders.contains(&a) || placeholders.contains(&b)
                 }
                 &AddGiven(..) => false,
                 &AddVerify(_) => false,
                 &AddCombination(_, ref two_regions) => {
-                    skols.contains(&two_regions.a) || skols.contains(&two_regions.b)
+                    placeholders.contains(&two_regions.a) || placeholders.contains(&two_regions.b)
                 }
                 &AddVar(..) | &OpenSnapshot | &Purged | &CommitedSnapshot => false,
             }
@@ -713,9 +685,7 @@ pub fn make_subregion(
         // cannot add constraints once regions are resolved
         debug!(
             "RegionConstraintCollector: make_subregion({:?}, {:?}) due to {:?}",
-            sub,
-            sup,
-            origin
+            sub, sup, origin
         );
 
         match (sub, sup) {
@@ -854,19 +824,19 @@ fn combine_vars(
 
     fn universe(&self, region: Region<'tcx>) -> ty::UniverseIndex {
         match *region {
-            ty::ReScope(..) |
-            ty::ReStatic |
-            ty::ReEmpty |
-            ty::ReErased |
-            ty::ReFree(..) |
-            ty::ReEarlyBound(..) => ty::UniverseIndex::ROOT,
-            ty::ReSkolemized(universe, _) => universe,
-            ty::ReClosureBound(vid) |
-            ty::ReVar(vid) => self.var_universe(vid),
-            ty::ReLateBound(..) =>
-                bug!("universe(): encountered bound region {:?}", region),
-            ty::ReCanonical(..) =>
-                bug!("region_universe(): encountered canonical region {:?}", region),
+            ty::ReScope(..)
+            | ty::ReStatic
+            | ty::ReEmpty
+            | ty::ReErased
+            | ty::ReFree(..)
+            ty::ReEarlyBound(..) => ty::UniverseIndex::ROOT,
+            ty::RePlaceholder(placeholder) => placeholder.universe,
+            ty::ReClosureBound(vid) | ty::ReVar(vid) => self.var_universe(vid),
+            ty::ReLateBound(..) => bug!("universe(): encountered bound region {:?}", region),
+            ty::ReCanonical(..) => bug!(
+                "region_universe(): encountered canonical region {:?}",
+                region
+            ),
         }
     }
 
@@ -886,7 +856,7 @@ pub fn vars_created_since_snapshot(&self, mark: &RegionSnapshot) -> Vec<RegionVi
     /// relations are considered. For example, one can say that only
     /// "incoming" edges to `r0` are desired, in which case one will
     /// get the set of regions `{r|r <= r0}`. This is used when
-    /// checking whether skolemized regions are being improperly
+    /// checking whether placeholder regions are being improperly
     /// related to other regions.
     pub fn tainted(
         &self,
@@ -897,9 +867,7 @@ pub fn tainted(
     ) -> FxHashSet<ty::Region<'tcx>> {
         debug!(
             "tainted(mark={:?}, r0={:?}, directions={:?})",
-            mark,
-            r0,
-            directions
+            mark, r0, directions
         );
 
         // `result_set` acts as a worklist: we explore all outgoing
index 66305ae8836ee90c1f63b23601179ac6def17a85..2ac185b681e48f8cad5678e685794eb49ccf0060 100644 (file)
@@ -18,6 +18,7 @@
 use hir::itemlikevisit::ItemLikeVisitor;
 
 use hir::def::Def;
+use hir::CodegenFnAttrFlags;
 use hir::def_id::{DefId, LOCAL_CRATE};
 use lint;
 use middle::privacy;
@@ -131,12 +132,10 @@ fn handle_field_pattern_match(&mut self, lhs: &hir::Pat, def: Def,
 
     fn mark_live_symbols(&mut self) {
         let mut scanned = FxHashSet();
-        while !self.worklist.is_empty() {
-            let id = self.worklist.pop().unwrap();
-            if scanned.contains(&id) {
+        while let Some(id) = self.worklist.pop() {
+            if !scanned.insert(id) {
                 continue
             }
-            scanned.insert(id);
 
             if let Some(ref node) = self.tcx.hir.find(id) {
                 self.live_symbols.insert(id);
@@ -212,7 +211,7 @@ fn visit_nested_body(&mut self, body: hir::BodyId) {
     }
 
     fn visit_variant_data(&mut self, def: &'tcx hir::VariantData, _: ast::Name,
-                        _: &hir::Generics, _: ast::NodeId, _: syntax_pos::Span) {
+                          _: &hir::Generics, _: ast::NodeId, _: syntax_pos::Span) {
         let has_repr_c = self.repr_has_repr_c;
         let inherited_pub_visibility = self.inherited_pub_visibility;
         let live_fields = def.fields().iter().filter(|f| {
@@ -304,14 +303,18 @@ fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt<'_, '_, '_>,
         return true;
     }
 
-    // #[used] also keeps the item alive forcefully,
-    // e.g. for placing it in a specific section.
-    if attr::contains_name(attrs, "used") {
+    // Don't lint about global allocators
+    if attr::contains_name(attrs, "global_allocator") {
         return true;
     }
 
-    // Don't lint about global allocators
-    if attr::contains_name(attrs, "global_allocator") {
+    let def_id = tcx.hir.local_def_id(id);
+    let cg_attrs = tcx.codegen_fn_attrs(def_id);
+
+    // #[used], #[no_mangle], #[export_name], etc also keeps the item alive
+    // forcefully, e.g. for placing it in a specific section.
+    if cg_attrs.contains_extern_indicator() ||
+        cg_attrs.flags.contains(CodegenFnAttrFlags::USED) {
         return true;
     }
 
@@ -494,8 +497,8 @@ fn symbol_is_live(&mut self,
                       ctor_id: Option<ast::NodeId>)
                       -> bool {
         if self.live_symbols.contains(&id)
-           || ctor_id.map_or(false,
-                             |ctor| self.live_symbols.contains(&ctor)) {
+           || ctor_id.map_or(false, |ctor| self.live_symbols.contains(&ctor))
+        {
             return true;
         }
         // If it's a type whose items are live, then it's live, too.
index 14551261819a6cd4309a87df5db14e3ed6d8cad9..95fb35165e7601599bed83d22c357c7e3eb55117 100644 (file)
@@ -163,7 +163,7 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 let src = tcx.used_crate_source(cnum);
                 if src.rlib.is_some() { continue }
                 sess.err(&format!("crate `{}` required to be available in rlib format, \
-                                  but was not found in this form",
+                                   but was not found in this form",
                                   tcx.crate_name(cnum)));
             }
             return Vec::new();
@@ -247,13 +247,13 @@ fn calculate_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     _ => "dylib",
                 };
                 sess.err(&format!("crate `{}` required to be available in {} format, \
-                                  but was not found in this form",
+                                   but was not found in this form",
                                   tcx.crate_name(cnum), kind));
             }
         }
     }
 
-    return ret;
+    ret
 }
 
 fn add_library(tcx: TyCtxt<'_, '_, '_>,
index b06d881bcaea41a54de2d5cdb04cb79918afe2c4..93fe607f5fa1499ca0882b8ffd42ca6a1f89ab90 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
 use hir::map as hir_map;
 use hir::def_id::{CRATE_DEF_INDEX};
 use session::{config, Session};
@@ -131,7 +130,7 @@ fn find_item(item: &Item, ctxt: &mut EntryContext<'_, '_>, at_root: bool) {
                 ctxt.attr_main_fn = Some((item.id, item.span));
             } else {
                 struct_span_err!(ctxt.session, item.span, E0137,
-                          "multiple functions with a #[main] attribute")
+                                 "multiple functions with a #[main] attribute")
                 .span_label(item.span, "additional #[main] function")
                 .span_label(ctxt.attr_main_fn.unwrap().1, "first #[main] function")
                 .emit();
@@ -141,11 +140,8 @@ fn find_item(item: &Item, ctxt: &mut EntryContext<'_, '_>, at_root: bool) {
             if ctxt.start_fn.is_none() {
                 ctxt.start_fn = Some((item.id, item.span));
             } else {
-                struct_span_err!(
-                    ctxt.session, item.span, E0138,
-                    "multiple 'start' functions")
-                    .span_label(ctxt.start_fn.unwrap().1,
-                                "previous `start` function here")
+                struct_span_err!(ctxt.session, item.span, E0138, "multiple 'start' functions")
+                    .span_label(ctxt.start_fn.unwrap().1, "previous `start` function here")
                     .span_label(item.span, "multiple `start` functions")
                     .emit();
             }
index 6a254f1a189b54c812618b939bbbf952468e068e..44572a1977ab4dd40580c44c3c4aa2e781d6daba 100644 (file)
@@ -35,12 +35,8 @@ pub enum SymbolExportLevel {
 
 impl SymbolExportLevel {
     pub fn is_below_threshold(self, threshold: SymbolExportLevel) -> bool {
-        if threshold == SymbolExportLevel::Rust {
-            // We export everything from Rust dylibs
-            true
-        } else {
-            self == SymbolExportLevel::C
-        }
+        threshold == SymbolExportLevel::Rust // export everything from Rust dylibs
+          || self == SymbolExportLevel::C
     }
 }
 
index 1a86dc4027e877d63038e0b0794156335439145c..d6b43ffe6da625dc73aefd8d0b4cb4761e88d814 100644 (file)
@@ -321,7 +321,7 @@ pub fn consume_body(&mut self, body: &hir::Body) {
                     region::Scope {
                         id: body.value.hir_id.local_id,
                         data: region::ScopeData::Node
-                    }));
+                }));
             let arg_cmt = Rc::new(self.mc.cat_rvalue(
                 arg.hir_id,
                 arg.pat.span,
@@ -402,20 +402,20 @@ pub fn walk_expr(&mut self, expr: &hir::Expr) {
                 self.walk_expr(&subexpr)
             }
 
-            hir::ExprKind::Unary(hir::UnDeref, ref base) => {      // *base
+            hir::ExprKind::Unary(hir::UnDeref, ref base) => { // *base
                 self.select_from_expr(&base);
             }
 
-            hir::ExprKind::Field(ref base, _) => {         // base.f
+            hir::ExprKind::Field(ref base, _) => { // base.f
                 self.select_from_expr(&base);
             }
 
-            hir::ExprKind::Index(ref lhs, ref rhs) => {       // lhs[rhs]
+            hir::ExprKind::Index(ref lhs, ref rhs) => { // lhs[rhs]
                 self.select_from_expr(&lhs);
                 self.consume_expr(&rhs);
             }
 
-            hir::ExprKind::Call(ref callee, ref args) => {    // callee(args)
+            hir::ExprKind::Call(ref callee, ref args) => { // callee(args)
                 self.walk_callee(expr, &callee);
                 self.consume_exprs(args);
             }
@@ -801,10 +801,8 @@ fn walk_arm(&mut self, discr_cmt: mc::cmt<'tcx>, arm: &hir::Arm, mode: MatchMode
             self.walk_pat(discr_cmt.clone(), &pat, mode);
         }
 
-        if let Some(ref guard) = arm.guard {
-            match guard {
-                hir::Guard::If(ref e) => self.consume_expr(e),
-            }
+        if let Some(hir::Guard::If(ref e)) = arm.guard {
+            self.consume_expr(e)
         }
 
         self.consume_expr(&arm.body);
@@ -826,12 +824,13 @@ fn determine_pat_move_mode(&mut self,
                                cmt_discr: mc::cmt<'tcx>,
                                pat: &hir::Pat,
                                mode: &mut TrackMatchMode) {
-        debug!("determine_pat_move_mode cmt_discr={:?} pat={:?}", cmt_discr,
-               pat);
+        debug!("determine_pat_move_mode cmt_discr={:?} pat={:?}", cmt_discr, pat);
+
         return_if_err!(self.mc.cat_pattern(cmt_discr, pat, |cmt_pat, pat| {
             if let PatKind::Binding(..) = pat.node {
-                let bm = *self.mc.tables.pat_binding_modes().get(pat.hir_id)
-                                                          .expect("missing binding mode");
+                let bm = *self.mc.tables.pat_binding_modes()
+                                        .get(pat.hir_id)
+                                        .expect("missing binding mode");
                 match bm {
                     ty::BindByReference(..) =>
                         mode.lub(BorrowingMatch),
index 8058f3dde668d8fd23f44eef940ecb1f15b929ed..9d54e798469f7f36fa33ccdae179cee9e895572d 100644 (file)
@@ -107,7 +107,7 @@ fn check_transmute(&self, span: Span, from: Ty<'tcx>, to: Ty<'tcx>) {
                 }
                 Err(LayoutError::Unknown(bad)) => {
                     if bad == ty {
-                        "this type's size can vary".to_string()
+                        "this type's size can vary".to_owned()
                     } else {
                         format!("size can vary because of {}", bad)
                     }
@@ -117,7 +117,7 @@ fn check_transmute(&self, span: Span, from: Ty<'tcx>, to: Ty<'tcx>) {
         };
 
         struct_span_err!(self.tcx.sess, span, E0512,
-            "transmute called with types of different sizes")
+                         "transmute called with types of different sizes")
             .note(&format!("source type: {} ({})", from, skeleton_string(from, sk_from)))
             .note(&format!("target type: {} ({})", to, skeleton_string(to, sk_to)))
             .emit();
index bfde4e4a3aed8abb8d94d85aa8381f15908f1633..0bd816b3e55f0ea5ea78ad1b1ffb015138187d0e 100644 (file)
@@ -39,7 +39,6 @@ macro_rules! language_item_table {
         $( $variant:ident, $name:expr, $method:ident; )*
     ) => {
 
-
 enum_from_u32! {
     #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
     pub enum LangItem {
@@ -145,8 +144,8 @@ fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItemCollector<'a, 'tcx> {
 
     fn collect_item(&mut self, item_index: usize, item_def_id: DefId) {
         // Check for duplicates.
-        match self.items.items[item_index] {
-            Some(original_def_id) if original_def_id != item_def_id => {
+        if let Some(original_def_id) = self.items.items[item_index] {
+            if original_def_id != item_def_id {
                 let name = LangItem::from_u32(item_index as u32).unwrap().name();
                 let mut err = match self.tcx.hir.span_if_local(item_def_id) {
                     Some(span) => struct_span_err!(
@@ -161,17 +160,13 @@ fn collect_item(&mut self, item_index: usize, item_def_id: DefId) {
                             name)),
                 };
                 if let Some(span) = self.tcx.hir.span_if_local(original_def_id) {
-                    span_note!(&mut err, span,
-                               "first defined here.");
+                    span_note!(&mut err, span, "first defined here.");
                 } else {
                     err.note(&format!("first defined in crate `{}`.",
                                       self.tcx.crate_name(original_def_id.krate)));
                 }
                 err.emit();
             }
-            _ => {
-                // OK.
-            }
         }
 
         // Matched.
@@ -194,7 +189,7 @@ pub fn extract(attrs: &[ast::Attribute]) -> Option<(Symbol, Span)> {
         }
     }
 
-    return None;
+    None
 }
 
 pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItems {
@@ -362,6 +357,9 @@ pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItems {
     AlignOffsetLangItem,             "align_offset",            align_offset_fn;
 
     TerminationTraitLangItem,        "termination",             termination;
+
+    Arc,                             "arc",                     arc;
+    Rc,                              "rc",                      rc;
 }
 
 impl<'a, 'tcx, 'gcx> TyCtxt<'a, 'tcx, 'gcx> {
index ec618de677318a613953bb3283ad4a7a9a35164d..6055a05158fe08a1e1ad93a1fa2833f03ea71614 100644 (file)
@@ -128,8 +128,8 @@ fn collect_feature(&mut self, feature: Symbol, since: Option<Symbol>, span: Span
                 let msg = format!(
                     "feature `{}` is declared {}, but was previously declared {}",
                     feature,
-                    if since.is_some() { "stable"} else { "unstable" },
-                    if since.is_none() { "stable"} else { "unstable" },
+                    if since.is_some() { "stable" } else { "unstable" },
+                    if since.is_none() { "stable" } else { "unstable" },
                 );
                 self.tcx.sess.struct_span_err_with_code(span, &msg,
                     DiagnosticId::Error("E0711".into())).emit();
index ff4b1fc2921b25bb8ce377c36382756362bc4409..1b258a23462c722b31a7e7875abb1ce38841b44e 100644 (file)
@@ -170,7 +170,7 @@ fn live_node_kind_to_string(lnk: LiveNodeKind, tcx: TyCtxt<'_, '_, '_>) -> Strin
         VarDefNode(s) => {
             format!("Var def node [{}]", cm.span_to_string(s))
         }
-        ExitNode => "Exit node".to_string(),
+        ExitNode => "Exit node".to_owned(),
     }
 }
 
@@ -257,7 +257,6 @@ enum VarKind {
 
 struct IrMaps<'a, 'tcx: 'a> {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-
     num_live_nodes: usize,
     num_vars: usize,
     live_node_map: HirIdMap<LiveNode>,
@@ -330,7 +329,7 @@ fn variable_name(&self, var: Variable) -> String {
             Local(LocalInfo { name, .. }) | Arg(_, name) => {
                 name.to_string()
             },
-            CleanExit => "<clean-exit>".to_string()
+            CleanExit => "<clean-exit>".to_owned()
         }
     }
 
@@ -474,13 +473,15 @@ fn visit_expr<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, expr: &'tcx Expr) {
         // construction site.
         let mut call_caps = Vec::new();
         ir.tcx.with_freevars(expr.id, |freevars| {
-            for fv in freevars {
+            call_caps.extend(freevars.iter().filter_map(|fv| {
                 if let Def::Local(rv) = fv.def {
                     let fv_ln = ir.add_live_node(FreeVarNode(fv.span));
                     let var_hid = ir.tcx.hir.node_to_hir_id(rv);
-                    call_caps.push(CaptureInfo { ln: fv_ln, var_hid });
+                    Some(CaptureInfo { ln: fv_ln, var_hid })
+                } else {
+                    None
                 }
-            }
+            }));
         });
         ir.set_captures(expr.id, call_caps);
 
@@ -918,8 +919,6 @@ fn acc(&mut self, ln: LiveNode, var: Variable, acc: u32) {
         self.rwu_table.assign_unpacked(idx, rwu);
     }
 
-    // _______________________________________________________________________
-
     fn compute(&mut self, body: &hir::Expr) -> LiveNode {
         // if there is a `break` or `again` at the top level, then it's
         // effectively a return---this only occurs in `for` loops,
@@ -941,10 +940,9 @@ fn compute(&mut self, body: &hir::Expr) -> LiveNode {
         let entry_ln = self.propagate_through_expr(body, s.fallthrough_ln);
 
         // hack to skip the loop unless debug! is enabled:
-        debug!("^^ liveness computation results for body {} (entry={:?})",
-               {
+        debug!("^^ liveness computation results for body {} (entry={:?})", {
                    for ln_idx in 0..self.ir.num_live_nodes {
-                       debug!("{:?}", self.ln_str(LiveNode(ln_idx as u32)));
+                        debug!("{:?}", self.ln_str(LiveNode(ln_idx as u32)));
                    }
                    body.id
                },
@@ -1026,241 +1024,232 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
         debug!("propagate_through_expr: {}", self.ir.tcx.hir.node_to_pretty_string(expr.id));
 
         match expr.node {
-          // Interesting cases with control flow or which gen/kill
-          hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) => {
-              self.access_path(expr.hir_id, path, succ, ACC_READ | ACC_USE)
-          }
+            // Interesting cases with control flow or which gen/kill
+            hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) => {
+                self.access_path(expr.hir_id, path, succ, ACC_READ | ACC_USE)
+            }
 
-          hir::ExprKind::Field(ref e, _) => {
-              self.propagate_through_expr(&e, succ)
-          }
+            hir::ExprKind::Field(ref e, _) => {
+                self.propagate_through_expr(&e, succ)
+            }
 
-          hir::ExprKind::Closure(.., blk_id, _, _) => {
-              debug!("{} is an ExprKind::Closure", self.ir.tcx.hir.node_to_pretty_string(expr.id));
-
-              // The next-node for a break is the successor of the entire
-              // loop. The next-node for a continue is the top of this loop.
-              let node = self.live_node(expr.hir_id, expr.span);
-
-              let break_ln = succ;
-              let cont_ln = node;
-              self.break_ln.insert(blk_id.node_id, break_ln);
-              self.cont_ln.insert(blk_id.node_id, cont_ln);
-
-              // the construction of a closure itself is not important,
-              // but we have to consider the closed over variables.
-              let caps = match self.ir.capture_info_map.get(&expr.id) {
-                  Some(caps) => caps.clone(),
-                  None => {
-                      span_bug!(expr.span, "no registered caps");
-                  }
-              };
-              caps.iter().rev().fold(succ, |succ, cap| {
-                  self.init_from_succ(cap.ln, succ);
-                  let var = self.variable(cap.var_hid, expr.span);
-                  self.acc(cap.ln, var, ACC_READ | ACC_USE);
-                  cap.ln
-              })
-          }
+            hir::ExprKind::Closure(.., blk_id, _, _) => {
+                debug!("{} is an ExprKind::Closure",
+                       self.ir.tcx.hir.node_to_pretty_string(expr.id));
+
+                // The next-node for a break is the successor of the entire
+                // loop. The next-node for a continue is the top of this loop.
+                let node = self.live_node(expr.hir_id, expr.span);
+
+                let break_ln = succ;
+                let cont_ln = node;
+                self.break_ln.insert(blk_id.node_id, break_ln);
+                self.cont_ln.insert(blk_id.node_id, cont_ln);
+
+                // the construction of a closure itself is not important,
+                // but we have to consider the closed over variables.
+                let caps = self.ir.capture_info_map.get(&expr.id).cloned().unwrap_or_else(||
+                    span_bug!(expr.span, "no registered caps"));
+
+                caps.iter().rev().fold(succ, |succ, cap| {
+                    self.init_from_succ(cap.ln, succ);
+                    let var = self.variable(cap.var_hid, expr.span);
+                    self.acc(cap.ln, var, ACC_READ | ACC_USE);
+                    cap.ln
+                })
+            }
 
-          hir::ExprKind::If(ref cond, ref then, ref els) => {
-            //
-            //     (cond)
-            //       |
-            //       v
-            //     (expr)
-            //     /   \
-            //    |     |
-            //    v     v
-            //  (then)(els)
-            //    |     |
-            //    v     v
-            //   (  succ  )
-            //
-            let else_ln = self.propagate_through_opt_expr(els.as_ref().map(|e| &**e), succ);
-            let then_ln = self.propagate_through_expr(&then, succ);
-            let ln = self.live_node(expr.hir_id, expr.span);
-            self.init_from_succ(ln, else_ln);
-            self.merge_from_succ(ln, then_ln, false);
-            self.propagate_through_expr(&cond, ln)
-          }
+            hir::ExprKind::If(ref cond, ref then, ref els) => {
+                //
+                //     (cond)
+                //       |
+                //       v
+                //     (expr)
+                //     /   \
+                //    |     |
+                //    v     v
+                //  (then)(els)
+                //    |     |
+                //    v     v
+                //   (  succ  )
+                //
+                let else_ln = self.propagate_through_opt_expr(els.as_ref().map(|e| &**e), succ);
+                let then_ln = self.propagate_through_expr(&then, succ);
+                let ln = self.live_node(expr.hir_id, expr.span);
+                self.init_from_succ(ln, else_ln);
+                self.merge_from_succ(ln, then_ln, false);
+                self.propagate_through_expr(&cond, ln)
+            }
 
-          hir::ExprKind::While(ref cond, ref blk, _) => {
-            self.propagate_through_loop(expr, WhileLoop(&cond), &blk, succ)
-          }
+            hir::ExprKind::While(ref cond, ref blk, _) => {
+                self.propagate_through_loop(expr, WhileLoop(&cond), &blk, succ)
+            }
 
-          // Note that labels have been resolved, so we don't need to look
-          // at the label ident
-          hir::ExprKind::Loop(ref blk, _, _) => {
-            self.propagate_through_loop(expr, LoopLoop, &blk, succ)
-          }
+            // Note that labels have been resolved, so we don't need to look
+            // at the label ident
+            hir::ExprKind::Loop(ref blk, _, _) => {
+                self.propagate_through_loop(expr, LoopLoop, &blk, succ)
+            }
 
-          hir::ExprKind::Match(ref e, ref arms, _) => {
-            //
-            //      (e)
-            //       |
-            //       v
-            //     (expr)
-            //     / | \
-            //    |  |  |
-            //    v  v  v
-            //   (..arms..)
-            //    |  |  |
-            //    v  v  v
-            //   (  succ  )
-            //
-            //
-            let ln = self.live_node(expr.hir_id, expr.span);
-            self.init_empty(ln, succ);
-            let mut first_merge = true;
-            for arm in arms {
-                let body_succ =
-                    self.propagate_through_expr(&arm.body, succ);
-                let guard_succ =
-                    self.propagate_through_opt_expr(
-                        arm.guard.as_ref().map(|g|
-                            match g {
-                                hir::Guard::If(e) => &**e,
-                            }),
-                        body_succ);
-                // only consider the first pattern; any later patterns must have
-                // the same bindings, and we also consider the first pattern to be
-                // the "authoritative" set of ids
-                let arm_succ =
-                    self.define_bindings_in_arm_pats(arm.pats.first().map(|p| &**p),
-                                                     guard_succ);
-                self.merge_from_succ(ln, arm_succ, first_merge);
-                first_merge = false;
-            };
-            self.propagate_through_expr(&e, ln)
-          }
+            hir::ExprKind::Match(ref e, ref arms, _) => {
+                //
+                //      (e)
+                //       |
+                //       v
+                //     (expr)
+                //     / | \
+                //    |  |  |
+                //    v  v  v
+                //   (..arms..)
+                //    |  |  |
+                //    v  v  v
+                //   (  succ  )
+                //
+                //
+                let ln = self.live_node(expr.hir_id, expr.span);
+                self.init_empty(ln, succ);
+                let mut first_merge = true;
+                for arm in arms {
+                    let body_succ = self.propagate_through_expr(&arm.body, succ);
+
+                    let guard_succ = self.propagate_through_opt_expr(
+                        arm.guard.as_ref().map(|hir::Guard::If(e)| &**e),
+                        body_succ
+                    );
+                    // only consider the first pattern; any later patterns must have
+                    // the same bindings, and we also consider the first pattern to be
+                    // the "authoritative" set of ids
+                    let arm_succ =
+                        self.define_bindings_in_arm_pats(arm.pats.first().map(|p| &**p),
+                                                         guard_succ);
+                    self.merge_from_succ(ln, arm_succ, first_merge);
+                    first_merge = false;
+                };
+                self.propagate_through_expr(&e, ln)
+            }
 
-          hir::ExprKind::Ret(ref o_e) => {
-            // ignore succ and subst exit_ln:
-            let exit_ln = self.s.exit_ln;
-            self.propagate_through_opt_expr(o_e.as_ref().map(|e| &**e), exit_ln)
-          }
+            hir::ExprKind::Ret(ref o_e) => {
+                // ignore succ and subst exit_ln:
+                let exit_ln = self.s.exit_ln;
+                self.propagate_through_opt_expr(o_e.as_ref().map(|e| &**e), exit_ln)
+            }
 
-          hir::ExprKind::Break(label, ref opt_expr) => {
-              // Find which label this break jumps to
-              let target = match label.target_id {
+            hir::ExprKind::Break(label, ref opt_expr) => {
+                // Find which label this break jumps to
+                let target = match label.target_id {
                     Ok(node_id) => self.break_ln.get(&node_id),
                     Err(err) => span_bug!(expr.span, "loop scope error: {}", err),
-              }.map(|x| *x);
-
-              // Now that we know the label we're going to,
-              // look it up in the break loop nodes table
+                }.cloned();
 
-              match target {
-                  Some(b) => self.propagate_through_opt_expr(opt_expr.as_ref().map(|e| &**e), b),
-                  None => span_bug!(expr.span, "break to unknown label")
-              }
-          }
+                // Now that we know the label we're going to,
+                // look it up in the break loop nodes table
 
-          hir::ExprKind::Continue(label) => {
-              // Find which label this expr continues to
-              let sc = match label.target_id {
-                    Ok(node_id) => node_id,
-                    Err(err) => span_bug!(expr.span, "loop scope error: {}", err),
-              };
+                match target {
+                    Some(b) => self.propagate_through_opt_expr(opt_expr.as_ref().map(|e| &**e), b),
+                    None => span_bug!(expr.span, "break to unknown label")
+                }
+            }
 
-              // Now that we know the label we're going to,
-              // look it up in the continue loop nodes table
+            hir::ExprKind::Continue(label) => {
+                // Find which label this expr continues to
+                let sc = label.target_id.unwrap_or_else(|err|
+                    span_bug!(expr.span, "loop scope error: {}", err));
 
-              match self.cont_ln.get(&sc) {
-                  Some(&b) => b,
-                  None => span_bug!(expr.span, "continue to unknown label")
-              }
-          }
-
-          hir::ExprKind::Assign(ref l, ref r) => {
-            // see comment on places in
-            // propagate_through_place_components()
-            let succ = self.write_place(&l, succ, ACC_WRITE);
-            let succ = self.propagate_through_place_components(&l, succ);
-            self.propagate_through_expr(&r, succ)
-          }
+                // Now that we know the label we're going to,
+                // look it up in the continue loop nodes table
+                self.cont_ln.get(&sc).cloned().unwrap_or_else(||
+                    span_bug!(expr.span, "continue to unknown label"))
+            }
 
-          hir::ExprKind::AssignOp(_, ref l, ref r) => {
-            // an overloaded assign op is like a method call
-            if self.tables.is_method_call(expr) {
-                let succ = self.propagate_through_expr(&l, succ);
-                self.propagate_through_expr(&r, succ)
-            } else {
+            hir::ExprKind::Assign(ref l, ref r) => {
                 // see comment on places in
                 // propagate_through_place_components()
-                let succ = self.write_place(&l, succ, ACC_WRITE|ACC_READ);
-                let succ = self.propagate_through_expr(&r, succ);
-                self.propagate_through_place_components(&l, succ)
+                let succ = self.write_place(&l, succ, ACC_WRITE);
+                let succ = self.propagate_through_place_components(&l, succ);
+                self.propagate_through_expr(&r, succ)
             }
-          }
 
-          // Uninteresting cases: just propagate in rev exec order
+            hir::ExprKind::AssignOp(_, ref l, ref r) => {
+                // an overloaded assign op is like a method call
+                if self.tables.is_method_call(expr) {
+                    let succ = self.propagate_through_expr(&l, succ);
+                    self.propagate_through_expr(&r, succ)
+                } else {
+                    // see comment on places in
+                    // propagate_through_place_components()
+                    let succ = self.write_place(&l, succ, ACC_WRITE|ACC_READ);
+                    let succ = self.propagate_through_expr(&r, succ);
+                    self.propagate_through_place_components(&l, succ)
+                }
+            }
 
-          hir::ExprKind::Array(ref exprs) => {
-            self.propagate_through_exprs(exprs, succ)
-          }
+            // Uninteresting cases: just propagate in rev exec order
 
-          hir::ExprKind::Struct(_, ref fields, ref with_expr) => {
-            let succ = self.propagate_through_opt_expr(with_expr.as_ref().map(|e| &**e), succ);
-            fields.iter().rev().fold(succ, |succ, field| {
-                self.propagate_through_expr(&field.expr, succ)
-            })
-          }
+            hir::ExprKind::Array(ref exprs) => {
+                self.propagate_through_exprs(exprs, succ)
+            }
 
-          hir::ExprKind::Call(ref f, ref args) => {
-            // FIXME(canndrew): This is_never should really be an is_uninhabited
-            let succ = if self.tables.expr_ty(expr).is_never() {
-                self.s.exit_ln
-            } else {
-                succ
-            };
-            let succ = self.propagate_through_exprs(args, succ);
-            self.propagate_through_expr(&f, succ)
-          }
+            hir::ExprKind::Struct(_, ref fields, ref with_expr) => {
+                let succ = self.propagate_through_opt_expr(with_expr.as_ref().map(|e| &**e), succ);
+                fields.iter().rev().fold(succ, |succ, field| {
+                    self.propagate_through_expr(&field.expr, succ)
+                })
+            }
 
-          hir::ExprKind::MethodCall(.., ref args) => {
-            // FIXME(canndrew): This is_never should really be an is_uninhabited
-            let succ = if self.tables.expr_ty(expr).is_never() {
-                self.s.exit_ln
-            } else {
-                succ
-            };
-            self.propagate_through_exprs(args, succ)
-          }
+            hir::ExprKind::Call(ref f, ref args) => {
+                // FIXME(canndrew): This is_never should really be an is_uninhabited
+                let succ = if self.tables.expr_ty(expr).is_never() {
+                    self.s.exit_ln
+                } else {
+                    succ
+                };
+                let succ = self.propagate_through_exprs(args, succ);
+                self.propagate_through_expr(&f, succ)
+            }
 
-          hir::ExprKind::Tup(ref exprs) => {
-            self.propagate_through_exprs(exprs, succ)
-          }
+            hir::ExprKind::MethodCall(.., ref args) => {
+                // FIXME(canndrew): This is_never should really be an is_uninhabited
+                let succ = if self.tables.expr_ty(expr).is_never() {
+                    self.s.exit_ln
+                } else {
+                    succ
+                };
 
-          hir::ExprKind::Binary(op, ref l, ref r) if op.node.is_lazy() => {
-            let r_succ = self.propagate_through_expr(&r, succ);
+                self.propagate_through_exprs(args, succ)
+            }
 
-            let ln = self.live_node(expr.hir_id, expr.span);
-            self.init_from_succ(ln, succ);
-            self.merge_from_succ(ln, r_succ, false);
+            hir::ExprKind::Tup(ref exprs) => {
+                self.propagate_through_exprs(exprs, succ)
+            }
 
-            self.propagate_through_expr(&l, ln)
-          }
+            hir::ExprKind::Binary(op, ref l, ref r) if op.node.is_lazy() => {
+                let r_succ = self.propagate_through_expr(&r, succ);
 
-          hir::ExprKind::Index(ref l, ref r) |
-          hir::ExprKind::Binary(_, ref l, ref r) => {
-            let r_succ = self.propagate_through_expr(&r, succ);
-            self.propagate_through_expr(&l, r_succ)
-          }
+                let ln = self.live_node(expr.hir_id, expr.span);
+                self.init_from_succ(ln, succ);
+                self.merge_from_succ(ln, r_succ, false);
 
-          hir::ExprKind::Box(ref e) |
-          hir::ExprKind::AddrOf(_, ref e) |
-          hir::ExprKind::Cast(ref e, _) |
-          hir::ExprKind::Type(ref e, _) |
-          hir::ExprKind::Unary(_, ref e) |
-          hir::ExprKind::Yield(ref e) |
-          hir::ExprKind::Repeat(ref e, _) => {
-            self.propagate_through_expr(&e, succ)
-          }
+                self.propagate_through_expr(&l, ln)
+            }
+
+            hir::ExprKind::Index(ref l, ref r) |
+            hir::ExprKind::Binary(_, ref l, ref r) => {
+                let r_succ = self.propagate_through_expr(&r, succ);
+                self.propagate_through_expr(&l, r_succ)
+            }
+
+            hir::ExprKind::Box(ref e) |
+            hir::ExprKind::AddrOf(_, ref e) |
+            hir::ExprKind::Cast(ref e, _) |
+            hir::ExprKind::Type(ref e, _) |
+            hir::ExprKind::Unary(_, ref e) |
+            hir::ExprKind::Yield(ref e) |
+            hir::ExprKind::Repeat(ref e, _) => {
+                self.propagate_through_expr(&e, succ)
+            }
 
-          hir::ExprKind::InlineAsm(ref ia, ref outputs, ref inputs) => {
-            let succ = ia.outputs.iter().zip(outputs).rev().fold(succ, |succ, (o, output)| {
+            hir::ExprKind::InlineAsm(ref ia, ref outputs, ref inputs) => {
+                let succ = ia.outputs.iter().zip(outputs).rev().fold(succ, |succ, (o, output)| {
                 // see comment on places
                 // in propagate_through_place_components()
                 if o.is_indirect {
@@ -1269,29 +1258,28 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
                     let acc = if o.is_rw { ACC_WRITE|ACC_READ } else { ACC_WRITE };
                     let succ = self.write_place(output, succ, acc);
                     self.propagate_through_place_components(output, succ)
-                }
-            });
+                }});
 
-            // Inputs are executed first. Propagate last because of rev order
-            self.propagate_through_exprs(inputs, succ)
-          }
+                // Inputs are executed first. Propagate last because of rev order
+                self.propagate_through_exprs(inputs, succ)
+            }
 
-          hir::ExprKind::Lit(..) | hir::ExprKind::Path(hir::QPath::TypeRelative(..)) => {
-            succ
-          }
+            hir::ExprKind::Lit(..) | hir::ExprKind::Path(hir::QPath::TypeRelative(..)) => {
+                succ
+            }
 
-          // Note that labels have been resolved, so we don't need to look
-          // at the label ident
-          hir::ExprKind::Block(ref blk, _) => {
-            self.propagate_through_block(&blk, succ)
-          }
+            // Note that labels have been resolved, so we don't need to look
+            // at the label ident
+            hir::ExprKind::Block(ref blk, _) => {
+                self.propagate_through_block(&blk, succ)
+            }
         }
     }
 
     fn propagate_through_place_components(&mut self,
-                                           expr: &Expr,
-                                           succ: LiveNode)
-                                           -> LiveNode {
+                                          expr: &Expr,
+                                          succ: LiveNode)
+                                          -> LiveNode {
         // # Places
         //
         // In general, the full flow graph structure for an
@@ -1349,18 +1337,17 @@ fn propagate_through_place_components(&mut self,
     }
 
     // see comment on propagate_through_place()
-    fn write_place(&mut self, expr: &Expr, succ: LiveNode, acc: u32)
-                    -> LiveNode {
+    fn write_place(&mut self, expr: &Expr, succ: LiveNode, acc: u32) -> LiveNode {
         match expr.node {
-          hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) => {
-              self.access_path(expr.hir_id, path, succ, acc)
-          }
+            hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) => {
+                self.access_path(expr.hir_id, path, succ, acc)
+            }
 
-          // We do not track other places, so just propagate through
-          // to their subcomponents.  Also, it may happen that
-          // non-places occur here, because those are detected in the
-          // later pass borrowck.
-          _ => succ
+            // We do not track other places, so just propagate through
+            // to their subcomponents.  Also, it may happen that
+            // non-places occur here, because those are detected in the
+            // later pass borrowck.
+            _ => succ
         }
     }
 
@@ -1379,10 +1366,10 @@ fn access_var(&mut self, hir_id: HirId, nid: NodeId, succ: LiveNode, acc: u32, s
     fn access_path(&mut self, hir_id: HirId, path: &hir::Path, succ: LiveNode, acc: u32)
                    -> LiveNode {
         match path.def {
-          Def::Local(nid) => {
-            self.access_var(hir_id, nid, succ, acc, path.span)
-          }
-          _ => succ
+            Def::Local(nid) => {
+              self.access_var(hir_id, nid, succ, acc, path.span)
+            }
+            _ => succ
         }
     }
 
@@ -1392,7 +1379,6 @@ fn propagate_through_loop(&mut self,
                               body: &hir::Block,
                               succ: LiveNode)
                               -> LiveNode {
-
         /*
 
         We model control flow like this:
@@ -1450,8 +1436,8 @@ fn propagate_through_loop(&mut self,
                     self.propagate_through_expr(&cond, ln)
                 }
             };
-            assert!(cond_ln == new_cond_ln);
-            assert!(body_ln == self.propagate_through_block(body, cond_ln));
+            assert_eq!(cond_ln, new_cond_ln);
+            assert_eq!(body_ln, self.propagate_through_block(body, cond_ln));
         }
 
         cond_ln
@@ -1505,49 +1491,49 @@ fn check_arm<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, arm: &'tcx hir::Arm) {
 
 fn check_expr<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, expr: &'tcx Expr) {
     match expr.node {
-      hir::ExprKind::Assign(ref l, _) => {
-        this.check_place(&l);
-
-        intravisit::walk_expr(this, expr);
-      }
-
-      hir::ExprKind::AssignOp(_, ref l, _) => {
-        if !this.tables.is_method_call(expr) {
+        hir::ExprKind::Assign(ref l, _) => {
             this.check_place(&l);
+
+            intravisit::walk_expr(this, expr);
         }
 
-        intravisit::walk_expr(this, expr);
-      }
+        hir::ExprKind::AssignOp(_, ref l, _) => {
+            if !this.tables.is_method_call(expr) {
+                this.check_place(&l);
+            }
 
-      hir::ExprKind::InlineAsm(ref ia, ref outputs, ref inputs) => {
-        for input in inputs {
-          this.visit_expr(input);
+            intravisit::walk_expr(this, expr);
         }
 
-        // Output operands must be places
-        for (o, output) in ia.outputs.iter().zip(outputs) {
-          if !o.is_indirect {
-            this.check_place(output);
-          }
-          this.visit_expr(output);
-        }
+        hir::ExprKind::InlineAsm(ref ia, ref outputs, ref inputs) => {
+            for input in inputs {
+                this.visit_expr(input);
+            }
 
-        intravisit::walk_expr(this, expr);
-      }
+            // Output operands must be places
+            for (o, output) in ia.outputs.iter().zip(outputs) {
+                if !o.is_indirect {
+                    this.check_place(output);
+                }
+                this.visit_expr(output);
+            }
 
-      // no correctness conditions related to liveness
-      hir::ExprKind::Call(..) | hir::ExprKind::MethodCall(..) | hir::ExprKind::If(..) |
-      hir::ExprKind::Match(..) | hir::ExprKind::While(..) | hir::ExprKind::Loop(..) |
-      hir::ExprKind::Index(..) | hir::ExprKind::Field(..) |
-      hir::ExprKind::Array(..) | hir::ExprKind::Tup(..) | hir::ExprKind::Binary(..) |
-      hir::ExprKind::Cast(..) | hir::ExprKind::Unary(..) | hir::ExprKind::Ret(..) |
-      hir::ExprKind::Break(..) | hir::ExprKind::Continue(..) | hir::ExprKind::Lit(_) |
-      hir::ExprKind::Block(..) | hir::ExprKind::AddrOf(..) |
-      hir::ExprKind::Struct(..) | hir::ExprKind::Repeat(..) |
-      hir::ExprKind::Closure(..) | hir::ExprKind::Path(_) | hir::ExprKind::Yield(..) |
-      hir::ExprKind::Box(..) | hir::ExprKind::Type(..) => {
-        intravisit::walk_expr(this, expr);
-      }
+            intravisit::walk_expr(this, expr);
+        }
+
+        // no correctness conditions related to liveness
+        hir::ExprKind::Call(..) | hir::ExprKind::MethodCall(..) | hir::ExprKind::If(..) |
+        hir::ExprKind::Match(..) | hir::ExprKind::While(..) | hir::ExprKind::Loop(..) |
+        hir::ExprKind::Index(..) | hir::ExprKind::Field(..) |
+        hir::ExprKind::Array(..) | hir::ExprKind::Tup(..) | hir::ExprKind::Binary(..) |
+        hir::ExprKind::Cast(..) | hir::ExprKind::Unary(..) | hir::ExprKind::Ret(..) |
+        hir::ExprKind::Break(..) | hir::ExprKind::Continue(..) | hir::ExprKind::Lit(_) |
+        hir::ExprKind::Block(..) | hir::ExprKind::AddrOf(..) |
+        hir::ExprKind::Struct(..) | hir::ExprKind::Repeat(..) |
+        hir::ExprKind::Closure(..) | hir::ExprKind::Path(_) | hir::ExprKind::Yield(..) |
+        hir::ExprKind::Box(..) | hir::ExprKind::Type(..) => {
+            intravisit::walk_expr(this, expr);
+        }
     }
 }
 
@@ -1576,7 +1562,7 @@ fn check_place(&mut self, expr: &'tcx Expr) {
 
     fn should_warn(&self, var: Variable) -> Option<String> {
         let name = self.ir.variable_name(var);
-        if name.is_empty() || name.as_bytes()[0] == ('_' as u8) {
+        if name.is_empty() || name.as_bytes()[0] == b'_' {
             None
         } else {
             Some(name)
@@ -1617,7 +1603,6 @@ fn warn_about_unused(&self,
         if !self.used_on_entry(ln, var) {
             let r = self.should_warn(var);
             if let Some(name) = r {
-
                 // annoying: for parameters in funcs like `fn(x: i32)
                 // {ret}`, there is only one node, so asking about
                 // assigned_on_exit() is not meaningful.
@@ -1627,8 +1612,7 @@ fn warn_about_unused(&self,
                     self.assigned_on_exit(ln, var).is_some()
                 };
 
-                let suggest_underscore_msg = format!("consider using `_{}` instead",
-                                                     name);
+                let suggest_underscore_msg = format!("consider using `_{}` instead", name);
 
                 if is_assigned {
                     self.ir.tcx
index 13c969cec297e9e37d83cfe2b4486c22089026fc..13e6f7a4c745a18c4e884d1c4579202f1540ed41 100644 (file)
@@ -83,6 +83,7 @@
 use syntax::ast::{self, Name};
 use syntax_pos::Span;
 
+use std::borrow::Cow;
 use std::fmt;
 use std::hash::{Hash, Hasher};
 use rustc_data_structures::sync::Lrc;
 
 #[derive(Clone, Debug, PartialEq)]
 pub enum Categorization<'tcx> {
-    Rvalue(ty::Region<'tcx>),              // temporary val, argument is its scope
+    Rvalue(ty::Region<'tcx>),            // temporary val, argument is its scope
     StaticItem,
-    Upvar(Upvar),                          // upvar referenced by closure env
-    Local(ast::NodeId),                    // local variable
+    Upvar(Upvar),                        // upvar referenced by closure env
+    Local(ast::NodeId),                  // local variable
     Deref(cmt<'tcx>, PointerKind<'tcx>), // deref of a ptr
-    Interior(cmt<'tcx>, InteriorKind),     // something interior: field, tuple, etc
-    Downcast(cmt<'tcx>, DefId),            // selects a particular enum variant (*1)
+    Interior(cmt<'tcx>, InteriorKind),   // something interior: field, tuple, etc
+    Downcast(cmt<'tcx>, DefId),          // selects a particular enum variant (*1)
 
     // (*1) downcast is only required if the enum has more than one variant
 }
@@ -149,8 +150,8 @@ fn hash<H: Hasher>(&self, h: &mut H) {
 
 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
 pub enum InteriorOffsetKind {
-    Index,            // e.g. `array_expr[index_expr]`
-    Pattern,          // e.g. `fn foo([_, a, _, _]: [A; 4]) { ... }`
+    Index,   // e.g. `array_expr[index_expr]`
+    Pattern, // e.g. `fn foo([_, a, _, _]: [A; 4]) { ... }`
 }
 
 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
@@ -580,7 +581,7 @@ pub fn cat_expr(&self, expr: &hir::Expr) -> McResult<cmt_<'tcx>> {
         fn helper<'a, 'gcx, 'tcx>(mc: &MemCategorizationContext<'a, 'gcx, 'tcx>,
                                   expr: &hir::Expr,
                                   adjustments: &[adjustment::Adjustment<'tcx>])
-                                   -> McResult<cmt_<'tcx>> {
+                                  -> McResult<cmt_<'tcx>> {
             match adjustments.split_last() {
                 None => mc.cat_expr_unadjusted(expr),
                 Some((adjustment, previous)) => {
@@ -640,61 +641,61 @@ pub fn cat_expr_unadjusted(&self, expr: &hir::Expr) -> McResult<cmt_<'tcx>> {
 
         let expr_ty = self.expr_ty(expr)?;
         match expr.node {
-          hir::ExprKind::Unary(hir::UnDeref, ref e_base) => {
-            if self.tables.is_method_call(expr) {
-                self.cat_overloaded_place(expr, e_base, NoteNone)
-            } else {
-                let base_cmt = Rc::new(self.cat_expr(&e_base)?);
-                self.cat_deref(expr, base_cmt, NoteNone)
+            hir::ExprKind::Unary(hir::UnDeref, ref e_base) => {
+                if self.tables.is_method_call(expr) {
+                    self.cat_overloaded_place(expr, e_base, NoteNone)
+                } else {
+                    let base_cmt = Rc::new(self.cat_expr(&e_base)?);
+                    self.cat_deref(expr, base_cmt, NoteNone)
+                }
             }
-          }
-
-          hir::ExprKind::Field(ref base, f_ident) => {
-            let base_cmt = Rc::new(self.cat_expr(&base)?);
-            debug!("cat_expr(cat_field): id={} expr={:?} base={:?}",
-                   expr.id,
-                   expr,
-                   base_cmt);
-            let f_index = self.tcx.field_index(expr.id, self.tables);
-            Ok(self.cat_field(expr, base_cmt, f_index, f_ident, expr_ty))
-          }
-
-          hir::ExprKind::Index(ref base, _) => {
-            if self.tables.is_method_call(expr) {
-                // If this is an index implemented by a method call, then it
-                // will include an implicit deref of the result.
-                // The call to index() returns a `&T` value, which
-                // is an rvalue. That is what we will be
-                // dereferencing.
-                self.cat_overloaded_place(expr, base, NoteIndex)
-            } else {
+
+            hir::ExprKind::Field(ref base, f_ident) => {
                 let base_cmt = Rc::new(self.cat_expr(&base)?);
-                self.cat_index(expr, base_cmt, expr_ty, InteriorOffsetKind::Index)
+                debug!("cat_expr(cat_field): id={} expr={:?} base={:?}",
+                       expr.id,
+                       expr,
+                       base_cmt);
+                let f_index = self.tcx.field_index(expr.id, self.tables);
+                Ok(self.cat_field(expr, base_cmt, f_index, f_ident, expr_ty))
+            }
+
+            hir::ExprKind::Index(ref base, _) => {
+                if self.tables.is_method_call(expr) {
+                    // If this is an index implemented by a method call, then it
+                    // will include an implicit deref of the result.
+                    // The call to index() returns a `&T` value, which
+                    // is an rvalue. That is what we will be
+                    // dereferencing.
+                    self.cat_overloaded_place(expr, base, NoteIndex)
+                } else {
+                    let base_cmt = Rc::new(self.cat_expr(&base)?);
+                    self.cat_index(expr, base_cmt, expr_ty, InteriorOffsetKind::Index)
+                }
+            }
+
+            hir::ExprKind::Path(ref qpath) => {
+                let def = self.tables.qpath_def(qpath, expr.hir_id);
+                self.cat_def(expr.hir_id, expr.span, expr_ty, def)
+            }
+
+            hir::ExprKind::Type(ref e, _) => {
+                self.cat_expr(&e)
+            }
+
+            hir::ExprKind::AddrOf(..) | hir::ExprKind::Call(..) |
+            hir::ExprKind::Assign(..) | hir::ExprKind::AssignOp(..) |
+            hir::ExprKind::Closure(..) | hir::ExprKind::Ret(..) |
+            hir::ExprKind::Unary(..) | hir::ExprKind::Yield(..) |
+            hir::ExprKind::MethodCall(..) | hir::ExprKind::Cast(..) |
+            hir::ExprKind::Array(..) | hir::ExprKind::Tup(..) | hir::ExprKind::If(..) |
+            hir::ExprKind::Binary(..) | hir::ExprKind::While(..) |
+            hir::ExprKind::Block(..) | hir::ExprKind::Loop(..) | hir::ExprKind::Match(..) |
+            hir::ExprKind::Lit(..) | hir::ExprKind::Break(..) |
+            hir::ExprKind::Continue(..) | hir::ExprKind::Struct(..) | hir::ExprKind::Repeat(..) |
+            hir::ExprKind::InlineAsm(..) | hir::ExprKind::Box(..) => {
+                Ok(self.cat_rvalue_node(expr.hir_id, expr.span, expr_ty))
             }
-          }
-
-          hir::ExprKind::Path(ref qpath) => {
-              let def = self.tables.qpath_def(qpath, expr.hir_id);
-              self.cat_def(expr.hir_id, expr.span, expr_ty, def)
-          }
-
-          hir::ExprKind::Type(ref e, _) => {
-            self.cat_expr(&e)
-          }
-
-          hir::ExprKind::AddrOf(..) | hir::ExprKind::Call(..) |
-          hir::ExprKind::Assign(..) | hir::ExprKind::AssignOp(..) |
-          hir::ExprKind::Closure(..) | hir::ExprKind::Ret(..) |
-          hir::ExprKind::Unary(..) | hir::ExprKind::Yield(..) |
-          hir::ExprKind::MethodCall(..) | hir::ExprKind::Cast(..) |
-          hir::ExprKind::Array(..) | hir::ExprKind::Tup(..) | hir::ExprKind::If(..) |
-          hir::ExprKind::Binary(..) | hir::ExprKind::While(..) |
-          hir::ExprKind::Block(..) | hir::ExprKind::Loop(..) | hir::ExprKind::Match(..) |
-          hir::ExprKind::Lit(..) | hir::ExprKind::Break(..) |
-          hir::ExprKind::Continue(..) | hir::ExprKind::Struct(..) | hir::ExprKind::Repeat(..) |
-          hir::ExprKind::InlineAsm(..) | hir::ExprKind::Box(..) => {
-            Ok(self.cat_rvalue_node(expr.hir_id, expr.span, expr_ty))
-          }
         }
     }
 
@@ -708,44 +709,45 @@ pub fn cat_def(&self,
                hir_id, expr_ty, def);
 
         match def {
-          Def::StructCtor(..) | Def::VariantCtor(..) | Def::Const(..) |
-          Def::AssociatedConst(..) | Def::Fn(..) | Def::Method(..) | Def::SelfCtor(..) => {
+            Def::StructCtor(..) | Def::VariantCtor(..) | Def::Const(..) |
+            Def::AssociatedConst(..) | Def::Fn(..) | Def::Method(..) | Def::SelfCtor(..) => {
                 Ok(self.cat_rvalue_node(hir_id, span, expr_ty))
-          }
+            }
 
-          Def::Static(def_id, mutbl) => {
-            // `#[thread_local]` statics may not outlive the current function.
-            for attr in &self.tcx.get_attrs(def_id)[..] {
-                if attr.check_name("thread_local") {
-                    return Ok(self.cat_rvalue_node(hir_id, span, expr_ty));
+            Def::Static(def_id, mutbl) => {
+                // `#[thread_local]` statics may not outlive the current function.
+                for attr in &self.tcx.get_attrs(def_id)[..] {
+                    if attr.check_name("thread_local") {
+                        return Ok(self.cat_rvalue_node(hir_id, span, expr_ty));
+                    }
                 }
+
+                Ok(cmt_ {
+                    hir_id,
+                    span:span,
+                    cat:Categorization::StaticItem,
+                    mutbl: if mutbl { McDeclared } else { McImmutable},
+                    ty:expr_ty,
+                    note: NoteNone
+                })
+            }
+
+            Def::Upvar(var_id, _, fn_node_id) => {
+                self.cat_upvar(hir_id, span, var_id, fn_node_id)
             }
-              Ok(cmt_ {
-                  hir_id,
-                  span:span,
-                  cat:Categorization::StaticItem,
-                  mutbl: if mutbl { McDeclared } else { McImmutable},
-                  ty:expr_ty,
-                  note: NoteNone
-              })
-          }
-
-          Def::Upvar(var_id, _, fn_node_id) => {
-              self.cat_upvar(hir_id, span, var_id, fn_node_id)
-          }
-
-          Def::Local(vid) => {
-            Ok(cmt_ {
-                hir_id,
-                span,
-                cat: Categorization::Local(vid),
-                mutbl: MutabilityCategory::from_local(self.tcx, self.tables, vid),
-                ty: expr_ty,
-                note: NoteNone
-            })
-          }
 
-          def => span_bug!(span, "unexpected definition in memory categorization: {:?}", def)
+            Def::Local(vid) => {
+                Ok(cmt_ {
+                    hir_id,
+                    span,
+                    cat: Categorization::Local(vid),
+                    mutbl: MutabilityCategory::from_local(self.tcx, self.tables, vid),
+                    ty: expr_ty,
+                    note: NoteNone
+                })
+            }
+
+            def => span_bug!(span, "unexpected definition in memory categorization: {:?}", def)
         }
     }
 
@@ -941,19 +943,13 @@ pub fn cat_rvalue_node(&self,
                            span: Span,
                            expr_ty: Ty<'tcx>)
                            -> cmt_<'tcx> {
-        debug!(
-            "cat_rvalue_node(id={:?}, span={:?}, expr_ty={:?})",
-            hir_id,
-            span,
-            expr_ty,
-        );
+        debug!("cat_rvalue_node(id={:?}, span={:?}, expr_ty={:?})",
+               hir_id, span, expr_ty);
+
         let promotable = self.rvalue_promotable_map.as_ref().map(|m| m.contains(&hir_id.local_id))
                                                             .unwrap_or(false);
 
-        debug!(
-            "cat_rvalue_node: promotable = {:?}",
-            promotable,
-        );
+        debug!("cat_rvalue_node: promotable = {:?}", promotable);
 
         // Always promote `[T; 0]` (even when e.g. borrowed mutably).
         let promotable = match expr_ty.sty {
@@ -961,10 +957,7 @@ pub fn cat_rvalue_node(&self,
             _ => promotable,
         };
 
-        debug!(
-            "cat_rvalue_node: promotable = {:?} (2)",
-            promotable,
-        );
+        debug!("cat_rvalue_node: promotable = {:?} (2)", promotable);
 
         // Compute maximum lifetime of this rvalue. This is 'static if
         // we can promote to a constant, otherwise equal to enclosing temp
@@ -1022,12 +1015,10 @@ fn cat_overloaded_place(
         base: &hir::Expr,
         note: Note,
     ) -> McResult<cmt_<'tcx>> {
-        debug!(
-            "cat_overloaded_place(expr={:?}, base={:?}, note={:?})",
-            expr,
-            base,
-            note,
-        );
+        debug!("cat_overloaded_place(expr={:?}, base={:?}, note={:?})",
+               expr,
+               base,
+               note);
 
         // Reconstruct the output assuming it's a reference with the
         // same region and mutability as the receiver. This holds for
@@ -1037,9 +1028,7 @@ fn cat_overloaded_place(
 
         let (region, mutbl) = match base_ty.sty {
             ty::Ref(region, _, mutbl) => (region, mutbl),
-            _ => {
-                span_bug!(expr.span, "cat_overloaded_place: base is not a reference")
-            }
+            _ => span_bug!(expr.span, "cat_overloaded_place: base is not a reference")
         };
         let ref_ty = self.tcx.mk_ref(region, ty::TypeAndMut {
             ty: place_ty,
@@ -1062,8 +1051,7 @@ pub fn cat_deref(
         let deref_ty = match base_cmt_ty.builtin_deref(true) {
             Some(mt) => mt.ty,
             None => {
-                debug!("Explicit deref of non-derefable type: {:?}",
-                       base_cmt_ty);
+                debug!("Explicit deref of non-derefable type: {:?}", base_cmt_ty);
                 return Err(());
             }
         };
@@ -1120,11 +1108,11 @@ fn cat_index<N: HirNode>(&self,
     }
 
     pub fn cat_imm_interior<N:HirNode>(&self,
-                                        node: &N,
-                                        base_cmt: cmt<'tcx>,
-                                        interior_ty: Ty<'tcx>,
-                                        interior: InteriorKind)
-                                        -> cmt_<'tcx> {
+                                       node: &N,
+                                       base_cmt: cmt<'tcx>,
+                                       interior_ty: Ty<'tcx>,
+                                       interior: InteriorKind)
+                                       -> cmt_<'tcx> {
         let ret = cmt_ {
             hir_id: node.hir_id(),
             span: node.span(),
@@ -1138,10 +1126,10 @@ pub fn cat_imm_interior<N:HirNode>(&self,
     }
 
     pub fn cat_downcast_if_needed<N:HirNode>(&self,
-                                              node: &N,
-                                              base_cmt: cmt<'tcx>,
-                                              variant_did: DefId)
-                                              -> cmt<'tcx> {
+                                             node: &N,
+                                             base_cmt: cmt<'tcx>,
+                                             variant_did: DefId)
+                                             -> cmt<'tcx> {
         // univariant enums do not need downcasts
         let base_did = self.tcx.parent_def_id(variant_did).unwrap();
         if self.tcx.adt_def(base_did).variants.len() != 1 {
@@ -1277,117 +1265,120 @@ fn cat_pattern_<F>(&self, mut cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F) -> McR
         op(cmt.clone(), pat);
 
         match pat.node {
-          PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => {
-            let def = self.tables.qpath_def(qpath, pat.hir_id);
-            let (cmt, expected_len) = match def {
-                Def::Err => {
-                    debug!("access to unresolvable pattern {:?}", pat);
-                    return Err(())
-                }
-                Def::VariantCtor(def_id, CtorKind::Fn) => {
-                    let enum_def = self.tcx.parent_def_id(def_id).unwrap();
-                    (self.cat_downcast_if_needed(pat, cmt, def_id),
-                     self.tcx.adt_def(enum_def).variant_with_id(def_id).fields.len())
-                }
-                Def::StructCtor(_, CtorKind::Fn) | Def::SelfCtor(..) => {
-                    match self.pat_ty_unadjusted(&pat)?.sty {
-                        ty::Adt(adt_def, _) => {
-                            (cmt, adt_def.non_enum_variant().fields.len())
-                        }
-                        ref ty => {
-                            span_bug!(pat.span, "tuple struct pattern unexpected type {:?}", ty);
+            PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => {
+                let def = self.tables.qpath_def(qpath, pat.hir_id);
+                let (cmt, expected_len) = match def {
+                    Def::Err => {
+                        debug!("access to unresolvable pattern {:?}", pat);
+                        return Err(())
+                    }
+                    Def::VariantCtor(def_id, CtorKind::Fn) => {
+                        let enum_def = self.tcx.parent_def_id(def_id).unwrap();
+                        (self.cat_downcast_if_needed(pat, cmt, def_id),
+                        self.tcx.adt_def(enum_def).variant_with_id(def_id).fields.len())
+                    }
+                    Def::StructCtor(_, CtorKind::Fn) | Def::SelfCtor(..) => {
+                        match self.pat_ty_unadjusted(&pat)?.sty {
+                            ty::Adt(adt_def, _) => {
+                                (cmt, adt_def.non_enum_variant().fields.len())
+                            }
+                            ref ty => {
+                                span_bug!(pat.span,
+                                          "tuple struct pattern unexpected type {:?}", ty);
+                            }
                         }
                     }
+                    def => {
+                        span_bug!(pat.span, "tuple struct pattern didn't resolve \
+                                             to variant or struct {:?}", def);
+                    }
+                };
+
+                for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) {
+                    let subpat_ty = self.pat_ty_adjusted(&subpat)?; // see (*2)
+                    let interior = InteriorField(FieldIndex(i, Name::intern(&i.to_string())));
+                    let subcmt = Rc::new(
+                        self.cat_imm_interior(pat, cmt.clone(), subpat_ty, interior));
+                    self.cat_pattern_(subcmt, &subpat, op)?;
                 }
-                def => {
-                    span_bug!(pat.span, "tuple struct pattern didn't resolve \
-                                         to variant or struct {:?}", def);
+            }
+
+            PatKind::Struct(ref qpath, ref field_pats, _) => {
+                // {f1: p1, ..., fN: pN}
+                let def = self.tables.qpath_def(qpath, pat.hir_id);
+                let cmt = match def {
+                    Def::Err => {
+                        debug!("access to unresolvable pattern {:?}", pat);
+                        return Err(())
+                    },
+                    Def::Variant(variant_did) |
+                    Def::VariantCtor(variant_did, ..) => {
+                        self.cat_downcast_if_needed(pat, cmt, variant_did)
+                    },
+                    _ => cmt
+                };
+
+                for fp in field_pats {
+                    let field_ty = self.pat_ty_adjusted(&fp.node.pat)?; // see (*2)
+                    let f_index = self.tcx.field_index(fp.node.id, self.tables);
+                    let cmt_field = Rc::new(self.cat_field(pat, cmt.clone(), f_index,
+                                                           fp.node.ident, field_ty));
+                    self.cat_pattern_(cmt_field, &fp.node.pat, op)?;
                 }
-            };
+            }
 
-            for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) {
-                let subpat_ty = self.pat_ty_adjusted(&subpat)?; // see (*2)
-                let interior = InteriorField(FieldIndex(i, Name::intern(&i.to_string())));
-                let subcmt = Rc::new(self.cat_imm_interior(pat, cmt.clone(), subpat_ty, interior));
-                self.cat_pattern_(subcmt, &subpat, op)?;
+            PatKind::Binding(.., Some(ref subpat)) => {
+                self.cat_pattern_(cmt, &subpat, op)?;
             }
-          }
-
-          PatKind::Struct(ref qpath, ref field_pats, _) => {
-            // {f1: p1, ..., fN: pN}
-            let def = self.tables.qpath_def(qpath, pat.hir_id);
-            let cmt = match def {
-                Def::Err => {
-                    debug!("access to unresolvable pattern {:?}", pat);
-                    return Err(())
-                },
-                Def::Variant(variant_did) |
-                Def::VariantCtor(variant_did, ..) => {
-                    self.cat_downcast_if_needed(pat, cmt, variant_did)
-                },
-                _ => cmt
-            };
-
-            for fp in field_pats {
-                let field_ty = self.pat_ty_adjusted(&fp.node.pat)?; // see (*2)
-                let f_index = self.tcx.field_index(fp.node.id, self.tables);
-                let cmt_field = Rc::new(self.cat_field(pat, cmt.clone(), f_index,
-                                                       fp.node.ident, field_ty));
-                self.cat_pattern_(cmt_field, &fp.node.pat, op)?;
+
+            PatKind::Tuple(ref subpats, ddpos) => {
+                // (p1, ..., pN)
+                let expected_len = match self.pat_ty_unadjusted(&pat)?.sty {
+                    ty::Tuple(ref tys) => tys.len(),
+                    ref ty => span_bug!(pat.span, "tuple pattern unexpected type {:?}", ty),
+                };
+                for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) {
+                    let subpat_ty = self.pat_ty_adjusted(&subpat)?; // see (*2)
+                    let interior = InteriorField(FieldIndex(i, Name::intern(&i.to_string())));
+                    let subcmt = Rc::new(
+                        self.cat_imm_interior(pat, cmt.clone(), subpat_ty, interior));
+                    self.cat_pattern_(subcmt, &subpat, op)?;
+                }
             }
-          }
-
-          PatKind::Binding(.., Some(ref subpat)) => {
-              self.cat_pattern_(cmt, &subpat, op)?;
-          }
-
-          PatKind::Tuple(ref subpats, ddpos) => {
-            // (p1, ..., pN)
-            let expected_len = match self.pat_ty_unadjusted(&pat)?.sty {
-                ty::Tuple(ref tys) => tys.len(),
-                ref ty => span_bug!(pat.span, "tuple pattern unexpected type {:?}", ty),
-            };
-            for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) {
-                let subpat_ty = self.pat_ty_adjusted(&subpat)?; // see (*2)
-                let interior = InteriorField(FieldIndex(i, Name::intern(&i.to_string())));
-                let subcmt = Rc::new(self.cat_imm_interior(pat, cmt.clone(), subpat_ty, interior));
+
+                PatKind::Box(ref subpat) | PatKind::Ref(ref subpat, _) => {
+                // box p1, &p1, &mut p1.  we can ignore the mutability of
+                // PatKind::Ref since that information is already contained
+                // in the type.
+                let subcmt = Rc::new(self.cat_deref(pat, cmt, NoteNone)?);
                 self.cat_pattern_(subcmt, &subpat, op)?;
             }
-          }
-
-          PatKind::Box(ref subpat) | PatKind::Ref(ref subpat, _) => {
-            // box p1, &p1, &mut p1.  we can ignore the mutability of
-            // PatKind::Ref since that information is already contained
-            // in the type.
-            let subcmt = Rc::new(self.cat_deref(pat, cmt, NoteNone)?);
-            self.cat_pattern_(subcmt, &subpat, op)?;
-          }
-
-          PatKind::Slice(ref before, ref slice, ref after) => {
-            let element_ty = match cmt.ty.builtin_index() {
-                Some(ty) => ty,
-                None => {
-                    debug!("Explicit index of non-indexable type {:?}", cmt);
-                    return Err(());
+
+            PatKind::Slice(ref before, ref slice, ref after) => {
+                let element_ty = match cmt.ty.builtin_index() {
+                    Some(ty) => ty,
+                    None => {
+                        debug!("Explicit index of non-indexable type {:?}", cmt);
+                        return Err(());
+                    }
+                };
+                let context = InteriorOffsetKind::Pattern;
+                let elt_cmt = Rc::new(self.cat_index(pat, cmt, element_ty, context)?);
+                for before_pat in before {
+                    self.cat_pattern_(elt_cmt.clone(), &before_pat, op)?;
+                }
+                if let Some(ref slice_pat) = *slice {
+                    self.cat_pattern_(elt_cmt.clone(), &slice_pat, op)?;
+                }
+                for after_pat in after {
+                    self.cat_pattern_(elt_cmt.clone(), &after_pat, op)?;
                 }
-            };
-            let context = InteriorOffsetKind::Pattern;
-            let elt_cmt = Rc::new(self.cat_index(pat, cmt, element_ty, context)?);
-            for before_pat in before {
-                self.cat_pattern_(elt_cmt.clone(), &before_pat, op)?;
-            }
-            if let Some(ref slice_pat) = *slice {
-                self.cat_pattern_(elt_cmt.clone(), &slice_pat, op)?;
-            }
-            for after_pat in after {
-                self.cat_pattern_(elt_cmt.clone(), &after_pat, op)?;
             }
-          }
 
-          PatKind::Path(_) | PatKind::Binding(.., None) |
-          PatKind::Lit(..) | PatKind::Range(..) | PatKind::Wild => {
-            // always ok
-          }
+            PatKind::Path(_) | PatKind::Binding(.., None) |
+            PatKind::Lit(..) | PatKind::Range(..) | PatKind::Wild => {
+                // always ok
+            }
         }
 
         Ok(())
@@ -1489,59 +1480,59 @@ pub fn upvar_cat(&self) -> Option<&Categorization<'tcx>> {
         }
     }
 
-    pub fn descriptive_string(&self, tcx: TyCtxt<'_, '_, '_>) -> String {
+    pub fn descriptive_string(&self, tcx: TyCtxt<'_, '_, '_>) -> Cow<'static, str> {
         match self.cat {
             Categorization::StaticItem => {
-                "static item".to_string()
+                "static item".into()
             }
             Categorization::Rvalue(..) => {
-                "non-place".to_string()
+                "non-place".into()
             }
             Categorization::Local(vid) => {
                 if tcx.hir.is_argument(vid) {
-                    "argument".to_string()
+                    "argument"
                 } else {
-                    "local variable".to_string()
-                }
+                    "local variable"
+                }.into()
             }
             Categorization::Deref(_, pk) => {
                 match self.upvar_cat() {
                     Some(&Categorization::Upvar(ref var)) => {
-                        var.to_string()
+                        var.to_string().into()
                     }
                     Some(_) => bug!(),
                     None => {
                         match pk {
                             Unique => {
-                                "`Box` content".to_string()
+                                "`Box` content"
                             }
                             UnsafePtr(..) => {
-                                "dereference of raw pointer".to_string()
+                                "dereference of raw pointer"
                             }
                             BorrowedPtr(..) => {
                                 match self.note {
-                                    NoteIndex => "indexed content".to_string(),
-                                    _ => "borrowed content".to_string(),
+                                    NoteIndex => "indexed content",
+                                    _ => "borrowed content"
                                 }
                             }
-                        }
+                        }.into()
                     }
                 }
             }
             Categorization::Interior(_, InteriorField(..)) => {
-                "field".to_string()
+                "field".into()
             }
             Categorization::Interior(_, InteriorElement(InteriorOffsetKind::Index)) => {
-                "indexed content".to_string()
+                "indexed content".into()
             }
             Categorization::Interior(_, InteriorElement(InteriorOffsetKind::Pattern)) => {
-                "pattern-bound indexed content".to_string()
+                "pattern-bound indexed content".into()
             }
             Categorization::Upvar(ref var) => {
-                var.to_string()
+                var.to_string().into()
             }
             Categorization::Downcast(ref cmt, _) => {
-                cmt.descriptive_string(tcx)
+                cmt.descriptive_string(tcx).into()
             }
         }
     }
index 9416d60c9d1a3bfeb05a4c56737f5d3b5ed39e26..55e5663f030b2ef99d5e2b7cb897377ffe77d016 100644 (file)
@@ -352,7 +352,7 @@ fn visit_item(&mut self, item: &hir::Item) {
         // which are currently akin to allocator symbols.
         let def_id = self.tcx.hir.local_def_id(item.id);
         let codegen_attrs = self.tcx.codegen_fn_attrs(def_id);
-        if codegen_attrs.linkage.is_some() ||
+        if codegen_attrs.contains_extern_indicator() ||
             codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) {
             self.worklist.push(item.id);
         }
@@ -371,7 +371,9 @@ fn visit_item(&mut self, item: &hir::Item) {
                     return
                 }
 
-                for default_method in self.tcx.provided_trait_methods(trait_def_id) {
+                let provided_trait_methods = self.tcx.provided_trait_methods(trait_def_id);
+                self.worklist.reserve(provided_trait_methods.len());
+                for default_method in provided_trait_methods {
                     let node_id = self.tcx
                                       .hir
                                       .as_local_node_id(default_method.def_id)
@@ -394,7 +396,6 @@ fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem) {
 #[derive(Clone)]
 pub struct ReachableSet(pub Lrc<NodeSet>);
 
-
 fn reachable_set<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) -> ReachableSet {
     debug_assert!(crate_num == LOCAL_CRATE);
 
index 01b0d2c27a1418b8b78988a670869341715633b2..edb571da7dbc50c010d07079f9b45e93960e2dde 100644 (file)
@@ -459,13 +459,13 @@ pub fn record_scope_parent(&mut self, child: Scope, parent: Option<(Scope, Scope
         }
     }
 
-    pub fn each_encl_scope<E>(&self, mut e:E) where E: FnMut(Scope, Scope) {
+    pub fn each_encl_scope<E>(&self, mut e: E) where E: FnMut(Scope, Scope) {
         for (&child, &parent) in &self.parent_map {
             e(child, parent.0)
         }
     }
 
-    pub fn each_var_scope<E>(&self, mut e:E) where E: FnMut(&hir::ItemLocalId, Scope) {
+    pub fn each_var_scope<E>(&self, mut e: E) where E: FnMut(&hir::ItemLocalId, Scope) {
         for (child, &parent) in self.var_map.iter() {
             e(child, parent)
         }
@@ -515,10 +515,8 @@ pub fn encl_scope(&self, id: Scope) -> Scope {
 
     /// Returns the lifetime of the local variable `var_id`
     pub fn var_scope(&self, var_id: hir::ItemLocalId) -> Scope {
-        match self.var_map.get(&var_id) {
-            Some(&r) => r,
-            None => { bug!("no enclosing scope for id {:?}", var_id); }
-        }
+        self.var_map.get(&var_id).cloned().unwrap_or_else(||
+            bug!("no enclosing scope for id {:?}", var_id))
     }
 
     pub fn temporary_scope(&self, expr_id: hir::ItemLocalId) -> Option<Scope> {
@@ -559,8 +557,7 @@ pub fn var_region(&self, id: hir::ItemLocalId) -> ty::RegionKind {
         scope
     }
 
-    pub fn scopes_intersect(&self, scope1: Scope, scope2: Scope)
-                            -> bool {
+    pub fn scopes_intersect(&self, scope1: Scope, scope2: Scope) -> bool {
         self.is_subscope_of(scope1, scope2) ||
         self.is_subscope_of(scope2, scope1)
     }
@@ -584,14 +581,13 @@ pub fn is_subscope_of(&self,
             }
         }
 
-        debug!("is_subscope_of({:?}, {:?})=true",
-               subscope, superscope);
+        debug!("is_subscope_of({:?}, {:?})=true", subscope, superscope);
 
         return true;
     }
 
     /// Returns the id of the innermost containing body
-    pub fn containing_body(&self, mut scope: Scope)-> Option<hir::ItemLocalId> {
+    pub fn containing_body(&self, mut scope: Scope) -> Option<hir::ItemLocalId> {
         loop {
             if let ScopeData::CallSite = scope.data {
                 return Some(scope.item_local_id());
@@ -664,8 +660,8 @@ pub fn nearest_common_ancestor(&self, scope_a: Scope, scope_b: Scope) -> Scope {
     /// Assuming that the provided region was defined within this `ScopeTree`,
     /// returns the outermost `Scope` that the region outlives.
     pub fn early_free_scope<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                                       br: &ty::EarlyBoundRegion)
-                                       -> Scope {
+                                      br: &ty::EarlyBoundRegion)
+                                      -> Scope {
         let param_owner = tcx.parent_def_id(br.def_id).unwrap();
 
         let param_owner_id = tcx.hir.as_local_node_id(param_owner).unwrap();
@@ -828,10 +824,8 @@ fn resolve_block<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, blk:
 fn resolve_arm<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, arm: &'tcx hir::Arm) {
     visitor.terminating_scopes.insert(arm.body.hir_id.local_id);
 
-    if let Some(ref g) = arm.guard {
-        match g {
-            hir::Guard::If(ref expr) => visitor.terminating_scopes.insert(expr.hir_id.local_id),
-        };
+    if let Some(hir::Guard::If(ref expr)) = arm.guard {
+        visitor.terminating_scopes.insert(expr.hir_id.local_id);
     }
 
     intravisit::walk_arm(visitor, arm);
@@ -890,11 +884,9 @@ fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr:
             // This ensures fixed size stacks.
 
             hir::ExprKind::Binary(
-                source_map::Spanned { node: hir::BinOpKind::And, .. },
-                _, ref r) |
+                source_map::Spanned { node: hir::BinOpKind::And, .. }, _, ref r) |
             hir::ExprKind::Binary(
-                source_map::Spanned { node: hir::BinOpKind::Or, .. },
-                _, ref r) => {
+                source_map::Spanned { node: hir::BinOpKind::Or, .. }, _, ref r) => {
                     // For shortcircuiting operators, mark the RHS as a terminating
                     // scope since it only executes conditionally.
                     terminating(r.hir_id.local_id);
index acdeeca1ce4df04c4305805c943ed219e67525dc..a10b387672ad6311a4da7e7497dbbcd17a46bd7b 100644 (file)
@@ -25,6 +25,7 @@
 use rustc::lint;
 use rustc_data_structures::sync::Lrc;
 use session::Session;
+use std::borrow::Cow;
 use std::cell::Cell;
 use std::mem::replace;
 use syntax::ast;
@@ -360,17 +361,17 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) {
         is_late_bound_map: |tcx, id| {
             let id = LocalDefId::from_def_id(DefId::local(id)); // (*)
             tcx.resolve_lifetimes(LOCAL_CRATE)
-                .late_bound
-                .get(&id)
-                .cloned()
+               .late_bound
+               .get(&id)
+               .cloned()
         },
 
         object_lifetime_defaults_map: |tcx, id| {
             let id = LocalDefId::from_def_id(DefId::local(id)); // (*)
             tcx.resolve_lifetimes(LOCAL_CRATE)
-                .object_lifetime_defaults
-                .get(&id)
-                .cloned()
+               .object_lifetime_defaults
+               .get(&id)
+               .cloned()
         },
 
         ..*providers
@@ -410,8 +411,8 @@ fn resolve_lifetimes<'tcx>(
     for (k, v) in named_region_map.object_lifetime_defaults {
         let hir_id = tcx.hir.node_to_hir_id(k);
         let map = rl.object_lifetime_defaults
-            .entry(hir_id.owner_local_def_id())
-            .or_default();
+                    .entry(hir_id.owner_local_def_id())
+                    .or_default();
         Lrc::get_mut(map)
             .unwrap()
             .insert(hir_id.local_id, Lrc::new(v));
@@ -621,140 +622,135 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
                 };
                 self.with(scope, |_, this| this.visit_ty(&mt.ty));
             }
-            hir::TyKind::Path(hir::QPath::Resolved(None, ref path)) => {
-                if let Def::Existential(exist_ty_did) = path.def {
-                    let id = self.tcx.hir.as_local_node_id(exist_ty_did).unwrap();
-
-                    // Resolve the lifetimes in the bounds to the lifetime defs in the generics.
-                    // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
-                    // `abstract type MyAnonTy<'b>: MyTrait<'b>;`
-                    //                          ^            ^ this gets resolved in the scope of
-                    //                                         the exist_ty generics
-                    let (generics, bounds) = match self.tcx.hir.expect_item(id).node {
-                        // named existential types don't need these hacks
-                        hir::ItemKind::Existential(hir::ExistTy{ impl_trait_fn: None, .. }) => {
-                            intravisit::walk_ty(self, ty);
-                            return;
-                        },
-                        hir::ItemKind::Existential(hir::ExistTy{
-                            ref generics,
-                            ref bounds,
-                            ..
-                        }) => (
-                            generics,
-                            bounds,
-                        ),
-                        ref i => bug!("impl Trait pointed to non-existential type?? {:#?}", i),
-                    };
+            hir::TyKind::Def(item_id, ref lifetimes) => {
+                // Resolve the lifetimes in the bounds to the lifetime defs in the generics.
+                // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
+                // `abstract type MyAnonTy<'b>: MyTrait<'b>;`
+                //                          ^            ^ this gets resolved in the scope of
+                //                                         the exist_ty generics
+                let (generics, bounds) = match self.tcx.hir.expect_item(item_id.id).node {
+                    // named existential types are reached via TyKind::Path
+                    // this arm is for `impl Trait` in the types of statics, constants and locals
+                    hir::ItemKind::Existential(hir::ExistTy{ impl_trait_fn: None, .. }) => {
+                        intravisit::walk_ty(self, ty);
+                        return;
+                    },
+                    // RPIT (return position impl trait)
+                    hir::ItemKind::Existential(hir::ExistTy{
+                        ref generics,
+                        ref bounds,
+                        ..
+                    }) => (
+                        generics,
+                        bounds,
+                    ),
+                    ref i => bug!("impl Trait pointed to non-existential type?? {:#?}", i),
+                };
 
-                    assert!(exist_ty_did.is_local());
-                    // Resolve the lifetimes that are applied to the existential type.
-                    // These are resolved in the current scope.
-                    // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
-                    // `fn foo<'a>() -> MyAnonTy<'a> { ... }`
-                    //          ^                 ^this gets resolved in the current scope
-                    for lifetime in &path.segments[0].args.as_ref().unwrap().args {
-                        if let hir::GenericArg::Lifetime(lifetime) = lifetime {
-                            self.visit_lifetime(lifetime);
-
-                            // Check for predicates like `impl for<'a> Trait<impl OtherTrait<'a>>`
-                            // and ban them. Type variables instantiated inside binders aren't
-                            // well-supported at the moment, so this doesn't work.
-                            // In the future, this should be fixed and this error should be removed.
-                            let def = self.map.defs.get(&lifetime.id).cloned();
-                            if let Some(Region::LateBound(_, def_id, _)) = def {
-                                if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) {
-                                    // Ensure that the parent of the def is an item, not HRTB
-                                    let parent_id = self.tcx.hir.get_parent_node(node_id);
-                                    let parent_impl_id = hir::ImplItemId { node_id: parent_id };
-                                    let parent_trait_id = hir::TraitItemId { node_id: parent_id };
-                                    let krate = self.tcx.hir.forest.krate();
-                                    if !(krate.items.contains_key(&parent_id)
-                                        || krate.impl_items.contains_key(&parent_impl_id)
-                                        || krate.trait_items.contains_key(&parent_trait_id))
-                                    {
-                                        span_err!(
-                                            self.tcx.sess,
-                                            lifetime.span,
-                                            E0657,
-                                            "`impl Trait` can only capture lifetimes \
-                                            bound at the fn or impl level"
-                                        );
-                                        self.uninsert_lifetime_on_error(lifetime, def.unwrap());
-                                    }
+                // Resolve the lifetimes that are applied to the existential type.
+                // These are resolved in the current scope.
+                // `fn foo<'a>() -> impl MyTrait<'a> { ... }` desugars to
+                // `fn foo<'a>() -> MyAnonTy<'a> { ... }`
+                //          ^                 ^this gets resolved in the current scope
+                for lifetime in lifetimes {
+                    if let hir::GenericArg::Lifetime(lifetime) = lifetime {
+                        self.visit_lifetime(lifetime);
+
+                        // Check for predicates like `impl for<'a> Trait<impl OtherTrait<'a>>`
+                        // and ban them. Type variables instantiated inside binders aren't
+                        // well-supported at the moment, so this doesn't work.
+                        // In the future, this should be fixed and this error should be removed.
+                        let def = self.map.defs.get(&lifetime.id).cloned();
+                        if let Some(Region::LateBound(_, def_id, _)) = def {
+                            if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) {
+                                // Ensure that the parent of the def is an item, not HRTB
+                                let parent_id = self.tcx.hir.get_parent_node(node_id);
+                                let parent_impl_id = hir::ImplItemId { node_id: parent_id };
+                                let parent_trait_id = hir::TraitItemId { node_id: parent_id };
+                                let krate = self.tcx.hir.forest.krate();
+                                if !(krate.items.contains_key(&parent_id)
+                                    || krate.impl_items.contains_key(&parent_impl_id)
+                                    || krate.trait_items.contains_key(&parent_trait_id))
+                                {
+                                    span_err!(
+                                        self.tcx.sess,
+                                        lifetime.span,
+                                        E0657,
+                                        "`impl Trait` can only capture lifetimes \
+                                         bound at the fn or impl level"
+                                    );
+                                    self.uninsert_lifetime_on_error(lifetime, def.unwrap());
                                 }
                             }
                         }
                     }
+                }
 
-                    // We want to start our early-bound indices at the end of the parent scope,
-                    // not including any parent `impl Trait`s.
-                    let mut index = self.next_early_index_for_abstract_type();
-                    debug!("visit_ty: index = {}", index);
+                // We want to start our early-bound indices at the end of the parent scope,
+                // not including any parent `impl Trait`s.
+                let mut index = self.next_early_index_for_abstract_type();
+                debug!("visit_ty: index = {}", index);
 
-                    let mut elision = None;
-                    let mut lifetimes = FxHashMap();
-                    let mut type_count = 0;
-                    for param in &generics.params {
-                        match param.kind {
-                            GenericParamKind::Lifetime { .. } => {
-                                let (name, reg) = Region::early(&self.tcx.hir, &mut index, &param);
-                                if let hir::ParamName::Plain(param_name) = name {
-                                    if param_name.name == keywords::UnderscoreLifetime.name() {
-                                        // Pick the elided lifetime "definition" if one exists
-                                        // and use it to make an elision scope.
-                                        elision = Some(reg);
-                                    } else {
-                                        lifetimes.insert(name, reg);
-                                    }
+                let mut elision = None;
+                let mut lifetimes = FxHashMap();
+                let mut type_count = 0;
+                for param in &generics.params {
+                    match param.kind {
+                        GenericParamKind::Lifetime { .. } => {
+                            let (name, reg) = Region::early(&self.tcx.hir, &mut index, &param);
+                            if let hir::ParamName::Plain(param_name) = name {
+                                if param_name.name == keywords::UnderscoreLifetime.name() {
+                                    // Pick the elided lifetime "definition" if one exists
+                                    // and use it to make an elision scope.
+                                    elision = Some(reg);
                                 } else {
                                     lifetimes.insert(name, reg);
                                 }
-                            }
-                            GenericParamKind::Type { .. } => {
-                                type_count += 1;
+                            } else {
+                                lifetimes.insert(name, reg);
                             }
                         }
+                        GenericParamKind::Type { .. } => {
+                            type_count += 1;
+                        }
                     }
-                    let next_early_index = index + type_count;
+                }
+                let next_early_index = index + type_count;
 
-                    if let Some(elision_region) = elision {
-                        let scope = Scope::Elision {
-                            elide: Elide::Exact(elision_region),
-                            s: self.scope,
-                        };
-                        self.with(scope, |_old_scope, this| {
-                            let scope = Scope::Binder {
-                                lifetimes,
-                                next_early_index,
-                                s: this.scope,
-                                track_lifetime_uses: true,
-                                abstract_type_parent: false,
-                            };
-                            this.with(scope, |_old_scope, this| {
-                                this.visit_generics(generics);
-                                for bound in bounds {
-                                    this.visit_param_bound(bound);
-                                }
-                            });
-                        });
-                    } else {
+                if let Some(elision_region) = elision {
+                    let scope = Scope::Elision {
+                        elide: Elide::Exact(elision_region),
+                        s: self.scope,
+                    };
+                    self.with(scope, |_old_scope, this| {
                         let scope = Scope::Binder {
                             lifetimes,
                             next_early_index,
-                            s: self.scope,
+                            s: this.scope,
                             track_lifetime_uses: true,
                             abstract_type_parent: false,
                         };
-                        self.with(scope, |_old_scope, this| {
+                        this.with(scope, |_old_scope, this| {
                             this.visit_generics(generics);
                             for bound in bounds {
                                 this.visit_param_bound(bound);
                             }
                         });
-                    }
+                    });
                 } else {
-                    intravisit::walk_ty(self, ty)
+                    let scope = Scope::Binder {
+                        lifetimes,
+                        next_early_index,
+                        s: self.scope,
+                        track_lifetime_uses: true,
+                        abstract_type_parent: false,
+                    };
+                    self.with(scope, |_old_scope, this| {
+                        this.visit_generics(generics);
+                        for bound in bounds {
+                            this.visit_param_bound(bound);
+                        }
+                    });
                 }
             }
             _ => intravisit::walk_ty(self, ty),
@@ -1255,24 +1251,24 @@ fn compute_object_lifetime_defaults(
                     let object_lifetime_default_reprs: String = result
                         .iter()
                         .map(|set| match *set {
-                            Set1::Empty => "BaseDefault".to_string(),
-                            Set1::One(Region::Static) => "'static".to_string(),
+                            Set1::Empty => "BaseDefault".into(),
+                            Set1::One(Region::Static) => "'static".into(),
                             Set1::One(Region::EarlyBound(mut i, _, _)) => {
                                 generics.params.iter().find_map(|param| match param.kind {
-                                        GenericParamKind::Lifetime { .. } => {
-                                            if i == 0 {
-                                                return Some(param.name.ident().to_string());
-                                            }
-                                            i -= 1;
-                                            None
+                                    GenericParamKind::Lifetime { .. } => {
+                                        if i == 0 {
+                                            return Some(param.name.ident().to_string().into());
                                         }
-                                        _ => None,
-                                    }).unwrap()
+                                        i -= 1;
+                                        None
+                                    }
+                                    _ => None,
+                                }).unwrap()
                             }
                             Set1::One(_) => bug!(),
-                            Set1::Many => "Ambiguous".to_string(),
+                            Set1::Many => "Ambiguous".into(),
                         })
-                        .collect::<Vec<String>>()
+                        .collect::<Vec<Cow<'static, str>>>()
                         .join(",");
                     tcx.sess.span_err(item.span, &object_lifetime_default_reprs);
                 }
@@ -1425,16 +1421,13 @@ fn check_uses_for_lifetimes_defined_by_scope(&mut self) {
         def_ids.sort_by_key(|&def_id| self.tcx.def_path_hash(def_id));
 
         for def_id in def_ids {
-            debug!(
-                "check_uses_for_lifetimes_defined_by_scope: def_id = {:?}",
-                def_id,
-            );
+            debug!("check_uses_for_lifetimes_defined_by_scope: def_id = {:?}", def_id);
 
             let lifetimeuseset = self.lifetime_uses.remove(&def_id);
-            debug!(
-                "check_uses_for_lifetimes_defined_by_scope: lifetimeuseset = {:?}",
-                lifetimeuseset
-            );
+
+            debug!("check_uses_for_lifetimes_defined_by_scope: lifetimeuseset = {:?}",
+                   lifetimeuseset);
+
             match lifetimeuseset {
                 Some(LifetimeUseSet::One(lifetime)) => {
                     let node_id = self.tcx.hir.as_local_node_id(def_id).unwrap();
@@ -1674,7 +1667,7 @@ fn resolve_lifetime_ref(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
                             "lifetimes used in `fn` or `Fn` syntax must be \
                              explicitly declared using `<...>` binders"
                         ).span_label(lifetime_ref.span, "in-band lifetime definition")
-                            .emit();
+                         .emit();
                     }
 
                     Region::Static
@@ -1694,7 +1687,7 @@ fn resolve_lifetime_ref(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
                 "use of undeclared lifetime name `{}`",
                 lifetime_ref
             ).span_label(lifetime_ref.span, "undeclared lifetime")
-                .emit();
+             .emit();
         }
     }
 
@@ -1877,18 +1870,15 @@ fn visit_fn_like_elision(
                 node: hir::TraitItemKind::Method(_, ref m),
                 ..
             }) => {
-                match self.tcx
+                if let hir::ItemKind::Trait(.., ref trait_items) = self.tcx
                     .hir
                     .expect_item(self.tcx.hir.get_parent(parent))
                     .node
                 {
-                    hir::ItemKind::Trait(.., ref trait_items) => {
-                        assoc_item_kind = trait_items
-                            .iter()
-                            .find(|ti| ti.id.node_id == parent)
-                            .map(|ti| ti.kind);
-                    }
-                    _ => {}
+                    assoc_item_kind = trait_items
+                        .iter()
+                        .find(|ti| ti.id.node_id == parent)
+                        .map(|ti| ti.kind);
                 }
                 match *m {
                     hir::TraitMethod::Required(_) => None,
@@ -1900,19 +1890,16 @@ fn visit_fn_like_elision(
                 node: hir::ImplItemKind::Method(_, body),
                 ..
             }) => {
-                match self.tcx
+                if let hir::ItemKind::Impl(.., ref self_ty, ref impl_items) = self.tcx
                     .hir
                     .expect_item(self.tcx.hir.get_parent(parent))
                     .node
                 {
-                    hir::ItemKind::Impl(.., ref self_ty, ref impl_items) => {
-                        impl_self = Some(self_ty);
-                        assoc_item_kind = impl_items
-                            .iter()
-                            .find(|ii| ii.id.node_id == parent)
-                            .map(|ii| ii.kind);
-                    }
-                    _ => {}
+                    impl_self = Some(self_ty);
+                    assoc_item_kind = impl_items
+                        .iter()
+                        .find(|ii| ii.id.node_id == parent)
+                        .map(|ii| ii.kind);
                 }
                 Some(body)
             }
@@ -2260,9 +2247,7 @@ fn resolve_object_lifetime_default(&mut self, lifetime_ref: &'tcx hir::Lifetime)
 
                 Scope::Body { .. } | Scope::ObjectLifetimeDefault { lifetime: None, .. } => return,
 
-                Scope::ObjectLifetimeDefault {
-                    lifetime: Some(l), ..
-                } => break l,
+                Scope::ObjectLifetimeDefault { lifetime: Some(l), .. } => break l,
             }
         };
         self.insert_lifetime(lifetime_ref, lifetime.shifted(late_depth));
@@ -2334,13 +2319,11 @@ fn check_lifetime_params(&mut self, old_scope: ScopeRef<'_>,
                                     lifetime_i.name.ident(),
                                 ),
                             ).help(&format!(
-                                "you can use the `'static` lifetime directly, in place \
-                                    of `{}`",
+                                "you can use the `'static` lifetime directly, in place of `{}`",
                                 lifetime_i.name.ident(),
                             )).emit();
                         }
-                        hir::LifetimeName::Param(_)
-                        | hir::LifetimeName::Implicit => {
+                        hir::LifetimeName::Param(_) | hir::LifetimeName::Implicit => {
                             self.resolve_lifetime_ref(lt);
                         }
                     }
@@ -2497,8 +2480,6 @@ fn uninsert_lifetime_on_error(&mut self, lifetime_ref: &'tcx hir::Lifetime, bad_
     }
 }
 
-///////////////////////////////////////////////////////////////////////////
-
 /// Detects late-bound lifetimes and inserts them into
 /// `map.late_bound`.
 ///
@@ -2514,10 +2495,8 @@ fn insert_late_bound_lifetimes(
     decl: &hir::FnDecl,
     generics: &hir::Generics,
 ) {
-    debug!(
-        "insert_late_bound_lifetimes(decl={:?}, generics={:?})",
-        decl, generics
-    );
+    debug!("insert_late_bound_lifetimes(decl={:?}, generics={:?})",
+           decl, generics);
 
     let mut constrained_by_input = ConstrainedCollector {
         regions: FxHashSet(),
@@ -2531,10 +2510,8 @@ fn insert_late_bound_lifetimes(
     };
     intravisit::walk_fn_ret_ty(&mut appears_in_output, &decl.output);
 
-    debug!(
-        "insert_late_bound_lifetimes: constrained_by_input={:?}",
-        constrained_by_input.regions
-    );
+    debug!("insert_late_bound_lifetimes: constrained_by_input={:?}",
+           constrained_by_input.regions);
 
     // Walk the lifetimes that appear in where clauses.
     //
@@ -2546,15 +2523,12 @@ fn insert_late_bound_lifetimes(
     appears_in_where_clause.visit_generics(generics);
 
     for param in &generics.params {
-        match param.kind {
-            hir::GenericParamKind::Lifetime { .. } => {
-                if !param.bounds.is_empty() {
-                    // `'a: 'b` means both `'a` and `'b` are referenced
-                    appears_in_where_clause
-                        .regions.insert(hir::LifetimeName::Param(param.name.modern()));
-                }
+        if let hir::GenericParamKind::Lifetime { .. } = param.kind {
+            if !param.bounds.is_empty() {
+                // `'a: 'b` means both `'a` and `'b` are referenced
+                appears_in_where_clause
+                    .regions.insert(hir::LifetimeName::Param(param.name.modern()));
             }
-            hir::GenericParamKind::Type { .. } => {}
         }
     }
 
@@ -2666,10 +2640,10 @@ pub fn report_missing_lifetime_specifiers(
         if count > 1 { "s" } else { "" }
     );
 
-    let msg = if count > 1 {
-        format!("expected {} lifetime parameters", count)
+    let msg: Cow<'static, str> = if count > 1 {
+        format!("expected {} lifetime parameters", count).into()
     } else {
-        "expected lifetime parameter".to_string()
+        "expected lifetime parameter".into()
     };
 
     err.span_label(span, msg);
index b7b149ea02988ba98e90110cdba356d931b978a9..9dd13dd2272b048a5e24ec4f358e0584b75ffd9c 100644 (file)
@@ -164,8 +164,10 @@ fn annotate<F>(&mut self, id: NodeId, attrs: &[Attribute],
                 if let (&Some(attr::RustcDeprecation {since: dep_since, ..}),
                         &attr::Stable {since: stab_since}) = (&stab.rustc_depr, &stab.level) {
                     // Explicit version of iter::order::lt to handle parse errors properly
-                    for (dep_v, stab_v) in
-                            dep_since.as_str().split('.').zip(stab_since.as_str().split('.')) {
+                    for (dep_v, stab_v) in dep_since.as_str()
+                                                    .split('.')
+                                                    .zip(stab_since.as_str().split('.'))
+                    {
                         if let (Ok(dep_v), Ok(stab_v)) = (dep_v.parse::<u64>(), stab_v.parse()) {
                             match dep_v.cmp(&stab_v) {
                                 Ordering::Less => {
@@ -523,15 +525,12 @@ fn skip_stability_check_due_to_privacy(self, mut def_id: DefId) -> bool {
             Some(Def::Method(_)) |
             Some(Def::AssociatedTy(_)) |
             Some(Def::AssociatedConst(_)) => {
-                match self.associated_item(def_id).container {
-                    ty::TraitContainer(trait_def_id) => {
-                        // Trait methods do not declare visibility (even
-                        // for visibility info in cstore). Use containing
-                        // trait instead, so methods of pub traits are
-                        // themselves considered pub.
-                        def_id = trait_def_id;
-                    }
-                    _ => {}
+                if let ty::TraitContainer(trait_def_id) = self.associated_item(def_id).container {
+                    // Trait methods do not declare visibility (even
+                    // for visibility info in cstore). Use containing
+                    // trait instead, so methods of pub traits are
+                    // themselves considered pub.
+                    def_id = trait_def_id;
                 }
             }
             _ => {}
@@ -561,8 +560,7 @@ fn skip_stability_check_due_to_privacy(self, mut def_id: DefId) -> bool {
     /// `id`.
     pub fn eval_stability(self, def_id: DefId, id: Option<NodeId>, span: Span) -> EvalResult {
         if span.allows_unstable() {
-            debug!("stability: \
-                    skipping span={:?} since it is internal", span);
+            debug!("stability: skipping span={:?} since it is internal", span);
             return EvalResult::Allow;
         }
 
@@ -770,8 +768,8 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
                     let param_env = self.tcx.param_env(def_id);
                     if !param_env.can_type_implement_copy(self.tcx, ty).is_ok() {
                         emit_feature_err(&self.tcx.sess.parse_sess,
-                                        "untagged_unions", item.span, GateIssue::Language,
-                                        "unions with non-`Copy` fields are unstable");
+                                         "untagged_unions", item.span, GateIssue::Language,
+                                         "unions with non-`Copy` fields are unstable");
                     }
                 }
             }
index 941bd4dda99d725d32b9ff2ceb1a57709ba11720..0d407765c9e10be413f07a9ada0c699efb0c7515 100644 (file)
@@ -113,13 +113,13 @@ fn verify<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
            items.$name().is_none() {
             if lang_items::$item == lang_items::PanicImplLangItem {
                 tcx.sess.err(&format!("`#[panic_handler]` function required, \
-                                        but not found"));
+                                       but not found"));
             } else if lang_items::$item == lang_items::OomLangItem {
                 tcx.sess.err(&format!("`#[alloc_error_handler]` function required, \
-                                        but not found"));
+                                       but not found"));
             } else {
                 tcx.sess.err(&format!("language item required, but not found: `{}`",
-                                        stringify!($name)));
+                                      stringify!($name)));
             }
         }
     )*
index d695ad88e47aa3d14cc8a355ac1508ce398652b5..c81d55e69b61a124b380142c3c7cb7b99ef5f847 100644 (file)
@@ -171,7 +171,7 @@ pub fn from_char(c: char) -> Self {
     pub fn from_uint(i: impl Into<u128>, size: Size) -> Self {
         let i = i.into();
         debug_assert_eq!(truncate(i, size), i,
-                    "Unsigned value {} does not fit in {} bits", i, size.bits());
+                         "Unsigned value {} does not fit in {} bits", i, size.bits());
         Scalar::Bits { bits: i, size: size.bytes() as u8 }
     }
 
@@ -181,7 +181,7 @@ pub fn from_int(i: impl Into<i128>, size: Size) -> Self {
         // `into` performed sign extension, we have to truncate
         let truncated = truncate(i as u128, size);
         debug_assert_eq!(sign_extend(truncated, size) as i128, i,
-                    "Signed value {} does not fit in {} bits", i, size.bits());
+                         "Signed value {} does not fit in {} bits", i, size.bits());
         Scalar::Bits { bits: truncated, size: size.bytes() as u8 }
     }
 
index 27ef01b93cda1df96c40cf1bc6d950191041ed93..2ae06e9ab0de79affb0a60c7c38dde9cbe217045 100644 (file)
@@ -12,7 +12,6 @@
 //!
 //! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/mir/index.html
 
-use graphviz::IntoCow;
 use hir::def::CtorKind;
 use hir::def_id::DefId;
 use hir::{self, HirId, InlineAsm};
@@ -327,22 +326,20 @@ pub fn source_info(&self, location: Location) -> &SourceInfo {
         if idx < stmts.len() {
             &stmts[idx].source_info
         } else {
-            assert!(idx == stmts.len());
+            assert_eq!(idx, stmts.len());
             &block.terminator().source_info
         }
     }
 
     /// Check if `sub` is a sub scope of `sup`
     pub fn is_sub_scope(&self, mut sub: SourceScope, sup: SourceScope) -> bool {
-        loop {
-            if sub == sup {
-                return true;
-            }
+        while sub != sup {
             match self.source_scopes[sub].parent_scope {
                 None => return false,
                 Some(p) => sub = p,
             }
         }
+        true
     }
 
     /// Return the return type, it always return first element from `local_decls` array
@@ -526,9 +523,7 @@ impl BorrowKind {
     pub fn allows_two_phase_borrow(&self) -> bool {
         match *self {
             BorrowKind::Shared | BorrowKind::Shallow | BorrowKind::Unique => false,
-            BorrowKind::Mut {
-                allow_two_phase_borrow,
-            } => allow_two_phase_borrow,
+            BorrowKind::Mut { allow_two_phase_borrow } => allow_two_phase_borrow,
         }
     }
 }
@@ -643,6 +638,26 @@ fn hash_stable<W: StableHasherResult>(
     }
 }
 
+/// `BlockTailInfo` is attached to the `LocalDecl` for temporaries
+/// created during evaluation of expressions in a block tail
+/// expression; that is, a block like `{ STMT_1; STMT_2; EXPR }`.
+///
+/// It is used to improve diagnostics when such temporaries are
+/// involved in borrow_check errors, e.g. explanations of where the
+/// temporaries come from, when their destructors are run, and/or how
+/// one might revise the code to satisfy the borrow checker's rules.
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
+pub struct BlockTailInfo {
+    /// If `true`, then the value resulting from evaluating this tail
+    /// expression is ignored by the block's expression context.
+    ///
+    /// Examples include `{ ...; tail };` and `let _ = { ...; tail };`
+    /// but not e.g. `let _x = { ...; tail };`
+    pub tail_result_is_ignored: bool,
+}
+
+impl_stable_hash_for!(struct BlockTailInfo { tail_result_is_ignored });
+
 /// A MIR local.
 ///
 /// This can be a binding declared by the user, a temporary inserted by the compiler, a function
@@ -682,6 +697,12 @@ pub struct LocalDecl<'tcx> {
     /// generator.
     pub internal: bool,
 
+    /// If this local is a temporary and `is_block_tail` is `Some`,
+    /// then it is a temporary created for evaluation of some
+    /// subexpression of some block's tail expression (with no
+    /// intervening statement context).
+    pub is_block_tail: Option<BlockTailInfo>,
+
     /// Type of this local.
     pub ty: Ty<'tcx>,
 
@@ -830,10 +851,19 @@ pub fn new_temp(ty: Ty<'tcx>, span: Span) -> Self {
         Self::new_local(ty, Mutability::Mut, false, span)
     }
 
-    /// Create a new immutable `LocalDecl` for a temporary.
+    /// Converts `self` into same `LocalDecl` except tagged as immutable.
+    #[inline]
+    pub fn immutable(mut self) -> Self {
+        self.mutability = Mutability::Not;
+        self
+    }
+
+    /// Converts `self` into same `LocalDecl` except tagged as internal temporary.
     #[inline]
-    pub fn new_immutable_temp(ty: Ty<'tcx>, span: Span) -> Self {
-        Self::new_local(ty, Mutability::Not, false, span)
+    pub fn block_tail(mut self, info: BlockTailInfo) -> Self {
+        assert!(self.is_block_tail.is_none());
+        self.is_block_tail = Some(info);
+        self
     }
 
     /// Create a new `LocalDecl` for a internal temporary.
@@ -861,6 +891,7 @@ fn new_local(
             visibility_scope: OUTERMOST_SOURCE_SCOPE,
             internal,
             is_user_variable: None,
+            is_block_tail: None,
         }
     }
 
@@ -879,6 +910,7 @@ pub fn new_return_place(return_ty: Ty<'_>, span: Span) -> LocalDecl<'_> {
             },
             visibility_scope: OUTERMOST_SOURCE_SCOPE,
             internal: false,
+            is_block_tail: None,
             name: None, // FIXME maybe we do want some name here?
             is_user_variable: None,
         }
@@ -1049,6 +1081,9 @@ pub enum TerminatorKind<'tcx> {
         destination: Option<(Place<'tcx>, BasicBlock)>,
         /// Cleanups to be done if the call unwinds.
         cleanup: Option<BasicBlock>,
+        /// Whether this is from a call in HIR, rather than from an overloaded
+        /// operator. True for overloaded function call.
+        from_hir_call: bool,
     },
 
     /// Jump to the target if the condition has the expected value,
@@ -1574,42 +1609,42 @@ pub fn fmt_successor_labels(&self) -> Vec<Cow<'static, str>> {
                         };
                         fmt_const_val(&mut s, &c).unwrap();
                         s.into()
-                    }).chain(iter::once(String::from("otherwise").into()))
+                    }).chain(iter::once("otherwise".into()))
                     .collect()
             }
             Call {
                 destination: Some(_),
                 cleanup: Some(_),
                 ..
-            } => vec!["return".into_cow(), "unwind".into_cow()],
+            } => vec!["return".into(), "unwind".into()],
             Call {
                 destination: Some(_),
                 cleanup: None,
                 ..
-            } => vec!["return".into_cow()],
+            } => vec!["return".into()],
             Call {
                 destination: None,
                 cleanup: Some(_),
                 ..
-            } => vec!["unwind".into_cow()],
+            } => vec!["unwind".into()],
             Call {
                 destination: None,
                 cleanup: None,
                 ..
             } => vec![],
-            Yield { drop: Some(_), .. } => vec!["resume".into_cow(), "drop".into_cow()],
-            Yield { drop: None, .. } => vec!["resume".into_cow()],
+            Yield { drop: Some(_), .. } => vec!["resume".into(), "drop".into()],
+            Yield { drop: None, .. } => vec!["resume".into()],
             DropAndReplace { unwind: None, .. } | Drop { unwind: None, .. } => {
-                vec!["return".into_cow()]
+                vec!["return".into()]
             }
             DropAndReplace {
                 unwind: Some(_), ..
             }
             | Drop {
                 unwind: Some(_), ..
-            } => vec!["return".into_cow(), "unwind".into_cow()],
+            } => vec!["return".into(), "unwind".into()],
             Assert { cleanup: None, .. } => vec!["".into()],
-            Assert { .. } => vec!["success".into_cow(), "unwind".into_cow()],
+            Assert { .. } => vec!["success".into(), "unwind".into()],
             FalseEdges {
                 ref imaginary_targets,
                 ..
@@ -2670,6 +2705,7 @@ pub enum ClosureOutlivesSubject<'tcx> {
  */
 
 CloneTypeFoldableAndLiftImpls! {
+    BlockTailInfo,
     Mutability,
     SourceInfo,
     UpvarDecl,
@@ -2713,6 +2749,7 @@ impl<'tcx> TypeFoldable<'tcx> for LocalDecl<'tcx> {
         user_ty,
         name,
         source_info,
+        is_block_tail,
         visibility_scope,
     }
 }
@@ -2810,6 +2847,7 @@ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F)
                 ref args,
                 ref destination,
                 cleanup,
+                from_hir_call,
             } => {
                 let dest = destination
                     .as_ref()
@@ -2820,6 +2858,7 @@ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F)
                     args: args.fold_with(folder),
                     destination: dest,
                     cleanup,
+                    from_hir_call,
                 }
             }
             Assert {
index 4d353a36db02a4b249cc0fe6e35b1b1adc392f0e..7520695a7cd90c8cc1c241ed0018be70809675a0 100644 (file)
@@ -325,7 +325,7 @@ pub fn build_cgu_name_no_mangle<I, C, S>(&mut self,
                 String::new()
             };
 
-            let crate_disambiguator = format!("{}", tcx.crate_disambiguator(cnum));
+            let crate_disambiguator = tcx.crate_disambiguator(cnum).to_string();
             // Using a shortened disambiguator of about 40 bits
             format!("{}.{}{}",
                 tcx.crate_name(cnum),
index 2a25e057a71493ef7bcb65298ba6393b4e72ee2b..fc7b4862b0ae5d0d927962e78c2a332367079e5e 100644 (file)
@@ -87,8 +87,8 @@ pub fn projection_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
                         assert!(index < adt_def.variants.len());
                         assert_eq!(adt_def, adt_def1);
                         PlaceTy::Downcast { adt_def,
-                                             substs,
-                                             variant_index: index }
+                                            substs,
+                                            variant_index: index }
                     }
                     _ => {
                         bug!("cannot downcast non-ADT type: `{:?}`", self)
@@ -151,7 +151,7 @@ pub fn is_upvar_field_projection<'cx, 'gcx>(&self, mir: &'cx Mir<'tcx>,
                     }
                 },
                 _ => None,
-            }\f
+            }
             _ => None,
         }
     }
@@ -255,9 +255,9 @@ pub fn ty<'a, 'gcx, D>(&self, local_decls: &D, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> T
 
 impl<'tcx> BinOp {
       pub fn ty<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                    lhs_ty: Ty<'tcx>,
-                    rhs_ty: Ty<'tcx>)
-                    -> Ty<'tcx> {
+                          lhs_ty: Ty<'tcx>,
+                          rhs_ty: Ty<'tcx>)
+                          -> Ty<'tcx> {
         // FIXME: handle SIMD correctly
         match self {
             &BinOp::Add | &BinOp::Sub | &BinOp::Mul | &BinOp::Div | &BinOp::Rem |
index 6de7e2215bf41bb426530d7f522f81871ccba221..7d8227053b373c3aa23ccdb6edf3150da8f66142 100644 (file)
@@ -468,7 +468,8 @@ fn super_terminator_kind(&mut self,
                     TerminatorKind::Call { ref $($mutability)* func,
                                            ref $($mutability)* args,
                                            ref $($mutability)* destination,
-                                           cleanup } => {
+                                           cleanup,
+                                           from_hir_call: _, } => {
                         self.visit_operand(func, source_location);
                         for arg in args {
                             self.visit_operand(arg, source_location);
@@ -727,6 +728,7 @@ fn super_local_decl(&mut self,
                     ref $($mutability)* visibility_scope,
                     internal: _,
                     is_user_variable: _,
+                    is_block_tail: _,
                 } = *local_decl;
 
                 self.visit_ty(ty, TyContext::LocalDecl {
index 7401d4099ff6dff05b6305276a9c6ce753ee5ed1..7add8ef05ee78377340d2bc9bfe6f90ea68f582a 100644 (file)
@@ -117,7 +117,7 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>,
 {
     debug!("overlap(a_def_id={:?}, b_def_id={:?})", a_def_id, b_def_id);
 
-    // For the purposes of this check, we don't bring any skolemized
+    // For the purposes of this check, we don't bring any placeholder
     // types into scope; instead, we replace the generic types with
     // fresh type variables, and hence we do our evaluations in an
     // empty environment.
@@ -475,6 +475,7 @@ fn ty_is_local_constructor(ty: Ty<'_>, in_crate: InCrate) -> bool {
 
         ty::Error => true,
 
+        ty::UnnormalizedProjection(..) |
         ty::Closure(..) |
         ty::Generator(..) |
         ty::GeneratorWitness(..) |
index 7695f26d701156272e31d9b59a710f6bab8124a4..da2173fead3707d1e34a5e2b3cb0bf9dffbb1b59 100644 (file)
@@ -46,7 +46,7 @@
 use ty::SubtypePredicate;
 use util::nodemap::{FxHashMap, FxHashSet};
 
-use syntax_pos::{DUMMY_SP, Span};
+use syntax_pos::{DUMMY_SP, Span, ExpnInfo, ExpnFormat};
 
 impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     pub fn report_fulfillment_errors(&self,
@@ -68,18 +68,30 @@ struct ErrorDescriptor<'tcx> {
             }).collect();
 
         for (index, error) in errors.iter().enumerate() {
-            error_map.entry(error.obligation.cause.span).or_default().push(
+            // We want to ignore desugarings here: spans are equivalent even
+            // if one is the result of a desugaring and the other is not.
+            let mut span = error.obligation.cause.span;
+            if let Some(ExpnInfo {
+                format: ExpnFormat::CompilerDesugaring(_),
+                def_site: Some(def_span),
+                ..
+            }) = span.ctxt().outer().expn_info() {
+                span = def_span;
+            }
+
+            error_map.entry(span).or_default().push(
                 ErrorDescriptor {
                     predicate: error.obligation.predicate.clone(),
                     index: Some(index)
-                });
+                }
+            );
 
             self.reported_trait_errors.borrow_mut()
-                .entry(error.obligation.cause.span).or_default()
+                .entry(span).or_default()
                 .push(error.obligation.predicate.clone());
         }
 
-        // We do this in 2 passes because we want to display errors in order, tho
+        // We do this in 2 passes because we want to display errors in order, though
         // maybe it *is* better to sort errors by span or something.
         let mut is_suppressed = vec![false; errors.len()];
         for (_, error_set) in error_map.iter() {
@@ -269,7 +281,8 @@ fn type_category<'tcx>(t: Ty<'tcx>) -> Option<u32> {
                 ty::Generator(..) => Some(18),
                 ty::Foreign(..) => Some(19),
                 ty::GeneratorWitness(..) => Some(20),
-                ty::Infer(..) | ty::Error => None
+                ty::Infer(..) | ty::Error => None,
+                ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
             }
         }
 
index 5ea936f750e2e24398963263b4b46a649defc494..7c1f87fbf3fefe1f25e2f488e1952e1e485ae8e1 100644 (file)
@@ -206,15 +206,15 @@ pub fn poly_project_and_unify_type<'cx, 'gcx, 'tcx>(
 
     let infcx = selcx.infcx();
     infcx.commit_if_ok(|snapshot| {
-        let (skol_predicate, skol_map) =
-            infcx.skolemize_late_bound_regions(&obligation.predicate);
+        let (placeholder_predicate, placeholder_map) =
+            infcx.replace_late_bound_regions_with_placeholders(&obligation.predicate);
 
-        let skol_obligation = obligation.with(skol_predicate);
+        let skol_obligation = obligation.with(placeholder_predicate);
         let r = match project_and_unify_type(selcx, &skol_obligation) {
             Ok(result) => {
                 let span = obligation.cause.span;
-                match infcx.leak_check(false, span, &skol_map, snapshot) {
-                    Ok(()) => Ok(infcx.plug_leaks(skol_map, snapshot, result)),
+                match infcx.leak_check(false, span, &placeholder_map, snapshot) {
+                    Ok(()) => Ok(infcx.plug_leaks(placeholder_map, snapshot, result)),
                     Err(e) => {
                         debug!("poly_project_and_unify_type: leak check encountered error {:?}", e);
                         Err(MismatchedProjectionTypes { err: e })
@@ -1571,11 +1571,11 @@ fn assoc_ty_def<'cx, 'gcx, 'tcx>(
 
 // # Cache
 
-/// The projection cache. Unlike the standard caches, this can
-/// include infcx-dependent type variables - therefore, we have to roll
-/// the cache back each time we roll a snapshot back, to avoid assumptions
-/// on yet-unresolved inference variables. Types with skolemized regions
-/// also have to be removed when the respective snapshot ends.
+/// The projection cache. Unlike the standard caches, this can include
+/// infcx-dependent type variables - therefore, we have to roll the
+/// cache back each time we roll a snapshot back, to avoid assumptions
+/// on yet-unresolved inference variables. Types with placeholder
+/// regions also have to be removed when the respective snapshot ends.
 ///
 /// Because of that, projection cache entries can be "stranded" and left
 /// inaccessible when type variables inside the key are resolved. We make no
@@ -1661,7 +1661,7 @@ pub fn rollback_to(&mut self, snapshot: ProjectionCacheSnapshot) {
         self.map.rollback_to(&snapshot.snapshot);
     }
 
-    pub fn rollback_skolemized(&mut self, snapshot: &ProjectionCacheSnapshot) {
+    pub fn rollback_placeholder(&mut self, snapshot: &ProjectionCacheSnapshot) {
         self.map.partial_rollback(&snapshot.snapshot, &|k| k.ty.has_re_skol());
     }
 
index f5fb183ec1a5d2d36873515861c93b7a9e9ba677..aaf03f8e7fb55b3bb82c5dfaf50896cc2e6d5b13 100644 (file)
@@ -253,5 +253,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'_, '_, 'tcx>, ty: Ty<'tcx>) ->
         | ty::Opaque(..)
         | ty::Infer(_)
         | ty::Generator(..) => false,
+
+        ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
     }
 }
index 860914d1984ecd90de81822eafdaf410b9e629e8..82d881e10b1688304313581adbd9d1977485650b 100644 (file)
 //!
 //! [rustc guide]: https://rust-lang-nursery.github.io/rustc-guide/traits/resolution.html#selection
 
-use self::SelectionCandidate::*;
 use self::EvaluationResult::*;
+use self::SelectionCandidate::*;
 
 use super::coherence::{self, Conflict};
-use super::DerivedObligationCause;
-use super::{IntercrateMode, TraitQueryMode};
 use super::project;
 use super::project::{normalize_with_depth, Normalized, ProjectionCacheKey};
-use super::{PredicateObligation, TraitObligation, ObligationCause};
-use super::{ObligationCauseCode, BuiltinDerivedObligation, ImplDerivedObligation};
-use super::{SelectionError, Unimplemented, OutputTypeParameterMismatch, Overflow};
-use super::{ObjectCastObligation, Obligation};
-use super::TraitNotObjectSafe;
+use super::util;
+use super::DerivedObligationCause;
 use super::Selection;
 use super::SelectionResult;
-use super::{VtableBuiltin, VtableImpl, VtableParam, VtableClosure, VtableGenerator,
-            VtableFnPointer, VtableObject, VtableAutoImpl};
-use super::{VtableImplData, VtableObjectData, VtableBuiltinData, VtableGeneratorData,
-            VtableClosureData, VtableAutoImplData, VtableFnPointerData};
-use super::util;
-
-use dep_graph::{DepNodeIndex, DepKind};
+use super::TraitNotObjectSafe;
+use super::{BuiltinDerivedObligation, ImplDerivedObligation, ObligationCauseCode};
+use super::{IntercrateMode, TraitQueryMode};
+use super::{ObjectCastObligation, Obligation};
+use super::{ObligationCause, PredicateObligation, TraitObligation};
+use super::{OutputTypeParameterMismatch, Overflow, SelectionError, Unimplemented};
+use super::{
+    VtableAutoImpl, VtableBuiltin, VtableClosure, VtableFnPointer, VtableGenerator, VtableImpl,
+    VtableObject, VtableParam,
+};
+use super::{
+    VtableAutoImplData, VtableBuiltinData, VtableClosureData, VtableFnPointerData,
+    VtableGeneratorData, VtableImplData, VtableObjectData,
+};
+
+use dep_graph::{DepKind, DepNodeIndex};
 use hir::def_id::DefId;
 use infer;
 use infer::{InferCtxt, InferOk, TypeFreshener};
-use ty::subst::{Subst, Substs};
-use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
+use middle::lang_items;
+use mir::interpret::GlobalId;
 use ty::fast_reject;
 use ty::relate::TypeRelation;
-use middle::lang_items;
-use mir::interpret::{GlobalId};
+use ty::subst::{Subst, Substs};
+use ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable};
 
+use hir;
 use rustc_data_structures::bit_set::GrowableBitSet;
 use rustc_data_structures::sync::Lock;
-use std::iter;
+use rustc_target::spec::abi::Abi;
 use std::cmp;
 use std::fmt;
+use std::iter;
 use std::mem;
 use std::rc::Rc;
-use rustc_target::spec::abi::Abi;
-use hir;
 use util::nodemap::{FxHashMap, FxHashSet};
 
-pub struct SelectionContext<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
+pub struct SelectionContext<'cx, 'gcx: 'cx + 'tcx, 'tcx: 'cx> {
     infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
 
-    /// Freshener used specifically for skolemizing entries on the
-    /// obligation stack. This ensures that all entries on the stack
-    /// at one time will have the same set of skolemized entries,
-    /// which is important for checking for trait bounds that
-    /// recursively require themselves.
+    /// Freshener used specifically for entries on the obligation
+    /// stack. This ensures that all entries on the stack at one time
+    /// will have the same set of placeholder entries, which is
+    /// important for checking for trait bounds that recursively
+    /// require themselves.
     freshener: TypeFreshener<'cx, 'gcx, 'tcx>,
 
     /// If true, indicates that the evaluation should be conservative
@@ -109,26 +113,43 @@ pub enum IntercrateAmbiguityCause {
 impl IntercrateAmbiguityCause {
     /// Emits notes when the overlap is caused by complex intercrate ambiguities.
     /// See #23980 for details.
-    pub fn add_intercrate_ambiguity_hint<'a, 'tcx>(&self,
-                                                   err: &mut ::errors::DiagnosticBuilder<'_>) {
+    pub fn add_intercrate_ambiguity_hint<'a, 'tcx>(
+        &self,
+        err: &mut ::errors::DiagnosticBuilder<'_>,
+    ) {
         err.note(&self.intercrate_ambiguity_hint());
     }
 
     pub fn intercrate_ambiguity_hint(&self) -> String {
         match self {
-            &IntercrateAmbiguityCause::DownstreamCrate { ref trait_desc, ref self_desc } => {
+            &IntercrateAmbiguityCause::DownstreamCrate {
+                ref trait_desc,
+                ref self_desc,
+            } => {
                 let self_desc = if let &Some(ref ty) = self_desc {
                     format!(" for type `{}`", ty)
-                } else { String::new() };
-                format!("downstream crates may implement trait `{}`{}", trait_desc, self_desc)
+                } else {
+                    String::new()
+                };
+                format!(
+                    "downstream crates may implement trait `{}`{}",
+                    trait_desc, self_desc
+                )
             }
-            &IntercrateAmbiguityCause::UpstreamCrateUpdate { ref trait_desc, ref self_desc } => {
+            &IntercrateAmbiguityCause::UpstreamCrateUpdate {
+                ref trait_desc,
+                ref self_desc,
+            } => {
                 let self_desc = if let &Some(ref ty) = self_desc {
                     format!(" for type `{}`", ty)
-                } else { String::new() };
-                format!("upstream crates may add new impl of trait `{}`{} \
-                         in future versions",
-                        trait_desc, self_desc)
+                } else {
+                    String::new()
+                };
+                format!(
+                    "upstream crates may add new impl of trait `{}`{} \
+                     in future versions",
+                    trait_desc, self_desc
+                )
             }
         }
     }
@@ -138,7 +159,7 @@ pub fn intercrate_ambiguity_hint(&self) -> String {
 struct TraitObligationStack<'prev, 'tcx: 'prev> {
     obligation: &'prev TraitObligation<'tcx>,
 
-    /// Trait ref from `obligation` but skolemized with the
+    /// Trait ref from `obligation` but "freshened" with the
     /// selection-context's freshener. Used to check for recursion.
     fresh_trait_ref: ty::PolyTraitRef<'tcx>,
 
@@ -147,8 +168,9 @@ struct TraitObligationStack<'prev, 'tcx: 'prev> {
 
 #[derive(Clone)]
 pub struct SelectionCache<'tcx> {
-    hashmap: Lock<FxHashMap<ty::TraitRef<'tcx>,
-                            WithDepNode<SelectionResult<'tcx, SelectionCandidate<'tcx>>>>>,
+    hashmap: Lock<
+        FxHashMap<ty::TraitRef<'tcx>, WithDepNode<SelectionResult<'tcx, SelectionCandidate<'tcx>>>>,
+    >,
 }
 
 /// The selection process begins by considering all impls, where
@@ -223,10 +245,12 @@ pub struct SelectionCache<'tcx> {
 /// required for associated types to work in default impls, as the bounds
 /// are visible both as projection bounds and as where-clauses from the
 /// parameter environment.
-#[derive(PartialEq,Eq,Debug,Clone)]
+#[derive(PartialEq, Eq, Debug, Clone)]
 enum SelectionCandidate<'tcx> {
     /// If has_nested is false, there are no *further* obligations
-    BuiltinCandidate { has_nested: bool },
+    BuiltinCandidate {
+        has_nested: bool,
+    },
     ParamCandidate(ty::PolyTraitRef<'tcx>),
     ImplCandidate(DefId),
     AutoImplCandidate(DefId),
@@ -258,11 +282,7 @@ impl<'a, 'tcx> ty::Lift<'tcx> for SelectionCandidate<'a> {
     type Lifted = SelectionCandidate<'tcx>;
     fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
         Some(match *self {
-            BuiltinCandidate { has_nested } => {
-                BuiltinCandidate {
-                    has_nested,
-                }
-            }
+            BuiltinCandidate { has_nested } => BuiltinCandidate { has_nested },
             ImplCandidate(def_id) => ImplCandidate(def_id),
             AutoImplCandidate(def_id) => AutoImplCandidate(def_id),
             ProjectionCandidate => ProjectionCandidate,
@@ -292,7 +312,7 @@ struct SelectionCandidateSet<'tcx> {
     ambiguous: bool,
 }
 
-#[derive(PartialEq,Eq,Debug,Clone)]
+#[derive(PartialEq, Eq, Debug, Clone)]
 struct EvaluatedCandidate<'tcx> {
     candidate: SelectionCandidate<'tcx>,
     evaluation: EvaluationResult,
@@ -306,7 +326,7 @@ enum BuiltinImplConditions<'tcx> {
     /// candidate (a where-clause or user-defined impl).
     None,
     /// It is unknown whether there is an impl.
-    Ambiguous
+    Ambiguous,
 }
 
 #[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
@@ -389,23 +409,17 @@ pub enum EvaluationResult {
 impl EvaluationResult {
     pub fn may_apply(self) -> bool {
         match self {
-            EvaluatedToOk |
-            EvaluatedToAmbig |
-            EvaluatedToUnknown => true,
+            EvaluatedToOk | EvaluatedToAmbig | EvaluatedToUnknown => true,
 
-            EvaluatedToErr |
-            EvaluatedToRecur => false
+            EvaluatedToErr | EvaluatedToRecur => false,
         }
     }
 
     fn is_stack_dependent(self) -> bool {
         match self {
-            EvaluatedToUnknown |
-            EvaluatedToRecur => true,
+            EvaluatedToUnknown | EvaluatedToRecur => true,
 
-            EvaluatedToOk |
-            EvaluatedToAmbig |
-            EvaluatedToErr => false,
+            EvaluatedToOk | EvaluatedToAmbig | EvaluatedToErr => false,
         }
     }
 }
@@ -422,7 +436,7 @@ fn is_stack_dependent(self) -> bool {
 /// Indicates that trait evaluation caused overflow.
 pub struct OverflowError;
 
-impl_stable_hash_for!(struct OverflowError { });
+impl_stable_hash_for!(struct OverflowError {});
 
 impl<'tcx> From<OverflowError> for SelectionError<'tcx> {
     fn from(OverflowError: OverflowError) -> SelectionError<'tcx> {
@@ -432,7 +446,7 @@ fn from(OverflowError: OverflowError) -> SelectionError<'tcx> {
 
 #[derive(Clone)]
 pub struct EvaluationCache<'tcx> {
-    hashmap: Lock<FxHashMap<ty::PolyTraitRef<'tcx>, WithDepNode<EvaluationResult>>>
+    hashmap: Lock<FxHashMap<ty::PolyTraitRef<'tcx>, WithDepNode<EvaluationResult>>>,
 }
 
 impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
@@ -447,8 +461,10 @@ pub fn new(infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>) -> SelectionContext<'cx, 'gcx
         }
     }
 
-    pub fn intercrate(infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
-                      mode: IntercrateMode) -> SelectionContext<'cx, 'gcx, 'tcx> {
+    pub fn intercrate(
+        infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
+        mode: IntercrateMode,
+    ) -> SelectionContext<'cx, 'gcx, 'tcx> {
         debug!("intercrate({:?})", mode);
         SelectionContext {
             infcx,
@@ -460,8 +476,10 @@ pub fn intercrate(infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
         }
     }
 
-    pub fn with_negative(infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
-                         allow_negative_impls: bool) -> SelectionContext<'cx, 'gcx, 'tcx> {
+    pub fn with_negative(
+        infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
+        allow_negative_impls: bool,
+    ) -> SelectionContext<'cx, 'gcx, 'tcx> {
         debug!("with_negative({:?})", allow_negative_impls);
         SelectionContext {
             infcx,
@@ -473,8 +491,10 @@ pub fn with_negative(infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
         }
     }
 
-    pub fn with_query_mode(infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
-                           query_mode: TraitQueryMode) -> SelectionContext<'cx, 'gcx, 'tcx> {
+    pub fn with_query_mode(
+        infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
+        query_mode: TraitQueryMode,
+    ) -> SelectionContext<'cx, 'gcx, 'tcx> {
         debug!("with_query_mode({:?})", query_mode);
         SelectionContext {
             infcx,
@@ -521,7 +541,8 @@ pub fn closure_typer(&self) -> &'cx InferCtxt<'cx, 'gcx, 'tcx> {
     /// Wraps the inference context's in_snapshot s.t. snapshot handling is only from the selection
     /// context's self.
     fn in_snapshot<R, F>(&mut self, f: F) -> R
-        where F: FnOnce(&mut Self, &infer::CombinedSnapshot<'cx, 'tcx>) -> R
+    where
+        F: FnOnce(&mut Self, &infer::CombinedSnapshot<'cx, 'tcx>) -> R,
     {
         self.infcx.in_snapshot(|snapshot| f(self, snapshot))
     }
@@ -529,20 +550,21 @@ fn in_snapshot<R, F>(&mut self, f: F) -> R
     /// Wraps a probe s.t. obligations collected during it are ignored and old obligations are
     /// retained.
     fn probe<R, F>(&mut self, f: F) -> R
-        where F: FnOnce(&mut Self, &infer::CombinedSnapshot<'cx, 'tcx>) -> R
+    where
+        F: FnOnce(&mut Self, &infer::CombinedSnapshot<'cx, 'tcx>) -> R,
     {
         self.infcx.probe(|snapshot| f(self, snapshot))
     }
 
     /// Wraps a commit_if_ok s.t. obligations collected during it are not returned in selection if
     /// the transaction fails and s.t. old obligations are retained.
-    fn commit_if_ok<T, E, F>(&mut self, f: F) -> Result<T, E> where
-        F: FnOnce(&mut Self, &infer::CombinedSnapshot<'cx, 'tcx>) -> Result<T, E>
+    fn commit_if_ok<T, E, F>(&mut self, f: F) -> Result<T, E>
+    where
+        F: FnOnce(&mut Self, &infer::CombinedSnapshot<'cx, 'tcx>) -> Result<T, E>,
     {
         self.infcx.commit_if_ok(|snapshot| f(self, snapshot))
     }
 
-
     ///////////////////////////////////////////////////////////////////////////
     // Selection
     //
@@ -560,8 +582,10 @@ fn commit_if_ok<T, E, F>(&mut self, f: F) -> Result<T, E> where
 
     /// Attempts to satisfy the obligation. If successful, this will affect the surrounding
     /// type environment by performing unification.
-    pub fn select(&mut self, obligation: &TraitObligation<'tcx>)
-                  -> SelectionResult<'tcx, Selection<'tcx>> {
+    pub fn select(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+    ) -> SelectionResult<'tcx, Selection<'tcx>> {
         debug!("select({:?})", obligation);
         debug_assert!(!obligation.predicate.has_escaping_regions());
 
@@ -573,19 +597,23 @@ pub fn select(&mut self, obligation: &TraitObligation<'tcx>)
                 // earlier.
                 assert!(self.query_mode == TraitQueryMode::Canonical);
                 return Err(SelectionError::Overflow);
-            },
-            Err(e) => { return Err(e); },
-            Ok(None) => { return Ok(None); },
-            Ok(Some(candidate)) => candidate
+            }
+            Err(e) => {
+                return Err(e);
+            }
+            Ok(None) => {
+                return Ok(None);
+            }
+            Ok(Some(candidate)) => candidate,
         };
 
         match self.confirm_candidate(obligation, candidate) {
             Err(SelectionError::Overflow) => {
                 assert!(self.query_mode == TraitQueryMode::Canonical);
                 Err(SelectionError::Overflow)
-            },
+            }
             Err(e) => Err(e),
-            Ok(candidate) => Ok(Some(candidate))
+            Ok(candidate) => Ok(Some(candidate)),
         }
     }
 
@@ -600,12 +628,8 @@ pub fn select(&mut self, obligation: &TraitObligation<'tcx>)
     // we can be sure it does not.
 
     /// Evaluates whether the obligation `obligation` can be satisfied (by any means).
-    pub fn predicate_may_hold_fatal(&mut self,
-                                    obligation: &PredicateObligation<'tcx>)
-                                    -> bool
-    {
-        debug!("predicate_may_hold_fatal({:?})",
-               obligation);
+    pub fn predicate_may_hold_fatal(&mut self, obligation: &PredicateObligation<'tcx>) -> bool {
+        debug!("predicate_may_hold_fatal({:?})", obligation);
 
         // This fatal query is a stopgap that should only be used in standard mode,
         // where we do not expect overflow to be propagated.
@@ -618,29 +642,34 @@ pub fn predicate_may_hold_fatal(&mut self,
 
     /// Evaluates whether the obligation `obligation` can be satisfied and returns
     /// an `EvaluationResult`.
-    pub fn evaluate_obligation_recursively(&mut self,
-                                           obligation: &PredicateObligation<'tcx>)
-                                           -> Result<EvaluationResult, OverflowError>
-    {
-        self.probe(|this, _|
+    pub fn evaluate_obligation_recursively(
+        &mut self,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> Result<EvaluationResult, OverflowError> {
+        self.probe(|this, _| {
             this.evaluate_predicate_recursively(TraitObligationStackList::empty(), obligation)
-        )
+        })
     }
 
     /// Evaluates the predicates in `predicates` recursively. Note that
     /// this applies projections in the predicates, and therefore
     /// is run within an inference probe.
-    fn evaluate_predicates_recursively<'a,'o,I>(&mut self,
-                                                stack: TraitObligationStackList<'o, 'tcx>,
-                                                predicates: I)
-                                                -> Result<EvaluationResult, OverflowError>
-        where I : IntoIterator<Item=&'a PredicateObligation<'tcx>>, 'tcx:'a
+    fn evaluate_predicates_recursively<'a, 'o, I>(
+        &mut self,
+        stack: TraitObligationStackList<'o, 'tcx>,
+        predicates: I,
+    ) -> Result<EvaluationResult, OverflowError>
+    where
+        I: IntoIterator<Item = &'a PredicateObligation<'tcx>>,
+        'tcx: 'a,
     {
         let mut result = EvaluatedToOk;
         for obligation in predicates {
             let eval = self.evaluate_predicate_recursively(stack, obligation)?;
-            debug!("evaluate_predicate_recursively({:?}) = {:?}",
-                   obligation, eval);
+            debug!(
+                "evaluate_predicate_recursively({:?}) = {:?}",
+                obligation, eval
+            );
             if let EvaluatedToErr = eval {
                 // fast-path - EvaluatedToErr is the top of the lattice,
                 // so we don't need to look on the other predicates.
@@ -652,13 +681,12 @@ fn evaluate_predicates_recursively<'a,'o,I>(&mut self,
         Ok(result)
     }
 
-    fn evaluate_predicate_recursively<'o>(&mut self,
-                                          previous_stack: TraitObligationStackList<'o, 'tcx>,
-                                          obligation: &PredicateObligation<'tcx>)
-                                           -> Result<EvaluationResult, OverflowError>
-    {
-        debug!("evaluate_predicate_recursively({:?})",
-               obligation);
+    fn evaluate_predicate_recursively<'o>(
+        &mut self,
+        previous_stack: TraitObligationStackList<'o, 'tcx>,
+        obligation: &PredicateObligation<'tcx>,
+    ) -> Result<EvaluationResult, OverflowError> {
+        debug!("evaluate_predicate_recursively({:?})", obligation);
 
         match obligation.predicate {
             ty::Predicate::Trait(ref t) => {
@@ -669,26 +697,29 @@ fn evaluate_predicate_recursively<'o>(&mut self,
 
             ty::Predicate::Subtype(ref p) => {
                 // does this code ever run?
-                match self.infcx.subtype_predicate(&obligation.cause, obligation.param_env, p) {
+                match self.infcx
+                    .subtype_predicate(&obligation.cause, obligation.param_env, p)
+                {
                     Some(Ok(InferOk { obligations, .. })) => {
                         self.evaluate_predicates_recursively(previous_stack, &obligations)
-                    },
+                    }
                     Some(Err(_)) => Ok(EvaluatedToErr),
                     None => Ok(EvaluatedToAmbig),
                 }
             }
 
-            ty::Predicate::WellFormed(ty) => {
-                match ty::wf::obligations(self.infcx,
-                                          obligation.param_env,
-                                          obligation.cause.body_id,
-                                          ty, obligation.cause.span) {
-                    Some(obligations) =>
-                        self.evaluate_predicates_recursively(previous_stack, obligations.iter()),
-                    None =>
-                        Ok(EvaluatedToAmbig),
+            ty::Predicate::WellFormed(ty) => match ty::wf::obligations(
+                self.infcx,
+                obligation.param_env,
+                obligation.cause.body_id,
+                ty,
+                obligation.cause.span,
+            ) {
+                Some(obligations) => {
+                    self.evaluate_predicates_recursively(previous_stack, obligations.iter())
                 }
-            }
+                None => Ok(EvaluatedToAmbig),
+            },
 
             ty::Predicate::TypeOutlives(ref binder) => {
                 assert!(!binder.has_escaping_regions());
@@ -790,17 +821,19 @@ fn evaluate_predicate_recursively<'o>(&mut self,
                 let project_obligation = obligation.with(data.clone());
                 match project::poly_project_and_unify_type(self, &project_obligation) {
                     Ok(Some(subobligations)) => {
-                        let result = self.evaluate_predicates_recursively(previous_stack,
-                                                                          subobligations.iter());
+                        let result = self.evaluate_predicates_recursively(
+                            previous_stack,
+                            subobligations.iter(),
+                        );
                         if let Some(key) =
                             ProjectionCacheKey::from_poly_projection_predicate(self, data)
                         {
                             self.infcx.projection_cache.borrow_mut().complete(key);
                         }
                         result
-                    },
+                    }
                     Ok(None) => Ok(EvaluatedToAmbig),
-                    Err(_) => Ok(EvaluatedToErr)
+                    Err(_) => Ok(EvaluatedToErr),
                 }
             }
 
@@ -812,8 +845,8 @@ fn evaluate_predicate_recursively<'o>(&mut self,
                         } else {
                             Ok(EvaluatedToErr)
                         }
-                    },
-                    None => Ok(EvaluatedToAmbig)
+                    }
+                    None => Ok(EvaluatedToAmbig),
                 }
             }
 
@@ -821,20 +854,16 @@ fn evaluate_predicate_recursively<'o>(&mut self,
                 let tcx = self.tcx();
                 match tcx.lift_to_global(&(obligation.param_env, substs)) {
                     Some((param_env, substs)) => {
-                        let instance = ty::Instance::resolve(
-                            tcx.global_tcx(),
-                            param_env,
-                            def_id,
-                            substs,
-                        );
+                        let instance =
+                            ty::Instance::resolve(tcx.global_tcx(), param_env, def_id, substs);
                         if let Some(instance) = instance {
                             let cid = GlobalId {
                                 instance,
-                                promoted: None
+                                promoted: None,
                             };
                             match self.tcx().const_eval(param_env.and(cid)) {
                                 Ok(_) => Ok(EvaluatedToOk),
-                                Err(_) => Ok(EvaluatedToErr)
+                                Err(_) => Ok(EvaluatedToErr),
                             }
                         } else {
                             Ok(EvaluatedToErr)
@@ -849,46 +878,50 @@ fn evaluate_predicate_recursively<'o>(&mut self,
         }
     }
 
-    fn evaluate_trait_predicate_recursively<'o>(&mut self,
-                                                previous_stack: TraitObligationStackList<'o, 'tcx>,
-                                                mut obligation: TraitObligation<'tcx>)
-                                                -> Result<EvaluationResult, OverflowError>
-    {
+    fn evaluate_trait_predicate_recursively<'o>(
+        &mut self,
+        previous_stack: TraitObligationStackList<'o, 'tcx>,
+        mut obligation: TraitObligation<'tcx>,
+    ) -> Result<EvaluationResult, OverflowError> {
         debug!("evaluate_trait_predicate_recursively({:?})", obligation);
 
         if self.intercrate.is_none() && obligation.is_global()
-            && obligation.param_env.caller_bounds.iter().all(|bound| bound.needs_subst()) {
+            && obligation
+                .param_env
+                .caller_bounds
+                .iter()
+                .all(|bound| bound.needs_subst())
+        {
             // If a param env has no global bounds, global obligations do not
             // depend on its particular value in order to work, so we can clear
             // out the param env and get better caching.
-            debug!("evaluate_trait_predicate_recursively({:?}) - in global", obligation);
+            debug!(
+                "evaluate_trait_predicate_recursively({:?}) - in global",
+                obligation
+            );
             obligation.param_env = obligation.param_env.without_caller_bounds();
         }
 
         let stack = self.push_stack(previous_stack, &obligation);
         let fresh_trait_ref = stack.fresh_trait_ref;
         if let Some(result) = self.check_evaluation_cache(obligation.param_env, fresh_trait_ref) {
-            debug!("CACHE HIT: EVAL({:?})={:?}",
-                   fresh_trait_ref,
-                   result);
+            debug!("CACHE HIT: EVAL({:?})={:?}", fresh_trait_ref, result);
             return Ok(result);
         }
 
         let (result, dep_node) = self.in_task(|this| this.evaluate_stack(&stack));
         let result = result?;
 
-        debug!("CACHE MISS: EVAL({:?})={:?}",
-               fresh_trait_ref,
-               result);
+        debug!("CACHE MISS: EVAL({:?})={:?}", fresh_trait_ref, result);
         self.insert_evaluation_cache(obligation.param_env, fresh_trait_ref, dep_node, result);
 
         Ok(result)
     }
 
-    fn evaluate_stack<'o>(&mut self,
-                          stack: &TraitObligationStack<'o, 'tcx>)
-                          -> Result<EvaluationResult, OverflowError>
-    {
+    fn evaluate_stack<'o>(
+        &mut self,
+        stack: &TraitObligationStack<'o, 'tcx>,
+    ) -> Result<EvaluationResult, OverflowError> {
         // In intercrate mode, whenever any of the types are unbound,
         // there can always be an impl. Even if there are no impls in
         // this crate, perhaps the type would be unified with
@@ -913,15 +946,18 @@ fn evaluate_stack<'o>(&mut self,
         // This suffices to allow chains like `FnMut` implemented in
         // terms of `Fn` etc, but we could probably make this more
         // precise still.
-        let unbound_input_types =
-            stack.fresh_trait_ref.skip_binder().input_types().any(|ty| ty.is_fresh());
+        let unbound_input_types = stack
+            .fresh_trait_ref
+            .skip_binder()
+            .input_types()
+            .any(|ty| ty.is_fresh());
         // this check was an imperfect workaround for a bug n the old
         // intercrate mode, it should be removed when that goes away.
-        if unbound_input_types &&
-            self.intercrate == Some(IntercrateMode::Issue43355)
-        {
-            debug!("evaluate_stack({:?}) --> unbound argument, intercrate -->  ambiguous",
-                   stack.fresh_trait_ref);
+        if unbound_input_types && self.intercrate == Some(IntercrateMode::Issue43355) {
+            debug!(
+                "evaluate_stack({:?}) --> unbound argument, intercrate -->  ambiguous",
+                stack.fresh_trait_ref
+            );
             // Heuristics: show the diagnostics when there are no candidates in crate.
             if self.intercrate_ambiguity_causes.is_some() {
                 debug!("evaluate_stack: intercrate_ambiguity_causes is some");
@@ -938,20 +974,23 @@ fn evaluate_stack<'o>(&mut self,
                             },
                         };
                         debug!("evaluate_stack: pushing cause = {:?}", cause);
-                        self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause);
+                        self.intercrate_ambiguity_causes
+                            .as_mut()
+                            .unwrap()
+                            .push(cause);
                     }
                 }
             }
             return Ok(EvaluatedToAmbig);
         }
-        if unbound_input_types &&
-              stack.iter().skip(1).any(
-                  |prev| stack.obligation.param_env == prev.obligation.param_env &&
-                      self.match_fresh_trait_refs(&stack.fresh_trait_ref,
-                                                  &prev.fresh_trait_ref))
-        {
-            debug!("evaluate_stack({:?}) --> unbound argument, recursive --> giving up",
-                   stack.fresh_trait_ref);
+        if unbound_input_types && stack.iter().skip(1).any(|prev| {
+            stack.obligation.param_env == prev.obligation.param_env
+                && self.match_fresh_trait_refs(&stack.fresh_trait_ref, &prev.fresh_trait_ref)
+        }) {
+            debug!(
+                "evaluate_stack({:?}) --> unbound argument, recursive --> giving up",
+                stack.fresh_trait_ref
+            );
             return Ok(EvaluatedToUnknown);
         }
 
@@ -969,29 +1008,31 @@ fn evaluate_stack<'o>(&mut self,
         // `Send`.
         //
         // Note that we do this comparison using the `fresh_trait_ref`
-        // fields. Because these have all been skolemized using
+        // fields. Because these have all been freshened using
         // `self.freshener`, we can be sure that (a) this will not
         // affect the inferencer state and (b) that if we see two
-        // skolemized types with the same index, they refer to the
-        // same unbound type variable.
-        if let Some(rec_index) =
-            stack.iter()
+        // fresh regions with the same index, they refer to the same
+        // unbound type variable.
+        if let Some(rec_index) = stack.iter()
                  .skip(1) // skip top-most frame
                  .position(|prev| stack.obligation.param_env == prev.obligation.param_env &&
                                   stack.fresh_trait_ref == prev.fresh_trait_ref)
         {
-            debug!("evaluate_stack({:?}) --> recursive",
-                   stack.fresh_trait_ref);
+            debug!("evaluate_stack({:?}) --> recursive", stack.fresh_trait_ref);
 
             let cycle = stack.iter().skip(1).take(rec_index + 1);
             let cycle = cycle.map(|stack| ty::Predicate::Trait(stack.obligation.predicate));
             if self.coinductive_match(cycle) {
-                debug!("evaluate_stack({:?}) --> recursive, coinductive",
-                       stack.fresh_trait_ref);
+                debug!(
+                    "evaluate_stack({:?}) --> recursive, coinductive",
+                    stack.fresh_trait_ref
+                );
                 return Ok(EvaluatedToOk);
             } else {
-                debug!("evaluate_stack({:?}) --> recursive, inductive",
-                       stack.fresh_trait_ref);
+                debug!(
+                    "evaluate_stack({:?}) --> recursive, inductive",
+                    stack.fresh_trait_ref
+                );
                 return Ok(EvaluatedToRecur);
             }
         }
@@ -1000,7 +1041,7 @@ fn evaluate_stack<'o>(&mut self,
             Ok(Some(c)) => self.evaluate_candidate(stack, &c),
             Ok(None) => Ok(EvaluatedToAmbig),
             Err(Overflow) => Err(OverflowError),
-            Err(..) => Ok(EvaluatedToErr)
+            Err(..) => Ok(EvaluatedToErr),
         }
     }
 
@@ -1013,7 +1054,8 @@ fn evaluate_stack<'o>(&mut self,
     /// - all the predicates at positions `X..` between `X` an the top are
     ///   also defaulted traits.
     pub fn coinductive_match<I>(&mut self, cycle: I) -> bool
-        where I: Iterator<Item=ty::Predicate<'tcx>>
+    where
+        I: Iterator<Item = ty::Predicate<'tcx>>,
     {
         let mut cycle = cycle;
         cycle.all(|predicate| self.coinductive_predicate(predicate))
@@ -1021,10 +1063,8 @@ pub fn coinductive_match<I>(&mut self, cycle: I) -> bool
 
     fn coinductive_predicate(&self, predicate: ty::Predicate<'tcx>) -> bool {
         let result = match predicate {
-            ty::Predicate::Trait(ref data) => {
-                self.tcx().trait_is_auto(data.def_id())
-            },
-            _ => false
+            ty::Predicate::Trait(ref data) => self.tcx().trait_is_auto(data.def_id()),
+            _ => false,
         };
         debug!("coinductive_predicate({:?}) = {:?}", predicate, result);
         result
@@ -1033,34 +1073,37 @@ fn coinductive_predicate(&self, predicate: ty::Predicate<'tcx>) -> bool {
     /// Further evaluate `candidate` to decide whether all type parameters match and whether nested
     /// obligations are met. Returns true if `candidate` remains viable after this further
     /// scrutiny.
-    fn evaluate_candidate<'o>(&mut self,
-                              stack: &TraitObligationStack<'o, 'tcx>,
-                              candidate: &SelectionCandidate<'tcx>)
-                              -> Result<EvaluationResult, OverflowError>
-    {
-        debug!("evaluate_candidate: depth={} candidate={:?}",
-               stack.obligation.recursion_depth, candidate);
+    fn evaluate_candidate<'o>(
+        &mut self,
+        stack: &TraitObligationStack<'o, 'tcx>,
+        candidate: &SelectionCandidate<'tcx>,
+    ) -> Result<EvaluationResult, OverflowError> {
+        debug!(
+            "evaluate_candidate: depth={} candidate={:?}",
+            stack.obligation.recursion_depth, candidate
+        );
         let result = self.probe(|this, _| {
             let candidate = (*candidate).clone();
             match this.confirm_candidate(stack.obligation, candidate) {
-                Ok(selection) => {
-                    this.evaluate_predicates_recursively(
-                        stack.list(),
-                        selection.nested_obligations().iter())
-                }
-                Err(..) => Ok(EvaluatedToErr)
+                Ok(selection) => this.evaluate_predicates_recursively(
+                    stack.list(),
+                    selection.nested_obligations().iter(),
+                ),
+                Err(..) => Ok(EvaluatedToErr),
             }
         })?;
-        debug!("evaluate_candidate: depth={} result={:?}",
-               stack.obligation.recursion_depth, result);
+        debug!(
+            "evaluate_candidate: depth={} result={:?}",
+            stack.obligation.recursion_depth, result
+        );
         Ok(result)
     }
 
-    fn check_evaluation_cache(&self,
-                              param_env: ty::ParamEnv<'tcx>,
-                              trait_ref: ty::PolyTraitRef<'tcx>)
-                              -> Option<EvaluationResult>
-    {
+    fn check_evaluation_cache(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        trait_ref: ty::PolyTraitRef<'tcx>,
+    ) -> Option<EvaluationResult> {
         let tcx = self.tcx();
         if self.can_use_global_caches(param_env) {
             let cache = tcx.evaluation_cache.hashmap.borrow();
@@ -1068,18 +1111,21 @@ fn check_evaluation_cache(&self,
                 return Some(cached.get(tcx));
             }
         }
-        self.infcx.evaluation_cache.hashmap
-                                   .borrow()
-                                   .get(&trait_ref)
-                                   .map(|v| v.get(tcx))
+        self.infcx
+            .evaluation_cache
+            .hashmap
+            .borrow()
+            .get(&trait_ref)
+            .map(|v| v.get(tcx))
     }
 
-    fn insert_evaluation_cache(&mut self,
-                               param_env: ty::ParamEnv<'tcx>,
-                               trait_ref: ty::PolyTraitRef<'tcx>,
-                               dep_node: DepNodeIndex,
-                               result: EvaluationResult)
-    {
+    fn insert_evaluation_cache(
+        &mut self,
+        param_env: ty::ParamEnv<'tcx>,
+        trait_ref: ty::PolyTraitRef<'tcx>,
+        dep_node: DepNodeIndex,
+        result: EvaluationResult,
+    ) {
         // Avoid caching results that depend on more than just the trait-ref
         // - the stack can create recursion.
         if result.is_stack_dependent() {
@@ -1090,28 +1136,30 @@ fn insert_evaluation_cache(&mut self,
             if let Some(trait_ref) = self.tcx().lift_to_global(&trait_ref) {
                 debug!(
                     "insert_evaluation_cache(trait_ref={:?}, candidate={:?}) global",
-                    trait_ref,
-                    result,
+                    trait_ref, result,
                 );
                 // This may overwrite the cache with the same value
                 // FIXME: Due to #50507 this overwrites the different values
                 // This should be changed to use HashMapExt::insert_same
                 // when that is fixed
-                self.tcx().evaluation_cache
-                          .hashmap.borrow_mut()
-                          .insert(trait_ref, WithDepNode::new(dep_node, result));
+                self.tcx()
+                    .evaluation_cache
+                    .hashmap
+                    .borrow_mut()
+                    .insert(trait_ref, WithDepNode::new(dep_node, result));
                 return;
             }
         }
 
         debug!(
             "insert_evaluation_cache(trait_ref={:?}, candidate={:?})",
-            trait_ref,
-            result,
+            trait_ref, result,
         );
-        self.infcx.evaluation_cache.hashmap
-                                   .borrow_mut()
-                                   .insert(trait_ref, WithDepNode::new(dep_node, result));
+        self.infcx
+            .evaluation_cache
+            .hashmap
+            .borrow_mut()
+            .insert(trait_ref, WithDepNode::new(dep_node, result));
     }
 
     ///////////////////////////////////////////////////////////////////////////
@@ -1124,10 +1172,10 @@ fn insert_evaluation_cache(&mut self,
     // [rustc guide]:
     // https://rust-lang-nursery.github.io/rustc-guide/traits/resolution.html#candidate-assembly
 
-    fn candidate_from_obligation<'o>(&mut self,
-                                     stack: &TraitObligationStack<'o, 'tcx>)
-                                     -> SelectionResult<'tcx, SelectionCandidate<'tcx>>
-    {
+    fn candidate_from_obligation<'o>(
+        &mut self,
+        stack: &TraitObligationStack<'o, 'tcx>,
+    ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
         // Watch out for overflow. This intentionally bypasses (and does
         // not update) the cache.
         let recursion_limit = *self.infcx.tcx.sess.recursion_limit.get();
@@ -1135,72 +1183,78 @@ fn candidate_from_obligation<'o>(&mut self,
             match self.query_mode {
                 TraitQueryMode::Standard => {
                     self.infcx().report_overflow_error(&stack.obligation, true);
-                },
+                }
                 TraitQueryMode::Canonical => {
                     return Err(Overflow);
-                },
+                }
             }
         }
 
-        // Check the cache. Note that we skolemize the trait-ref
-        // separately rather than using `stack.fresh_trait_ref` -- this
-        // is because we want the unbound variables to be replaced
-        // with fresh skolemized types starting from index 0.
-        let cache_fresh_trait_pred =
-            self.infcx.freshen(stack.obligation.predicate.clone());
-        debug!("candidate_from_obligation(cache_fresh_trait_pred={:?}, obligation={:?})",
-               cache_fresh_trait_pred,
-               stack);
+        // Check the cache. Note that we freshen the trait-ref
+        // separately rather than using `stack.fresh_trait_ref` --
+        // this is because we want the unbound variables to be
+        // replaced with fresh types starting from index 0.
+        let cache_fresh_trait_pred = self.infcx.freshen(stack.obligation.predicate.clone());
+        debug!(
+            "candidate_from_obligation(cache_fresh_trait_pred={:?}, obligation={:?})",
+            cache_fresh_trait_pred, stack
+        );
         debug_assert!(!stack.obligation.predicate.has_escaping_regions());
 
-        if let Some(c) = self.check_candidate_cache(stack.obligation.param_env,
-                                                    &cache_fresh_trait_pred) {
-            debug!("CACHE HIT: SELECT({:?})={:?}",
-                   cache_fresh_trait_pred,
-                   c);
+        if let Some(c) =
+            self.check_candidate_cache(stack.obligation.param_env, &cache_fresh_trait_pred)
+        {
+            debug!("CACHE HIT: SELECT({:?})={:?}", cache_fresh_trait_pred, c);
             return c;
         }
 
         // If no match, compute result and insert into cache.
-        let (candidate, dep_node) = self.in_task(|this|
-            this.candidate_from_obligation_no_cache(stack)
-        );
+        let (candidate, dep_node) =
+            self.in_task(|this| this.candidate_from_obligation_no_cache(stack));
 
-        debug!("CACHE MISS: SELECT({:?})={:?}",
-               cache_fresh_trait_pred, candidate);
-        self.insert_candidate_cache(stack.obligation.param_env,
-                                    cache_fresh_trait_pred,
-                                    dep_node,
-                                    candidate.clone());
+        debug!(
+            "CACHE MISS: SELECT({:?})={:?}",
+            cache_fresh_trait_pred, candidate
+        );
+        self.insert_candidate_cache(
+            stack.obligation.param_env,
+            cache_fresh_trait_pred,
+            dep_node,
+            candidate.clone(),
+        );
         candidate
     }
 
     fn in_task<OP, R>(&mut self, op: OP) -> (R, DepNodeIndex)
-        where OP: FnOnce(&mut Self) -> R
+    where
+        OP: FnOnce(&mut Self) -> R,
     {
-        let (result, dep_node) = self.tcx().dep_graph.with_anon_task(DepKind::TraitSelect, ||
-            op(self)
-        );
+        let (result, dep_node) = self.tcx()
+            .dep_graph
+            .with_anon_task(DepKind::TraitSelect, || op(self));
         self.tcx().dep_graph.read_index(dep_node);
         (result, dep_node)
     }
 
     // Treat negative impls as unimplemented
-    fn filter_negative_impls(&self, candidate: SelectionCandidate<'tcx>)
-                             -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
+    fn filter_negative_impls(
+        &self,
+        candidate: SelectionCandidate<'tcx>,
+    ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
         if let ImplCandidate(def_id) = candidate {
-            if !self.allow_negative_impls &&
-                self.tcx().impl_polarity(def_id) == hir::ImplPolarity::Negative {
-                return Err(Unimplemented)
+            if !self.allow_negative_impls
+                && self.tcx().impl_polarity(def_id) == hir::ImplPolarity::Negative
+            {
+                return Err(Unimplemented);
             }
         }
         Ok(Some(candidate))
     }
 
-    fn candidate_from_obligation_no_cache<'o>(&mut self,
-                                              stack: &TraitObligationStack<'o, 'tcx>)
-                                              -> SelectionResult<'tcx, SelectionCandidate<'tcx>>
-    {
+    fn candidate_from_obligation_no_cache<'o>(
+        &mut self,
+        stack: &TraitObligationStack<'o, 'tcx>,
+    ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
         if stack.obligation.predicate.references_error() {
             // If we encounter a `Error`, we generally prefer the
             // most "optimistic" result in response -- that is, the
@@ -1220,18 +1274,20 @@ fn candidate_from_obligation_no_cache<'o>(&mut self,
                 if let Ok(candidate_set) = self.assemble_candidates(stack) {
                     let mut no_candidates_apply = true;
                     {
-                        let evaluated_candidates = candidate_set.vec.iter().map(|c|
-                            self.evaluate_candidate(stack, &c));
+                        let evaluated_candidates = candidate_set
+                            .vec
+                            .iter()
+                            .map(|c| self.evaluate_candidate(stack, &c));
 
                         for ec in evaluated_candidates {
                             match ec {
                                 Ok(c) => {
                                     if c.may_apply() {
                                         no_candidates_apply = false;
-                                        break
+                                        break;
                                     }
-                                },
-                                Err(e) => return Err(e.into())
+                                }
+                                Err(e) => return Err(e.into()),
                             }
                         }
                     }
@@ -1251,10 +1307,16 @@ fn candidate_from_obligation_no_cache<'o>(&mut self,
                                 self_desc,
                             }
                         } else {
-                            IntercrateAmbiguityCause::DownstreamCrate { trait_desc, self_desc }
+                            IntercrateAmbiguityCause::DownstreamCrate {
+                                trait_desc,
+                                self_desc,
+                            }
                         };
                         debug!("evaluate_stack: pushing cause = {:?}", cause);
-                        self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause);
+                        self.intercrate_ambiguity_causes
+                            .as_mut()
+                            .unwrap()
+                            .push(cause);
                     }
                 }
             }
@@ -1270,10 +1332,12 @@ fn candidate_from_obligation_no_cache<'o>(&mut self,
 
         let mut candidates = candidate_set.vec;
 
-        debug!("assembled {} candidates for {:?}: {:?}",
-               candidates.len(),
-               stack,
-               candidates);
+        debug!(
+            "assembled {} candidates for {:?}: {:?}",
+            candidates.len(),
+            stack,
+            candidates
+        );
 
         // At this point, we know that each of the entries in the
         // candidate set is *individually* applicable. Now we have to
@@ -1319,10 +1383,12 @@ fn candidate_from_obligation_no_cache<'o>(&mut self,
         let mut candidates: Vec<EvaluatedCandidate<'_>> =
             candidates?.into_iter().filter_map(|c| c).collect();
 
-        debug!("winnowed to {} candidates for {:?}: {:?}",
-               candidates.len(),
-               stack,
-               candidates);
+        debug!(
+            "winnowed to {} candidates for {:?}: {:?}",
+            candidates.len(),
+            stack,
+            candidates
+        );
 
         // If there are STILL multiple candidate, we can further
         // reduce the list by dropping duplicates -- including
@@ -1330,18 +1396,24 @@ fn candidate_from_obligation_no_cache<'o>(&mut self,
         if candidates.len() > 1 {
             let mut i = 0;
             while i < candidates.len() {
-                let is_dup =
-                    (0..candidates.len())
-                    .filter(|&j| i != j)
-                    .any(|j| self.candidate_should_be_dropped_in_favor_of(&candidates[i],
-                                                                          &candidates[j]));
+                let is_dup = (0..candidates.len()).filter(|&j| i != j).any(|j| {
+                    self.candidate_should_be_dropped_in_favor_of(&candidates[i], &candidates[j])
+                });
                 if is_dup {
-                    debug!("Dropping candidate #{}/{}: {:?}",
-                           i, candidates.len(), candidates[i]);
+                    debug!(
+                        "Dropping candidate #{}/{}: {:?}",
+                        i,
+                        candidates.len(),
+                        candidates[i]
+                    );
                     candidates.swap_remove(i);
                 } else {
-                    debug!("Retaining candidate #{}/{}: {:?}",
-                           i, candidates.len(), candidates[i]);
+                    debug!(
+                        "Retaining candidate #{}/{}: {:?}",
+                        i,
+                        candidates.len(),
+                        candidates[i]
+                    );
                     i += 1;
 
                     // If there are *STILL* multiple candidates, give up
@@ -1371,10 +1443,7 @@ fn candidate_from_obligation_no_cache<'o>(&mut self,
         self.filter_negative_impls(candidates.pop().unwrap().candidate)
     }
 
-    fn is_knowable<'o>(&mut self,
-                       stack: &TraitObligationStack<'o, 'tcx>)
-                       -> Option<Conflict>
-    {
+    fn is_knowable<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) -> Option<Conflict> {
         debug!("is_knowable(intercrate={:?})", self.intercrate);
 
         if !self.intercrate.is_some() {
@@ -1382,7 +1451,8 @@ fn is_knowable<'o>(&mut self,
         }
 
         let obligation = &stack.obligation;
-        let predicate = self.infcx().resolve_type_vars_if_possible(&obligation.predicate);
+        let predicate = self.infcx()
+            .resolve_type_vars_if_possible(&obligation.predicate);
 
         // ok to skip binder because of the nature of the
         // trait-ref-is-knowable check, which does not care about
@@ -1390,8 +1460,13 @@ fn is_knowable<'o>(&mut self,
         let trait_ref = predicate.skip_binder().trait_ref;
 
         let result = coherence::trait_ref_is_knowable(self.tcx(), trait_ref);
-        if let (Some(Conflict::Downstream { used_to_be_broken: true }),
-                Some(IntercrateMode::Issue43355)) = (result, self.intercrate) {
+        if let (
+            Some(Conflict::Downstream {
+                used_to_be_broken: true,
+            }),
+            Some(IntercrateMode::Issue43355),
+        ) = (result, self.intercrate)
+        {
             debug!("is_knowable: IGNORING conflict to be bug-compatible with #43355");
             None
         } else {
@@ -1429,11 +1504,11 @@ fn can_use_global_caches(&self, param_env: ty::ParamEnv<'tcx>) -> bool {
         true
     }
 
-    fn check_candidate_cache(&mut self,
-                             param_env: ty::ParamEnv<'tcx>,
-                             cache_fresh_trait_pred: &ty::PolyTraitPredicate<'tcx>)
-                             -> Option<SelectionResult<'tcx, SelectionCandidate<'tcx>>>
-    {
+    fn check_candidate_cache(
+        &mut self,
+        param_env: ty::ParamEnv<'tcx>,
+        cache_fresh_trait_pred: &ty::PolyTraitPredicate<'tcx>,
+    ) -> Option<SelectionResult<'tcx, SelectionCandidate<'tcx>>> {
         let tcx = self.tcx();
         let trait_ref = &cache_fresh_trait_pred.skip_binder().trait_ref;
         if self.can_use_global_caches(param_env) {
@@ -1442,18 +1517,21 @@ fn check_candidate_cache(&mut self,
                 return Some(cached.get(tcx));
             }
         }
-        self.infcx.selection_cache.hashmap
-                                  .borrow()
-                                  .get(trait_ref)
-                                  .map(|v| v.get(tcx))
+        self.infcx
+            .selection_cache
+            .hashmap
+            .borrow()
+            .get(trait_ref)
+            .map(|v| v.get(tcx))
     }
 
-    fn insert_candidate_cache(&mut self,
-                              param_env: ty::ParamEnv<'tcx>,
-                              cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>,
-                              dep_node: DepNodeIndex,
-                              candidate: SelectionResult<'tcx, SelectionCandidate<'tcx>>)
-    {
+    fn insert_candidate_cache(
+        &mut self,
+        param_env: ty::ParamEnv<'tcx>,
+        cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>,
+        dep_node: DepNodeIndex,
+        candidate: SelectionResult<'tcx, SelectionCandidate<'tcx>>,
+    ) {
         let tcx = self.tcx();
         let trait_ref = cache_fresh_trait_pred.skip_binder().trait_ref;
         if self.can_use_global_caches(param_env) {
@@ -1464,13 +1542,13 @@ fn insert_candidate_cache(&mut self,
                 if let Some(candidate) = tcx.lift_to_global(&candidate) {
                     debug!(
                         "insert_candidate_cache(trait_ref={:?}, candidate={:?}) global",
-                        trait_ref,
-                        candidate,
+                        trait_ref, candidate,
                     );
                     // This may overwrite the cache with the same value
                     tcx.selection_cache
-                       .hashmap.borrow_mut()
-                       .insert(trait_ref, WithDepNode::new(dep_node, candidate));
+                        .hashmap
+                        .borrow_mut()
+                        .insert(trait_ref, WithDepNode::new(dep_node, candidate));
                     return;
                 }
             }
@@ -1478,24 +1556,26 @@ fn insert_candidate_cache(&mut self,
 
         debug!(
             "insert_candidate_cache(trait_ref={:?}, candidate={:?}) local",
-            trait_ref,
-            candidate,
+            trait_ref, candidate,
         );
-        self.infcx.selection_cache.hashmap
-                                  .borrow_mut()
-                                  .insert(trait_ref, WithDepNode::new(dep_node, candidate));
+        self.infcx
+            .selection_cache
+            .hashmap
+            .borrow_mut()
+            .insert(trait_ref, WithDepNode::new(dep_node, candidate));
     }
 
-    fn assemble_candidates<'o>(&mut self,
-                               stack: &TraitObligationStack<'o, 'tcx>)
-                               -> Result<SelectionCandidateSet<'tcx>, SelectionError<'tcx>>
-    {
-        let obligation = stack.obligation;
+    fn assemble_candidates<'o>(
+        &mut self,
+        stack: &TraitObligationStack<'o, 'tcx>,
+    ) -> Result<SelectionCandidateSet<'tcx>, SelectionError<'tcx>> {
+        let TraitObligationStack { obligation, .. } = *stack;
         let ref obligation = Obligation {
             param_env: obligation.param_env,
             cause: obligation.cause.clone(),
             recursion_depth: obligation.recursion_depth,
-            predicate: self.infcx().resolve_type_vars_if_possible(&obligation.predicate)
+            predicate: self.infcx()
+                .resolve_type_vars_if_possible(&obligation.predicate),
         };
 
         if obligation.predicate.skip_binder().self_ty().is_ty_var() {
@@ -1508,12 +1588,15 @@ fn assemble_candidates<'o>(&mut self,
             // Take the fast path out - this also improves
             // performance by preventing assemble_candidates_from_impls from
             // matching every impl for this trait.
-            return Ok(SelectionCandidateSet { vec: vec![], ambiguous: true });
+            return Ok(SelectionCandidateSet {
+                vec: vec![],
+                ambiguous: true,
+            });
         }
 
         let mut candidates = SelectionCandidateSet {
             vec: Vec::new(),
-            ambiguous: false
+            ambiguous: false,
         };
 
         // Other bounds. Consider both in-scope bounds from fn decl
@@ -1522,8 +1605,10 @@ fn assemble_candidates<'o>(&mut self,
         let lang_items = self.tcx().lang_items();
 
         if lang_items.copy_trait() == Some(def_id) {
-            debug!("obligation self ty is {:?}",
-                   obligation.predicate.skip_binder().self_ty());
+            debug!(
+                "obligation self ty is {:?}",
+                obligation.predicate.skip_binder().self_ty()
+            );
 
             // User-defined copy impls are permitted, but only for
             // structs and enums.
@@ -1536,8 +1621,7 @@ fn assemble_candidates<'o>(&mut self,
             // Sized is never implementable by end-users, it is
             // always automatically computed.
             let sized_conditions = self.sized_conditions(obligation);
-            self.assemble_builtin_bound_candidates(sized_conditions,
-                                                   &mut candidates)?;
+            self.assemble_builtin_bound_candidates(sized_conditions, &mut candidates)?;
         } else if lang_items.unsize_trait() == Some(def_id) {
             self.assemble_candidates_for_unsizing(obligation, &mut candidates);
         } else {
@@ -1567,27 +1651,29 @@ fn assemble_candidates<'o>(&mut self,
         Ok(candidates)
     }
 
-    fn assemble_candidates_from_projected_tys(&mut self,
-                                              obligation: &TraitObligation<'tcx>,
-                                              candidates: &mut SelectionCandidateSet<'tcx>)
-    {
+    fn assemble_candidates_from_projected_tys(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        candidates: &mut SelectionCandidateSet<'tcx>,
+    ) {
         debug!("assemble_candidates_for_projected_tys({:?})", obligation);
 
-        // before we go into the whole skolemization thing, just
+        // before we go into the whole placeholder thing, just
         // quickly check if the self-type is a projection at all.
         match obligation.predicate.skip_binder().trait_ref.self_ty().sty {
             ty::Projection(_) | ty::Opaque(..) => {}
             ty::Infer(ty::TyVar(_)) => {
-                span_bug!(obligation.cause.span,
-                          "Self=_ should have been handled by assemble_candidates");
+                span_bug!(
+                    obligation.cause.span,
+                    "Self=_ should have been handled by assemble_candidates"
+                );
             }
-            _ => return
+            _ => return,
         }
 
-        let result = self.probe(|this, snapshot|
-            this.match_projection_obligation_against_definition_bounds(obligation,
-                                                                       snapshot)
-        );
+        let result = self.probe(|this, snapshot| {
+            this.match_projection_obligation_against_definition_bounds(obligation, snapshot)
+        });
 
         if result {
             candidates.vec.push(ProjectionCandidate);
@@ -1597,65 +1683,76 @@ fn assemble_candidates_from_projected_tys(&mut self,
     fn match_projection_obligation_against_definition_bounds(
         &mut self,
         obligation: &TraitObligation<'tcx>,
-        snapshot: &infer::CombinedSnapshot<'cx, 'tcx>)
-        -> bool
-    {
-        let poly_trait_predicate =
-            self.infcx().resolve_type_vars_if_possible(&obligation.predicate);
-        let (skol_trait_predicate, skol_map) =
-            self.infcx().skolemize_late_bound_regions(&poly_trait_predicate);
-        debug!("match_projection_obligation_against_definition_bounds: \
-                skol_trait_predicate={:?} skol_map={:?}",
-               skol_trait_predicate,
-               skol_map);
+        snapshot: &infer::CombinedSnapshot<'cx, 'tcx>,
+    ) -> bool {
+        let poly_trait_predicate = self.infcx()
+            .resolve_type_vars_if_possible(&obligation.predicate);
+        let (skol_trait_predicate, placeholder_map) = self.infcx()
+            .replace_late_bound_regions_with_placeholders(&poly_trait_predicate);
+        debug!(
+            "match_projection_obligation_against_definition_bounds: \
+             skol_trait_predicate={:?} placeholder_map={:?}",
+            skol_trait_predicate, placeholder_map
+        );
 
         let (def_id, substs) = match skol_trait_predicate.trait_ref.self_ty().sty {
-            ty::Projection(ref data) =>
-                (data.trait_ref(self.tcx()).def_id, data.substs),
+            ty::Projection(ref data) => (data.trait_ref(self.tcx()).def_id, data.substs),
             ty::Opaque(def_id, substs) => (def_id, substs),
             _ => {
                 span_bug!(
                     obligation.cause.span,
                     "match_projection_obligation_against_definition_bounds() called \
                      but self-ty is not a projection: {:?}",
-                    skol_trait_predicate.trait_ref.self_ty());
+                    skol_trait_predicate.trait_ref.self_ty()
+                );
             }
         };
-        debug!("match_projection_obligation_against_definition_bounds: \
-                def_id={:?}, substs={:?}",
-               def_id, substs);
+        debug!(
+            "match_projection_obligation_against_definition_bounds: \
+             def_id={:?}, substs={:?}",
+            def_id, substs
+        );
 
         let predicates_of = self.tcx().predicates_of(def_id);
         let bounds = predicates_of.instantiate(self.tcx(), substs);
-        debug!("match_projection_obligation_against_definition_bounds: \
-                bounds={:?}",
-               bounds);
+        debug!(
+            "match_projection_obligation_against_definition_bounds: \
+             bounds={:?}",
+            bounds
+        );
 
-        let matching_bound =
-            util::elaborate_predicates(self.tcx(), bounds.predicates)
+        let matching_bound = util::elaborate_predicates(self.tcx(), bounds.predicates)
             .filter_to_traits()
-            .find(
-                |bound| self.probe(
-                    |this, _| this.match_projection(obligation,
-                                                    bound.clone(),
-                                                    skol_trait_predicate.trait_ref.clone(),
-                                                    &skol_map,
-                                                    snapshot)));
-
-        debug!("match_projection_obligation_against_definition_bounds: \
-                matching_bound={:?}",
-               matching_bound);
+            .find(|bound| {
+                self.probe(|this, _| {
+                    this.match_projection(
+                        obligation,
+                        bound.clone(),
+                        skol_trait_predicate.trait_ref.clone(),
+                        &placeholder_map,
+                        snapshot,
+                    )
+                })
+            });
+
+        debug!(
+            "match_projection_obligation_against_definition_bounds: \
+             matching_bound={:?}",
+            matching_bound
+        );
         match matching_bound {
             None => false,
             Some(bound) => {
                 // Repeat the successful match, if any, this time outside of a probe.
-                let result = self.match_projection(obligation,
-                                                   bound,
-                                                   skol_trait_predicate.trait_ref.clone(),
-                                                   &skol_map,
-                                                   snapshot);
+                let result = self.match_projection(
+                    obligation,
+                    bound,
+                    skol_trait_predicate.trait_ref.clone(),
+                    &placeholder_map,
+                    snapshot,
+                );
 
-                self.infcx.pop_skolemized(skol_map, snapshot);
+                self.infcx.pop_placeholders(placeholder_map, snapshot);
 
                 assert!(result);
                 true
@@ -1663,39 +1760,48 @@ fn match_projection_obligation_against_definition_bounds(
         }
     }
 
-    fn match_projection(&mut self,
-                        obligation: &TraitObligation<'tcx>,
-                        trait_bound: ty::PolyTraitRef<'tcx>,
-                        skol_trait_ref: ty::TraitRef<'tcx>,
-                        skol_map: &infer::SkolemizationMap<'tcx>,
-                        snapshot: &infer::CombinedSnapshot<'cx, 'tcx>)
-                        -> bool
-    {
+    fn match_projection(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        trait_bound: ty::PolyTraitRef<'tcx>,
+        skol_trait_ref: ty::TraitRef<'tcx>,
+        placeholder_map: &infer::PlaceholderMap<'tcx>,
+        snapshot: &infer::CombinedSnapshot<'cx, 'tcx>,
+    ) -> bool {
         debug_assert!(!skol_trait_ref.has_escaping_regions());
-        if self.infcx.at(&obligation.cause, obligation.param_env)
-                     .sup(ty::Binder::dummy(skol_trait_ref), trait_bound).is_err() {
+        if self.infcx
+            .at(&obligation.cause, obligation.param_env)
+            .sup(ty::Binder::dummy(skol_trait_ref), trait_bound)
+            .is_err()
+        {
             return false;
         }
 
-        self.infcx.leak_check(false, obligation.cause.span, skol_map, snapshot).is_ok()
+        self.infcx
+            .leak_check(false, obligation.cause.span, placeholder_map, snapshot)
+            .is_ok()
     }
 
     /// Given an obligation like `<SomeTrait for T>`, search the obligations that the caller
     /// supplied to find out whether it is listed among them.
     ///
     /// Never affects inference environment.
-    fn assemble_candidates_from_caller_bounds<'o>(&mut self,
-                                                  stack: &TraitObligationStack<'o, 'tcx>,
-                                                  candidates: &mut SelectionCandidateSet<'tcx>)
-                                                  -> Result<(),SelectionError<'tcx>>
-    {
-        debug!("assemble_candidates_from_caller_bounds({:?})",
-               stack.obligation);
+    fn assemble_candidates_from_caller_bounds<'o>(
+        &mut self,
+        stack: &TraitObligationStack<'o, 'tcx>,
+        candidates: &mut SelectionCandidateSet<'tcx>,
+    ) -> Result<(), SelectionError<'tcx>> {
+        debug!(
+            "assemble_candidates_from_caller_bounds({:?})",
+            stack.obligation
+        );
 
-        let all_bounds =
-            stack.obligation.param_env.caller_bounds
-                                      .iter()
-                                      .filter_map(|o| o.to_opt_poly_trait_ref());
+        let all_bounds = stack
+            .obligation
+            .param_env
+            .caller_bounds
+            .iter()
+            .filter_map(|o| o.to_opt_poly_trait_ref());
 
         // micro-optimization: filter out predicates relating to different
         // traits.
@@ -1716,26 +1822,26 @@ fn assemble_candidates_from_caller_bounds<'o>(&mut self,
         Ok(())
     }
 
-    fn evaluate_where_clause<'o>(&mut self,
-                                 stack: &TraitObligationStack<'o, 'tcx>,
-                                 where_clause_trait_ref: ty::PolyTraitRef<'tcx>)
-                                 -> Result<EvaluationResult, OverflowError>
-    {
-        self.probe(move |this, _|
+    fn evaluate_where_clause<'o>(
+        &mut self,
+        stack: &TraitObligationStack<'o, 'tcx>,
+        where_clause_trait_ref: ty::PolyTraitRef<'tcx>,
+    ) -> Result<EvaluationResult, OverflowError> {
+        self.probe(move |this, _| {
             match this.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) {
                 Ok(obligations) => {
                     this.evaluate_predicates_recursively(stack.list(), obligations.iter())
                 }
-                Err(()) => Ok(EvaluatedToErr)
+                Err(()) => Ok(EvaluatedToErr),
             }
-        )
+        })
     }
 
-    fn assemble_generator_candidates(&mut self,
-                                   obligation: &TraitObligation<'tcx>,
-                                   candidates: &mut SelectionCandidateSet<'tcx>)
-                                   -> Result<(),SelectionError<'tcx>>
-    {
+    fn assemble_generator_candidates(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        candidates: &mut SelectionCandidateSet<'tcx>,
+    ) -> Result<(), SelectionError<'tcx>> {
         if self.tcx().lang_items().gen_trait() != Some(obligation.predicate.def_id()) {
             return Ok(());
         }
@@ -1746,9 +1852,10 @@ fn assemble_generator_candidates(&mut self,
         let self_ty = *obligation.self_ty().skip_binder();
         match self_ty.sty {
             ty::Generator(..) => {
-                debug!("assemble_generator_candidates: self_ty={:?} obligation={:?}",
-                       self_ty,
-                       obligation);
+                debug!(
+                    "assemble_generator_candidates: self_ty={:?} obligation={:?}",
+                    self_ty, obligation
+                );
 
                 candidates.vec.push(GeneratorCandidate);
             }
@@ -1768,14 +1875,19 @@ fn assemble_generator_candidates(&mut self,
     /// Note: the type parameters on a closure candidate are modeled as *output* type
     /// parameters and hence do not affect whether this trait is a match or not. They will be
     /// unified during the confirmation step.
-    fn assemble_closure_candidates(&mut self,
-                                   obligation: &TraitObligation<'tcx>,
-                                   candidates: &mut SelectionCandidateSet<'tcx>)
-                                   -> Result<(),SelectionError<'tcx>>
-    {
-        let kind = match self.tcx().lang_items().fn_trait_kind(obligation.predicate.def_id()) {
+    fn assemble_closure_candidates(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        candidates: &mut SelectionCandidateSet<'tcx>,
+    ) -> Result<(), SelectionError<'tcx>> {
+        let kind = match self.tcx()
+            .lang_items()
+            .fn_trait_kind(obligation.predicate.def_id())
+        {
             Some(k) => k,
-            None => { return Ok(()); }
+            None => {
+                return Ok(());
+            }
         };
 
         // ok to skip binder because the substs on closure types never
@@ -1783,11 +1895,16 @@ fn assemble_closure_candidates(&mut self,
         // type/region parameters
         match obligation.self_ty().skip_binder().sty {
             ty::Closure(closure_def_id, closure_substs) => {
-                debug!("assemble_unboxed_candidates: kind={:?} obligation={:?}",
-                       kind, obligation);
+                debug!(
+                    "assemble_unboxed_candidates: kind={:?} obligation={:?}",
+                    kind, obligation
+                );
                 match self.infcx.closure_kind(closure_def_id, closure_substs) {
                     Some(closure_kind) => {
-                        debug!("assemble_unboxed_candidates: closure_kind = {:?}", closure_kind);
+                        debug!(
+                            "assemble_unboxed_candidates: closure_kind = {:?}",
+                            closure_kind
+                        );
                         if closure_kind.extends(kind) {
                             candidates.vec.push(ClosureCandidate);
                         }
@@ -1809,13 +1926,17 @@ fn assemble_closure_candidates(&mut self,
     }
 
     /// Implement one of the `Fn()` family for a fn pointer.
-    fn assemble_fn_pointer_candidates(&mut self,
-                                      obligation: &TraitObligation<'tcx>,
-                                      candidates: &mut SelectionCandidateSet<'tcx>)
-                                      -> Result<(),SelectionError<'tcx>>
-    {
+    fn assemble_fn_pointer_candidates(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        candidates: &mut SelectionCandidateSet<'tcx>,
+    ) -> Result<(), SelectionError<'tcx>> {
         // We provide impl of all fn traits for fn pointers.
-        if self.tcx().lang_items().fn_trait_kind(obligation.predicate.def_id()).is_none() {
+        if self.tcx()
+            .lang_items()
+            .fn_trait_kind(obligation.predicate.def_id())
+            .is_none()
+        {
             return Ok(());
         }
 
@@ -1833,7 +1954,8 @@ fn assemble_fn_pointer_candidates(&mut self,
                     abi: Abi::Rust,
                     variadic: false,
                     ..
-                } = self_ty.fn_sig(self.tcx()).skip_binder() {
+                } = self_ty.fn_sig(self.tcx()).skip_binder()
+                {
                     candidates.vec.push(FnPointerCandidate);
                 }
             }
@@ -1844,37 +1966,41 @@ fn assemble_fn_pointer_candidates(&mut self,
     }
 
     /// Search for impls that might apply to `obligation`.
-    fn assemble_candidates_from_impls(&mut self,
-                                      obligation: &TraitObligation<'tcx>,
-                                      candidates: &mut SelectionCandidateSet<'tcx>)
-                                      -> Result<(), SelectionError<'tcx>>
-    {
-        debug!("assemble_candidates_from_impls(obligation={:?})", obligation);
+    fn assemble_candidates_from_impls(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        candidates: &mut SelectionCandidateSet<'tcx>,
+    ) -> Result<(), SelectionError<'tcx>> {
+        debug!(
+            "assemble_candidates_from_impls(obligation={:?})",
+            obligation
+        );
 
         self.tcx().for_each_relevant_impl(
             obligation.predicate.def_id(),
             obligation.predicate.skip_binder().trait_ref.self_ty(),
             |impl_def_id| {
-                self.probe(|this, snapshot| /* [1] */
-                    if let Ok(skol_map) = this.match_impl(impl_def_id, obligation, snapshot) {
+                self.probe(|this, snapshot| {
+                    if let Ok(placeholder_map) = this.match_impl(impl_def_id, obligation, snapshot)
+                    {
                         candidates.vec.push(ImplCandidate(impl_def_id));
 
-                        // NB: we can safely drop the skol map
-                        // since we are in a probe [1]
-                        mem::drop(skol_map);
+                        // NB: we can safely drop the placeholder map
+                        // since we are in a probe.
+                        mem::drop(placeholder_map);
                     }
-                );
-            }
+                });
+            },
         );
 
         Ok(())
     }
 
-    fn assemble_candidates_from_auto_impls(&mut self,
-                                           obligation: &TraitObligation<'tcx>,
-                                           candidates: &mut SelectionCandidateSet<'tcx>)
-                                           -> Result<(), SelectionError<'tcx>>
-    {
+    fn assemble_candidates_from_auto_impls(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        candidates: &mut SelectionCandidateSet<'tcx>,
+    ) -> Result<(), SelectionError<'tcx>> {
         // OK to skip binder here because the tests we do below do not involve bound regions
         let self_ty = *obligation.self_ty().skip_binder();
         debug!("assemble_candidates_from_auto_impls(self_ty={:?})", self_ty);
@@ -1895,8 +2021,7 @@ fn assemble_candidates_from_auto_impls(&mut self,
                     // still be provided by a manual implementation for
                     // this trait and type.
                 }
-                ty::Param(..) |
-                ty::Projection(..) => {
+                ty::Param(..) | ty::Projection(..) => {
                     // In these cases, we don't know what the actual
                     // type is.  Therefore, we cannot break it down
                     // into its constituent types. So we don't
@@ -1915,9 +2040,7 @@ fn assemble_candidates_from_auto_impls(&mut self,
                     // the auto impl might apply, we don't know
                     candidates.ambiguous = true;
                 }
-                _ => {
-                    candidates.vec.push(AutoImplCandidate(def_id.clone()))
-                }
+                _ => candidates.vec.push(AutoImplCandidate(def_id.clone())),
             }
         }
 
@@ -1925,12 +2048,15 @@ fn assemble_candidates_from_auto_impls(&mut self,
     }
 
     /// Search for impls that might apply to `obligation`.
-    fn assemble_candidates_from_object_ty(&mut self,
-                                          obligation: &TraitObligation<'tcx>,
-                                          candidates: &mut SelectionCandidateSet<'tcx>)
-    {
-        debug!("assemble_candidates_from_object_ty(self_ty={:?})",
-               obligation.self_ty().skip_binder());
+    fn assemble_candidates_from_object_ty(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        candidates: &mut SelectionCandidateSet<'tcx>,
+    ) {
+        debug!(
+            "assemble_candidates_from_object_ty(self_ty={:?})",
+            obligation.self_ty().skip_binder()
+        );
 
         // Object-safety candidates are only applicable to object-safe
         // traits. Including this check is useful because it helps
@@ -1951,9 +2077,13 @@ fn assemble_candidates_from_object_ty(&mut self,
             let self_ty = this.tcx().erase_late_bound_regions(&obligation.self_ty());
             let poly_trait_ref = match self_ty.sty {
                 ty::Dynamic(ref data, ..) => {
-                    if data.auto_traits().any(|did| did == obligation.predicate.def_id()) {
-                        debug!("assemble_candidates_from_object_ty: matched builtin bound, \
-                                pushing candidate");
+                    if data.auto_traits()
+                        .any(|did| did == obligation.predicate.def_id())
+                    {
+                        debug!(
+                            "assemble_candidates_from_object_ty: matched builtin bound, \
+                             pushing candidate"
+                        );
                         candidates.vec.push(BuiltinObjectCandidate);
                         return;
                     }
@@ -1968,25 +2098,27 @@ fn assemble_candidates_from_object_ty(&mut self,
                     candidates.ambiguous = true; // could wind up being an object type
                     return;
                 }
-                _ => return
+                _ => return,
             };
 
-            debug!("assemble_candidates_from_object_ty: poly_trait_ref={:?}",
-                   poly_trait_ref);
+            debug!(
+                "assemble_candidates_from_object_ty: poly_trait_ref={:?}",
+                poly_trait_ref
+            );
 
             // Count only those upcast versions that match the trait-ref
             // we are looking for. Specifically, do not only check for the
             // correct trait, but also the correct type parameters.
             // For example, we may be trying to upcast `Foo` to `Bar<i32>`,
             // but `Foo` is declared as `trait Foo : Bar<u32>`.
-            let upcast_trait_refs =
-                util::supertraits(this.tcx(), poly_trait_ref)
-                .filter(|upcast_trait_ref|
+            let upcast_trait_refs = util::supertraits(this.tcx(), poly_trait_ref)
+                .filter(|upcast_trait_ref| {
                     this.probe(|this, _| {
                         let upcast_trait_ref = upcast_trait_ref.clone();
-                        this.match_poly_trait_ref(obligation, upcast_trait_ref).is_ok()
+                        this.match_poly_trait_ref(obligation, upcast_trait_ref)
+                            .is_ok()
                     })
-                )
+                })
                 .count();
 
             if upcast_trait_refs > 1 {
@@ -1999,9 +2131,11 @@ fn assemble_candidates_from_object_ty(&mut self,
     }
 
     /// Search for unsizing that might apply to `obligation`.
-    fn assemble_candidates_for_unsizing(&mut self,
-                                        obligation: &TraitObligation<'tcx>,
-                                        candidates: &mut SelectionCandidateSet<'tcx>) {
+    fn assemble_candidates_for_unsizing(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        candidates: &mut SelectionCandidateSet<'tcx>,
+    ) {
         // We currently never consider higher-ranked obligations e.g.
         // `for<'a> &'a T: Unsize<Trait+'a>` to be implemented. This is not
         // because they are a priori invalid, and we could potentially add support
@@ -2023,10 +2157,17 @@ fn assemble_candidates_for_unsizing(&mut self,
                 return;
             }
         };
-        let target = obligation.predicate.skip_binder().trait_ref.substs.type_at(1);
+        let target = obligation
+            .predicate
+            .skip_binder()
+            .trait_ref
+            .substs
+            .type_at(1);
 
-        debug!("assemble_candidates_for_unsizing(source={:?}, target={:?})",
-               source, target);
+        debug!(
+            "assemble_candidates_for_unsizing(source={:?}, target={:?})",
+            source, target
+        );
 
         let may_apply = match (&source.sty, &target.sty) {
             // Trait+Kx+'a -> Trait+Ky+'b (upcasts).
@@ -2043,11 +2184,13 @@ fn assemble_candidates_for_unsizing(&mut self,
                 // We always upcast when we can because of reason
                 // #2 (region bounds).
                 match (data_a.principal(), data_b.principal()) {
-                    (Some(a), Some(b)) => a.def_id() == b.def_id() &&
-                        data_b.auto_traits()
+                    (Some(a), Some(b)) => {
+                        a.def_id() == b.def_id()
+                            && data_b.auto_traits()
                             // All of a's auto traits need to be in b's auto traits.
-                            .all(|b| data_a.auto_traits().any(|a| a == b)),
-                    _ => false
+                            .all(|b| data_a.auto_traits().any(|a| a == b))
+                    }
+                    _ => false,
                 }
             }
 
@@ -2057,8 +2200,7 @@ fn assemble_candidates_for_unsizing(&mut self,
             // Ambiguous handling is below T -> Trait, because inference
             // variables can still implement Unsize<Trait> and nested
             // obligations will have the final say (likely deferred).
-            (&ty::Infer(ty::TyVar(_)), _) |
-            (_, &ty::Infer(ty::TyVar(_))) => {
+            (&ty::Infer(ty::TyVar(_)), _) | (_, &ty::Infer(ty::TyVar(_))) => {
                 debug!("assemble_candidates_for_unsizing: ambiguous");
                 candidates.ambiguous = true;
                 false
@@ -2073,11 +2215,9 @@ fn assemble_candidates_for_unsizing(&mut self,
             }
 
             // (.., T) -> (.., U).
-            (&ty::Tuple(tys_a), &ty::Tuple(tys_b)) => {
-                tys_a.len() == tys_b.len()
-            }
+            (&ty::Tuple(tys_a), &ty::Tuple(tys_b)) => tys_a.len() == tys_b.len(),
 
-            _ => false
+            _ => false,
         };
 
         if may_apply {
@@ -2090,9 +2230,8 @@ fn assemble_candidates_for_unsizing(&mut self,
     //
     // Winnowing is the process of attempting to resolve ambiguity by
     // probing further. During the winnowing process, we unify all
-    // type variables (ignoring skolemization) and then we also
-    // attempt to evaluate recursive bounds to see if they are
-    // satisfied.
+    // type variables and then we also attempt to evaluate recursive
+    // bounds to see if they are satisfied.
 
     /// Returns true if `victim` should be dropped in favor of
     /// `other`.  Generally speaking we will drop duplicate
@@ -2102,9 +2241,8 @@ fn assemble_candidates_for_unsizing(&mut self,
     fn candidate_should_be_dropped_in_favor_of<'o>(
         &mut self,
         victim: &EvaluatedCandidate<'tcx>,
-        other: &EvaluatedCandidate<'tcx>)
-        -> bool
-    {
+        other: &EvaluatedCandidate<'tcx>,
+    ) -> bool {
         if victim.candidate == other.candidate {
             return true;
         }
@@ -2112,9 +2250,8 @@ fn candidate_should_be_dropped_in_favor_of<'o>(
         // Check if a bound would previously have been removed when normalizing
         // the param_env so that it can be given the lowest priority. See
         // #50825 for the motivation for this.
-        let is_global = |cand: &ty::PolyTraitRef<'_>| {
-            cand.is_global() && !cand.has_late_bound_regions()
-        };
+        let is_global =
+            |cand: &ty::PolyTraitRef<'_>| cand.is_global() && !cand.has_late_bound_regions();
 
         match other.candidate {
             // Prefer BuiltinCandidate { has_nested: false } to anything else.
@@ -2123,58 +2260,57 @@ fn candidate_should_be_dropped_in_favor_of<'o>(
             BuiltinCandidate { has_nested: false } => true,
             ParamCandidate(ref cand) => match victim.candidate {
                 AutoImplCandidate(..) => {
-                    bug!("default implementations shouldn't be recorded \
-                          when there are other valid candidates");
+                    bug!(
+                        "default implementations shouldn't be recorded \
+                         when there are other valid candidates"
+                    );
                 }
                 // Prefer BuiltinCandidate { has_nested: false } to anything else.
                 // This is a fix for #53123 and prevents winnowing from accidentally extending the
                 // lifetime of a variable.
                 BuiltinCandidate { has_nested: false } => false,
-                ImplCandidate(..) |
-                ClosureCandidate |
-                GeneratorCandidate |
-                FnPointerCandidate |
-                BuiltinObjectCandidate |
-                BuiltinUnsizeCandidate |
-                BuiltinCandidate { .. } => {
+                ImplCandidate(..)
+                | ClosureCandidate
+                | GeneratorCandidate
+                | FnPointerCandidate
+                | BuiltinObjectCandidate
+                | BuiltinUnsizeCandidate
+                BuiltinCandidate { .. } => {
                     // Global bounds from the where clause should be ignored
                     // here (see issue #50825). Otherwise, we have a where
                     // clause so don't go around looking for impls.
                     !is_global(cand)
                 }
-                ObjectCandidate |
-                ProjectionCandidate => {
+                ObjectCandidate | ProjectionCandidate => {
                     // Arbitrarily give param candidates priority
                     // over projection and object candidates.
                     !is_global(cand)
-                },
+                }
                 ParamCandidate(..) => false,
             },
-            ObjectCandidate |
-            ProjectionCandidate => match victim.candidate {
+            ObjectCandidate | ProjectionCandidate => match victim.candidate {
                 AutoImplCandidate(..) => {
-                    bug!("default implementations shouldn't be recorded \
-                          when there are other valid candidates");
+                    bug!(
+                        "default implementations shouldn't be recorded \
+                         when there are other valid candidates"
+                    );
                 }
                 // Prefer BuiltinCandidate { has_nested: false } to anything else.
                 // This is a fix for #53123 and prevents winnowing from accidentally extending the
                 // lifetime of a variable.
                 BuiltinCandidate { has_nested: false } => false,
-                ImplCandidate(..) |
-                ClosureCandidate |
-                GeneratorCandidate |
-                FnPointerCandidate |
-                BuiltinObjectCandidate |
-                BuiltinUnsizeCandidate |
-                BuiltinCandidate { .. } => {
-                    true
-                }
-                ObjectCandidate |
-                ProjectionCandidate => {
+                ImplCandidate(..)
+                | ClosureCandidate
+                | GeneratorCandidate
+                | FnPointerCandidate
+                | BuiltinObjectCandidate
+                | BuiltinUnsizeCandidate
+                | BuiltinCandidate { .. } => true,
+                ObjectCandidate | ProjectionCandidate => {
                     // Arbitrarily give param candidates priority
                     // over projection and object candidates.
                     true
-                },
+                }
                 ParamCandidate(ref cand) => is_global(cand),
             },
             ImplCandidate(other_def) => {
@@ -2185,25 +2321,25 @@ fn candidate_should_be_dropped_in_favor_of<'o>(
                     match victim.candidate {
                         ImplCandidate(victim_def) => {
                             let tcx = self.tcx().global_tcx();
-                            return tcx.specializes((other_def, victim_def)) ||
-                                tcx.impls_are_allowed_to_overlap(other_def, victim_def);
+                            return tcx.specializes((other_def, victim_def))
+                                || tcx.impls_are_allowed_to_overlap(other_def, victim_def);
                         }
                         ParamCandidate(ref cand) => {
                             // Prefer the impl to a global where clause candidate.
                             return is_global(cand);
                         }
-                        _ => ()
+                        _ => (),
                     }
                 }
 
                 false
-            },
-            ClosureCandidate |
-            GeneratorCandidate |
-            FnPointerCandidate |
-            BuiltinObjectCandidate |
-            BuiltinUnsizeCandidate |
-            BuiltinCandidate { has_nested: true } => {
+            }
+            ClosureCandidate
+            | GeneratorCandidate
+            | FnPointerCandidate
+            | BuiltinObjectCandidate
+            | BuiltinUnsizeCandidate
+            BuiltinCandidate { has_nested: true } => {
                 match victim.candidate {
                     ParamCandidate(ref cand) => {
                         // Prefer these to a global where-clause bound
@@ -2213,7 +2349,7 @@ fn candidate_should_be_dropped_in_favor_of<'o>(
                     _ => false,
                 }
             }
-            _ => false
+            _ => false,
         }
     }
 
@@ -2223,16 +2359,16 @@ fn candidate_should_be_dropped_in_favor_of<'o>(
     // These cover the traits that are built-in to the language
     // itself: `Copy`, `Clone` and `Sized`.
 
-    fn assemble_builtin_bound_candidates<'o>(&mut self,
-                                             conditions: BuiltinImplConditions<'tcx>,
-                                             candidates: &mut SelectionCandidateSet<'tcx>)
-                                             -> Result<(), SelectionError<'tcx>>
-    {
+    fn assemble_builtin_bound_candidates<'o>(
+        &mut self,
+        conditions: BuiltinImplConditions<'tcx>,
+        candidates: &mut SelectionCandidateSet<'tcx>,
+    ) -> Result<(), SelectionError<'tcx>> {
         match conditions {
             BuiltinImplConditions::Where(nested) => {
                 debug!("builtin_bound: nested={:?}", nested);
                 candidates.vec.push(BuiltinCandidate {
-                    has_nested: nested.skip_binder().len() > 0
+                    has_nested: nested.skip_binder().len() > 0,
                 });
             }
             BuiltinImplConditions::None => {}
@@ -2245,82 +2381,105 @@ fn assemble_builtin_bound_candidates<'o>(&mut self,
         Ok(())
     }
 
-    fn sized_conditions(&mut self,
-                        obligation: &TraitObligation<'tcx>)
-                        -> BuiltinImplConditions<'tcx>
-    {
+    fn sized_conditions(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+    ) -> BuiltinImplConditions<'tcx> {
         use self::BuiltinImplConditions::{Ambiguous, None, Where};
 
         // NOTE: binder moved to (*)
-        let self_ty = self.infcx.shallow_resolve(
-            obligation.predicate.skip_binder().self_ty());
+        let self_ty = self.infcx
+            .shallow_resolve(obligation.predicate.skip_binder().self_ty());
 
         match self_ty.sty {
-            ty::Infer(ty::IntVar(_)) | ty::Infer(ty::FloatVar(_)) |
-            ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Float(_) |
-            ty::FnDef(..) | ty::FnPtr(_) | ty::RawPtr(..) |
-            ty::Char | ty::Ref(..) | ty::Generator(..) |
-            ty::GeneratorWitness(..) | ty::Array(..) | ty::Closure(..) |
-            ty::Never | ty::Error => {
+            ty::Infer(ty::IntVar(_))
+            | ty::Infer(ty::FloatVar(_))
+            | ty::Uint(_)
+            | ty::Int(_)
+            | ty::Bool
+            | ty::Float(_)
+            | ty::FnDef(..)
+            | ty::FnPtr(_)
+            | ty::RawPtr(..)
+            | ty::Char
+            | ty::Ref(..)
+            | ty::Generator(..)
+            | ty::GeneratorWitness(..)
+            | ty::Array(..)
+            | ty::Closure(..)
+            | ty::Never
+            | ty::Error => {
                 // safe for everything
                 Where(ty::Binder::dummy(Vec::new()))
             }
 
             ty::Str | ty::Slice(_) | ty::Dynamic(..) | ty::Foreign(..) => None,
 
-            ty::Tuple(tys) => {
-                Where(ty::Binder::bind(tys.last().into_iter().cloned().collect()))
-            }
+            ty::Tuple(tys) => Where(ty::Binder::bind(tys.last().into_iter().cloned().collect())),
 
             ty::Adt(def, substs) => {
                 let sized_crit = def.sized_constraint(self.tcx());
                 // (*) binder moved here
                 Where(ty::Binder::bind(
-                    sized_crit.iter().map(|ty| ty.subst(self.tcx(), substs)).collect()
+                    sized_crit
+                        .iter()
+                        .map(|ty| ty.subst(self.tcx(), substs))
+                        .collect(),
                 ))
             }
 
             ty::Projection(_) | ty::Param(_) | ty::Opaque(..) => None,
             ty::Infer(ty::TyVar(_)) => Ambiguous,
 
-            ty::Infer(ty::CanonicalTy(_)) |
-            ty::Infer(ty::FreshTy(_)) |
-            ty::Infer(ty::FreshIntTy(_)) |
-            ty::Infer(ty::FreshFloatTy(_)) => {
-                bug!("asked to assemble builtin bounds of unexpected type: {:?}",
-                     self_ty);
+            ty::UnnormalizedProjection(..)
+            | ty::Infer(ty::CanonicalTy(_))
+            | ty::Infer(ty::FreshTy(_))
+            | ty::Infer(ty::FreshIntTy(_))
+            | ty::Infer(ty::FreshFloatTy(_)) => {
+                bug!(
+                    "asked to assemble builtin bounds of unexpected type: {:?}",
+                    self_ty
+                );
             }
         }
     }
 
-    fn copy_clone_conditions(&mut self,
-                             obligation: &TraitObligation<'tcx>)
-                             -> BuiltinImplConditions<'tcx>
-    {
+    fn copy_clone_conditions(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+    ) -> BuiltinImplConditions<'tcx> {
         // NOTE: binder moved to (*)
-        let self_ty = self.infcx.shallow_resolve(
-            obligation.predicate.skip_binder().self_ty());
+        let self_ty = self.infcx
+            .shallow_resolve(obligation.predicate.skip_binder().self_ty());
 
         use self::BuiltinImplConditions::{Ambiguous, None, Where};
 
         match self_ty.sty {
-            ty::Infer(ty::IntVar(_)) | ty::Infer(ty::FloatVar(_)) |
-            ty::FnDef(..) | ty::FnPtr(_) | ty::Error => {
-                Where(ty::Binder::dummy(Vec::new()))
-            }
-
-            ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Float(_) |
-            ty::Char | ty::RawPtr(..) | ty::Never |
-            ty::Ref(_, _, hir::MutImmutable) => {
+            ty::Infer(ty::IntVar(_))
+            | ty::Infer(ty::FloatVar(_))
+            | ty::FnDef(..)
+            | ty::FnPtr(_)
+            | ty::Error => Where(ty::Binder::dummy(Vec::new())),
+
+            ty::Uint(_)
+            | ty::Int(_)
+            | ty::Bool
+            | ty::Float(_)
+            | ty::Char
+            | ty::RawPtr(..)
+            | ty::Never
+            | ty::Ref(_, _, hir::MutImmutable) => {
                 // Implementations provided in libcore
                 None
             }
 
-            ty::Dynamic(..) | ty::Str | ty::Slice(..) |
-            ty::Generator(..) | ty::GeneratorWitness(..) | ty::Foreign(..) |
-            ty::Ref(_, _, hir::MutMutable) => {
-                None
-            }
+            ty::Dynamic(..)
+            | ty::Str
+            | ty::Slice(..)
+            | ty::Generator(..)
+            | ty::GeneratorWitness(..)
+            | ty::Foreign(..)
+            | ty::Ref(_, _, hir::MutMutable) => None,
 
             ty::Array(element_ty, _) => {
                 // (*) binder moved here
@@ -2337,7 +2496,9 @@ fn copy_clone_conditions(&mut self,
                 let is_copy_trait = Some(trait_id) == self.tcx().lang_items().copy_trait();
                 let is_clone_trait = Some(trait_id) == self.tcx().lang_items().clone_trait();
                 if is_copy_trait || is_clone_trait {
-                    Where(ty::Binder::bind(substs.upvar_tys(def_id, self.tcx()).collect()))
+                    Where(ty::Binder::bind(
+                        substs.upvar_tys(def_id, self.tcx()).collect(),
+                    ))
                 } else {
                     None
                 }
@@ -2355,12 +2516,15 @@ fn copy_clone_conditions(&mut self,
                 Ambiguous
             }
 
-            ty::Infer(ty::CanonicalTy(_)) |
-            ty::Infer(ty::FreshTy(_)) |
-            ty::Infer(ty::FreshIntTy(_)) |
-            ty::Infer(ty::FreshFloatTy(_)) => {
-                bug!("asked to assemble builtin bounds of unexpected type: {:?}",
-                     self_ty);
+            ty::UnnormalizedProjection(..)
+            | ty::Infer(ty::CanonicalTy(_))
+            | ty::Infer(ty::FreshTy(_))
+            | ty::Infer(ty::FreshIntTy(_))
+            | ty::Infer(ty::FreshFloatTy(_)) => {
+                bug!(
+                    "asked to assemble builtin bounds of unexpected type: {:?}",
+                    self_ty
+                );
             }
         }
     }
@@ -2378,55 +2542,54 @@ fn copy_clone_conditions(&mut self,
     /// ```
     fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Vec<Ty<'tcx>> {
         match t.sty {
-            ty::Uint(_) |
-            ty::Int(_) |
-            ty::Bool |
-            ty::Float(_) |
-            ty::FnDef(..) |
-            ty::FnPtr(_) |
-            ty::Str |
-            ty::Error |
-            ty::Infer(ty::IntVar(_)) |
-            ty::Infer(ty::FloatVar(_)) |
-            ty::Never |
-            ty::Char => {
-                Vec::new()
-            }
-
-            ty::Dynamic(..) |
-            ty::Param(..) |
-            ty::Foreign(..) |
-            ty::Projection(..) |
-            ty::Infer(ty::CanonicalTy(_)) |
-            ty::Infer(ty::TyVar(_)) |
-            ty::Infer(ty::FreshTy(_)) |
-            ty::Infer(ty::FreshIntTy(_)) |
-            ty::Infer(ty::FreshFloatTy(_)) => {
-                bug!("asked to assemble constituent types of unexpected type: {:?}",
-                     t);
-            }
-
-            ty::RawPtr(ty::TypeAndMut { ty: element_ty, ..}) |
-            ty::Ref(_, element_ty, _) => {
-                vec![element_ty]
-            },
+            ty::Uint(_)
+            | ty::Int(_)
+            | ty::Bool
+            | ty::Float(_)
+            | ty::FnDef(..)
+            | ty::FnPtr(_)
+            | ty::Str
+            | ty::Error
+            | ty::Infer(ty::IntVar(_))
+            | ty::Infer(ty::FloatVar(_))
+            | ty::Never
+            | ty::Char => Vec::new(),
+
+            ty::UnnormalizedProjection(..)
+            | ty::Dynamic(..)
+            | ty::Param(..)
+            | ty::Foreign(..)
+            | ty::Projection(..)
+            | ty::Infer(ty::CanonicalTy(_))
+            | ty::Infer(ty::TyVar(_))
+            | ty::Infer(ty::FreshTy(_))
+            | ty::Infer(ty::FreshIntTy(_))
+            | ty::Infer(ty::FreshFloatTy(_)) => {
+                bug!(
+                    "asked to assemble constituent types of unexpected type: {:?}",
+                    t
+                );
+            }
 
-            ty::Array(element_ty, _) | ty::Slice(element_ty) => {
+            ty::RawPtr(ty::TypeAndMut { ty: element_ty, .. }) | ty::Ref(_, element_ty, _) => {
                 vec![element_ty]
             }
 
+            ty::Array(element_ty, _) | ty::Slice(element_ty) => vec![element_ty],
+
             ty::Tuple(ref tys) => {
                 // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
                 tys.to_vec()
             }
 
-            ty::Closure(def_id, ref substs) => {
-                substs.upvar_tys(def_id, self.tcx()).collect()
-            }
+            ty::Closure(def_id, ref substs) => substs.upvar_tys(def_id, self.tcx()).collect(),
 
             ty::Generator(def_id, ref substs, _) => {
                 let witness = substs.witness(def_id, self.tcx());
-                substs.upvar_tys(def_id, self.tcx()).chain(iter::once(witness)).collect()
+                substs
+                    .upvar_tys(def_id, self.tcx())
+                    .chain(iter::once(witness))
+                    .collect()
             }
 
             ty::GeneratorWitness(types) => {
@@ -2437,15 +2600,9 @@ fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Vec<Ty<'tcx>> {
             }
 
             // for `PhantomData<T>`, we pass `T`
-            ty::Adt(def, substs) if def.is_phantom_data() => {
-                substs.types().collect()
-            }
+            ty::Adt(def, substs) if def.is_phantom_data() => substs.types().collect(),
 
-            ty::Adt(def, substs) => {
-                def.all_fields()
-                    .map(|f| f.ty(self.tcx(), substs))
-                    .collect()
-            }
+            ty::Adt(def, substs) => def.all_fields().map(|f| f.ty(self.tcx(), substs)).collect(),
 
             ty::Opaque(def_id, substs) => {
                 // We can resolve the `impl Trait` to its concrete type,
@@ -2456,14 +2613,14 @@ fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Vec<Ty<'tcx>> {
         }
     }
 
-    fn collect_predicates_for_types(&mut self,
-                                    param_env: ty::ParamEnv<'tcx>,
-                                    cause: ObligationCause<'tcx>,
-                                    recursion_depth: usize,
-                                    trait_def_id: DefId,
-                                    types: ty::Binder<Vec<Ty<'tcx>>>)
-                                    -> Vec<PredicateObligation<'tcx>>
-    {
+    fn collect_predicates_for_types(
+        &mut self,
+        param_env: ty::ParamEnv<'tcx>,
+        cause: ObligationCause<'tcx>,
+        recursion_depth: usize,
+        trait_def_id: DefId,
+        types: ty::Binder<Vec<Ty<'tcx>>>,
+    ) -> Vec<PredicateObligation<'tcx>> {
         // Because the types were potentially derived from
         // higher-ranked obligations they may reference late-bound
         // regions. For example, `for<'a> Foo<&'a int> : Copy` would
@@ -2473,34 +2630,45 @@ fn collect_predicates_for_types(&mut self,
         //
         // The strategy is to:
         //
-        // 1. Instantiate those regions to skolemized regions (e.g.,
+        // 1. Instantiate those regions to placeholder regions (e.g.,
         //    `for<'a> &'a int` becomes `&0 int`.
         // 2. Produce something like `&'0 int : Copy`
         // 3. Re-bind the regions back to `for<'a> &'a int : Copy`
 
-        types.skip_binder().into_iter().flat_map(|ty| { // binder moved -\
-            let ty: ty::Binder<Ty<'tcx>> = ty::Binder::bind(ty); // <----/
-
-            self.in_snapshot(|this, snapshot| {
-                let (skol_ty, skol_map) =
-                    this.infcx().skolemize_late_bound_regions(&ty);
-                let Normalized { value: normalized_ty, mut obligations } =
-                    project::normalize_with_depth(this,
-                                                  param_env,
-                                                  cause.clone(),
-                                                  recursion_depth,
-                                                  &skol_ty);
-                let skol_obligation =
-                    this.tcx().predicate_for_trait_def(param_env,
-                                                       cause.clone(),
-                                                       trait_def_id,
-                                                       recursion_depth,
-                                                       normalized_ty,
-                                                       &[]);
-                obligations.push(skol_obligation);
-                this.infcx().plug_leaks(skol_map, snapshot, obligations)
+        types
+            .skip_binder()
+            .into_iter()
+            .flat_map(|ty| {
+                // binder moved -\
+                let ty: ty::Binder<Ty<'tcx>> = ty::Binder::bind(ty); // <----/
+
+                self.in_snapshot(|this, snapshot| {
+                    let (skol_ty, placeholder_map) = this.infcx()
+                        .replace_late_bound_regions_with_placeholders(&ty);
+                    let Normalized {
+                        value: normalized_ty,
+                        mut obligations,
+                    } = project::normalize_with_depth(
+                        this,
+                        param_env,
+                        cause.clone(),
+                        recursion_depth,
+                        &skol_ty,
+                    );
+                    let skol_obligation = this.tcx().predicate_for_trait_def(
+                        param_env,
+                        cause.clone(),
+                        trait_def_id,
+                        recursion_depth,
+                        normalized_ty,
+                        &[],
+                    );
+                    obligations.push(skol_obligation);
+                    this.infcx()
+                        .plug_leaks(placeholder_map, snapshot, obligations)
+                })
             })
-        }).collect()
+            .collect()
     }
 
     ///////////////////////////////////////////////////////////////////////////
@@ -2513,14 +2681,12 @@ fn collect_predicates_for_types(&mut self,
     // [rustc guide]:
     // https://rust-lang-nursery.github.io/rustc-guide/traits/resolution.html#confirmation
 
-    fn confirm_candidate(&mut self,
-                         obligation: &TraitObligation<'tcx>,
-                         candidate: SelectionCandidate<'tcx>)
-                         -> Result<Selection<'tcx>, SelectionError<'tcx>>
-    {
-        debug!("confirm_candidate({:?}, {:?})",
-               obligation,
-               candidate);
+    fn confirm_candidate(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        candidate: SelectionCandidate<'tcx>,
+    ) -> Result<Selection<'tcx>, SelectionError<'tcx>> {
+        debug!("confirm_candidate({:?}, {:?})", obligation, candidate);
 
         match candidate {
             BuiltinCandidate { has_nested } => {
@@ -2538,9 +2704,10 @@ fn confirm_candidate(&mut self,
                 Ok(VtableAutoImpl(data))
             }
 
-            ImplCandidate(impl_def_id) => {
-                Ok(VtableImpl(self.confirm_impl_candidate(obligation, impl_def_id)))
-            }
+            ImplCandidate(impl_def_id) => Ok(VtableImpl(self.confirm_impl_candidate(
+                obligation,
+                impl_def_id,
+            ))),
 
             ClosureCandidate => {
                 let vtable_closure = self.confirm_closure_candidate(obligation)?;
@@ -2567,8 +2734,7 @@ fn confirm_candidate(&mut self,
             }
 
             FnPointerCandidate => {
-                let data =
-                    self.confirm_fn_pointer_candidate(obligation)?;
+                let data = self.confirm_fn_pointer_candidate(obligation)?;
                 Ok(VtableFnPointer(data))
             }
 
@@ -2584,25 +2750,20 @@ fn confirm_candidate(&mut self,
         }
     }
 
-    fn confirm_projection_candidate(&mut self,
-                                    obligation: &TraitObligation<'tcx>)
-    {
+    fn confirm_projection_candidate(&mut self, obligation: &TraitObligation<'tcx>) {
         self.in_snapshot(|this, snapshot| {
             let result =
-                this.match_projection_obligation_against_definition_bounds(obligation,
-                                                                           snapshot);
+                this.match_projection_obligation_against_definition_bounds(obligation, snapshot);
             assert!(result);
         })
     }
 
-    fn confirm_param_candidate(&mut self,
-                               obligation: &TraitObligation<'tcx>,
-                               param: ty::PolyTraitRef<'tcx>)
-                               -> Vec<PredicateObligation<'tcx>>
-    {
-        debug!("confirm_param_candidate({:?},{:?})",
-               obligation,
-               param);
+    fn confirm_param_candidate(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        param: ty::PolyTraitRef<'tcx>,
+    ) -> Vec<PredicateObligation<'tcx>> {
+        debug!("confirm_param_candidate({:?},{:?})", obligation, param);
 
         // During evaluation, we already checked that this
         // where-clause trait-ref could be unified with the obligation
@@ -2611,54 +2772,62 @@ fn confirm_param_candidate(&mut self,
         match self.match_where_clause_trait_ref(obligation, param.clone()) {
             Ok(obligations) => obligations,
             Err(()) => {
-                bug!("Where clause `{:?}` was applicable to `{:?}` but now is not",
-                     param,
-                     obligation);
+                bug!(
+                    "Where clause `{:?}` was applicable to `{:?}` but now is not",
+                    param,
+                    obligation
+                );
             }
         }
     }
 
-    fn confirm_builtin_candidate(&mut self,
-                                 obligation: &TraitObligation<'tcx>,
-                                 has_nested: bool)
-                                 -> VtableBuiltinData<PredicateObligation<'tcx>>
-    {
-        debug!("confirm_builtin_candidate({:?}, {:?})",
-               obligation, has_nested);
+    fn confirm_builtin_candidate(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        has_nested: bool,
+    ) -> VtableBuiltinData<PredicateObligation<'tcx>> {
+        debug!(
+            "confirm_builtin_candidate({:?}, {:?})",
+            obligation, has_nested
+        );
 
         let lang_items = self.tcx().lang_items();
         let obligations = if has_nested {
             let trait_def = obligation.predicate.def_id();
-            let conditions =
-                if Some(trait_def) == lang_items.sized_trait() {
-                    self.sized_conditions(obligation)
-                } else if Some(trait_def) == lang_items.copy_trait() {
-                    self.copy_clone_conditions(obligation)
-                } else if Some(trait_def) == lang_items.clone_trait() {
-                    self.copy_clone_conditions(obligation)
-                } else {
-                    bug!("unexpected builtin trait {:?}", trait_def)
+            let conditions = if Some(trait_def) == lang_items.sized_trait() {
+                self.sized_conditions(obligation)
+            } else if Some(trait_def) == lang_items.copy_trait() {
+                self.copy_clone_conditions(obligation)
+            } else if Some(trait_def) == lang_items.clone_trait() {
+                self.copy_clone_conditions(obligation)
+            } else {
+                bug!("unexpected builtin trait {:?}", trait_def)
             };
             let nested = match conditions {
                 BuiltinImplConditions::Where(nested) => nested,
-                _ => bug!("obligation {:?} had matched a builtin impl but now doesn't",
-                          obligation)
+                _ => bug!(
+                    "obligation {:?} had matched a builtin impl but now doesn't",
+                    obligation
+                ),
             };
 
             let cause = obligation.derived_cause(BuiltinDerivedObligation);
-            self.collect_predicates_for_types(obligation.param_env,
-                                              cause,
-                                              obligation.recursion_depth+1,
-                                              trait_def,
-                                              nested)
+            self.collect_predicates_for_types(
+                obligation.param_env,
+                cause,
+                obligation.recursion_depth + 1,
+                trait_def,
+                nested,
+            )
         } else {
             vec![]
         };
 
-        debug!("confirm_builtin_candidate: obligations={:?}",
-               obligations);
+        debug!("confirm_builtin_candidate: obligations={:?}", obligations);
 
-        VtableBuiltinData { nested: obligations }
+        VtableBuiltinData {
+            nested: obligations,
+        }
     }
 
     /// This handles the case where a `auto trait Foo` impl is being used.
@@ -2666,14 +2835,15 @@ fn confirm_builtin_candidate(&mut self,
     ///
     /// 1. For each constituent type `Y` in `X`, `Y : Foo` holds
     /// 2. For each where-clause `C` declared on `Foo`, `[Self => X] C` holds.
-    fn confirm_auto_impl_candidate(&mut self,
-                                   obligation: &TraitObligation<'tcx>,
-                                   trait_def_id: DefId)
-                                   -> VtableAutoImplData<PredicateObligation<'tcx>>
-    {
-        debug!("confirm_auto_impl_candidate({:?}, {:?})",
-               obligation,
-               trait_def_id);
+    fn confirm_auto_impl_candidate(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        trait_def_id: DefId,
+    ) -> VtableAutoImplData<PredicateObligation<'tcx>> {
+        debug!(
+            "confirm_auto_impl_candidate({:?}, {:?})",
+            obligation, trait_def_id
+        );
 
         let types = obligation.predicate.map_bound(|inner| {
             let self_ty = self.infcx.shallow_resolve(inner.self_ty());
@@ -2683,12 +2853,12 @@ fn confirm_auto_impl_candidate(&mut self,
     }
 
     /// See `confirm_auto_impl_candidate`
-    fn vtable_auto_impl(&mut self,
-                        obligation: &TraitObligation<'tcx>,
-                        trait_def_id: DefId,
-                        nested: ty::Binder<Vec<Ty<'tcx>>>)
-                        -> VtableAutoImplData<PredicateObligation<'tcx>>
-    {
+    fn vtable_auto_impl(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        trait_def_id: DefId,
+        nested: ty::Binder<Vec<Ty<'tcx>>>,
+    ) -> VtableAutoImplData<PredicateObligation<'tcx>> {
         debug!("vtable_auto_impl: nested={:?}", nested);
 
         let cause = obligation.derived_cause(BuiltinDerivedObligation);
@@ -2697,20 +2867,23 @@ fn vtable_auto_impl(&mut self,
             cause,
             obligation.recursion_depth + 1,
             trait_def_id,
-            nested);
+            nested,
+        );
 
         let trait_obligations: Vec<PredicateObligation<'_>> = self.in_snapshot(|this, snapshot| {
             let poly_trait_ref = obligation.predicate.to_poly_trait_ref();
-            let (trait_ref, skol_map) =
-                this.infcx().skolemize_late_bound_regions(&poly_trait_ref);
+            let (trait_ref, placeholder_map) = this.infcx()
+                .replace_late_bound_regions_with_placeholders(&poly_trait_ref);
             let cause = obligation.derived_cause(ImplDerivedObligation);
-            this.impl_or_trait_obligations(cause,
-                                           obligation.recursion_depth + 1,
-                                           obligation.param_env,
-                                           trait_def_id,
-                                           &trait_ref.substs,
-                                           skol_map,
-                                           snapshot)
+            this.impl_or_trait_obligations(
+                cause,
+                obligation.recursion_depth + 1,
+                obligation.param_env,
+                trait_def_id,
+                &trait_ref.substs,
+                placeholder_map,
+                snapshot,
+            )
         });
 
         // Adds the predicates from the trait.  Note that this contains a `Self: Trait`
@@ -2721,65 +2894,64 @@ fn vtable_auto_impl(&mut self,
 
         VtableAutoImplData {
             trait_def_id,
-            nested: obligations
+            nested: obligations,
         }
     }
 
-    fn confirm_impl_candidate(&mut self,
-                              obligation: &TraitObligation<'tcx>,
-                              impl_def_id: DefId)
-                              -> VtableImplData<'tcx, PredicateObligation<'tcx>>
-    {
-        debug!("confirm_impl_candidate({:?},{:?})",
-               obligation,
-               impl_def_id);
+    fn confirm_impl_candidate(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        impl_def_id: DefId,
+    ) -> VtableImplData<'tcx, PredicateObligation<'tcx>> {
+        debug!("confirm_impl_candidate({:?},{:?})", obligation, impl_def_id);
 
         // First, create the substitutions by matching the impl again,
         // this time not in a probe.
         self.in_snapshot(|this, snapshot| {
-            let (substs, skol_map) =
-                this.rematch_impl(impl_def_id, obligation,
-                                  snapshot);
+            let (substs, placeholder_map) = this.rematch_impl(impl_def_id, obligation, snapshot);
             debug!("confirm_impl_candidate substs={:?}", substs);
             let cause = obligation.derived_cause(ImplDerivedObligation);
-            this.vtable_impl(impl_def_id,
-                             substs,
-                             cause,
-                             obligation.recursion_depth + 1,
-                             obligation.param_env,
-                             skol_map,
-                             snapshot)
+            this.vtable_impl(
+                impl_def_id,
+                substs,
+                cause,
+                obligation.recursion_depth + 1,
+                obligation.param_env,
+                placeholder_map,
+                snapshot,
+            )
         })
     }
 
-    fn vtable_impl(&mut self,
-                   impl_def_id: DefId,
-                   mut substs: Normalized<'tcx, &'tcx Substs<'tcx>>,
-                   cause: ObligationCause<'tcx>,
-                   recursion_depth: usize,
-                   param_env: ty::ParamEnv<'tcx>,
-                   skol_map: infer::SkolemizationMap<'tcx>,
-                   snapshot: &infer::CombinedSnapshot<'cx, 'tcx>)
-                   -> VtableImplData<'tcx, PredicateObligation<'tcx>>
-    {
-        debug!("vtable_impl(impl_def_id={:?}, substs={:?}, recursion_depth={}, skol_map={:?})",
-               impl_def_id,
-               substs,
-               recursion_depth,
-               skol_map);
-
-        let mut impl_obligations =
-            self.impl_or_trait_obligations(cause,
-                                           recursion_depth,
-                                           param_env,
-                                           impl_def_id,
-                                           &substs.value,
-                                           skol_map,
-                                           snapshot);
-
-        debug!("vtable_impl: impl_def_id={:?} impl_obligations={:?}",
-               impl_def_id,
-               impl_obligations);
+    fn vtable_impl(
+        &mut self,
+        impl_def_id: DefId,
+        mut substs: Normalized<'tcx, &'tcx Substs<'tcx>>,
+        cause: ObligationCause<'tcx>,
+        recursion_depth: usize,
+        param_env: ty::ParamEnv<'tcx>,
+        placeholder_map: infer::PlaceholderMap<'tcx>,
+        snapshot: &infer::CombinedSnapshot<'cx, 'tcx>,
+    ) -> VtableImplData<'tcx, PredicateObligation<'tcx>> {
+        debug!(
+            "vtable_impl(impl_def_id={:?}, substs={:?}, recursion_depth={}, placeholder_map={:?})",
+            impl_def_id, substs, recursion_depth, placeholder_map
+        );
+
+        let mut impl_obligations = self.impl_or_trait_obligations(
+            cause,
+            recursion_depth,
+            param_env,
+            impl_def_id,
+            &substs.value,
+            placeholder_map,
+            snapshot,
+        );
+
+        debug!(
+            "vtable_impl: impl_def_id={:?} impl_obligations={:?}",
+            impl_def_id, impl_obligations
+        );
 
         // Because of RFC447, the impl-trait-ref and obligations
         // are sufficient to determine the impl substs, without
@@ -2788,29 +2960,30 @@ fn vtable_impl(&mut self,
         // e.g. `impl<U: Tr, V: Iterator<Item=U>> Foo<<U as Tr>::T> for V`
         impl_obligations.append(&mut substs.obligations);
 
-        VtableImplData { impl_def_id,
-                         substs: substs.value,
-                         nested: impl_obligations }
+        VtableImplData {
+            impl_def_id,
+            substs: substs.value,
+            nested: impl_obligations,
+        }
     }
 
-    fn confirm_object_candidate(&mut self,
-                                obligation: &TraitObligation<'tcx>)
-                                -> VtableObjectData<'tcx, PredicateObligation<'tcx>>
-    {
-        debug!("confirm_object_candidate({:?})",
-               obligation);
+    fn confirm_object_candidate(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+    ) -> VtableObjectData<'tcx, PredicateObligation<'tcx>> {
+        debug!("confirm_object_candidate({:?})", obligation);
 
         // FIXME skipping binder here seems wrong -- we should
         // probably flatten the binder from the obligation and the
         // binder from the object. Have to try to make a broken test
         // case that results. -nmatsakis
-        let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
+        let self_ty = self.infcx
+            .shallow_resolve(*obligation.self_ty().skip_binder());
         let poly_trait_ref = match self_ty.sty {
             ty::Dynamic(ref data, ..) => {
                 data.principal().unwrap().with_self_ty(self.tcx(), self_ty)
             }
-            _ => span_bug!(obligation.cause.span,
-                           "object candidate with non-object")
+            _ => span_bug!(obligation.cause.span, "object candidate with non-object"),
         };
 
         let mut upcast_trait_ref = None;
@@ -2826,20 +2999,16 @@ fn confirm_object_candidate(&mut self,
             // where we can unify because otherwise select would have
             // reported an ambiguity. (When we do find a match, also
             // record it for later.)
-            let nonmatching =
-                util::supertraits(tcx, poly_trait_ref)
-                .take_while(|&t|
-                    match self.commit_if_ok(|this, _|
-                        this.match_poly_trait_ref(obligation, t))
-                    {
-                        Ok(obligations) => {
-                            upcast_trait_ref = Some(t);
-                            nested.extend(obligations);
-                            false
-                        }
-                        Err(_) => { true }
+            let nonmatching = util::supertraits(tcx, poly_trait_ref).take_while(
+                |&t| match self.commit_if_ok(|this, _| this.match_poly_trait_ref(obligation, t)) {
+                    Ok(obligations) => {
+                        upcast_trait_ref = Some(t);
+                        nested.extend(obligations);
+                        false
                     }
-                );
+                    Err(_) => true,
+                },
+            );
 
             // Additionally, for each of the nonmatching predicates that
             // we pass over, we sum up the set of number of vtable
@@ -2855,138 +3024,154 @@ fn confirm_object_candidate(&mut self,
         }
     }
 
-    fn confirm_fn_pointer_candidate(&mut self, obligation: &TraitObligation<'tcx>)
-        -> Result<VtableFnPointerData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>>
-    {
-        debug!("confirm_fn_pointer_candidate({:?})",
-               obligation);
+    fn confirm_fn_pointer_candidate(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+    ) -> Result<VtableFnPointerData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> {
+        debug!("confirm_fn_pointer_candidate({:?})", obligation);
 
         // ok to skip binder; it is reintroduced below
-        let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
+        let self_ty = self.infcx
+            .shallow_resolve(*obligation.self_ty().skip_binder());
         let sig = self_ty.fn_sig(self.tcx());
-        let trait_ref =
-            self.tcx().closure_trait_ref_and_return_type(obligation.predicate.def_id(),
-                                                         self_ty,
-                                                         sig,
-                                                         util::TupleArgumentsFlag::Yes)
+        let trait_ref = self.tcx()
+            .closure_trait_ref_and_return_type(
+                obligation.predicate.def_id(),
+                self_ty,
+                sig,
+                util::TupleArgumentsFlag::Yes,
+            )
             .map_bound(|(trait_ref, _)| trait_ref);
 
-        let Normalized { value: trait_ref, obligations } =
-            project::normalize_with_depth(self,
-                                          obligation.param_env,
-                                          obligation.cause.clone(),
-                                          obligation.recursion_depth + 1,
-                                          &trait_ref);
+        let Normalized {
+            value: trait_ref,
+            obligations,
+        } = project::normalize_with_depth(
+            self,
+            obligation.param_env,
+            obligation.cause.clone(),
+            obligation.recursion_depth + 1,
+            &trait_ref,
+        );
 
-        self.confirm_poly_trait_refs(obligation.cause.clone(),
-                                     obligation.param_env,
-                                     obligation.predicate.to_poly_trait_ref(),
-                                     trait_ref)?;
-        Ok(VtableFnPointerData { fn_ty: self_ty, nested: obligations })
+        self.confirm_poly_trait_refs(
+            obligation.cause.clone(),
+            obligation.param_env,
+            obligation.predicate.to_poly_trait_ref(),
+            trait_ref,
+        )?;
+        Ok(VtableFnPointerData {
+            fn_ty: self_ty,
+            nested: obligations,
+        })
     }
 
-    fn confirm_generator_candidate(&mut self,
-                                   obligation: &TraitObligation<'tcx>)
-                                   -> Result<VtableGeneratorData<'tcx, PredicateObligation<'tcx>>,
-                                             SelectionError<'tcx>>
-    {
+    fn confirm_generator_candidate(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+    ) -> Result<VtableGeneratorData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> {
         // ok to skip binder because the substs on generator types never
         // touch bound regions, they just capture the in-scope
         // type/region parameters
-        let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
+        let self_ty = self.infcx
+            .shallow_resolve(obligation.self_ty().skip_binder());
         let (generator_def_id, substs) = match self_ty.sty {
             ty::Generator(id, substs, _) => (id, substs),
-            _ => bug!("closure candidate for non-closure {:?}", obligation)
+            _ => bug!("closure candidate for non-closure {:?}", obligation),
         };
 
-        debug!("confirm_generator_candidate({:?},{:?},{:?})",
-               obligation,
-               generator_def_id,
-               substs);
+        debug!(
+            "confirm_generator_candidate({:?},{:?},{:?})",
+            obligation, generator_def_id, substs
+        );
 
-        let trait_ref =
-            self.generator_trait_ref_unnormalized(obligation, generator_def_id, substs);
+        let trait_ref = self.generator_trait_ref_unnormalized(obligation, generator_def_id, substs);
         let Normalized {
             value: trait_ref,
-            mut obligations
-        } = normalize_with_depth(self,
-                                 obligation.param_env,
-                                 obligation.cause.clone(),
-                                 obligation.recursion_depth+1,
-                                 &trait_ref);
-
-        debug!("confirm_generator_candidate(generator_def_id={:?}, \
-                trait_ref={:?}, obligations={:?})",
-               generator_def_id,
-               trait_ref,
-               obligations);
-
-        obligations.extend(
-            self.confirm_poly_trait_refs(obligation.cause.clone(),
-                                        obligation.param_env,
-                                        obligation.predicate.to_poly_trait_ref(),
-                                        trait_ref)?);
+            mut obligations,
+        } = normalize_with_depth(
+            self,
+            obligation.param_env,
+            obligation.cause.clone(),
+            obligation.recursion_depth + 1,
+            &trait_ref,
+        );
+
+        debug!(
+            "confirm_generator_candidate(generator_def_id={:?}, \
+             trait_ref={:?}, obligations={:?})",
+            generator_def_id, trait_ref, obligations
+        );
+
+        obligations.extend(self.confirm_poly_trait_refs(
+            obligation.cause.clone(),
+            obligation.param_env,
+            obligation.predicate.to_poly_trait_ref(),
+            trait_ref,
+        )?);
 
         Ok(VtableGeneratorData {
             generator_def_id: generator_def_id,
             substs: substs.clone(),
-            nested: obligations
+            nested: obligations,
         })
     }
 
-    fn confirm_closure_candidate(&mut self,
-                                 obligation: &TraitObligation<'tcx>)
-                                 -> Result<VtableClosureData<'tcx, PredicateObligation<'tcx>>,
-                                           SelectionError<'tcx>>
-    {
+    fn confirm_closure_candidate(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+    ) -> Result<VtableClosureData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>> {
         debug!("confirm_closure_candidate({:?})", obligation);
 
         let kind = self.tcx()
-                       .lang_items()
-                       .fn_trait_kind(obligation.predicate.def_id())
-                       .unwrap_or_else(|| bug!("closure candidate for non-fn trait {:?}",
-                                               obligation));
+            .lang_items()
+            .fn_trait_kind(obligation.predicate.def_id())
+            .unwrap_or_else(|| bug!("closure candidate for non-fn trait {:?}", obligation));
 
         // ok to skip binder because the substs on closure types never
         // touch bound regions, they just capture the in-scope
         // type/region parameters
-        let self_ty = self.infcx.shallow_resolve(obligation.self_ty().skip_binder());
+        let self_ty = self.infcx
+            .shallow_resolve(obligation.self_ty().skip_binder());
         let (closure_def_id, substs) = match self_ty.sty {
             ty::Closure(id, substs) => (id, substs),
-            _ => bug!("closure candidate for non-closure {:?}", obligation)
+            _ => bug!("closure candidate for non-closure {:?}", obligation),
         };
 
-        let trait_ref =
-            self.closure_trait_ref_unnormalized(obligation, closure_def_id, substs);
+        let trait_ref = self.closure_trait_ref_unnormalized(obligation, closure_def_id, substs);
         let Normalized {
             value: trait_ref,
-            mut obligations
-        } = normalize_with_depth(self,
-                                 obligation.param_env,
-                                 obligation.cause.clone(),
-                                 obligation.recursion_depth+1,
-                                 &trait_ref);
-
-        debug!("confirm_closure_candidate(closure_def_id={:?}, trait_ref={:?}, obligations={:?})",
-               closure_def_id,
-               trait_ref,
-               obligations);
-
-        obligations.extend(
-            self.confirm_poly_trait_refs(obligation.cause.clone(),
-                                         obligation.param_env,
-                                         obligation.predicate.to_poly_trait_ref(),
-                                         trait_ref)?);
+            mut obligations,
+        } = normalize_with_depth(
+            self,
+            obligation.param_env,
+            obligation.cause.clone(),
+            obligation.recursion_depth + 1,
+            &trait_ref,
+        );
+
+        debug!(
+            "confirm_closure_candidate(closure_def_id={:?}, trait_ref={:?}, obligations={:?})",
+            closure_def_id, trait_ref, obligations
+        );
+
+        obligations.extend(self.confirm_poly_trait_refs(
+            obligation.cause.clone(),
+            obligation.param_env,
+            obligation.predicate.to_poly_trait_ref(),
+            trait_ref,
+        )?);
 
         obligations.push(Obligation::new(
             obligation.cause.clone(),
             obligation.param_env,
-            ty::Predicate::ClosureKind(closure_def_id, substs, kind)));
+            ty::Predicate::ClosureKind(closure_def_id, substs, kind),
+        ));
 
         Ok(VtableClosureData {
             closure_def_id,
             substs: substs.clone(),
-            nested: obligations
+            nested: obligations,
         })
     }
 
@@ -3015,13 +3200,13 @@ fn confirm_closure_candidate(&mut self,
     /// because these output type parameters should not affect the
     /// selection of the impl. Therefore, if there is a mismatch, we
     /// report an error to the user.
-    fn confirm_poly_trait_refs(&mut self,
-                               obligation_cause: ObligationCause<'tcx>,
-                               obligation_param_env: ty::ParamEnv<'tcx>,
-                               obligation_trait_ref: ty::PolyTraitRef<'tcx>,
-                               expected_trait_ref: ty::PolyTraitRef<'tcx>)
-                               -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>>
-    {
+    fn confirm_poly_trait_refs(
+        &mut self,
+        obligation_cause: ObligationCause<'tcx>,
+        obligation_param_env: ty::ParamEnv<'tcx>,
+        obligation_trait_ref: ty::PolyTraitRef<'tcx>,
+        expected_trait_ref: ty::PolyTraitRef<'tcx>,
+    ) -> Result<Vec<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
         let obligation_trait_ref = obligation_trait_ref.clone();
         self.infcx
             .at(&obligation_cause, obligation_param_env)
@@ -3030,21 +3215,28 @@ fn confirm_poly_trait_refs(&mut self,
             .map_err(|e| OutputTypeParameterMismatch(expected_trait_ref, obligation_trait_ref, e))
     }
 
-    fn confirm_builtin_unsize_candidate(&mut self,
-                                        obligation: &TraitObligation<'tcx>,)
-        -> Result<VtableBuiltinData<PredicateObligation<'tcx>>, SelectionError<'tcx>>
-    {
+    fn confirm_builtin_unsize_candidate(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+    ) -> Result<VtableBuiltinData<PredicateObligation<'tcx>>, SelectionError<'tcx>> {
         let tcx = self.tcx();
 
         // assemble_candidates_for_unsizing should ensure there are no late bound
         // regions here. See the comment there for more details.
-        let source = self.infcx.shallow_resolve(
-            obligation.self_ty().no_late_bound_regions().unwrap());
-        let target = obligation.predicate.skip_binder().trait_ref.substs.type_at(1);
+        let source = self.infcx
+            .shallow_resolve(obligation.self_ty().no_late_bound_regions().unwrap());
+        let target = obligation
+            .predicate
+            .skip_binder()
+            .trait_ref
+            .substs
+            .type_at(1);
         let target = self.infcx.shallow_resolve(target);
 
-        debug!("confirm_builtin_unsize_candidate(source={:?}, target={:?})",
-               source, target);
+        debug!(
+            "confirm_builtin_unsize_candidate(source={:?}, target={:?})",
+            source, target
+        );
 
         let mut nested = vec![];
         match (&source.sty, &target.sty) {
@@ -3053,47 +3245,64 @@ fn confirm_builtin_unsize_candidate(&mut self,
                 // See assemble_candidates_for_unsizing for more info.
                 let existential_predicates = data_a.map_bound(|data_a| {
                     let principal = data_a.principal();
-                    let iter = principal.into_iter().map(ty::ExistentialPredicate::Trait)
-                        .chain(data_a.projection_bounds()
-                            .map(|x| ty::ExistentialPredicate::Projection(x)))
-                        .chain(data_b.auto_traits().map(ty::ExistentialPredicate::AutoTrait));
+                    let iter = principal
+                        .into_iter()
+                        .map(ty::ExistentialPredicate::Trait)
+                        .chain(
+                            data_a
+                                .projection_bounds()
+                                .map(|x| ty::ExistentialPredicate::Projection(x)),
+                        )
+                        .chain(
+                            data_b
+                                .auto_traits()
+                                .map(ty::ExistentialPredicate::AutoTrait),
+                        );
                     tcx.mk_existential_predicates(iter)
                 });
                 let new_trait = tcx.mk_dynamic(existential_predicates, r_b);
-                let InferOk { obligations, .. } =
-                    self.infcx.at(&obligation.cause, obligation.param_env)
-                              .eq(target, new_trait)
-                              .map_err(|_| Unimplemented)?;
+                let InferOk { obligations, .. } = self.infcx
+                    .at(&obligation.cause, obligation.param_env)
+                    .eq(target, new_trait)
+                    .map_err(|_| Unimplemented)?;
                 nested.extend(obligations);
 
                 // Register one obligation for 'a: 'b.
-                let cause = ObligationCause::new(obligation.cause.span,
-                                                 obligation.cause.body_id,
-                                                 ObjectCastObligation(target));
+                let cause = ObligationCause::new(
+                    obligation.cause.span,
+                    obligation.cause.body_id,
+                    ObjectCastObligation(target),
+                );
                 let outlives = ty::OutlivesPredicate(r_a, r_b);
-                nested.push(Obligation::with_depth(cause,
-                                                   obligation.recursion_depth + 1,
-                                                   obligation.param_env,
-                                                   ty::Binder::bind(outlives).to_predicate()));
+                nested.push(Obligation::with_depth(
+                    cause,
+                    obligation.recursion_depth + 1,
+                    obligation.param_env,
+                    ty::Binder::bind(outlives).to_predicate(),
+                ));
             }
 
             // T -> Trait.
             (_, &ty::Dynamic(ref data, r)) => {
-                let mut object_dids =
-                    data.auto_traits().chain(data.principal().map(|p| p.def_id()));
+                let mut object_dids = data.auto_traits()
+                    .chain(data.principal().map(|p| p.def_id()));
                 if let Some(did) = object_dids.find(|did| !tcx.is_object_safe(*did)) {
-                    return Err(TraitNotObjectSafe(did))
+                    return Err(TraitNotObjectSafe(did));
                 }
 
-                let cause = ObligationCause::new(obligation.cause.span,
-                                                 obligation.cause.body_id,
-                                                 ObjectCastObligation(target));
+                let cause = ObligationCause::new(
+                    obligation.cause.span,
+                    obligation.cause.body_id,
+                    ObjectCastObligation(target),
+                );
 
                 let predicate_to_obligation = |predicate| {
-                    Obligation::with_depth(cause.clone(),
-                                           obligation.recursion_depth + 1,
-                                           obligation.param_env,
-                                           predicate)
+                    Obligation::with_depth(
+                        cause.clone(),
+                        obligation.recursion_depth + 1,
+                        obligation.param_env,
+                        predicate,
+                    )
                 };
 
                 // Create obligations:
@@ -3102,9 +3311,10 @@ fn confirm_builtin_unsize_candidate(&mut self,
                 //  words, if the object type is Foo+Send, this would create an obligation for the
                 //  Send check.)
                 //  - Projection predicates
-                nested.extend(data.iter().map(|d|
-                    predicate_to_obligation(d.with_self_ty(tcx, source))
-                ));
+                nested.extend(
+                    data.iter()
+                        .map(|d| predicate_to_obligation(d.with_self_ty(tcx, source))),
+                );
 
                 // We can only make objects from sized types.
                 let tr = ty::TraitRef {
@@ -3117,22 +3327,22 @@ fn confirm_builtin_unsize_candidate(&mut self,
                 // being cast to `Foo+'a` outlives `'a`:
                 let outlives = ty::OutlivesPredicate(source, r);
                 nested.push(predicate_to_obligation(
-                    ty::Binder::dummy(outlives).to_predicate()));
+                    ty::Binder::dummy(outlives).to_predicate(),
+                ));
             }
 
             // [T; n] -> [T].
             (&ty::Array(a, _), &ty::Slice(b)) => {
-                let InferOk { obligations, .. } =
-                    self.infcx.at(&obligation.cause, obligation.param_env)
-                              .eq(b, a)
-                              .map_err(|_| Unimplemented)?;
+                let InferOk { obligations, .. } = self.infcx
+                    .at(&obligation.cause, obligation.param_env)
+                    .eq(b, a)
+                    .map_err(|_| Unimplemented)?;
                 nested.extend(obligations);
             }
 
             // Struct<T> -> Struct<U>.
             (&ty::Adt(def, substs_a), &ty::Adt(_, substs_b)) => {
-                let fields = def
-                    .all_fields()
+                let fields = def.all_fields()
                     .map(|f| tcx.type_of(f.did))
                     .collect::<Vec<_>>();
 
@@ -3178,18 +3388,18 @@ fn confirm_builtin_unsize_candidate(&mut self,
 
                 // Check that the source struct with the target's
                 // unsized parameters is equal to the target.
-                let params = substs_a.iter().enumerate().map(|(i, &k)|
+                let params = substs_a.iter().enumerate().map(|(i, &k)| {
                     if ty_params.contains(i) {
                         substs_b.type_at(i).into()
                     } else {
                         k
                     }
-                );
+                });
                 let new_struct = tcx.mk_adt(def, tcx.mk_substs(params));
-                let InferOk { obligations, .. } =
-                    self.infcx.at(&obligation.cause, obligation.param_env)
-                              .eq(target, new_struct)
-                              .map_err(|_| Unimplemented)?;
+                let InferOk { obligations, .. } = self.infcx
+                    .at(&obligation.cause, obligation.param_env)
+                    .eq(target, new_struct)
+                    .map_err(|_| Unimplemented)?;
                 nested.extend(obligations);
 
                 // Construct the nested Field<T>: Unsize<Field<U>> predicate.
@@ -3199,7 +3409,8 @@ fn confirm_builtin_unsize_candidate(&mut self,
                     obligation.predicate.def_id(),
                     obligation.recursion_depth + 1,
                     inner_source,
-                    &[inner_target.into()]));
+                    &[inner_target.into()],
+                ));
             }
 
             // (.., T) -> (.., U).
@@ -3217,10 +3428,10 @@ fn confirm_builtin_unsize_candidate(&mut self,
                 // Check that the source tuple with the target's
                 // last element is equal to the target.
                 let new_tuple = tcx.mk_tup(a_mid.iter().cloned().chain(iter::once(b_last)));
-                let InferOk { obligations, .. } =
-                    self.infcx.at(&obligation.cause, obligation.param_env)
-                              .eq(target, new_tuple)
-                              .map_err(|_| Unimplemented)?;
+                let InferOk { obligations, .. } = self.infcx
+                    .at(&obligation.cause, obligation.param_env)
+                    .eq(target, new_tuple)
+                    .map_err(|_| Unimplemented)?;
                 nested.extend(obligations);
 
                 // Construct the nested T: Unsize<U> predicate.
@@ -3230,10 +3441,11 @@ fn confirm_builtin_unsize_candidate(&mut self,
                     obligation.predicate.def_id(),
                     obligation.recursion_depth + 1,
                     a_last,
-                    &[b_last.into()]));
+                    &[b_last.into()],
+                ));
             }
 
-            _ => bug!()
+            _ => bug!(),
         };
 
         Ok(VtableBuiltinData { nested: nested })
@@ -3249,30 +3461,39 @@ fn confirm_builtin_unsize_candidate(&mut self,
     // run inside of a `probe()` so that their side-effects are
     // contained.
 
-    fn rematch_impl(&mut self,
-                    impl_def_id: DefId,
-                    obligation: &TraitObligation<'tcx>,
-                    snapshot: &infer::CombinedSnapshot<'cx, 'tcx>)
-                    -> (Normalized<'tcx, &'tcx Substs<'tcx>>,
-                        infer::SkolemizationMap<'tcx>)
-    {
+    fn rematch_impl(
+        &mut self,
+        impl_def_id: DefId,
+        obligation: &TraitObligation<'tcx>,
+        snapshot: &infer::CombinedSnapshot<'cx, 'tcx>,
+    ) -> (
+        Normalized<'tcx, &'tcx Substs<'tcx>>,
+        infer::PlaceholderMap<'tcx>,
+    ) {
         match self.match_impl(impl_def_id, obligation, snapshot) {
-            Ok((substs, skol_map)) => (substs, skol_map),
+            Ok((substs, placeholder_map)) => (substs, placeholder_map),
             Err(()) => {
-                bug!("Impl {:?} was matchable against {:?} but now is not",
-                     impl_def_id,
-                     obligation);
+                bug!(
+                    "Impl {:?} was matchable against {:?} but now is not",
+                    impl_def_id,
+                    obligation
+                );
             }
         }
     }
 
-    fn match_impl(&mut self,
-                  impl_def_id: DefId,
-                  obligation: &TraitObligation<'tcx>,
-                  snapshot: &infer::CombinedSnapshot<'cx, 'tcx>)
-                  -> Result<(Normalized<'tcx, &'tcx Substs<'tcx>>,
-                             infer::SkolemizationMap<'tcx>), ()>
-    {
+    fn match_impl(
+        &mut self,
+        impl_def_id: DefId,
+        obligation: &TraitObligation<'tcx>,
+        snapshot: &infer::CombinedSnapshot<'cx, 'tcx>,
+    ) -> Result<
+        (
+            Normalized<'tcx, &'tcx Substs<'tcx>>,
+            infer::PlaceholderMap<'tcx>,
+        ),
+        (),
+    > {
         let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap();
 
         // Before we create the substitutions and everything, first
@@ -3282,73 +3503,78 @@ fn match_impl(&mut self,
             return Err(());
         }
 
-        let (skol_obligation, skol_map) = self.infcx().skolemize_late_bound_regions(
-            &obligation.predicate);
+        let (skol_obligation, placeholder_map) = self.infcx()
+            .replace_late_bound_regions_with_placeholders(&obligation.predicate);
         let skol_obligation_trait_ref = skol_obligation.trait_ref;
 
-        let impl_substs = self.infcx.fresh_substs_for_item(obligation.cause.span,
-                                                           impl_def_id);
-
-        let impl_trait_ref = impl_trait_ref.subst(self.tcx(),
-                                                  impl_substs);
-
-        let Normalized { value: impl_trait_ref, obligations: mut nested_obligations } =
-            project::normalize_with_depth(self,
-                                          obligation.param_env,
-                                          obligation.cause.clone(),
-                                          obligation.recursion_depth + 1,
-                                          &impl_trait_ref);
-
-        debug!("match_impl(impl_def_id={:?}, obligation={:?}, \
-               impl_trait_ref={:?}, skol_obligation_trait_ref={:?})",
-               impl_def_id,
-               obligation,
-               impl_trait_ref,
-               skol_obligation_trait_ref);
-
-        let InferOk { obligations, .. } =
-            self.infcx.at(&obligation.cause, obligation.param_env)
-                      .eq(skol_obligation_trait_ref, impl_trait_ref)
-                      .map_err(|e|
-                          debug!("match_impl: failed eq_trait_refs due to `{}`", e)
-                      )?;
+        let impl_substs = self.infcx
+            .fresh_substs_for_item(obligation.cause.span, impl_def_id);
+
+        let impl_trait_ref = impl_trait_ref.subst(self.tcx(), impl_substs);
+
+        let Normalized {
+            value: impl_trait_ref,
+            obligations: mut nested_obligations,
+        } = project::normalize_with_depth(
+            self,
+            obligation.param_env,
+            obligation.cause.clone(),
+            obligation.recursion_depth + 1,
+            &impl_trait_ref,
+        );
+
+        debug!(
+            "match_impl(impl_def_id={:?}, obligation={:?}, \
+             impl_trait_ref={:?}, skol_obligation_trait_ref={:?})",
+            impl_def_id, obligation, impl_trait_ref, skol_obligation_trait_ref
+        );
+
+        let InferOk { obligations, .. } = self.infcx
+            .at(&obligation.cause, obligation.param_env)
+            .eq(skol_obligation_trait_ref, impl_trait_ref)
+            .map_err(|e| debug!("match_impl: failed eq_trait_refs due to `{}`", e))?;
         nested_obligations.extend(obligations);
 
-        if let Err(e) = self.infcx.leak_check(false,
-                                              obligation.cause.span,
-                                              &skol_map,
-                                              snapshot) {
+        if let Err(e) =
+            self.infcx
+                .leak_check(false, obligation.cause.span, &placeholder_map, snapshot)
+        {
             debug!("match_impl: failed leak check due to `{}`", e);
             return Err(());
         }
 
         debug!("match_impl: success impl_substs={:?}", impl_substs);
-        Ok((Normalized {
-            value: impl_substs,
-            obligations: nested_obligations
-        }, skol_map))
+        Ok((
+            Normalized {
+                value: impl_substs,
+                obligations: nested_obligations,
+            },
+            placeholder_map,
+        ))
     }
 
-    fn fast_reject_trait_refs(&mut self,
-                              obligation: &TraitObligation<'_>,
-                              impl_trait_ref: &ty::TraitRef<'_>)
-                              -> bool
-    {
+    fn fast_reject_trait_refs(
+        &mut self,
+        obligation: &TraitObligation<'_>,
+        impl_trait_ref: &ty::TraitRef<'_>,
+    ) -> bool {
         // We can avoid creating type variables and doing the full
         // substitution if we find that any of the input types, when
         // simplified, do not match.
 
-        obligation.predicate.skip_binder().input_types()
+        obligation
+            .predicate
+            .skip_binder()
+            .input_types()
             .zip(impl_trait_ref.input_types())
             .any(|(obligation_ty, impl_ty)| {
                 let simplified_obligation_ty =
                     fast_reject::simplify_type(self.tcx(), obligation_ty, true);
-                let simplified_impl_ty =
-                    fast_reject::simplify_type(self.tcx(), impl_ty, false);
+                let simplified_impl_ty = fast_reject::simplify_type(self.tcx(), impl_ty, false);
 
-                simplified_obligation_ty.is_some() &&
-                    simplified_impl_ty.is_some() &&
-                    simplified_obligation_ty != simplified_impl_ty
+                simplified_obligation_ty.is_some()
+                    && simplified_impl_ty.is_some()
+                    && simplified_obligation_ty != simplified_impl_ty
             })
     }
 
@@ -3357,50 +3583,54 @@ fn fast_reject_trait_refs(&mut self,
     /// result from the normalization. Normalization is necessary
     /// because where-clauses are stored in the parameter environment
     /// unnormalized.
-    fn match_where_clause_trait_ref(&mut self,
-                                    obligation: &TraitObligation<'tcx>,
-                                    where_clause_trait_ref: ty::PolyTraitRef<'tcx>)
-                                    -> Result<Vec<PredicateObligation<'tcx>>, ()>
-    {
+    fn match_where_clause_trait_ref(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        where_clause_trait_ref: ty::PolyTraitRef<'tcx>,
+    ) -> Result<Vec<PredicateObligation<'tcx>>, ()> {
         self.match_poly_trait_ref(obligation, where_clause_trait_ref)
     }
 
     /// Returns `Ok` if `poly_trait_ref` being true implies that the
     /// obligation is satisfied.
-    fn match_poly_trait_ref(&mut self,
-                            obligation: &TraitObligation<'tcx>,
-                            poly_trait_ref: ty::PolyTraitRef<'tcx>)
-                            -> Result<Vec<PredicateObligation<'tcx>>, ()>
-    {
-        debug!("match_poly_trait_ref: obligation={:?} poly_trait_ref={:?}",
-               obligation,
-               poly_trait_ref);
+    fn match_poly_trait_ref(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        poly_trait_ref: ty::PolyTraitRef<'tcx>,
+    ) -> Result<Vec<PredicateObligation<'tcx>>, ()> {
+        debug!(
+            "match_poly_trait_ref: obligation={:?} poly_trait_ref={:?}",
+            obligation, poly_trait_ref
+        );
 
-        self.infcx.at(&obligation.cause, obligation.param_env)
-                  .sup(obligation.predicate.to_poly_trait_ref(), poly_trait_ref)
-                  .map(|InferOk { obligations, .. }| obligations)
-                  .map_err(|_| ())
+        self.infcx
+            .at(&obligation.cause, obligation.param_env)
+            .sup(obligation.predicate.to_poly_trait_ref(), poly_trait_ref)
+            .map(|InferOk { obligations, .. }| obligations)
+            .map_err(|_| ())
     }
 
     ///////////////////////////////////////////////////////////////////////////
     // Miscellany
 
-    fn match_fresh_trait_refs(&self,
-                              previous: &ty::PolyTraitRef<'tcx>,
-                              current: &ty::PolyTraitRef<'tcx>)
-                              -> bool
-    {
+    fn match_fresh_trait_refs(
+        &self,
+        previous: &ty::PolyTraitRef<'tcx>,
+        current: &ty::PolyTraitRef<'tcx>,
+    ) -> bool {
         let mut matcher = ty::_match::Match::new(self.tcx());
         matcher.relate(previous, current).is_ok()
     }
 
-    fn push_stack<'o,'s:'o>(&mut self,
-                            previous_stack: TraitObligationStackList<'s, 'tcx>,
-                            obligation: &'o TraitObligation<'tcx>)
-                            -> TraitObligationStack<'o, 'tcx>
-    {
-        let fresh_trait_ref =
-            obligation.predicate.to_poly_trait_ref().fold_with(&mut self.freshener);
+    fn push_stack<'o, 's: 'o>(
+        &mut self,
+        previous_stack: TraitObligationStackList<'s, 'tcx>,
+        obligation: &'o TraitObligation<'tcx>,
+    ) -> TraitObligationStack<'o, 'tcx> {
+        let fresh_trait_ref = obligation
+            .predicate
+            .to_poly_trait_ref()
+            .fold_with(&mut self.freshener);
 
         TraitObligationStack {
             obligation,
@@ -3409,12 +3639,12 @@ fn push_stack<'o,'s:'o>(&mut self,
         }
     }
 
-    fn closure_trait_ref_unnormalized(&mut self,
-                                      obligation: &TraitObligation<'tcx>,
-                                      closure_def_id: DefId,
-                                      substs: ty::ClosureSubsts<'tcx>)
-                                      -> ty::PolyTraitRef<'tcx>
-    {
+    fn closure_trait_ref_unnormalized(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        closure_def_id: DefId,
+        substs: ty::ClosureSubsts<'tcx>,
+    ) -> ty::PolyTraitRef<'tcx> {
         let closure_type = self.infcx.closure_sig(closure_def_id, substs);
 
         // (1) Feels icky to skip the binder here, but OTOH we know
@@ -3422,21 +3652,22 @@ fn closure_trait_ref_unnormalized(&mut self,
         // in fact unparameterized (or at least does not reference any
         // regions bound in the obligation). Still probably some
         // refactoring could make this nicer.
-        self.tcx().closure_trait_ref_and_return_type(obligation.predicate.def_id(),
-                                                     obligation.predicate
-                                                               .skip_binder()
-                                                               .self_ty(), // (1)
-                                                     closure_type,
-                                                     util::TupleArgumentsFlag::No)
+        self.tcx()
+            .closure_trait_ref_and_return_type(
+                obligation.predicate.def_id(),
+                obligation.predicate.skip_binder().self_ty(), // (1)
+                closure_type,
+                util::TupleArgumentsFlag::No,
+            )
             .map_bound(|(trait_ref, _)| trait_ref)
     }
 
-    fn generator_trait_ref_unnormalized(&mut self,
-                                        obligation: &TraitObligation<'tcx>,
-                                        closure_def_id: DefId,
-                                        substs: ty::GeneratorSubsts<'tcx>)
-                                        -> ty::PolyTraitRef<'tcx>
-    {
+    fn generator_trait_ref_unnormalized(
+        &mut self,
+        obligation: &TraitObligation<'tcx>,
+        closure_def_id: DefId,
+        substs: ty::GeneratorSubsts<'tcx>,
+    ) -> ty::PolyTraitRef<'tcx> {
         let gen_sig = substs.poly_sig(closure_def_id, self.tcx());
 
         // (1) Feels icky to skip the binder here, but OTOH we know
@@ -3445,11 +3676,12 @@ fn generator_trait_ref_unnormalized(&mut self,
         // regions bound in the obligation). Still probably some
         // refactoring could make this nicer.
 
-        self.tcx().generator_trait_ref_and_outputs(obligation.predicate.def_id(),
-                                                   obligation.predicate
-                                                             .skip_binder()
-                                                             .self_ty(), // (1)
-                                                   gen_sig)
+        self.tcx()
+            .generator_trait_ref_and_outputs(
+                obligation.predicate.def_id(),
+                obligation.predicate.skip_binder().self_ty(), // (1)
+                gen_sig,
+            )
             .map_bound(|(trait_ref, ..)| trait_ref)
     }
 
@@ -3457,16 +3689,16 @@ fn generator_trait_ref_unnormalized(&mut self,
     /// impl or trait. The obligations are substituted and fully
     /// normalized. This is used when confirming an impl or default
     /// impl.
-    fn impl_or_trait_obligations(&mut self,
-                                 cause: ObligationCause<'tcx>,
-                                 recursion_depth: usize,
-                                 param_env: ty::ParamEnv<'tcx>,
-                                 def_id: DefId, // of impl or trait
-                                 substs: &Substs<'tcx>, // for impl or trait
-                                 skol_map: infer::SkolemizationMap<'tcx>,
-                                 snapshot: &infer::CombinedSnapshot<'cx, 'tcx>)
-                                 -> Vec<PredicateObligation<'tcx>>
-    {
+    fn impl_or_trait_obligations(
+        &mut self,
+        cause: ObligationCause<'tcx>,
+        recursion_depth: usize,
+        param_env: ty::ParamEnv<'tcx>,
+        def_id: DefId,         // of impl or trait
+        substs: &Substs<'tcx>, // for impl or trait
+        placeholder_map: infer::PlaceholderMap<'tcx>,
+        snapshot: &infer::CombinedSnapshot<'cx, 'tcx>,
+    ) -> Vec<PredicateObligation<'tcx>> {
         debug!("impl_or_trait_obligations(def_id={:?})", def_id);
         let tcx = self.tcx();
 
@@ -3486,17 +3718,25 @@ fn impl_or_trait_obligations(&mut self,
         // that order.
         let predicates = tcx.predicates_of(def_id);
         assert_eq!(predicates.parent, None);
-        let mut predicates: Vec<_> = predicates.predicates.iter().flat_map(|(predicate, _)| {
-            let predicate = normalize_with_depth(self, param_env, cause.clone(), recursion_depth,
-                                                 &predicate.subst(tcx, substs));
-            predicate.obligations.into_iter().chain(
-                Some(Obligation {
+        let mut predicates: Vec<_> = predicates
+            .predicates
+            .iter()
+            .flat_map(|(predicate, _)| {
+                let predicate = normalize_with_depth(
+                    self,
+                    param_env,
+                    cause.clone(),
+                    recursion_depth,
+                    &predicate.subst(tcx, substs),
+                );
+                predicate.obligations.into_iter().chain(Some(Obligation {
                     cause: cause.clone(),
                     recursion_depth,
                     param_env,
-                    predicate: predicate.value
+                    predicate: predicate.value,
                 }))
-        }).collect();
+            })
+            .collect();
 
         // We are performing deduplication here to avoid exponential blowups
         // (#38528) from happening, but the real cause of the duplication is
@@ -3519,16 +3759,17 @@ fn impl_or_trait_obligations(&mut self,
             let mut seen = FxHashSet();
             predicates.retain(|i| seen.insert(i.clone()));
         }
-        self.infcx().plug_leaks(skol_map, snapshot, predicates)
+        self.infcx()
+            .plug_leaks(placeholder_map, snapshot, predicates)
     }
 }
 
 impl<'tcx> TraitObligation<'tcx> {
     #[allow(unused_comparisons)]
-    pub fn derived_cause(&self,
-                         variant: fn(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>)
-                         -> ObligationCause<'tcx>
-    {
+    pub fn derived_cause(
+        &self,
+        variant: fn(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>,
+    ) -> ObligationCause<'tcx> {
         /*!
          * Creates a cause for obligations that are derived from
          * `obligation` by a recursive search (e.g., for a builtin
@@ -3547,10 +3788,14 @@ pub fn derived_cause(&self,
         if obligation.recursion_depth >= 0 {
             let derived_cause = DerivedObligationCause {
                 parent_trait_ref: obligation.predicate.to_poly_trait_ref(),
-                parent_code: Rc::new(obligation.cause.code.clone())
+                parent_code: Rc::new(obligation.cause.code.clone()),
             };
             let derived_code = variant(derived_cause);
-            ObligationCause::new(obligation.cause.span, obligation.cause.body_id, derived_code)
+            ObligationCause::new(
+                obligation.cause.span,
+                obligation.cause.body_id,
+                derived_code,
+            )
         } else {
             obligation.cause.clone()
         }
@@ -3560,7 +3805,7 @@ pub fn derived_cause(&self,
 impl<'tcx> SelectionCache<'tcx> {
     pub fn new() -> SelectionCache<'tcx> {
         SelectionCache {
-            hashmap: Lock::new(FxHashMap())
+            hashmap: Lock::new(FxHashMap()),
         }
     }
 
@@ -3572,7 +3817,7 @@ pub fn clear(&self) {
 impl<'tcx> EvaluationCache<'tcx> {
     pub fn new() -> EvaluationCache<'tcx> {
         EvaluationCache {
-            hashmap: Lock::new(FxHashMap())
+            hashmap: Lock::new(FxHashMap()),
         }
     }
 
@@ -3581,46 +3826,46 @@ pub fn clear(&self) {
     }
 }
 
-impl<'o,'tcx> TraitObligationStack<'o,'tcx> {
-    fn list(&'o self) -> TraitObligationStackList<'o,'tcx> {
+impl<'o, 'tcx> TraitObligationStack<'o, 'tcx> {
+    fn list(&'o self) -> TraitObligationStackList<'o, 'tcx> {
         TraitObligationStackList::with(self)
     }
 
-    fn iter(&'o self) -> TraitObligationStackList<'o,'tcx> {
+    fn iter(&'o self) -> TraitObligationStackList<'o, 'tcx> {
         self.list()
     }
 }
 
 #[derive(Copy, Clone)]
-struct TraitObligationStackList<'o,'tcx:'o> {
-    head: Option<&'o TraitObligationStack<'o,'tcx>>
+struct TraitObligationStackList<'o, 'tcx: 'o> {
+    head: Option<&'o TraitObligationStack<'o, 'tcx>>,
 }
 
-impl<'o,'tcx> TraitObligationStackList<'o,'tcx> {
-    fn empty() -> TraitObligationStackList<'o,'tcx> {
+impl<'o, 'tcx> TraitObligationStackList<'o, 'tcx> {
+    fn empty() -> TraitObligationStackList<'o, 'tcx> {
         TraitObligationStackList { head: None }
     }
 
-    fn with(r: &'o TraitObligationStack<'o,'tcx>) -> TraitObligationStackList<'o,'tcx> {
+    fn with(r: &'o TraitObligationStack<'o, 'tcx>) -> TraitObligationStackList<'o, 'tcx> {
         TraitObligationStackList { head: Some(r) }
     }
 }
 
-impl<'o,'tcx> Iterator for TraitObligationStackList<'o,'tcx>{
-    type Item = &'o TraitObligationStack<'o,'tcx>;
+impl<'o, 'tcx> Iterator for TraitObligationStackList<'o, 'tcx> {
+    type Item = &'o TraitObligationStack<'o, 'tcx>;
 
-    fn next(&mut self) -> Option<&'o TraitObligationStack<'o,'tcx>> {
+    fn next(&mut self) -> Option<&'o TraitObligationStack<'o, 'tcx>> {
         match self.head {
             Some(o) => {
                 *self = o.previous;
                 Some(o)
             }
-            None => None
+            None => None,
         }
     }
 }
 
-impl<'o,'tcx> fmt::Debug for TraitObligationStack<'o,'tcx> {
+impl<'o, 'tcx> fmt::Debug for TraitObligationStack<'o, 'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "TraitObligationStack({:?})", self.obligation)
     }
@@ -3629,12 +3874,15 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 #[derive(Clone, Eq, PartialEq)]
 pub struct WithDepNode<T> {
     dep_node: DepNodeIndex,
-    cached_value: T
+    cached_value: T,
 }
 
 impl<T: Clone> WithDepNode<T> {
     pub fn new(dep_node: DepNodeIndex, cached_value: T) -> Self {
-        WithDepNode { dep_node, cached_value }
+        WithDepNode {
+            dep_node,
+            cached_value,
+        }
     }
 
     pub fn get(&self, tcx: TyCtxt<'_, '_, '_>) -> T {
index 84ffa22e5dd2ec7a3dec5ebd69b30a2361fcaf3c..2c713c0f7f1aacba204236ff10315f49a859e62c 100644 (file)
@@ -184,7 +184,7 @@ pub(super) fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         return false;
     }
 
-    // create a parameter environment corresponding to a (skolemized) instantiation of impl1
+    // create a parameter environment corresponding to a (placeholder) instantiation of impl1
     let penv = tcx.param_env(impl1_def_id);
     let impl1_trait_ref = tcx.impl_trait_ref(impl1_def_id).unwrap();
 
index ae87d30ec942711254f433149c21612809efe235..8738f574148239e37966edc1ef3ef1a90f2f532e 100644 (file)
@@ -178,19 +178,19 @@ pub fn decode_predicates<'a, 'tcx, D>(decoder: &mut D)
     Ok(ty::GenericPredicates {
         parent: Decodable::decode(decoder)?,
         predicates: (0..decoder.read_usize()?).map(|_| {
-                // Handle shorthands first, if we have an usize > 0x80.
-                let predicate = if decoder.positioned_at_shorthand() {
-                    let pos = decoder.read_usize()?;
-                    assert!(pos >= SHORTHAND_OFFSET);
-                    let shorthand = pos - SHORTHAND_OFFSET;
-
-                    decoder.with_position(shorthand, ty::Predicate::decode)
-                } else {
-                    ty::Predicate::decode(decoder)
-                }?;
-                Ok((predicate, Decodable::decode(decoder)?))
-            })
-            .collect::<Result<Vec<_>, _>>()?,
+            // Handle shorthands first, if we have an usize > 0x80.
+            let predicate = if decoder.positioned_at_shorthand() {
+                let pos = decoder.read_usize()?;
+                assert!(pos >= SHORTHAND_OFFSET);
+                let shorthand = pos - SHORTHAND_OFFSET;
+
+                decoder.with_position(shorthand, ty::Predicate::decode)
+            } else {
+                ty::Predicate::decode(decoder)
+            }?;
+            Ok((predicate, Decodable::decode(decoder)?))
+        })
+        .collect::<Result<Vec<_>, _>>()?,
     })
 }
 
@@ -267,7 +267,7 @@ pub fn decode_const<'a, 'tcx, D>(decoder: &mut D)
 
 #[inline]
 pub fn decode_allocation<'a, 'tcx, D>(decoder: &mut D)
-                                 -> Result<&'tcx Allocation, D::Error>
+    -> Result<&'tcx Allocation, D::Error>
     where D: TyDecoder<'a, 'tcx>,
           'tcx: 'a,
 {
index 85559c892c4af67232ec4fc929c21d291ed97b84..46ba5f5ef362dfb30e6f5b5deb2186dbe577d255 100644 (file)
@@ -190,8 +190,8 @@ fn intern_ty(
             // types/regions in the global interner
             if local as *const _ as usize == global as *const _ as usize {
                 bug!("Attempted to intern `{:?}` which contains \
-                    inference types/regions in the global type context",
-                    &ty_struct);
+                      inference types/regions in the global type context",
+                     &ty_struct);
             }
 
             // Don't be &mut TyS.
@@ -272,9 +272,9 @@ fn validate_hir_id_for_typeck_tables(local_id_root: Option<DefId>,
 
                     bug!("node {} with HirId::owner {:?} cannot be placed in \
                           TypeckTables with local_id_root {:?}",
-                          tcx.hir.node_to_string(node_id),
-                          DefId::local(hir_id.owner),
-                          local_id_root)
+                         tcx.hir.node_to_string(node_id),
+                         DefId::local(hir_id.owner),
+                         local_id_root)
                 });
             }
         } else {
@@ -540,16 +540,13 @@ pub fn node_types_mut(&mut self) -> LocalTableInContextMut<'_, Ty<'tcx>> {
     }
 
     pub fn node_id_to_type(&self, id: hir::HirId) -> Ty<'tcx> {
-        match self.node_id_to_type_opt(id) {
-            Some(ty) => ty,
-            None => {
-                bug!("node_id_to_type: no type for node `{}`",
-                    tls::with(|tcx| {
-                        let id = tcx.hir.hir_to_node_id(id);
-                        tcx.hir.node_to_string(id)
-                    }))
-            }
-        }
+        self.node_id_to_type_opt(id).unwrap_or_else(||
+            bug!("node_id_to_type: no type for node `{}`",
+                 tls::with(|tcx| {
+                     let id = tcx.hir.hir_to_node_id(id);
+                     tcx.hir.node_to_string(id)
+                 }))
+        )
     }
 
     pub fn node_id_to_type_opt(&self, id: hir::HirId) -> Option<Ty<'tcx>> {
@@ -686,7 +683,7 @@ pub fn pat_adjustments(&self) -> LocalTableInContext<'_, Vec<Ty<'tcx>>> {
     }
 
     pub fn pat_adjustments_mut(&mut self)
-                           -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>> {
+                               -> LocalTableInContextMut<'_, Vec<Ty<'tcx>>> {
         LocalTableInContextMut {
             local_id_root: self.local_id_root,
             data: &mut self.pat_adjustments,
@@ -1199,8 +1196,8 @@ pub fn create_and_enter<F, R>(s: &'tcx Session,
             let hir_id = hir.node_to_hir_id(k);
             let map = trait_map.entry(hir_id.owner).or_default();
             Lrc::get_mut(map).unwrap()
-                            .insert(hir_id.local_id,
-                                    Lrc::new(StableVec::new(v)));
+                             .insert(hir_id.local_id,
+                                     Lrc::new(StableVec::new(v)));
         }
 
         let gcx = &GlobalCtxt {
@@ -2188,7 +2185,6 @@ pub fn go(tcx: TyCtxt<'_, '_, '_>) {
                 };
                 $(let mut $variant = total;)*
 
-
                 for &Interned(t) in tcx.interners.type_.borrow().iter() {
                     let variant = match t.sty {
                         ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) |
@@ -2207,7 +2203,7 @@ pub fn go(tcx: TyCtxt<'_, '_, '_>) {
                 }
                 println!("Ty interner             total           ty region  both");
                 $(println!("    {:18}: {uses:6} {usespc:4.1}%, \
-{ty:4.1}% {region:5.1}% {both:4.1}%",
+                            {ty:4.1}% {region:5.1}% {both:4.1}%",
                            stringify!($variant),
                            uses = $variant.total,
                            usespc = $variant.total as f64 * 100.0 / total.total as f64,
@@ -2216,7 +2212,7 @@ pub fn go(tcx: TyCtxt<'_, '_, '_>) {
                            both = $variant.both_infer as f64 * 100.0  / total.total as f64);
                   )*
                 println!("                  total {uses:6}        \
-{ty:4.1}% {region:5.1}% {both:4.1}%",
+                          {ty:4.1}% {region:5.1}% {both:4.1}%",
                          uses = total.total,
                          ty = total.ty_infer as f64 * 100.0  / total.total as f64,
                          region = total.region_infer as f64 * 100.0  / total.total as f64,
@@ -2234,7 +2230,7 @@ pub fn print_debug_stats(self) {
             self,
             Adt, Array, Slice, RawPtr, Ref, FnDef, FnPtr,
             Generator, GeneratorWitness, Dynamic, Closure, Tuple,
-            Param, Infer, Projection, Opaque, Foreign);
+            Param, Infer, UnnormalizedProjection, Projection, Opaque, Foreign);
 
         println!("Substs interner: #{}", self.interners.substs.borrow().len());
         println!("Region interner: #{}", self.interners.region.borrow().len());
@@ -2653,7 +2649,7 @@ pub fn mk_projection(self,
         }
 
     pub fn mk_closure(self, closure_id: DefId, closure_substs: ClosureSubsts<'tcx>)
-                                          -> Ty<'tcx> {
+                      -> Ty<'tcx> {
         self.mk_ty(Closure(closure_id, closure_substs))
     }
 
@@ -2686,8 +2682,8 @@ pub fn mk_infer(self, it: InferTy) -> Ty<'tcx> {
     }
 
     pub fn mk_ty_param(self,
-                    index: u32,
-                    name: InternedString) -> Ty<'tcx> {
+                       index: u32,
+                       name: InternedString) -> Ty<'tcx> {
         self.mk_ty(Param(ParamTy { idx: index, name: name }))
     }
 
index 9f9d918415e7e8221bb414a393bdb736829b85e1..3123f0fbe31de3c9308c3b1999db83abe7862e52 100644 (file)
@@ -10,6 +10,7 @@
 
 use hir::def_id::DefId;
 use ty::{self, BoundRegion, Region, Ty, TyCtxt};
+use std::borrow::Cow;
 use std::fmt;
 use rustc_target::spec::abi;
 use syntax::ast;
@@ -71,7 +72,7 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         use self::TypeError::*;
         fn report_maybe_different(f: &mut fmt::Formatter<'_>,
-                                  expected: String, found: String) -> fmt::Result {
+                                  expected: &str, found: &str) -> fmt::Result {
             // A naive approach to making sure that we're not reporting silly errors such as:
             // (expected closure, found closure).
             if expected == found {
@@ -126,15 +127,15 @@ fn report_maybe_different(f: &mut fmt::Formatter<'_>,
                        br)
             }
             Sorts(values) => ty::tls::with(|tcx| {
-                report_maybe_different(f, values.expected.sort_string(tcx),
-                                       values.found.sort_string(tcx))
+                report_maybe_different(f, &values.expected.sort_string(tcx),
+                                       &values.found.sort_string(tcx))
             }),
             Traits(values) => ty::tls::with(|tcx| {
                 report_maybe_different(f,
-                                       format!("trait `{}`",
-                                               tcx.item_path_str(values.expected)),
-                                       format!("trait `{}`",
-                                               tcx.item_path_str(values.found)))
+                                       &format!("trait `{}`",
+                                                tcx.item_path_str(values.expected)),
+                                       &format!("trait `{}`",
+                                                tcx.item_path_str(values.found)))
             }),
             IntMismatch(ref values) => {
                 write!(f, "expected `{:?}`, found `{:?}`",
@@ -162,8 +163,8 @@ fn report_maybe_different(f: &mut fmt::Formatter<'_>,
                        values.found)
             },
             ExistentialMismatch(ref values) => {
-                report_maybe_different(f, format!("trait `{}`", values.expected),
-                                       format!("trait `{}`", values.found))
+                report_maybe_different(f, &format!("trait `{}`", values.expected),
+                                       &format!("trait `{}`", values.found))
             }
             OldStyleLUB(ref err) => {
                 write!(f, "{}", err)
@@ -173,22 +174,22 @@ fn report_maybe_different(f: &mut fmt::Formatter<'_>,
 }
 
 impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> {
-    pub fn sort_string(&self, tcx: TyCtxt<'a, 'gcx, 'lcx>) -> String {
+    pub fn sort_string(&self, tcx: TyCtxt<'a, 'gcx, 'lcx>) -> Cow<'static, str> {
         match self.sty {
             ty::Bool | ty::Char | ty::Int(_) |
-            ty::Uint(_) | ty::Float(_) | ty::Str | ty::Never => self.to_string(),
-            ty::Tuple(ref tys) if tys.is_empty() => self.to_string(),
+            ty::Uint(_) | ty::Float(_) | ty::Str | ty::Never => self.to_string().into(),
+            ty::Tuple(ref tys) if tys.is_empty() => self.to_string().into(),
 
-            ty::Adt(def, _) => format!("{} `{}`", def.descr(), tcx.item_path_str(def.did)),
-            ty::Foreign(def_id) => format!("extern type `{}`", tcx.item_path_str(def_id)),
+            ty::Adt(def, _) => format!("{} `{}`", def.descr(), tcx.item_path_str(def.did)).into(),
+            ty::Foreign(def_id) => format!("extern type `{}`", tcx.item_path_str(def_id)).into(),
             ty::Array(_, n) => {
                 match n.assert_usize(tcx) {
-                    Some(n) => format!("array of {} elements", n),
-                    None => "array".to_string(),
+                    Some(n) => format!("array of {} elements", n).into(),
+                    None => "array".into(),
                 }
             }
-            ty::Slice(_) => "slice".to_string(),
-            ty::RawPtr(_) => "*-ptr".to_string(),
+            ty::Slice(_) => "slice".into(),
+            ty::RawPtr(_) => "*-ptr".into(),
             ty::Ref(region, ty, mutbl) => {
                 let tymut = ty::TypeAndMut { ty, mutbl };
                 let tymut_string = tymut.to_string();
@@ -199,38 +200,39 @@ pub fn sort_string(&self, tcx: TyCtxt<'a, 'gcx, 'lcx>) -> String {
                     format!("{}reference", match mutbl {
                         hir::Mutability::MutMutable => "mutable ",
                         _ => ""
-                    })
+                    }).into()
                 } else {
-                    format!("&{}", tymut_string)
+                    format!("&{}", tymut_string).into()
                 }
             }
-            ty::FnDef(..) => "fn item".to_string(),
-            ty::FnPtr(_) => "fn pointer".to_string(),
+            ty::FnDef(..) => "fn item".into(),
+            ty::FnPtr(_) => "fn pointer".into(),
             ty::Dynamic(ref inner, ..) => {
-                inner.principal().map_or_else(|| "trait".to_string(),
-                    |p| format!("trait {}", tcx.item_path_str(p.def_id())))
+                inner.principal().map_or_else(|| "trait".into(),
+                    |p| format!("trait {}", tcx.item_path_str(p.def_id())).into())
             }
-            ty::Closure(..) => "closure".to_string(),
-            ty::Generator(..) => "generator".to_string(),
-            ty::GeneratorWitness(..) => "generator witness".to_string(),
-            ty::Tuple(..) => "tuple".to_string(),
-            ty::Infer(ty::TyVar(_)) => "inferred type".to_string(),
-            ty::Infer(ty::IntVar(_)) => "integral variable".to_string(),
-            ty::Infer(ty::FloatVar(_)) => "floating-point variable".to_string(),
+            ty::Closure(..) => "closure".into(),
+            ty::Generator(..) => "generator".into(),
+            ty::GeneratorWitness(..) => "generator witness".into(),
+            ty::Tuple(..) => "tuple".into(),
+            ty::Infer(ty::TyVar(_)) => "inferred type".into(),
+            ty::Infer(ty::IntVar(_)) => "integral variable".into(),
+            ty::Infer(ty::FloatVar(_)) => "floating-point variable".into(),
             ty::Infer(ty::CanonicalTy(_)) |
-            ty::Infer(ty::FreshTy(_)) => "skolemized type".to_string(),
-            ty::Infer(ty::FreshIntTy(_)) => "skolemized integral type".to_string(),
-            ty::Infer(ty::FreshFloatTy(_)) => "skolemized floating-point type".to_string(),
-            ty::Projection(_) => "associated type".to_string(),
+            ty::Infer(ty::FreshTy(_)) => "fresh type".into(),
+            ty::Infer(ty::FreshIntTy(_)) => "fresh integral type".into(),
+            ty::Infer(ty::FreshFloatTy(_)) => "fresh floating-point type".into(),
+            ty::Projection(_) => "associated type".into(),
+            ty::UnnormalizedProjection(_) => "non-normalized associated type".into(),
             ty::Param(ref p) => {
                 if p.is_self() {
-                    "Self".to_string()
+                    "Self".into()
                 } else {
-                    "type parameter".to_string()
+                    "type parameter".into()
                 }
             }
-            ty::Opaque(..) => "opaque type".to_string(),
-            ty::Error => "type error".to_string(),
+            ty::Opaque(..) => "opaque type".into(),
+            ty::Error => "type error".into(),
         }
     }
 }
@@ -250,20 +252,19 @@ pub fn note_and_explain_type_err(self,
                     db.note("no two closures, even if identical, have the same type");
                     db.help("consider boxing your closure and/or using it as a trait object");
                 }
-                match (&values.found.sty, &values.expected.sty) { // Issue #53280
-                    (ty::Infer(ty::IntVar(_)), ty::Float(_)) => {
-                        if let Ok(snippet) = self.sess.source_map().span_to_snippet(sp) {
-                            if snippet.chars().all(|c| c.is_digit(10) || c == '-' || c == '_') {
-                                db.span_suggestion_with_applicability(
-                                    sp,
-                                    "use a float literal",
-                                    format!("{}.0", snippet),
-                                    Applicability::MachineApplicable
-                                );
-                            }
+                if let (ty::Infer(ty::IntVar(_)), ty::Float(_)) =
+                       (&values.found.sty, &values.expected.sty) // Issue #53280
+                {
+                    if let Ok(snippet) = self.sess.source_map().span_to_snippet(sp) {
+                        if snippet.chars().all(|c| c.is_digit(10) || c == '-' || c == '_') {
+                            db.span_suggestion_with_applicability(
+                                sp,
+                                "use a float literal",
+                                format!("{}.0", snippet),
+                                Applicability::MachineApplicable
+                            );
                         }
-                    },
-                    _ => {}
+                    }
                 }
             },
             OldStyleLUB(err) => {
index 2d055fd307dc440029ec65e495d2234c10ea25f0..0f68e7aba4defd062d37b05e57d5ee1181eda1a8 100644 (file)
@@ -103,6 +103,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
         ty::FnPtr(ref f) => {
             Some(FunctionSimplifiedType(f.skip_binder().inputs().len()))
         }
+        ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
         ty::Projection(_) | ty::Param(_) => {
             if can_simplify_params {
                 // In normalized types, projections don't unify with
index 08d10578238737b21a28118b489dfd33f90ce252..c3d41873009a7b1d294a88e611b96e8f1d127df9 100644 (file)
@@ -62,9 +62,7 @@ fn add_bound_computation(&mut self, computation: &FlagComputation) {
         let outer_exclusive_binder = computation.outer_exclusive_binder;
         if outer_exclusive_binder > ty::INNERMOST {
             self.add_exclusive_binder(outer_exclusive_binder.shifted_out(1));
-        } else {
-            // otherwise, this binder captures nothing
-        }
+        } // otherwise, this binder captures nothing
     }
 
     fn add_sty(&mut self, st: &ty::TyKind<'_>) {
@@ -150,6 +148,8 @@ fn add_sty(&mut self, st: &ty::TyKind<'_>) {
                 self.add_projection_ty(data);
             }
 
+            &ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
+
             &ty::Opaque(_, substs) => {
                 self.add_flags(TypeFlags::HAS_PROJECTION);
                 self.add_substs(substs);
index 6bf493b496c8b92b60a9d1b358a5bdcfdbc7bb11..f54dcfa37e944021697c6275ed7a8373ec64d34d 100644 (file)
@@ -667,12 +667,14 @@ pub fn shift_regions<'a, 'gcx, 'tcx, T>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
 /// we already use the term "free region". It refers to the regions that we use to represent bound
 /// regions on a fn definition while we are typechecking its body.
 ///
-/// To clarify, conceptually there is no particular difference between an "escaping" region and a
-/// "free" region. However, there is a big difference in practice. Basically, when "entering" a
-/// binding level, one is generally required to do some sort of processing to a bound region, such
-/// as replacing it with a fresh/skolemized region, or making an entry in the environment to
-/// represent the scope to which it is attached, etc. An escaping region represents a bound region
-/// for which this processing has not yet been done.
+/// To clarify, conceptually there is no particular difference between
+/// an "escaping" region and a "free" region. However, there is a big
+/// difference in practice. Basically, when "entering" a binding
+/// level, one is generally required to do some sort of processing to
+/// a bound region, such as replacing it with a fresh/placeholder
+/// region, or making an entry in the environment to represent the
+/// scope to which it is attached, etc. An escaping region represents
+/// a bound region for which this processing has not yet been done.
 struct HasEscapingRegionsVisitor {
     /// Anything bound by `outer_index` or "above" is escaping
     outer_index: ty::DebruijnIndex,
@@ -780,11 +782,10 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
     }
 
     fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
-        match *r {
-            ty::ReLateBound(debruijn, br) if debruijn == self.current_index => {
+        if let ty::ReLateBound(debruijn, br) = *r {
+             if debruijn == self.current_index {
                 self.regions.insert(br);
             }
-            _ => { }
         }
         false
     }
index c152c0fb8e94cea9ccdf9b272929902b93044756..7bc77e1b1a14053350f9b25e3bdfde56772840dd 100644 (file)
@@ -66,12 +66,7 @@ pub fn contains(&self,
                     tcx: TyCtxt<'a, 'gcx, 'tcx>,
                     id: DefId) -> bool
     {
-        for root_id in self.root_ids.iter() {
-            if tcx.is_descendant_of(id, *root_id) {
-                return true;
-            }
-        }
-        false
+        self.root_ids.iter().any(|root_id| tcx.is_descendant_of(id, *root_id))
     }
 
     /// Calculate the intersection of a collection of forests.
@@ -92,11 +87,7 @@ pub fn intersection<I>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
             }
             ret.root_ids.extend(old_ret.drain());
 
-            for id in next_forest.root_ids {
-                if ret.contains(tcx, id) {
-                    next_ret.push(id);
-                }
-            }
+            next_ret.extend(next_forest.root_ids.into_iter().filter(|&id| ret.contains(tcx, id)));
 
             mem::swap(&mut next_ret, &mut ret.root_ids);
             next_ret.drain();
@@ -112,11 +103,7 @@ pub fn union<I>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
         let mut ret = DefIdForest::empty();
         let mut next_ret = SmallVec::new();
         for next_forest in iter {
-            for id in ret.root_ids.drain() {
-                if !next_forest.contains(tcx, id) {
-                    next_ret.push(id);
-                }
-            }
+            next_ret.extend(ret.root_ids.drain().filter(|&id| !next_forest.contains(tcx, id)));
 
             for id in next_forest.root_ids {
                 if !next_ret.contains(&id) {
index 3416d6594c7f7c98b7d5444efc7686f3ccfdbcfd..3d205215d64c60ef121690b25703720520b1bc1d 100644 (file)
@@ -231,11 +231,11 @@ pub fn resolve(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 
     pub fn resolve_closure(
-                    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                    def_id: DefId,
-                    substs: ty::ClosureSubsts<'tcx>,
-                    requested_kind: ty::ClosureKind)
-    -> Instance<'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);
 
@@ -255,8 +255,8 @@ fn resolve_associated_item<'a, 'tcx>(
 ) -> Option<Instance<'tcx>> {
     let def_id = trait_item.def_id;
     debug!("resolve_associated_item(trait_item={:?}, \
-                                    trait_id={:?}, \
-           rcvr_substs={:?})",
+            trait_id={:?}, \
+            rcvr_substs={:?})",
            def_id, trait_id, rcvr_substs);
 
     let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs);
@@ -280,7 +280,7 @@ fn resolve_associated_item<'a, 'tcx>(
         traits::VtableClosure(closure_data) => {
             let trait_closure_kind = tcx.lang_items().fn_trait_kind(trait_id).unwrap();
             Some(Instance::resolve_closure(tcx, closure_data.closure_def_id, closure_data.substs,
-                                 trait_closure_kind))
+                                           trait_closure_kind))
         }
         traits::VtableFnPointer(ref data) => {
             Some(Instance {
@@ -310,7 +310,7 @@ fn resolve_associated_item<'a, 'tcx>(
 }
 
 fn needs_fn_once_adapter_shim<'a, 'tcx>(actual_closure_kind: ty::ClosureKind,
-                              trait_closure_kind: ty::ClosureKind)
+                                        trait_closure_kind: ty::ClosureKind)
     -> Result<bool, ()>
 {
     match (actual_closure_kind, trait_closure_kind) {
@@ -344,13 +344,14 @@ fn needs_fn_once_adapter_shim<'a, 'tcx>(actual_closure_kind: ty::ClosureKind,
 }
 
 fn fn_once_adapter_instance<'a, 'tcx>(
-                            tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                            closure_did: DefId,
-                            substs: ty::ClosureSubsts<'tcx>,
-                            ) -> Instance<'tcx> {
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    closure_did: DefId,
+    substs: ty::ClosureSubsts<'tcx>)
+    -> Instance<'tcx>
+{
     debug!("fn_once_adapter_shim({:?}, {:?})",
-    closure_did,
-    substs);
+           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::AssociatedKind::Method)
index c8d104e6c321f4c6e3d88a2a412e617660ed96c7..ab0813240364c687c855d7108da3ec9ef268e4a6 100644 (file)
@@ -221,7 +221,7 @@ pub fn try_push_visible_item_path<T>(
 
             let data = cur_def_key.disambiguated_data.data;
             let symbol = data.get_opt_name().map(|n| n.as_str()).unwrap_or_else(|| {
-                if let DefPathData::CrateRoot = data {  // reexported `extern crate` (#43189)
+                if let DefPathData::CrateRoot = data { // reexported `extern crate` (#43189)
                     self.original_crate_name(cur_def.krate).as_str()
                 } else {
                     Symbol::intern("<unnamed>").as_str()
@@ -365,9 +365,7 @@ fn push_impl_path<T>(
 
         if let Some(trait_ref) = impl_trait_ref {
             // Trait impls.
-            buffer.push(&format!("<{} as {}>",
-                                 self_ty,
-                                 trait_ref));
+            buffer.push(&format!("<{} as {}>", self_ty, trait_ref));
             return;
         }
 
@@ -463,6 +461,7 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option<DefId> {
         ty::Str |
         ty::FnPtr(_) |
         ty::Projection(_) |
+        ty::UnnormalizedProjection(..) |
         ty::Param(_) |
         ty::Opaque(..) |
         ty::Infer(_) |
index 8bfe46568eb198791f12a879d4821a3a69b23326..05d4aeb6ddec4b0fa2964e409f52860a50d623bf 100644 (file)
@@ -32,11 +32,11 @@ pub trait IntegerExt {
     fn to_ty<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, signed: bool) -> Ty<'tcx>;
     fn from_attr<C: HasDataLayout>(cx: C, ity: attr::IntType) -> Integer;
     fn repr_discr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                  ty: Ty<'tcx>,
-                  repr: &ReprOptions,
-                  min: i128,
-                  max: i128)
-                  -> (Integer, bool);
+                            ty: Ty<'tcx>,
+                            repr: &ReprOptions,
+                            min: i128,
+                            max: i128)
+                            -> (Integer, bool);
 }
 
 impl IntegerExt for Integer {
@@ -76,11 +76,11 @@ fn from_attr<C: HasDataLayout>(cx: C, ity: attr::IntType) -> Integer {
     /// N.B.: u128 values above i128::MAX will be treated as signed, but
     /// that shouldn't affect anything, other than maybe debuginfo.
     fn repr_discr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                  ty: Ty<'tcx>,
-                  repr: &ReprOptions,
-                  min: i128,
-                  max: i128)
-                  -> (Integer, bool) {
+                            ty: Ty<'tcx>,
+                            repr: &ReprOptions,
+                            min: i128,
+                            max: i128)
+                            -> (Integer, bool) {
         // Theoretically, negative values could be larger in unsigned representation
         // than the unsigned representation of the signed minimum. However, if there
         // are any negative values, the only valid unsigned representation is u128
@@ -96,7 +96,7 @@ fn repr_discr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             let fit = if ity.is_signed() { signed_fit } else { unsigned_fit };
             if discr < fit {
                 bug!("Integer::repr_discr: `#[repr]` hint too small for \
-                  discriminant range of enum `{}", ty)
+                      discriminant range of enum `{}", ty)
             }
             return (discr, ity.is_signed());
         }
@@ -106,7 +106,7 @@ fn repr_discr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 // WARNING: the ARM EABI has two variants; the one corresponding
                 // to `at_least == I32` appears to be used on Linux and NetBSD,
                 // but some systems may use the variant corresponding to no
-                // lower bound.  However, we don't run on those yet...?
+                // lower bound. However, we don't run on those yet...?
                 "arm" => min_from_extern = Some(I32),
                 _ => min_from_extern = Some(I32),
             }
@@ -250,6 +250,7 @@ enum StructKind {
             /// A univariant, but with a prefix of an arbitrary size & alignment (e.g. enum tag).
             Prefixed(Size, Align),
         }
+
         let univariant_uninterned = |fields: &[TyLayout<'_>], repr: &ReprOptions, kind| {
             let packed = repr.packed();
             if packed && repr.align > 0 {
@@ -324,7 +325,7 @@ enum StructKind {
                 let field = fields[i as usize];
                 if !sized {
                     bug!("univariant: field #{} of `{}` comes after unsized field",
-                        offsets.len(), ty);
+                         offsets.len(), ty);
                 }
 
                 if field.is_unsized() {
@@ -628,7 +629,7 @@ enum StructKind {
                 };
 
                 univariant(&tys.iter().map(|ty| self.layout_of(ty)).collect::<Result<Vec<_>, _>>()?,
-                    &ReprOptions::default(), kind)?
+                           &ReprOptions::default(), kind)?
             }
 
             // SIMD vector types.
@@ -640,7 +641,7 @@ enum StructKind {
                     Abi::Scalar(ref scalar) => scalar.clone(),
                     _ => {
                         tcx.sess.fatal(&format!("monomorphising SIMD type `{}` with \
-                                                a non-machine element type `{}`",
+                                                 a non-machine element type `{}`",
                                                 ty, element.ty));
                     }
                 };
@@ -743,7 +744,7 @@ enum StructKind {
                     // Only one variant is present.
                     (present_second.is_none() &&
                     // Representation optimizations are allowed.
-                     !def.repr.inhibit_enum_layout_opt());
+                    !def.repr.inhibit_enum_layout_opt());
                 if is_struct {
                     // Struct, or univariant enum equivalent to a struct.
                     // (Typechecking will reject discriminant-sizing attrs.)
@@ -755,7 +756,7 @@ enum StructKind {
                         let param_env = tcx.param_env(def.did);
                         let last_field = def.variants[v].fields.last().unwrap();
                         let always_sized = tcx.type_of(last_field.did)
-                          .is_sized(tcx.at(DUMMY_SP), param_env);
+                                              .is_sized(tcx.at(DUMMY_SP), param_env);
                         if !always_sized { StructKind::MaybeUnsized }
                         else { StructKind::AlwaysSized }
                     };
@@ -1123,7 +1124,7 @@ enum StructKind {
                 }
                 tcx.layout_raw(param_env.and(normalized))?
             }
-            ty::GeneratorWitness(..) | ty::Infer(_) => {
+            ty::UnnormalizedProjection(..) | ty::GeneratorWitness(..) | ty::Infer(_) => {
                 bug!("LayoutDetails::compute: unexpected type `{}`", ty)
             }
             ty::Param(_) | ty::Error => {
@@ -1258,8 +1259,8 @@ fn record_layout_for_printing_outlined(self, layout: TyLayout<'tcx>) {
                         let fields: Vec<_> =
                             variant_def.fields.iter().map(|f| f.ident.name).collect();
                         build_variant_info(Some(variant_def.name),
-                                            &fields,
-                                            layout.for_variant(self, i))
+                                           &fields,
+                                           layout.for_variant(self, i))
                     })
                     .collect();
                 record(adt_kind.into(), adt_packed, match layout.variants {
@@ -1702,8 +1703,8 @@ fn field(this: TyLayout<'tcx>, cx: C, i: usize) -> C::TyLayout {
                 }
             }
 
-            ty::Projection(_) | ty::Opaque(..) | ty::Param(_) |
-            ty::Infer(_) | ty::Error => {
+            ty::Projection(_) | ty::UnnormalizedProjection(..) |
+            ty::Opaque(..) | ty::Param(_) | ty::Infer(_) | ty::Error => {
                 bug!("TyLayout::field_type: unexpected type `{}`", this.ty)
             }
         })
index 57afbafc2a5f626ea3885f293db30a59623aef2a..2e8734a6aa8ebf730e5979b8ed7a40a0f65a7dd8 100644 (file)
@@ -862,24 +862,22 @@ pub struct GenericParamDef {
 
 impl GenericParamDef {
     pub fn to_early_bound_region_data(&self) -> ty::EarlyBoundRegion {
-        match self.kind {
-            GenericParamDefKind::Lifetime => {
-                ty::EarlyBoundRegion {
-                    def_id: self.def_id,
-                    index: self.index,
-                    name: self.name,
-                }
+        if let GenericParamDefKind::Lifetime = self.kind {
+            ty::EarlyBoundRegion {
+                def_id: self.def_id,
+                index: self.index,
+                name: self.name,
             }
-            _ => bug!("cannot convert a non-lifetime parameter def to an early bound region")
+        } else {
+            bug!("cannot convert a non-lifetime parameter def to an early bound region")
         }
     }
 
     pub fn to_bound_region(&self) -> ty::BoundRegion {
-        match self.kind {
-            GenericParamDefKind::Lifetime => {
-                self.to_early_bound_region_data().to_bound_region()
-            }
-            _ => bug!("cannot convert a non-lifetime parameter def to an early bound region")
+        if let GenericParamDefKind::Lifetime = self.kind {
+            self.to_early_bound_region_data().to_bound_region()
+        } else {
+            bug!("cannot convert a non-lifetime parameter def to an early bound region")
         }
     }
 }
@@ -957,7 +955,7 @@ pub fn region_param(&'tcx self,
             }
         } else {
             tcx.generics_of(self.parent.expect("parent_count>0 but no parent?"))
-                .region_param(param, tcx)
+               .region_param(param, tcx)
         }
     }
 
@@ -974,7 +972,7 @@ pub fn type_param(&'tcx self,
             }
         } else {
             tcx.generics_of(self.parent.expect("parent_count>0 but no parent?"))
-                .type_param(param, tcx)
+               .type_param(param, tcx)
         }
     }
 }
@@ -1376,7 +1374,7 @@ pub fn walk_tys(&self) -> IntoIter<Ty<'tcx>> {
             }
         };
 
-        // The only reason to collect into a vector here is that I was
+        // FIXME: The only reason to collect into a vector here is that I was
         // too lazy to make the full (somewhat complicated) iterator
         // type that would be needed here. But I wanted this fn to
         // return an iterator conceptually, rather than a `Vec`, so as
@@ -1479,18 +1477,17 @@ pub fn is_empty(&self) -> bool {
 /// region `'a` is in a subuniverse U2 of U1, because we can name it
 /// inside the fn type but not outside.
 ///
-/// Universes are related to **skolemization** -- which is a way of
-/// doing type- and trait-checking around these "forall" binders (also
-/// called **universal quantification**). The idea is that when, in
-/// the body of `bar`, we refer to `T` as a type, we aren't referring
-/// to any type in particular, but rather a kind of "fresh" type that
-/// is distinct from all other types we have actually declared. This
-/// is called a **skolemized** type, and we use universes to talk
-/// about this. In other words, a type name in universe 0 always
-/// corresponds to some "ground" type that the user declared, but a
-/// type name in a non-zero universe is a skolemized type -- an
-/// idealized representative of "types in general" that we use for
-/// checking generic functions.
+/// Universes are used to do type- and trait-checking around these
+/// "forall" binders (also called **universal quantification**). The
+/// idea is that when, in the body of `bar`, we refer to `T` as a
+/// type, we aren't referring to any type in particular, but rather a
+/// kind of "fresh" type that is distinct from all other types we have
+/// actually declared. This is called a **placeholder** type, and we
+/// use universes to talk about this. In other words, a type name in
+/// universe 0 always corresponds to some "ground" type that the user
+/// declared, but a type name in a non-zero universe is a placeholder
+/// type -- an idealized representative of "types in general" that we
+/// use for checking generic functions.
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
 pub struct UniverseIndex(u32);
 
@@ -1553,6 +1550,18 @@ fn from(index: u32) -> Self {
     }
 }
 
+/// The "placeholder index" fully defines a placeholder region.
+/// Placeholder regions are identified by both a **universe** as well
+/// as a "bound-region" within that universe. The `bound_region` is
+/// basically a name -- distinct bound regions within the same
+/// universe are just two regions with an unknown relationship to one
+/// another.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, PartialOrd, Ord)]
+pub struct Placeholder {
+    pub universe: UniverseIndex,
+    pub name: BoundRegion,
+}
+
 /// When type checking, we use the `ParamEnv` to track
 /// details about the set of where-clauses that are in scope at this
 /// particular point.
@@ -1695,9 +1704,13 @@ pub struct AdtFlags: u32 {
         const IS_FUNDAMENTAL      = 1 << 2;
         const IS_UNION            = 1 << 3;
         const IS_BOX              = 1 << 4;
+        /// Indicates whether the type is an `Arc`.
+        const IS_ARC              = 1 << 5;
+        /// Indicates whether the type is an `Rc`.
+        const IS_RC               = 1 << 6;
         /// Indicates whether the variant list of this ADT is `#[non_exhaustive]`.
         /// (i.e., this flag is never set unless this ADT is an enum).
-        const IS_VARIANT_LIST_NON_EXHAUSTIVE   = 1 << 5;
+        const IS_VARIANT_LIST_NON_EXHAUSTIVE   = 1 << 7;
     }
 }
 
@@ -2017,6 +2030,12 @@ fn new(tcx: TyCtxt<'_, '_, '_>,
         if Some(did) == tcx.lang_items().owned_box() {
             flags = flags | AdtFlags::IS_BOX;
         }
+        if Some(did) == tcx.lang_items().arc() {
+            flags = flags | AdtFlags::IS_ARC;
+        }
+        if Some(did) == tcx.lang_items().rc() {
+            flags = flags | AdtFlags::IS_RC;
+        }
         if kind == AdtKind::Enum && tcx.has_attr(did, "non_exhaustive") {
             debug!("found non-exhaustive variant list for {:?}", did);
             flags = flags | AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE;
@@ -2095,6 +2114,16 @@ pub fn is_phantom_data(&self) -> bool {
         self.flags.intersects(AdtFlags::IS_PHANTOM_DATA)
     }
 
+    /// Returns `true` if this is `Arc<T>`.
+    pub fn is_arc(&self) -> bool {
+        self.flags.intersects(AdtFlags::IS_ARC)
+    }
+
+    /// Returns `true` if this is `Rc<T>`.
+    pub fn is_rc(&self) -> bool {
+        self.flags.intersects(AdtFlags::IS_RC)
+    }
+
     /// Returns true if this is Box<T>.
     #[inline]
     pub fn is_box(&self) -> bool {
@@ -2193,7 +2222,7 @@ pub fn eval_explicit_discr(
                 if !expr_did.is_local() {
                     span_bug!(tcx.def_span(expr_did),
                         "variant discriminant evaluation succeeded \
-                            in its crate but failed locally");
+                         in its crate but failed locally");
                 }
                 None
             }
@@ -2329,9 +2358,9 @@ fn sized_constraint_for_ty(&self,
                 debug!("sized_constraint_for_ty({:?}) intermediate = {:?}",
                        ty, adt_tys);
                 adt_tys.iter()
-                    .map(|ty| ty.subst(tcx, substs))
-                    .flat_map(|ty| self.sized_constraint_for_ty(tcx, ty))
-                    .collect()
+                       .map(|ty| ty.subst(tcx, substs))
+                       .flat_map(|ty| self.sized_constraint_for_ty(tcx, ty))
+                       .collect()
             }
 
             Projection(..) | Opaque(..) => {
@@ -2340,6 +2369,8 @@ fn sized_constraint_for_ty(&self,
                 vec![ty]
             }
 
+            UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
+
             Param(..) => {
                 // perf hack: if there is a `T: Sized` bound, then
                 // we know that `T` is Sized and do not need to check
@@ -2870,9 +2901,7 @@ pub fn with_freevars<T, F>(self, fid: NodeId, f: F) -> T where
     }
 }
 
-fn associated_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
-    -> AssociatedItem
-{
+fn associated_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> AssociatedItem {
     let id = tcx.hir.as_local_node_id(def_id).unwrap();
     let parent_id = tcx.hir.get_parent(id);
     let parent_def_id = tcx.hir.local_def_id(parent_id);
@@ -2986,8 +3015,8 @@ pub fn is_impl_trait_defn(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Option<DefI
 /// See `ParamEnv` struct def'n for details.
 fn param_env<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                        def_id: DefId)
-                       -> ParamEnv<'tcx> {
-
+                       -> ParamEnv<'tcx>
+{
     // The param_env of an impl Trait type is its defining function's param_env
     if let Some(parent) = is_impl_trait_defn(tcx, def_id) {
         return param_env(tcx, parent);
index 68f670708768706bc3390756b2c10ed34bf64688..b49664b6247332a16e7c799a43428ad2fd6bd8ac 100644 (file)
@@ -73,7 +73,6 @@ fn compute_components(&self, ty: Ty<'tcx>, out: &mut Vec<Component<'tcx>>) {
         // projection).
         match ty.sty {
             ty::Closure(def_id, ref substs) => {
-
                 for upvar_ty in substs.upvar_tys(def_id, *self) {
                     self.compute_components(upvar_ty, out);
                 }
@@ -124,6 +123,8 @@ fn compute_components(&self, ty: Ty<'tcx>, out: &mut Vec<Component<'tcx>>) {
                 }
             }
 
+            ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
+
             // We assume that inference variables are fully resolved.
             // So, if we encounter an inference variable, just record
             // the unresolved variable as a component.
@@ -181,9 +182,5 @@ fn capture_components(&self, ty: Ty<'tcx>) -> Vec<Component<'tcx>> {
 }
 
 fn push_region_constraints<'tcx>(out: &mut Vec<Component<'tcx>>, regions: Vec<ty::Region<'tcx>>) {
-    for r in regions {
-        if !r.is_late_bound() {
-            out.push(Component::Region(r));
-        }
-    }
+    out.extend(regions.iter().filter(|&r| !r.is_late_bound()).map(|r| Component::Region(r)));
 }
index 66d7541633cde29cd2a10af21ae72c0bccc4e129..79eab3c6f34b9eb79f674d974860cc624714671f 100644 (file)
@@ -23,6 +23,7 @@
 use ty::query::QueryCache;
 use util::profiling::ProfileCategory;
 
+use std::borrow::Cow;
 use std::hash::Hash;
 use std::fmt::Debug;
 use syntax_pos::symbol::InternedString;
@@ -55,7 +56,7 @@ pub(super) trait QueryAccessors<'tcx>: QueryConfig<'tcx> {
 }
 
 pub(super) trait QueryDescription<'tcx>: QueryAccessors<'tcx> {
-    fn describe(tcx: TyCtxt<'_, '_, '_>, key: Self::Key) -> String;
+    fn describe(tcx: TyCtxt<'_, '_, '_>, key: Self::Key) -> Cow<'static, str>;
 
     #[inline]
     fn cache_on_disk(_: Self::Key) -> bool {
@@ -70,12 +71,12 @@ fn try_load_from_disk(_: TyCtxt<'_, 'tcx, 'tcx>,
 }
 
 impl<'tcx, M: QueryAccessors<'tcx, Key=DefId>> QueryDescription<'tcx> for M {
-    default fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> String {
+    default fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> {
         if !tcx.sess.verbose() {
-            format!("processing `{}`", tcx.item_path_str(def_id))
+            format!("processing `{}`", tcx.item_path_str(def_id)).into()
         } else {
             let name = unsafe { ::std::intrinsics::type_name::<M>() };
-            format!("processing `{}` applied to `{:?}`", name, def_id)
+            format!("processing `{}` applied to `{:?}`", name, def_id).into()
         }
     }
 }
@@ -84,57 +85,59 @@ impl<'tcx> QueryDescription<'tcx> for queries::normalize_projection_ty<'tcx> {
     fn describe(
         _tcx: TyCtxt<'_, '_, '_>,
         goal: CanonicalProjectionGoal<'tcx>,
-    ) -> String {
-        format!("normalizing `{:?}`", goal)
+    ) -> Cow<'static, str> {
+        format!("normalizing `{:?}`", goal).into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::implied_outlives_bounds<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: CanonicalTyGoal<'tcx>) -> String {
-        format!("computing implied outlives bounds for `{:?}`", goal)
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: CanonicalTyGoal<'tcx>) -> Cow<'static, str> {
+        format!("computing implied outlives bounds for `{:?}`", goal).into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::dropck_outlives<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: CanonicalTyGoal<'tcx>) -> String {
-        format!("computing dropck types for `{:?}`", goal)
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: CanonicalTyGoal<'tcx>) -> Cow<'static, str> {
+        format!("computing dropck types for `{:?}`", goal).into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::normalize_ty_after_erasing_regions<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: ParamEnvAnd<'tcx, Ty<'tcx>>) -> String {
-        format!("normalizing `{:?}`", goal)
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: ParamEnvAnd<'tcx, Ty<'tcx>>) -> Cow<'static, str> {
+        format!("normalizing `{:?}`", goal).into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::evaluate_obligation<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: CanonicalPredicateGoal<'tcx>) -> String {
-        format!("evaluating trait selection obligation `{}`", goal.value.value)
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: CanonicalPredicateGoal<'tcx>) -> Cow<'static, str> {
+        format!("evaluating trait selection obligation `{}`", goal.value.value).into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::type_op_eq<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: CanonicalTypeOpEqGoal<'tcx>) -> String {
-        format!("evaluating `type_op_eq` `{:?}`", goal)
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: CanonicalTypeOpEqGoal<'tcx>) -> Cow<'static, str> {
+        format!("evaluating `type_op_eq` `{:?}`", goal).into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::type_op_subtype<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: CanonicalTypeOpSubtypeGoal<'tcx>) -> String {
-        format!("evaluating `type_op_subtype` `{:?}`", goal)
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: CanonicalTypeOpSubtypeGoal<'tcx>)
+                -> Cow<'static, str> {
+        format!("evaluating `type_op_subtype` `{:?}`", goal).into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::type_op_prove_predicate<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: CanonicalTypeOpProvePredicateGoal<'tcx>) -> String {
-        format!("evaluating `type_op_prove_predicate` `{:?}`", goal)
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, goal: CanonicalTypeOpProvePredicateGoal<'tcx>)
+                -> Cow<'static, str> {
+        format!("evaluating `type_op_prove_predicate` `{:?}`", goal).into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::type_op_normalize_ty<'tcx> {
     fn describe(_tcx: TyCtxt<'_, '_, '_>,
-                goal: CanonicalTypeOpNormalizeGoal<'tcx, Ty<'tcx>>) -> String {
-        format!("normalizing `{:?}`", goal)
+                goal: CanonicalTypeOpNormalizeGoal<'tcx, Ty<'tcx>>) -> Cow<'static, str> {
+        format!("normalizing `{:?}`", goal).into()
     }
 }
 
@@ -142,8 +145,8 @@ impl<'tcx> QueryDescription<'tcx> for queries::type_op_normalize_predicate<'tcx>
     fn describe(
         _tcx: TyCtxt<'_, '_, '_>,
         goal: CanonicalTypeOpNormalizeGoal<'tcx, ty::Predicate<'tcx>>,
-    ) -> String {
-        format!("normalizing `{:?}`", goal)
+    ) -> Cow<'static, str> {
+        format!("normalizing `{:?}`", goal).into()
     }
 }
 
@@ -151,134 +154,141 @@ impl<'tcx> QueryDescription<'tcx> for queries::type_op_normalize_poly_fn_sig<'tc
     fn describe(
         _tcx: TyCtxt<'_, '_, '_>,
         goal: CanonicalTypeOpNormalizeGoal<'tcx, ty::PolyFnSig<'tcx>>,
-    ) -> String {
-        format!("normalizing `{:?}`", goal)
+    ) -> Cow<'static, str> {
+        format!("normalizing `{:?}`", goal).into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::type_op_normalize_fn_sig<'tcx> {
     fn describe(_tcx: TyCtxt<'_, '_, '_>,
-                goal: CanonicalTypeOpNormalizeGoal<'tcx, ty::FnSig<'tcx>>) -> String {
-        format!("normalizing `{:?}`", goal)
+                goal: CanonicalTypeOpNormalizeGoal<'tcx, ty::FnSig<'tcx>>) -> Cow<'static, str> {
+        format!("normalizing `{:?}`", goal).into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::is_copy_raw<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> String {
-        format!("computing whether `{}` is `Copy`", env.value)
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
+                -> Cow<'static, str> {
+        format!("computing whether `{}` is `Copy`", env.value).into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::is_sized_raw<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> String {
-        format!("computing whether `{}` is `Sized`", env.value)
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
+                -> Cow<'static, str> {
+        format!("computing whether `{}` is `Sized`", env.value).into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::is_freeze_raw<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> String {
-        format!("computing whether `{}` is freeze", env.value)
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
+                -> Cow<'static, str> {
+        format!("computing whether `{}` is freeze", env.value).into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::needs_drop_raw<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> String {
-        format!("computing whether `{}` needs drop", env.value)
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
+                -> Cow<'static, str> {
+        format!("computing whether `{}` needs drop", env.value).into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::layout_raw<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> String {
-        format!("computing layout of `{}`", env.value)
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>)
+                -> Cow<'static, str> {
+        format!("computing layout of `{}`", env.value).into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::super_predicates_of<'tcx> {
-    fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> String {
+    fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> {
         format!("computing the supertraits of `{}`",
-                tcx.item_path_str(def_id))
+                tcx.item_path_str(def_id)).into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::erase_regions_ty<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, ty: Ty<'tcx>) -> String {
-        format!("erasing regions from `{:?}`", ty)
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, ty: Ty<'tcx>) -> Cow<'static, str> {
+        format!("erasing regions from `{:?}`", ty).into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::type_param_predicates<'tcx> {
-    fn describe(tcx: TyCtxt<'_, '_, '_>, (_, def_id): (DefId, DefId)) -> String {
+    fn describe(tcx: TyCtxt<'_, '_, '_>, (_, def_id): (DefId, DefId)) -> Cow<'static, str> {
         let id = tcx.hir.as_local_node_id(def_id).unwrap();
         format!("computing the bounds for type parameter `{}`",
-                tcx.hir.ty_param_name(id))
+                tcx.hir.ty_param_name(id)).into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::coherent_trait<'tcx> {
-    fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> String {
+    fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> {
         format!("coherence checking all impls of trait `{}`",
-                tcx.item_path_str(def_id))
+                tcx.item_path_str(def_id)).into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::upstream_monomorphizations<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, k: CrateNum) -> String {
-        format!("collecting available upstream monomorphizations `{:?}`", k)
+    fn describe(_: TyCtxt<'_, '_, '_>, k: CrateNum) -> Cow<'static, str> {
+        format!("collecting available upstream monomorphizations `{:?}`", k).into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::crate_inherent_impls<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, k: CrateNum) -> String {
-        format!("all inherent impls defined in crate `{:?}`", k)
+    fn describe(_: TyCtxt<'_, '_, '_>, k: CrateNum) -> Cow<'static, str> {
+        format!("all inherent impls defined in crate `{:?}`", k).into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::crate_inherent_impls_overlap_check<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "check for overlap between inherent impls defined in this crate".to_string()
+    fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "check for overlap between inherent impls defined in this crate".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::crate_variances<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "computing the variances for items in this crate".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "computing the variances for items in this crate".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::inferred_outlives_crate<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "computing the inferred outlives predicates for items in this crate".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "computing the inferred outlives predicates for items in this crate".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::mir_shims<'tcx> {
-    fn describe(tcx: TyCtxt<'_, '_, '_>, def: ty::InstanceDef<'tcx>) -> String {
+    fn describe(tcx: TyCtxt<'_, '_, '_>, def: ty::InstanceDef<'tcx>) -> Cow<'static, str> {
         format!("generating MIR shim for `{}`",
-                tcx.item_path_str(def.def_id()))
+                tcx.item_path_str(def.def_id())).into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::privacy_access_levels<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "privacy access levels".to_string()
+    fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "privacy access levels".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::typeck_item_bodies<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "type-checking all item bodies".to_string()
+    fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "type-checking all item bodies".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::reachable_set<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "reachability".to_string()
+    fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "reachability".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::const_eval<'tcx> {
-    fn describe(tcx: TyCtxt<'_, '_, '_>, key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>) -> String {
-        format!("const-evaluating `{}`", tcx.item_path_str(key.value.instance.def.def_id()))
+    fn describe(tcx: TyCtxt<'_, '_, '_>, key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
+        -> Cow<'static, str>
+    {
+        format!("const-evaluating `{}`", tcx.item_path_str(key.value.instance.def.def_id())).into()
     }
 
     #[inline]
@@ -295,14 +305,14 @@ fn try_load_from_disk<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::mir_keys<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "getting a list of all mir_keys".to_string()
+    fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "getting a list of all mir_keys".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::symbol_name<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, instance: ty::Instance<'tcx>) -> String {
-        format!("computing the symbol for `{}`", instance)
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, instance: ty::Instance<'tcx>) -> Cow<'static, str> {
+        format!("computing the symbol for `{}`", instance).into()
     }
 
     #[inline]
@@ -319,64 +329,64 @@ fn try_load_from_disk<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::describe_def<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> String {
+    fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> Cow<'static, str> {
         bug!("describe_def")
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::def_span<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> String {
+    fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> Cow<'static, str> {
         bug!("def_span")
     }
 }
 
 
 impl<'tcx> QueryDescription<'tcx> for queries::lookup_stability<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> String {
+    fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> Cow<'static, str> {
         bug!("stability")
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::lookup_deprecation_entry<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> String {
+    fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> Cow<'static, str> {
         bug!("deprecation")
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::item_attrs<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> String {
+    fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> Cow<'static, str> {
         bug!("item_attrs")
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::is_reachable_non_generic<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> String {
+    fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> Cow<'static, str> {
         bug!("is_reachable_non_generic")
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::fn_arg_names<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> String {
+    fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> Cow<'static, str> {
         bug!("fn_arg_names")
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::impl_parent<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> String {
+    fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> Cow<'static, str> {
         bug!("impl_parent")
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::trait_of_item<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> String {
+    fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> Cow<'static, str> {
         bug!("trait_of_item")
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::const_is_rvalue_promotable_to_static<'tcx> {
-    fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> String {
+    fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> {
         format!("const checking if rvalue is promotable to static `{}`",
-            tcx.item_path_str(def_id))
+            tcx.item_path_str(def_id)).into()
     }
 
     #[inline]
@@ -386,30 +396,31 @@ fn cache_on_disk(_: Self::Key) -> bool {
 
     #[inline]
     fn try_load_from_disk<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                          id: SerializedDepNodeIndex)
-                          -> Option<Self::Value> {
+                              id: SerializedDepNodeIndex)
+                              -> Option<Self::Value> {
         tcx.queries.on_disk_cache.try_load_query_result(tcx, id)
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::rvalue_promotable_map<'tcx> {
-    fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> String {
+    fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> {
         format!("checking which parts of `{}` are promotable to static",
-                tcx.item_path_str(def_id))
+                tcx.item_path_str(def_id)).into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::is_mir_available<'tcx> {
-    fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> String {
+    fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> {
         format!("checking if item is mir available: `{}`",
-            tcx.item_path_str(def_id))
+                tcx.item_path_str(def_id)).into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::codegen_fulfill_obligation<'tcx> {
     fn describe(tcx: TyCtxt<'_, '_, '_>,
-                key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)) -> String {
+                key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)) -> Cow<'static, str> {
         format!("checking if `{}` fulfills its obligations", tcx.item_path_str(key.1.def_id()))
+            .into()
     }
 
     #[inline]
@@ -426,320 +437,320 @@ fn try_load_from_disk<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::trait_impls_of<'tcx> {
-    fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> String {
-        format!("trait impls of `{}`", tcx.item_path_str(def_id))
+    fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> {
+        format!("trait impls of `{}`", tcx.item_path_str(def_id)).into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::is_object_safe<'tcx> {
-    fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> String {
-        format!("determine object safety of trait `{}`", tcx.item_path_str(def_id))
+    fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> {
+        format!("determine object safety of trait `{}`", tcx.item_path_str(def_id)).into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::is_const_fn_raw<'tcx> {
-    fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> String {
-        format!("checking if item is const fn: `{}`", tcx.item_path_str(def_id))
+    fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> {
+        format!("checking if item is const fn: `{}`", tcx.item_path_str(def_id)).into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::dylib_dependency_formats<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "dylib dependency formats of crate".to_string()
+    fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "dylib dependency formats of crate".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::is_panic_runtime<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "checking if the crate is_panic_runtime".to_string()
+    fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "checking if the crate is_panic_runtime".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::is_compiler_builtins<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "checking if the crate is_compiler_builtins".to_string()
+    fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "checking if the crate is_compiler_builtins".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::has_global_allocator<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "checking if the crate has_global_allocator".to_string()
+    fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "checking if the crate has_global_allocator".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::has_panic_handler<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "checking if the crate has_panic_handler".to_string()
+    fn describe(_: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "checking if the crate has_panic_handler".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::extern_crate<'tcx> {
-    fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> String {
-        "getting crate's ExternCrateData".to_string()
+    fn describe(_: TyCtxt<'_, '_, '_>, _: DefId) -> Cow<'static, str> {
+        "getting crate's ExternCrateData".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::lint_levels<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "computing the lint levels for items in this crate".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "computing the lint levels for items in this crate".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::specializes<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: (DefId, DefId)) -> String {
-        "computing whether impls specialize one another".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: (DefId, DefId)) -> Cow<'static, str> {
+        "computing whether impls specialize one another".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::in_scope_traits_map<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: DefIndex) -> String {
-        "traits in scope at a block".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: DefIndex) -> Cow<'static, str> {
+        "traits in scope at a block".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::is_no_builtins<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "test whether a crate has #![no_builtins]".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "test whether a crate has #![no_builtins]".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::panic_strategy<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "query a crate's configured panic strategy".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "query a crate's configured panic strategy".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::is_profiler_runtime<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "query a crate is #![profiler_runtime]".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "query a crate is #![profiler_runtime]".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::is_sanitizer_runtime<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "query a crate is #![sanitizer_runtime]".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "query a crate is #![sanitizer_runtime]".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::reachable_non_generics<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "looking up the exported symbols of a crate".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "looking up the exported symbols of a crate".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::native_libraries<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "looking up the native libraries of a linked crate".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "looking up the native libraries of a linked crate".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::foreign_modules<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "looking up the foreign modules of a linked crate".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "looking up the foreign modules of a linked crate".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::plugin_registrar_fn<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "looking up the plugin registrar for a crate".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "looking up the plugin registrar for a crate".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::derive_registrar_fn<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "looking up the derive registrar for a crate".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "looking up the derive registrar for a crate".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::crate_disambiguator<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "looking up the disambiguator a crate".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "looking up the disambiguator a crate".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::crate_hash<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "looking up the hash a crate".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "looking up the hash a crate".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::original_crate_name<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "looking up the original name a crate".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "looking up the original name a crate".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::extra_filename<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "looking up the extra filename for a crate".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "looking up the extra filename for a crate".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::implementations_of_trait<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: (CrateNum, DefId)) -> String {
-        "looking up implementations of a trait in a crate".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: (CrateNum, DefId)) -> Cow<'static, str> {
+        "looking up implementations of a trait in a crate".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::all_trait_implementations<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "looking up all (?) trait implementations".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "looking up all (?) trait implementations".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::link_args<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "looking up link arguments for a crate".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "looking up link arguments for a crate".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::resolve_lifetimes<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "resolving lifetimes".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "resolving lifetimes".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::named_region_map<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: DefIndex) -> String {
-        "looking up a named region".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: DefIndex) -> Cow<'static, str> {
+        "looking up a named region".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::is_late_bound_map<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: DefIndex) -> String {
-        "testing if a region is late bound".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: DefIndex) -> Cow<'static, str> {
+        "testing if a region is late bound".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::object_lifetime_defaults_map<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: DefIndex) -> String {
-        "looking up lifetime defaults for a region".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: DefIndex) -> Cow<'static, str> {
+        "looking up lifetime defaults for a region".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::dep_kind<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "fetching what a dependency looks like".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "fetching what a dependency looks like".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::crate_name<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "fetching what a crate is named".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "fetching what a crate is named".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::get_lib_features<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        format!("calculating the lib features map")
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "calculating the lib features map".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::defined_lib_features<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        format!("calculating the lib features defined in a crate")
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "calculating the lib features defined in a crate".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::get_lang_items<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "calculating the lang items map".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "calculating the lang items map".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::defined_lang_items<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "calculating the lang items defined in a crate".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "calculating the lang items defined in a crate".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::missing_lang_items<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "calculating the missing lang items in a crate".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "calculating the missing lang items in a crate".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::visible_parent_map<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "calculating the visible parent map".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "calculating the visible parent map".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::missing_extern_crate_item<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "seeing if we're missing an `extern crate` item for this crate".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "seeing if we're missing an `extern crate` item for this crate".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::used_crate_source<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "looking at the source for a crate".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "looking at the source for a crate".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::postorder_cnums<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "generating a postorder list of CrateNums".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "generating a postorder list of CrateNums".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::maybe_unused_extern_crates<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "looking up all possibly unused extern crates".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "looking up all possibly unused extern crates".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::stability_index<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "calculating the stability index for the local crate".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "calculating the stability index for the local crate".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::all_traits<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "fetching all foreign and local traits".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "fetching all foreign and local traits".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::all_crate_nums<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "fetching all foreign CrateNum instances".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "fetching all foreign CrateNum instances".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::exported_symbols<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "exported_symbols".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "exported_symbols".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::collect_and_partition_mono_items<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "collect_and_partition_mono_items".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "collect_and_partition_mono_items".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::codegen_unit<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: InternedString) -> String {
-        "codegen_unit".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: InternedString) -> Cow<'static, str> {
+        "codegen_unit".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::output_filenames<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "output_filenames".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "output_filenames".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::vtable_methods<'tcx> {
-    fn describe(tcx: TyCtxt<'_, '_, '_>, key: ty::PolyTraitRef<'tcx> ) -> String {
-        format!("finding all methods for trait {}", tcx.item_path_str(key.def_id()))
+    fn describe(tcx: TyCtxt<'_, '_, '_>, key: ty::PolyTraitRef<'tcx> ) -> Cow<'static, str> {
+        format!("finding all methods for trait {}", tcx.item_path_str(key.def_id())).into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::features_query<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "looking up enabled feature gates".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "looking up enabled feature gates".into()
     }
 }
 
@@ -776,20 +787,20 @@ fn try_load_from_disk<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::substitute_normalize_and_test_predicates<'tcx> {
-    fn describe(tcx: TyCtxt<'_, '_, '_>, key: (DefId, &'tcx Substs<'tcx>)) -> String {
-        format!("testing substituted normalized predicates:`{}`", tcx.item_path_str(key.0))
+    fn describe(tcx: TyCtxt<'_, '_, '_>, key: (DefId, &'tcx Substs<'tcx>)) -> Cow<'static, str> {
+        format!("testing substituted normalized predicates:`{}`", tcx.item_path_str(key.0)).into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::target_features_whitelist<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "looking up the whitelist of target features".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "looking up the whitelist of target features".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::instance_def_size_estimate<'tcx> {
-    fn describe(tcx: TyCtxt<'_, '_, '_>, def: ty::InstanceDef<'tcx>) -> String {
-        format!("estimating size for `{}`", tcx.item_path_str(def.def_id()))
+    fn describe(tcx: TyCtxt<'_, '_, '_>, def: ty::InstanceDef<'tcx>) -> Cow<'static, str> {
+        format!("estimating size for `{}`", tcx.item_path_str(def.def_id())).into()
     }
 }
 
@@ -809,26 +820,26 @@ fn try_load_from_disk<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::program_clauses_for<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: DefId) -> String {
-        "generating chalk-style clauses".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: DefId) -> Cow<'static, str> {
+        "generating chalk-style clauses".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::program_clauses_for_env<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: ty::ParamEnv<'tcx>) -> String {
-        "generating chalk-style clauses for param env".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: ty::ParamEnv<'tcx>) -> Cow<'static, str> {
+        "generating chalk-style clauses for param env".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::wasm_import_module_map<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "wasm import module map".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "wasm import module map".into()
     }
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::dllimport_foreign_items<'tcx> {
-    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> String {
-        "wasm import module map".to_string()
+    fn describe(_tcx: TyCtxt<'_, '_, '_>, _: CrateNum) -> Cow<'static, str> {
+        "wasm import module map".into()
     }
 }
 
index d07891fca12aea5144fbe378051805c345a2eb43..d588bc8c0cb5ca6992b57884fbad14e5ee5e81ec 100644 (file)
@@ -123,9 +123,11 @@ fn find_cycle_in_stack<'lcx>(
         let mut cycle = Vec::new();
 
         while let Some(job) = current_job {
-            cycle.insert(0, job.info.clone());
+            cycle.push(job.info.clone());
 
             if ptr::eq(&*job, self) {
+                cycle.reverse();
+
                 // This is the end of the cycle
                 // The span entry we included was for the usage
                 // of the cycle itself, and not part of the cycle
@@ -324,16 +326,16 @@ fn connected_to_root<'tcx>(
     query: Lrc<QueryJob<'tcx>>,
     visited: &mut FxHashSet<*const QueryJob<'tcx>>
 ) -> bool {
-    // We already visited this or we're deliberately ignoring it
-    if visited.contains(&query.as_ptr()) {
-        return false;
-    }
-
     // This query is connected to the root (it has no query parent), return true
     if query.parent.is_none() {
         return true;
     }
 
+    // We already visited this or we're deliberately ignoring it
+    if visited.contains(&query.as_ptr()) {
+        return false;
+    }
+
     visited.insert(query.as_ptr());
 
     let mut connected = false;
@@ -368,13 +370,11 @@ fn remove_cycle<'tcx>(
         // Reverse the stack so earlier entries require later entries
         stack.reverse();
 
-        // Extract the spans and queries into separate arrays
-        let mut spans: Vec<_> = stack.iter().map(|e| e.0).collect();
-        let queries = stack.into_iter().map(|e| e.1);
+        // The stack is a vector of pairs of spans and queries
+        let (mut spans, queries): (Vec<_>, Vec<_>) = stack.into_iter().unzip();
 
         // Shift the spans so that queries are matched with the span for their waitee
-        let last = spans.pop().unwrap();
-        spans.insert(0, last);
+        spans.rotate_right(1);
 
         // Zip them back together
         let mut stack: Vec<_> = spans.into_iter().zip(queries).collect();
@@ -388,7 +388,7 @@ fn remove_cycle<'tcx>(
 
         // Find the queries in the cycle which are
         // connected to queries outside the cycle
-        let entry_points: Vec<Lrc<QueryJob<'tcx>>> = stack.iter().filter_map(|query| {
+        let entry_points = stack.iter().filter_map(|query| {
             // Mark all the other queries in the cycle as already visited
             let mut visited = FxHashSet::from_iter(stack.iter().filter_map(|q| {
                 if q.1.as_ptr() != query.1.as_ptr() {
@@ -403,21 +403,21 @@ fn remove_cycle<'tcx>(
             } else {
                 None
             }
-        }).collect();
+        });
 
         // Deterministically pick an entry point
         // FIXME: Sort this instead
         let mut hcx = tcx.create_stable_hashing_context();
-        let entry_point = entry_points.iter().min_by_key(|q| {
+        let entry_point = entry_points.min_by_key(|q| {
             let mut stable_hasher = StableHasher::<u64>::new();
             q.info.query.hash_stable(&mut hcx, &mut stable_hasher);
             stable_hasher.finish()
         }).unwrap().as_ptr();
 
-        // Shift the stack until our entry point is first
-        while stack[0].1.as_ptr() != entry_point {
-            let last = stack.pop().unwrap();
-            stack.insert(0, last);
+        // Shift the stack so that our entry point is first
+        let entry_point_pos = stack.iter().position(|(_, query)| query.as_ptr() == entry_point);
+        if let Some(pos) = entry_point_pos {
+            stack.rotate_right(pos);
         }
 
         // Create the cycle error
index 44c9c55b8a4eb0880c20ad81ed084890798c459a..7f5bc35f91f9bbc4a60c14af289903767b664748 100644 (file)
@@ -56,6 +56,7 @@
 use rustc_data_structures::sync::Lrc;
 use rustc_target::spec::PanicStrategy;
 
+use std::borrow::Cow;
 use std::ops::Deref;
 use std::sync::Arc;
 use syntax_pos::{Span, DUMMY_SP};
index bb877864632237effd2ddd6921e7d8c02a99313c..ce580c7803355ea8e5de3b3baabd1ad4351572bf 100644 (file)
@@ -254,23 +254,19 @@ pub fn serialize<'a, 'tcx, E>(&self,
             })?;
 
             // Encode diagnostics
-            let diagnostics_index = {
-                let mut diagnostics_index = EncodedDiagnosticsIndex::new();
-
-                for (dep_node_index, diagnostics) in self.current_diagnostics
-                                                        .borrow()
-                                                        .iter() {
-                    let pos = AbsoluteBytePos::new(encoder.position());
-                    // Let's make sure we get the expected type here:
-                    let diagnostics: &EncodedDiagnostics = diagnostics;
-                    let dep_node_index =
-                        SerializedDepNodeIndex::new(dep_node_index.index());
-                    encoder.encode_tagged(dep_node_index, diagnostics)?;
-                    diagnostics_index.push((dep_node_index, pos));
-                }
-
-                diagnostics_index
-            };
+            let diagnostics_index: EncodedDiagnosticsIndex = self.current_diagnostics.borrow()
+                .iter()
+                .map(|(dep_node_index, diagnostics)|
+            {
+                let pos = AbsoluteBytePos::new(encoder.position());
+                // Let's make sure we get the expected type here:
+                let diagnostics: &EncodedDiagnostics = diagnostics;
+                let dep_node_index = SerializedDepNodeIndex::new(dep_node_index.index());
+                encoder.encode_tagged(dep_node_index, diagnostics)?;
+
+                Ok((dep_node_index, pos))
+            })
+            .collect::<Result<_, _>>()?;
 
             let interpret_alloc_index = {
                 let mut interpret_alloc_index = Vec::new();
@@ -282,6 +278,7 @@ pub fn serialize<'a, 'tcx, E>(&self,
                         // otherwise, abort
                         break;
                     }
+                    interpret_alloc_index.reserve(new_n);
                     for idx in n..new_n {
                         let id = encoder.interpret_allocs_inverse[idx];
                         let pos = encoder.position() as u32;
@@ -441,16 +438,15 @@ fn compute_cnum_map(tcx: TyCtxt<'_, '_, '_>,
         tcx.dep_graph.with_ignore(|| {
             let current_cnums = tcx.all_crate_nums(LOCAL_CRATE).iter().map(|&cnum| {
                 let crate_name = tcx.original_crate_name(cnum)
-                                    .as_str()
                                     .to_string();
                 let crate_disambiguator = tcx.crate_disambiguator(cnum);
                 ((crate_name, crate_disambiguator), cnum)
             }).collect::<FxHashMap<_,_>>();
 
             let map_size = prev_cnums.iter()
-                                    .map(|&(cnum, ..)| cnum)
-                                    .max()
-                                    .unwrap_or(0) + 1;
+                                     .map(|&(cnum, ..)| cnum)
+                                     .max()
+                                     .unwrap_or(0) + 1;
             let mut map = IndexVec::new();
             map.resize(map_size as usize, None);
 
@@ -465,7 +461,6 @@ fn compute_cnum_map(tcx: TyCtxt<'_, '_, '_>,
     }
 }
 
-
 //- DECODING -------------------------------------------------------------------
 
 /// A decoder that can read the incr. comp. cache. It is similar to the one
@@ -494,7 +489,7 @@ fn file_index_to_file(&self, index: SourceFileIndex) -> Lrc<SourceFile> {
         file_index_to_file.borrow_mut().entry(index).or_insert_with(|| {
             let stable_id = file_index_to_stable_id[&index];
             source_map.source_file_by_stable_id(stable_id)
-                   .expect("Failed to lookup SourceFile in new context.")
+                .expect("Failed to lookup SourceFile in new context.")
         }).clone()
     }
 }
@@ -761,7 +756,7 @@ fn specialized_decode(&mut self) -> Result<mir::ClearCrossCrate<T>, Self::Error>
 
 struct CacheEncoder<'enc, 'a, 'tcx, E>
     where E: 'enc + ty_codec::TyEncoder,
-          'tcx: 'a,
+             'tcx: 'a,
 {
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     encoder: &'enc mut E,
@@ -839,9 +834,7 @@ fn specialized_encode(&mut self, span: &Span) -> Result<(), Self::Error> {
         let (file_lo, line_lo, col_lo) = match self.source_map
                                                    .byte_pos_to_line_and_col(span_data.lo) {
             Some(pos) => pos,
-            None => {
-                return TAG_INVALID_SPAN.encode(self);
-            }
+            None => return TAG_INVALID_SPAN.encode(self)
         };
 
         if !file_lo.contains(span_data.hi) {
index fbd3a8f69bc45f36b34df95903e19b3723748ae4..39a59cf090ea80b5b99363c616ada5dc16d4a588 100644 (file)
@@ -449,14 +449,14 @@ fn load_from_disk_and_cache_in_memory<Q: QueryDescription<'gcx>>(
             let prev_dep_node_index =
                 self.dep_graph.prev_dep_node_index_of(dep_node);
             let result = Q::try_load_from_disk(self.global_tcx(),
-                                                    prev_dep_node_index);
+                                               prev_dep_node_index);
 
             // We always expect to find a cached result for things that
             // can be forced from DepNode.
             debug_assert!(!dep_node.kind.can_reconstruct_query_key() ||
-                            result.is_some(),
-                            "Missing on-disk cache entry for {:?}",
-                            dep_node);
+                          result.is_some(),
+                          "Missing on-disk cache entry for {:?}",
+                          dep_node);
             result
         } else {
             // Some things are never cached on disk.
@@ -491,7 +491,7 @@ fn load_from_disk_and_cache_in_memory<Q: QueryDescription<'gcx>>(
             assert!(Some(self.dep_graph.fingerprint_of(dep_node_index)) ==
                     self.dep_graph.prev_fingerprint_of(dep_node),
                     "Fingerprint for green query instance not loaded \
-                        from cache: {:?}", dep_node);
+                     from cache: {:?}", dep_node);
 
             debug!("BEGIN verify_ich({:?})", dep_node);
             let mut hcx = self.create_stable_hashing_context();
@@ -530,8 +530,8 @@ fn force_query_with_job<Q: QueryDescription<'gcx>>(
         //    (see for example #48923)
         assert!(!self.dep_graph.dep_node_exists(&dep_node),
                 "Forcing query with already existing DepNode.\n\
-                    - query-key: {:?}\n\
-                    - dep-node: {:?}",
+                 - query-key: {:?}\n\
+                 - dep-node: {:?}",
                 key, dep_node);
 
         profq_msg!(self, ProfileQueriesMsg::ProviderBegin);
@@ -709,14 +709,19 @@ pub fn collect_active_jobs(&self) -> Vec<Lrc<QueryJob<$tcx>>> {
 
                 // We use try_lock here since we are only called from the
                 // deadlock handler, and this shouldn't be locked
-                $(for v in self.$name.try_lock().unwrap().active.values() {
-                    match *v {
-                        QueryResult::Started(ref job) => jobs.push(job.clone()),
-                        _ => (),
-                    }
-                })*
-
-                return jobs;
+                $(
+                    jobs.extend(
+                        self.$name.try_lock().unwrap().active.values().filter_map(|v|
+                            if let QueryResult::Started(ref job) = *v {
+                                Some(job.clone())
+                            } else {
+                                None
+                            }
+                        )
+                    );
+                )*
+
+                jobs
             }
         }
 
@@ -733,14 +738,14 @@ pub fn name(&self) -> &'static str {
                 }
             }
 
-            pub fn describe(&self, tcx: TyCtxt<'_, '_, '_>) -> String {
+            pub fn describe(&self, tcx: TyCtxt<'_, '_, '_>) -> Cow<'static, str> {
                 let (r, name) = match *self {
                     $(Query::$name(key) => {
                         (queries::$name::describe(tcx, key), stringify!($name))
                     })*
                 };
                 if tcx.sess.verbose() {
-                    format!("{} [{}]", r, name)
+                    format!("{} [{}]", r, name).into()
                 } else {
                     r
                 }
@@ -753,9 +758,8 @@ pub fn default_span(&self, tcx: TyCtxt<'_, $tcx, '_>, span: Span) -> Span {
                 }
                 // The def_span query is used to calculate default_span,
                 // so exit to avoid infinite recursion
-                match *self {
-                    Query::def_span(..) => return span,
-                    _ => ()
+                if let Query::def_span(..) = *self {
+                    return span
                 }
                 match *self {
                     $(Query::$name(key) => key.default_span(tcx),)*
@@ -1028,13 +1032,10 @@ macro_rules! force {
                     )
                 );
 
-                match tcx.force_query::<::ty::query::queries::$query<'_>>(
+                if let Err(e) = tcx.force_query::<::ty::query::queries::$query<'_>>(
                     $key, DUMMY_SP, *dep_node
                 ) {
-                    Ok(_) => {},
-                    Err(e) => {
-                        tcx.report_cycle(e).emit();
-                    }
+                    tcx.report_cycle(e).emit();
                 }
             }
         }
index 547f7cecc4e060c404ab65ee49b6a5b23722790d..082c1bd5fea441be7f8d46f01d92b1dbb2f109ee 100644 (file)
@@ -274,9 +274,10 @@ fn relate<'a, 'gcx, R>(relation: &mut R,
         if a.len() != b.len() {
             Err(TypeError::ProjectionBoundsLength(expected_found(relation, &a.len(), &b.len())))
         } else {
-            a.iter().zip(b)
-                .map(|(a, b)| relation.relate(a, b))
-                .collect()
+            a.iter()
+             .zip(b)
+             .map(|(a, b)| relation.relate(a, b))
+             .collect()
         }
     }
 }
@@ -331,7 +332,7 @@ fn relate<'a, 'gcx, R>(relation: &mut R,
                            -> RelateResult<'tcx, GeneratorWitness<'tcx>>
         where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a
     {
-        assert!(a.0.len() == b.0.len());
+        assert_eq!(a.0.len(), b.0.len());
         let tcx = relation.tcx();
         let types = tcx.mk_type_list(a.0.iter().zip(b.0).map(|(a, b)| relation.relate(a, b)))?;
         Ok(GeneratorWitness(types))
@@ -478,27 +479,24 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
                     ConstValue::Unevaluated(def_id, substs) => {
                         // FIXME(eddyb) get the right param_env.
                         let param_env = ty::ParamEnv::empty();
-                        match tcx.lift_to_global(&substs) {
-                            Some(substs) => {
-                                let instance = ty::Instance::resolve(
-                                    tcx.global_tcx(),
-                                    param_env,
-                                    def_id,
-                                    substs,
-                                );
-                                if let Some(instance) = instance {
-                                    let cid = GlobalId {
-                                        instance,
-                                        promoted: None
-                                    };
-                                    if let Some(s) = tcx.const_eval(param_env.and(cid))
-                                                        .ok()
-                                                        .map(|c| c.unwrap_usize(tcx)) {
-                                        return Ok(s)
-                                    }
+                        if let Some(substs) = tcx.lift_to_global(&substs) {
+                            let instance = ty::Instance::resolve(
+                                tcx.global_tcx(),
+                                param_env,
+                                def_id,
+                                substs,
+                            );
+                            if let Some(instance) = instance {
+                                let cid = GlobalId {
+                                    instance,
+                                    promoted: None
+                                };
+                                if let Some(s) = tcx.const_eval(param_env.and(cid))
+                                                    .ok()
+                                                    .map(|c| c.unwrap_usize(tcx)) {
+                                    return Ok(s)
                                 }
-                            },
-                            None => {}
+                            }
                         }
                         tcx.sess.delay_span_bug(tcx.def_span(def_id),
                             "array length could not be evaluated");
index aab268c07c4fbf36473610facf7a79aff6daf3f8..83a9491cf4673c57cc6629775a8d9c0c3a6d9b0c 100644 (file)
@@ -386,12 +386,12 @@ impl<'a, 'tcx> Lift<'tcx> for ty::GenSig<'a> {
     type Lifted = ty::GenSig<'tcx>;
     fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
         tcx.lift(&(self.yield_ty, self.return_ty))
-            .map(|(yield_ty, return_ty)| {
-                ty::GenSig {
-                    yield_ty,
-                    return_ty,
-                }
-            })
+           .map(|(yield_ty, return_ty)| {
+               ty::GenSig {
+                   yield_ty,
+                   return_ty,
+               }
+           })
     }
 }
 
@@ -452,7 +452,6 @@ fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lif
             CyclicTy(t) => return tcx.lift(&t).map(|t| CyclicTy(t)),
             ProjectionMismatched(x) => ProjectionMismatched(x),
             ProjectionBoundsLength(x) => ProjectionBoundsLength(x),
-
             Sorts(ref x) => return tcx.lift(x).map(Sorts),
             OldStyleLUB(ref x) => return tcx.lift(x).map(OldStyleLUB),
             ExistentialMismatch(ref x) => return tcx.lift(x).map(ExistentialMismatch)
@@ -817,22 +816,16 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
         use ty::InstanceDef::*;
         self.substs.visit_with(visitor) ||
         match self.def {
-            Item(did) => did.visit_with(visitor),
-            Intrinsic(did) => did.visit_with(visitor),
-            FnPtrShim(did, ty) => {
-                did.visit_with(visitor) ||
-                ty.visit_with(visitor)
+            Item(did) | Intrinsic(did) | Virtual(did, _) => {
+                did.visit_with(visitor)
             },
-            Virtual(did, _) => did.visit_with(visitor),
-            ClosureOnceShim { call_once } => call_once.visit_with(visitor),
-            DropGlue(did, ty) => {
-                did.visit_with(visitor) ||
-                ty.visit_with(visitor)
+            FnPtrShim(did, ty) | CloneShim(did, ty) => {
+                did.visit_with(visitor) || ty.visit_with(visitor)
             },
-            CloneShim(did, ty) => {
-                did.visit_with(visitor) ||
-                ty.visit_with(visitor)
+            DropGlue(did, ty) => {
+                did.visit_with(visitor) || ty.visit_with(visitor)
             },
+            ClosureOnceShim { call_once } => call_once.visit_with(visitor),
         }
     }
 }
@@ -876,6 +869,9 @@ fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F)
             ty::GeneratorWitness(types) => ty::GeneratorWitness(types.fold_with(folder)),
             ty::Closure(did, substs) => ty::Closure(did, substs.fold_with(folder)),
             ty::Projection(ref data) => ty::Projection(data.fold_with(folder)),
+            ty::UnnormalizedProjection(ref data) => {
+                ty::UnnormalizedProjection(data.fold_with(folder))
+            }
             ty::Opaque(did, substs) => ty::Opaque(did, substs.fold_with(folder)),
             ty::Bool | ty::Char | ty::Str | ty::Int(_) |
             ty::Uint(_) | ty::Float(_) | ty::Error | ty::Infer(_) |
@@ -910,7 +906,9 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
             }
             ty::GeneratorWitness(ref types) => types.visit_with(visitor),
             ty::Closure(_did, ref substs) => substs.visit_with(visitor),
-            ty::Projection(ref data) => data.visit_with(visitor),
+            ty::Projection(ref data) | ty::UnnormalizedProjection(ref data) => {
+                data.visit_with(visitor)
+            }
             ty::Opaque(_, ref substs) => substs.visit_with(visitor),
             ty::Bool | ty::Char | ty::Str | ty::Int(_) |
             ty::Uint(_) | ty::Float(_) | ty::Error | ty::Infer(_) |
index 6c40dd892391671f8fd7770b83dd5db68c8a37e6..145c122e75d681070cfa2f1616b2c2185dcef61f 100644 (file)
@@ -126,10 +126,25 @@ pub enum TyKind<'tcx> {
     Ref(Region<'tcx>, Ty<'tcx>, hir::Mutability),
 
     /// The anonymous type of a function declaration/definition. Each
-    /// function has a unique type.
+    /// function has a unique type, which is output (for a function
+    /// named `foo` returning an `i32`) as `fn() -> i32 {foo}`.
+    ///
+    /// For example the type of `bar` here:
+    ///
+    /// ```rust
+    /// fn foo() -> i32 { 1 }
+    /// let bar = foo; // bar: fn() -> i32 {foo}
+    /// ```
     FnDef(DefId, &'tcx Substs<'tcx>),
 
     /// A pointer to a function.  Written as `fn() -> i32`.
+    ///
+    /// For example the type of `bar` here:
+    ///
+    /// ```rust
+    /// fn foo() -> i32 { 1 }
+    /// let bar: fn() -> i32 = foo;
+    /// ```
     FnPtr(PolyFnSig<'tcx>),
 
     /// A trait, defined with `trait`.
@@ -157,6 +172,11 @@ pub enum TyKind<'tcx> {
     /// `<T as Trait<..>>::N`.
     Projection(ProjectionTy<'tcx>),
 
+    /// A placeholder type used when we do not have enough information
+    /// to normalize the projection of an associated type to an
+    /// existing concrete type. Currently only used with chalk-engine.
+    UnnormalizedProjection(ProjectionTy<'tcx>),
+
     /// Opaque (`impl Trait`) type found in a return type.
     /// The `DefId` comes either from
     /// * the `impl Trait` ast::Ty node,
@@ -704,7 +724,7 @@ pub fn erase_self_ty(tcx: TyCtxt<'a, 'gcx, 'tcx>,
     /// Object types don't have a self-type specified. Therefore, when
     /// we convert the principal trait-ref into a normal trait-ref,
     /// you must give *some* self-type. A common choice is `mk_err()`
-    /// or some skolemized type.
+    /// or some placeholder type.
     pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, self_ty: Ty<'tcx>)
         -> ty::TraitRef<'tcx>  {
         // otherwise the escaping regions would be captured by the binder
@@ -727,7 +747,7 @@ pub fn def_id(&self) -> DefId {
     /// Object types don't have a self-type specified. Therefore, when
     /// we convert the principal trait-ref into a normal trait-ref,
     /// you must give *some* self-type. A common choice is `mk_err()`
-    /// or some skolemized type.
+    /// or some placeholder type.
     pub fn with_self_ty(&self, tcx: TyCtxt<'_, '_, 'tcx>,
                         self_ty: Ty<'tcx>)
                         -> ty::PolyTraitRef<'tcx>  {
@@ -738,7 +758,7 @@ pub fn with_self_ty(&self, tcx: TyCtxt<'_, '_, 'tcx>,
 /// Binder is a binder for higher-ranked lifetimes. It is part of the
 /// compiler's representation for things like `for<'a> Fn(&'a isize)`
 /// (which would be represented by the type `PolyTraitRef ==
-/// Binder<TraitRef>`). Note that when we skolemize, instantiate,
+/// Binder<TraitRef>`). Note that when we instantiate,
 /// erase, or otherwise "discharge" these bound regions, we change the
 /// type from `Binder<T>` to just `T` (see
 /// e.g. `liberate_late_bound_regions`).
@@ -987,11 +1007,7 @@ pub fn is_self(&self) -> bool {
         // FIXME(#50125): Ignoring `Self` with `idx != 0` might lead to weird behavior elsewhere,
         // but this should only be possible when using `-Z continue-parse-after-error` like
         // `compile-fail/issue-36638.rs`.
-        if self.name == keywords::SelfType.name().as_str() && self.idx == 0 {
-            true
-        } else {
-            false
-        }
+        self.name == keywords::SelfType.name().as_str() && self.idx == 0
     }
 }
 
@@ -1061,10 +1077,10 @@ pub struct DebruijnIndex {
 ///
 /// Unlike Param-s, bound regions are not supposed to exist "in the wild"
 /// outside their binder, e.g. in types passed to type inference, and
-/// should first be substituted (by skolemized regions, free regions,
+/// should first be substituted (by placeholder regions, free regions,
 /// or region variables).
 ///
-/// ## Skolemized and Free Regions
+/// ## Placeholder and Free Regions
 ///
 /// One often wants to work with bound regions without knowing their precise
 /// identity. For example, when checking a function, the lifetime of a borrow
@@ -1072,12 +1088,11 @@ pub struct DebruijnIndex {
 /// it must be ensured that bounds on the region can't be accidentally
 /// assumed without being checked.
 ///
-/// The process of doing that is called "skolemization". The bound regions
-/// are replaced by skolemized markers, which don't satisfy any relation
-/// not explicitly provided.
+/// To do this, we replace the bound regions with placeholder markers,
+/// which don't satisfy any relation not explicitly provided.
 ///
-/// There are 2 kinds of skolemized regions in rustc: `ReFree` and
-/// `ReSkolemized`. When checking an item's body, `ReFree` is supposed
+/// There are 2 kinds of placeholder regions in rustc: `ReFree` and
+/// `RePlaceholder`. When checking an item's body, `ReFree` is supposed
 /// to be used. These also support explicit bounds: both the internally-stored
 /// *scope*, which the region is assumed to outlive, as well as other
 /// relations stored in the `FreeRegionMap`. Note that these relations
@@ -1086,14 +1101,14 @@ pub struct DebruijnIndex {
 ///
 /// When working with higher-ranked types, some region relations aren't
 /// yet known, so you can't just call `resolve_regions_and_report_errors`.
-/// `ReSkolemized` is designed for this purpose. In these contexts,
+/// `RePlaceholder` is designed for this purpose. In these contexts,
 /// there's also the risk that some inference variable laying around will
-/// get unified with your skolemized region: if you want to check whether
+/// get unified with your placeholder region: if you want to check whether
 /// `for<'a> Foo<'_>: 'a`, and you substitute your bound region `'a`
-/// with a skolemized region `'%a`, the variable `'_` would just be
-/// instantiated to the skolemized region `'%a`, which is wrong because
+/// with a placeholder region `'%a`, the variable `'_` would just be
+/// instantiated to the placeholder region `'%a`, which is wrong because
 /// the inference variable is supposed to satisfy the relation
-/// *for every value of the skolemized region*. To ensure that doesn't
+/// *for every value of the placeholder region*. To ensure that doesn't
 /// happen, you can use `leak_check`. This is more clearly explained
 /// by the [rustc guide].
 ///
@@ -1127,9 +1142,9 @@ pub enum RegionKind {
     /// A region variable.  Should not exist after typeck.
     ReVar(RegionVid),
 
-    /// A skolemized region - basically the higher-ranked version of ReFree.
+    /// A placeholder region - basically the higher-ranked version of ReFree.
     /// Should not exist after typeck.
-    ReSkolemized(ty::UniverseIndex, BoundRegion),
+    RePlaceholder(ty::Placeholder),
 
     /// Empty lifetime is for data that is never accessed.
     /// Bottom in the region lattice. We treat ReEmpty somewhat
@@ -1333,7 +1348,7 @@ pub fn has_name(&self) -> bool {
             RegionKind::ReScope(..) => false,
             RegionKind::ReStatic => true,
             RegionKind::ReVar(..) => false,
-            RegionKind::ReSkolemized(_, br) => br.is_named(),
+            RegionKind::RePlaceholder(placeholder) => placeholder.name.is_named(),
             RegionKind::ReEmpty => false,
             RegionKind::ReErased => false,
             RegionKind::ReClosureBound(..) => false,
@@ -1405,7 +1420,7 @@ pub fn type_flags(&self) -> TypeFlags {
                 flags = flags | TypeFlags::HAS_FREE_REGIONS;
                 flags = flags | TypeFlags::HAS_RE_INFER;
             }
-            ty::ReSkolemized(..) => {
+            ty::RePlaceholder(..) => {
                 flags = flags | TypeFlags::HAS_FREE_REGIONS;
                 flags = flags | TypeFlags::HAS_RE_SKOL;
             }
@@ -1598,6 +1613,22 @@ pub fn is_unsafe_ptr(&self) -> bool {
         }
     }
 
+    /// Returns `true` if this type is an `Arc<T>`.
+    pub fn is_arc(&self) -> bool {
+        match self.sty {
+            Adt(def, _) => def.is_arc(),
+            _ => false,
+        }
+    }
+
+    /// Returns `true` if this type is an `Rc<T>`.
+    pub fn is_rc(&self) -> bool {
+        match self.sty {
+            Adt(def, _) => def.is_rc(),
+            _ => false,
+        }
+    }
+
     pub fn is_box(&self) -> bool {
         match self.sty {
             Adt(def, _) => def.is_box(),
@@ -1806,7 +1837,7 @@ pub fn regions(&self) -> Vec<ty::Region<'tcx>> {
             Generator(_, GeneratorSubsts { ref substs }, _) => {
                 substs.regions().collect()
             }
-            Projection(ref data) => {
+            Projection(ref data) | UnnormalizedProjection(ref data) => {
                 data.substs.regions().collect()
             }
             FnDef(..) |
@@ -1886,6 +1917,8 @@ pub fn is_trivially_sized(&self, tcx: TyCtxt<'_, '_, 'tcx>) -> bool {
 
             ty::Projection(_) | ty::Param(_) | ty::Opaque(..) => false,
 
+            ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
+
             ty::Infer(ty::TyVar(_)) => false,
 
             ty::Infer(ty::CanonicalTy(_)) |
@@ -2021,18 +2054,14 @@ pub fn unwrap_bits(
         tcx: TyCtxt<'_, '_, '_>,
         ty: ParamEnvAnd<'tcx, Ty<'tcx>>,
     ) -> u128 {
-        match self.assert_bits(tcx, ty) {
-            Some(val) => val,
-            None => bug!("expected bits of {}, got {:#?}", ty.value, self),
-        }
+        self.assert_bits(tcx, ty).unwrap_or_else(||
+            bug!("expected bits of {}, got {:#?}", ty.value, self))
     }
 
     #[inline]
     pub fn unwrap_usize(&self, tcx: TyCtxt<'_, '_, '_>) -> u64 {
-        match self.assert_usize(tcx) {
-            Some(val) => val,
-            None => bug!("expected constant usize, got {:#?}", self),
-        }
+        self.assert_usize(tcx).unwrap_or_else(||
+            bug!("expected constant usize, got {:#?}", self))
     }
 }
 
index 4b3a70e525ec3d11a9382e9b73fb717a56daf654..c0a42fd5854822a0b49a1d3cb97536f32d136248 100644 (file)
@@ -205,10 +205,9 @@ pub fn extend_to<F>(&self,
     where F: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> Kind<'tcx>
     {
         Substs::for_item(tcx, def_id, |param, substs| {
-            match self.get(param.index as usize) {
-                Some(&kind) => kind,
-                None => mk_kind(param, substs),
-            }
+            self.get(param.index as usize)
+                .cloned()
+                .unwrap_or_else(|| mk_kind(param, substs))
         })
     }
 
@@ -230,6 +229,7 @@ pub fn extend_to<F>(&self,
                       mk_kind: &mut F)
     where F: FnMut(&ty::GenericParamDef, &[Kind<'tcx>]) -> Kind<'tcx>
     {
+        substs.reserve(defs.params.len());
         for param in &defs.params {
             let kind = mk_kind(param, substs);
             assert_eq!(param.index as usize, substs.len());
@@ -361,7 +361,7 @@ impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Substs<'tcx> {}
 
 pub trait Subst<'tcx> : Sized {
     fn subst<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                      substs: &[Kind<'tcx>]) -> Self {
+                       substs: &[Kind<'tcx>]) -> Self {
         self.subst_spanned(tcx, substs, None)
     }
 
@@ -489,7 +489,7 @@ fn ty_for_param(&self, p: ty::ParamTy, source_ty: Ty<'tcx>) -> Ty<'tcx> {
                 span_bug!(
                     span,
                     "Type parameter `{:?}` ({:?}/{}) out of range \
-                         when substituting (root type={:?}) substs={:?}",
+                     when substituting (root type={:?}) substs={:?}",
                     p,
                     source_ty,
                     p.idx,
index 22277128383b503d7039e394462039f6484397f9..af678c3e9924b7d20fca9cfb46225b3a7c8d3f90 100644 (file)
@@ -138,10 +138,8 @@ pub fn for_each_relevant_impl<F: FnMut(DefId)>(self,
                 }
             }
         } else {
-            for v in impls.non_blanket_impls.values() {
-                for &impl_def_id in v {
-                    f(impl_def_id);
-                }
+            for &impl_def_id in impls.non_blanket_impls.values().flatten() {
+                f(impl_def_id);
             }
         }
     }
@@ -173,9 +171,9 @@ pub(super) fn trait_impls_of_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 fast_reject::simplify_type(tcx, impl_self_ty, false)
             {
                 impls.non_blanket_impls
-                    .entry(simplified_self_ty)
-                    .or_default()
-                    .push(impl_def_id);
+                     .entry(simplified_self_ty)
+                     .or_default()
+                     .push(impl_def_id);
             } else {
                 impls.blanket_impls.push(impl_def_id);
             }
index 93fc77359e43ab082160b05a1ebe8675b1827412..dfe42e0c6610904e579161e2cc5e6b2d27c0bcc3 100644 (file)
@@ -119,17 +119,17 @@ fn disr_incr<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, val: Option<Discr<'tc
 impl IntTypeExt for attr::IntType {
     fn to_ty<'a, 'gcx, 'tcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
         match *self {
-            SignedInt(ast::IntTy::I8)      => tcx.types.i8,
-            SignedInt(ast::IntTy::I16)     => tcx.types.i16,
-            SignedInt(ast::IntTy::I32)     => tcx.types.i32,
-            SignedInt(ast::IntTy::I64)     => tcx.types.i64,
+            SignedInt(ast::IntTy::I8)       => tcx.types.i8,
+            SignedInt(ast::IntTy::I16)      => tcx.types.i16,
+            SignedInt(ast::IntTy::I32)      => tcx.types.i32,
+            SignedInt(ast::IntTy::I64)      => tcx.types.i64,
             SignedInt(ast::IntTy::I128)     => tcx.types.i128,
-            SignedInt(ast::IntTy::Isize)   => tcx.types.isize,
+            SignedInt(ast::IntTy::Isize)    => tcx.types.isize,
             UnsignedInt(ast::UintTy::U8)    => tcx.types.u8,
             UnsignedInt(ast::UintTy::U16)   => tcx.types.u16,
             UnsignedInt(ast::UintTy::U32)   => tcx.types.u32,
             UnsignedInt(ast::UintTy::U64)   => tcx.types.u64,
-            UnsignedInt(ast::UintTy::U128)   => tcx.types.u128,
+            UnsignedInt(ast::UintTy::U128)  => tcx.types.u128,
             UnsignedInt(ast::UintTy::Usize) => tcx.types.usize,
         }
     }
@@ -205,11 +205,11 @@ pub fn can_type_implement_copy<'a>(self,
             let mut infringing = Vec::new();
             for variant in &adt.variants {
                 for field in &variant.fields {
-                    let span = tcx.def_span(field.did);
                     let ty = field.ty(tcx, substs);
                     if ty.references_error() {
                         continue;
                     }
+                    let span = tcx.def_span(field.did);
                     let cause = ObligationCause { span, ..ObligationCause::dummy() };
                     let ctx = traits::FulfillmentContext::new();
                     match traits::fully_normalize(&infcx, ctx, cause, self, &ty) {
@@ -257,16 +257,13 @@ pub fn type_id_hash(self, ty: Ty<'tcx>) -> u64 {
 
 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     pub fn has_error_field(self, ty: Ty<'tcx>) -> bool {
-        match ty.sty {
-            ty::Adt(def, substs) => {
-                for field in def.all_fields() {
-                    let field_ty = field.ty(self, substs);
-                    if let Error = field_ty.sty {
-                        return true;
-                    }
+        if let ty::Adt(def, substs) = ty.sty {
+            for field in def.all_fields() {
+                let field_ty = field.ty(self, substs);
+                if let Error = field_ty.sty {
+                    return true;
                 }
             }
-            _ => (),
         }
         false
     }
@@ -421,7 +418,7 @@ pub fn calculate_dtor(
         let ty = self.type_of(adt_did);
         self.for_each_relevant_impl(drop_trait, ty, |impl_did| {
             if let Some(item) = self.associated_items(impl_did).next() {
-                if let Ok(()) = validate(self, impl_did) {
+                if validate(self, impl_did).is_ok() {
                     dtor_did = Some(item.def_id);
                 }
             }
@@ -513,7 +510,9 @@ pub fn destructor_constraints(self, def: &'tcx ty::AdtDef)
                         false
                     }
                 }
-            }).map(|(&item_param, _)| item_param).collect();
+            })
+            .map(|(&item_param, _)| item_param)
+            .collect();
         debug!("destructor_constraint({:?}) = {:?}", def.did, result);
         result
     }
@@ -674,8 +673,8 @@ pub fn needs_drop(&'tcx self,
     pub fn is_representable(&'tcx self,
                             tcx: TyCtxt<'a, 'tcx, 'tcx>,
                             sp: Span)
-                            -> Representability {
-
+                            -> Representability
+    {
         // Iterate until something non-representable is found
         fn fold_repr<It: Iterator<Item=Representability>>(iter: It) -> Representability {
             iter.fold(Representability::Representable, |r1, r2| {
@@ -904,20 +903,17 @@ fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let (param_env, ty) = query.into_parts();
 
     let needs_drop = |ty: Ty<'tcx>| -> bool {
-        match tcx.try_needs_drop_raw(DUMMY_SP, param_env.and(ty)) {
-            Ok(v) => v,
-            Err(mut bug) => {
-                // Cycles should be reported as an error by `check_representable`.
-                //
-                // Consider the type as not needing drop in the meanwhile to
-                // avoid further errors.
-                //
-                // In case we forgot to emit a bug elsewhere, delay our
-                // diagnostic to get emitted as a compiler bug.
-                bug.delay_as_bug();
-                false
-            }
-        }
+        tcx.try_needs_drop_raw(DUMMY_SP, param_env.and(ty)).unwrap_or_else(|mut bug| {
+            // Cycles should be reported as an error by `check_representable`.
+            //
+            // Consider the type as not needing drop in the meanwhile to
+            // avoid further errors.
+            //
+            // In case we forgot to emit a bug elsewhere, delay our
+            // diagnostic to get emitted as a compiler bug.
+            bug.delay_as_bug();
+            false
+        })
     };
 
     assert!(!ty.needs_infer());
@@ -958,6 +954,8 @@ fn needs_drop_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         ty::Dynamic(..) | ty::Projection(..) | ty::Param(_) |
         ty::Opaque(..) | ty::Infer(_) | ty::Error => true,
 
+        ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
+
         // Structural recursion.
         ty::Array(ty, _) | ty::Slice(ty) => needs_drop(ty),
 
index cf87c2d457471b7a72300ef5865c0233b83f9be8..47fbfba87748ba073270d06b01e64e0db7ce2cb2 100644 (file)
@@ -54,7 +54,7 @@ fn next(&mut self) -> Option<Ty<'tcx>> {
         debug!("next(): stack={:?}", self.stack);
         match self.stack.pop() {
             None => {
-                return None;
+                None
             }
             Some(ty) => {
                 self.last_subtree = self.stack.len();
@@ -97,7 +97,7 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
         ty::Ref(_, ty, _) => {
             stack.push(ty);
         }
-        ty::Projection(ref data) => {
+        ty::Projection(ref data) | ty::UnnormalizedProjection(ref data) => {
             stack.extend(data.substs.types().rev());
         }
         ty::Dynamic(ref obj, ..) => {
index 63206a660df411ddb022bc149fee9fd9a49ed947..7af838845cd61ee916677ff32ad37619bd5a3b4f 100644 (file)
@@ -223,8 +223,8 @@ fn compute_const(&mut self, constant: &'tcx ty::Const<'tcx>) {
             let predicate = ty::Predicate::ConstEvaluatable(def_id, substs);
             let cause = self.cause(traits::MiscObligation);
             self.out.push(traits::Obligation::new(cause,
-                                                    self.param_env,
-                                                    predicate));
+                                                  self.param_env,
+                                                  predicate));
         }
     }
 
@@ -289,6 +289,8 @@ fn compute(&mut self, ty0: Ty<'tcx>) -> bool {
                     self.compute_projection(data);
                 }
 
+                ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
+
                 ty::Adt(def, substs) => {
                     // WfNominalType
                     let obligations = self.nominal_obligations(def.did, substs);
@@ -493,6 +495,7 @@ fn from_object_ty(&mut self, ty: Ty<'tcx>,
 
             let explicit_bound = region;
 
+            self.out.reserve(implicit_bounds.len());
             for implicit_bound in implicit_bounds {
                 let cause = self.cause(traits::ObjectTypeBound(ty, explicit_bound));
                 let outlives = ty::Binder::dummy(
@@ -518,7 +521,7 @@ pub fn object_region_bounds<'a, 'gcx, 'tcx>(
 {
     // Since we don't actually *know* the self type for an object,
     // this "open(err)" serves as a kind of dummy standin -- basically
-    // a skolemized type.
+    // a placeholder type.
     let open_ty = tcx.mk_infer(ty::FreshTy(0));
 
     let predicates = existential_predicates.iter().filter_map(|predicate| {
index 10382008e0d43a692e07501268bc91ba3017a3be..33534ab27f1470e125e0ba0afc6de37f4fa804aa 100644 (file)
@@ -18,7 +18,7 @@
 use ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr};
 use ty::{Param, RawPtr, Ref, Never, Tuple};
 use ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Opaque};
-use ty::{Dynamic, Int, Uint, Infer};
+use ty::{UnnormalizedProjection, Dynamic, Int, Uint, Infer};
 use ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, GenericParamCount, GenericParamDefKind};
 use util::nodemap::FxHashSet;
 
@@ -803,7 +803,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                 }
                 ty::ReLateBound(_, br) |
                 ty::ReFree(ty::FreeRegion { bound_region: br, .. }) |
-                ty::ReSkolemized(_, br) => {
+                ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
                     write!(f, "{}", br)
                 }
                 ty::ReScope(scope) if cx.identify_regions => {
@@ -872,8 +872,8 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                     write!(f, "'?{}", c.index())
                 }
 
-                ty::ReSkolemized(universe, ref bound_region) => {
-                    write!(f, "ReSkolemized({:?}, {:?})", universe, bound_region)
+                ty::RePlaceholder(placeholder) => {
+                    write!(f, "RePlaceholder({:?})", placeholder)
                 }
 
                 ty::ReEmpty => write!(f, "ReEmpty"),
@@ -1143,6 +1143,11 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                 }
                 Foreign(def_id) => parameterized(f, subst::Substs::empty(), def_id, &[]),
                 Projection(ref data) => data.print(f, cx),
+                UnnormalizedProjection(ref data) => {
+                    write!(f, "Unnormalized(")?;
+                    data.print(f, cx)?;
+                    write!(f, ")")
+                }
                 Opaque(def_id, substs) => {
                     if cx.is_verbose {
                         return write!(f, "Opaque({:?}, {:?})", def_id, substs);
index 40bfbf1596a478f5ce9b2593e49efa8dd80e34d9..34ee03b895f9f6615522f5a4cf5e54f558950dd6 100644 (file)
@@ -426,7 +426,7 @@ pub fn borrow_of_local_data<'tcx>(cmt: &mc::cmt_<'tcx>) -> bool {
             // These cannot exist in borrowck
             RegionKind::ReVar(..) |
             RegionKind::ReCanonical(..) |
-            RegionKind::ReSkolemized(..) |
+            RegionKind::RePlaceholder(..) |
             RegionKind::ReClosureBound(..) |
             RegionKind::ReErased => span_bug!(borrow_span,
                                               "unexpected region in borrowck {:?}",
index dc400c6ef3eadec1aca7a3306ca1c9e72383b890..1f83c30a3876a215b7a9c8fa584bc334bea2496a 100644 (file)
@@ -368,7 +368,7 @@ fn guarantee_valid(&mut self,
                     ty::ReClosureBound(..) |
                     ty::ReLateBound(..) |
                     ty::ReVar(..) |
-                    ty::ReSkolemized(..) |
+                    ty::RePlaceholder(..) |
                     ty::ReErased => {
                         span_bug!(
                             cmt.span,
index 321257aefdb5aff6d9a80e989cd89531e80de99e..0ef0d284770f555f4577a758e68c5a590a4c3e93 100644 (file)
@@ -38,6 +38,7 @@
 use rustc_mir::util::suggest_ref_mut;
 use rustc::util::nodemap::FxHashSet;
 
+use std::borrow::Cow;
 use std::cell::{Cell, RefCell};
 use std::fmt;
 use std::rc::Rc;
@@ -808,34 +809,34 @@ fn report_bckerr(&self, err: &BckError<'a, 'tcx>) {
 
         match err.code {
             err_mutbl => {
-                let descr = match err.cmt.note {
+                let descr: Cow<'static, str> = match err.cmt.note {
                     mc::NoteClosureEnv(_) | mc::NoteUpvarRef(_) => {
-                        self.cmt_to_string(&err.cmt)
+                        self.cmt_to_cow_str(&err.cmt)
                     }
                     _ => match opt_loan_path_is_field(&err.cmt) {
                         (None, true) => {
                             format!("{} of {} binding",
-                                    self.cmt_to_string(&err.cmt),
-                                    err.cmt.mutbl.to_user_str())
+                                    self.cmt_to_cow_str(&err.cmt),
+                                    err.cmt.mutbl.to_user_str()).into()
 
                         }
                         (None, false) => {
                             format!("{} {}",
                                     err.cmt.mutbl.to_user_str(),
-                                    self.cmt_to_string(&err.cmt))
+                                    self.cmt_to_cow_str(&err.cmt)).into()
 
                         }
                         (Some(lp), true) => {
                             format!("{} `{}` of {} binding",
-                                    self.cmt_to_string(&err.cmt),
+                                    self.cmt_to_cow_str(&err.cmt),
                                     self.loan_path_to_string(&lp),
-                                    err.cmt.mutbl.to_user_str())
+                                    err.cmt.mutbl.to_user_str()).into()
                         }
                         (Some(lp), false) => {
                             format!("{} {} `{}`",
                                     err.cmt.mutbl.to_user_str(),
-                                    self.cmt_to_string(&err.cmt),
-                                    self.loan_path_to_string(&lp))
+                                    self.cmt_to_cow_str(&err.cmt),
+                                    self.loan_path_to_string(&lp)).into()
                         }
                     }
                 };
@@ -1058,11 +1059,11 @@ fn report_bckerr(&self, err: &BckError<'a, 'tcx>) {
             err_borrowed_pointer_too_short(loan_scope, ptr_scope) => {
                 let descr = self.cmt_to_path_or_string(err.cmt);
                 let mut db = self.lifetime_too_short_for_reborrow(error_span, &descr, Origin::Ast);
-                let descr = match opt_loan_path(&err.cmt) {
+                let descr: Cow<'static, str> = match opt_loan_path(&err.cmt) {
                     Some(lp) => {
-                        format!("`{}`", self.loan_path_to_string(&lp))
+                        format!("`{}`", self.loan_path_to_string(&lp)).into()
                     }
-                    None => self.cmt_to_string(&err.cmt),
+                    None => self.cmt_to_cow_str(&err.cmt)
                 };
                 self.tcx.note_and_explain_region(
                     &self.region_scope_tree,
@@ -1477,14 +1478,14 @@ pub fn loan_path_to_string(&self, loan_path: &LoanPath<'tcx>) -> String {
         result
     }
 
-    pub fn cmt_to_string(&self, cmt: &mc::cmt_<'tcx>) -> String {
+    pub fn cmt_to_cow_str(&self, cmt: &mc::cmt_<'tcx>) -> Cow<'static, str> {
         cmt.descriptive_string(self.tcx)
     }
 
     pub fn cmt_to_path_or_string(&self, cmt: &mc::cmt_<'tcx>) -> String {
         match opt_loan_path(cmt) {
             Some(lp) => format!("`{}`", self.loan_path_to_string(&lp)),
-            None => self.cmt_to_string(cmt),
+            None => self.cmt_to_cow_str(cmt).into_owned(),
         }
     }
 }
index f10361cb076bd2fd1e02bc4cac45ebc6856e46bb..b1f89ce33fcfa58339a4ac31e5ec8f4160face2c 100644 (file)
@@ -76,10 +76,14 @@ fn check_unused_mut_pat(&self, pats: &[P<hir::Pat>]) {
             }
 
             let (hir_id, span) = ids[0];
-            let mut_span = tcx.sess.source_map().span_until_non_whitespace(span);
+            if span.compiler_desugaring_kind().is_some() {
+                // If the `mut` arises as part of a desugaring, we should ignore it.
+                continue;
+            }
 
             // Ok, every name wasn't used mutably, so issue a warning that this
             // didn't need to be mutable.
+            let mut_span = tcx.sess.source_map().span_until_non_whitespace(span);
             tcx.struct_span_lint_hir(UNUSED_MUT,
                                      hir_id,
                                      span,
index c03180c02fe634f5d1c6b5c62a304cd2eb40fcb4..e18c8b9dec463d770dd1b19f0db6595730ab3fd9 100644 (file)
@@ -89,6 +89,7 @@ pub fn to_linker<'a>(&'a self,
                 Box::new(WasmLd {
                     cmd,
                     sess,
+                    info: self
                 }) as Box<dyn Linker>
             }
         }
@@ -926,6 +927,7 @@ fn exported_symbols(tcx: TyCtxt, crate_type: CrateType) -> Vec<String> {
 pub struct WasmLd<'a> {
     cmd: Command,
     sess: &'a Session,
+    info: &'a LinkerInfo,
 }
 
 impl<'a> Linker for WasmLd<'a> {
@@ -1021,7 +1023,10 @@ fn no_default_libraries(&mut self) {
     fn build_dylib(&mut self, _out_filename: &Path) {
     }
 
-    fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType) {
+    fn export_symbols(&mut self, _tmpdir: &Path, crate_type: CrateType) {
+        for sym in self.info.exports[&crate_type].iter() {
+            self.cmd.arg("--export").arg(&sym);
+        }
     }
 
     fn subsystem(&mut self, _subsystem: &str) {
index f9eb80a1988af469263c9df86cef856d7dd88ed6..2f110fd552a8da8515449b7d46ac9a9a2c3cb094 100644 (file)
@@ -173,6 +173,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
         }
         ty::Error |
         ty::Infer(_) |
+        ty::UnnormalizedProjection(..) |
         ty::Projection(..) |
         ty::Opaque(..) |
         ty::GeneratorWitness(..) |
index 709fceb492509e9c88cddac93057e6d66d32c55c..db95b46c38ebeee537e0948fb2bcd5d39a1589a6 100644 (file)
@@ -412,7 +412,13 @@ fn codegen_terminator(&mut self,
                 bug!("undesugared DropAndReplace in codegen: {:?}", terminator);
             }
 
-            mir::TerminatorKind::Call { ref func, ref args, ref destination, cleanup } => {
+            mir::TerminatorKind::Call {
+                ref func,
+                ref args,
+                ref destination,
+                cleanup,
+                from_hir_call: _
+            } => {
                 // Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar.
                 let callee = self.codegen_operand(&bx, func);
 
index 7eda6e94dd0715f5a4cca9c7f981aa24c1385915..f04e5496ce443fb503c821c7c09b0fae140b422f 100644 (file)
@@ -1163,18 +1163,6 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
     }
 }
 
-declare_lint! {
-    PRIVATE_NO_MANGLE_FNS,
-    Warn,
-    "functions marked #[no_mangle] should be exported"
-}
-
-declare_lint! {
-    PRIVATE_NO_MANGLE_STATICS,
-    Warn,
-    "statics marked #[no_mangle] should be exported"
-}
-
 declare_lint! {
     NO_MANGLE_CONST_ITEMS,
     Deny,
@@ -1192,52 +1180,16 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
 
 impl LintPass for InvalidNoMangleItems {
     fn get_lints(&self) -> LintArray {
-        lint_array!(PRIVATE_NO_MANGLE_FNS,
-                    PRIVATE_NO_MANGLE_STATICS,
-                    NO_MANGLE_CONST_ITEMS,
+        lint_array!(NO_MANGLE_CONST_ITEMS,
                     NO_MANGLE_GENERIC_ITEMS)
     }
 }
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems {
     fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
-        let suggest_export = |vis: &hir::Visibility, err: &mut DiagnosticBuilder| {
-            let suggestion = match vis.node {
-                hir::VisibilityKind::Inherited => {
-                    // inherited visibility is empty span at item start; need an extra space
-                    Some("pub ".to_owned())
-                },
-                hir::VisibilityKind::Restricted { .. } |
-                hir::VisibilityKind::Crate(_) => {
-                    Some("pub".to_owned())
-                },
-                hir::VisibilityKind::Public => {
-                    err.help("try exporting the item with a `pub use` statement");
-                    None
-                }
-            };
-            if let Some(replacement) = suggestion {
-                err.span_suggestion_with_applicability(
-                    vis.span,
-                    "try making it public",
-                    replacement,
-                    Applicability::MachineApplicable
-                );
-            }
-        };
-
         match it.node {
             hir::ItemKind::Fn(.., ref generics, _) => {
                 if let Some(no_mangle_attr) = attr::find_by_name(&it.attrs, "no_mangle") {
-                    if attr::contains_name(&it.attrs, "linkage") {
-                        return;
-                    }
-                    if !cx.access_levels.is_reachable(it.id) {
-                        let msg = "function is marked #[no_mangle], but not exported";
-                        let mut err = cx.struct_span_lint(PRIVATE_NO_MANGLE_FNS, it.span, msg);
-                        suggest_export(&it.vis, &mut err);
-                        err.emit();
-                    }
                     for param in &generics.params {
                         match param.kind {
                             GenericParamKind::Lifetime { .. } => {}
@@ -1261,15 +1213,6 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
                     }
                 }
             }
-            hir::ItemKind::Static(..) => {
-                if attr::contains_name(&it.attrs, "no_mangle") &&
-                    !cx.access_levels.is_reachable(it.id) {
-                        let msg = "static is marked #[no_mangle], but not exported";
-                        let mut err = cx.struct_span_lint(PRIVATE_NO_MANGLE_STATICS, it.span, msg);
-                        suggest_export(&it.vis, &mut err);
-                        err.emit();
-                    }
-            }
             hir::ItemKind::Const(..) => {
                 if attr::contains_name(&it.attrs, "no_mangle") {
                     // Const items do not refer to a particular location in memory, and therefore
@@ -1785,8 +1728,6 @@ fn get_lints(&self) -> LintArray {
             UNUSED_DOC_COMMENTS,
             UNCONDITIONAL_RECURSION,
             PLUGIN_AS_LIBRARY,
-            PRIVATE_NO_MANGLE_FNS,
-            PRIVATE_NO_MANGLE_STATICS,
             NO_MANGLE_CONST_ITEMS,
             NO_MANGLE_GENERIC_ITEMS,
             MUTABLE_TRANSMUTES,
index 98d4c87dc3b5e810159c8c271c07ecd36f77ad78..bdf09007fdd466a51a2f0a24aeac3f1c69e4fd86 100644 (file)
@@ -387,4 +387,8 @@ macro_rules! add_lint_group {
         "converted into hard error, see https://github.com/rust-lang/rust/issues/48950");
     store.register_removed("resolve_trait_on_defaulted_unit",
         "converted into hard error, see https://github.com/rust-lang/rust/issues/48950");
+    store.register_removed("private_no_mangle_fns",
+        "no longer an warning, #[no_mangle] functions always exported");
+    store.register_removed("private_no_mangle_statics",
+        "no longer an warning, #[no_mangle] statics always exported");
 }
index 01d4d0f8cdb67be3395918b71bea4702296a6f17..a441f7a87f763c4bba857b80abbdf93153d51958 100644 (file)
@@ -722,6 +722,7 @@ fn check_type_for_ffi(&self,
             ty::Closure(..) |
             ty::Generator(..) |
             ty::GeneratorWitness(..) |
+            ty::UnnormalizedProjection(..) |
             ty::Projection(..) |
             ty::Opaque(..) |
             ty::FnDef(..) => bug!("Unexpected type in foreign function"),
index 7a9d18676cf6c9d2e405a819d4de8aeaea599fd6..ae178888b6a1cda42a65a67f3ccddb11cbce2a4a 100644 (file)
@@ -65,9 +65,8 @@ fn check_stmt(&mut self, cx: &LateContext, s: &hir::Stmt) {
             ty::Adt(def, _) => {
                 if def.variants.is_empty() {
                     return;
-                } else {
-                    check_must_use(cx, def.did, s.span, "")
                 }
+                check_must_use(cx, def.did, s.span, "")
             },
             _ => false,
         };
@@ -337,21 +336,13 @@ fn check_expr(&mut self, cx: &EarlyContext, e: &ast::Expr) {
             AssignOp(.., ref value) => (value, "assigned value", false),
             // either function/method call, or something this lint doesn't care about
             ref call_or_other => {
-                let args_to_check;
-                let call_kind;
-                match *call_or_other {
-                    Call(_, ref args) => {
-                        call_kind = "function";
-                        args_to_check = &args[..];
-                    },
-                    MethodCall(_, ref args) => {
-                        call_kind = "method";
-                        // first "argument" is self (which sometimes needs parens)
-                        args_to_check = &args[1..];
-                    }
+                let (args_to_check, call_kind) = match *call_or_other {
+                    Call(_, ref args) => (&args[..], "function"),
+                    // first "argument" is self (which sometimes needs parens)
+                    MethodCall(_, ref args) => (&args[1..], "method"),
                     // actual catch-all arm
                     _ => { return; }
-                }
+                };
                 // Don't lint if this is a nested macro expansion: otherwise, the lint could
                 // trigger in situations that macro authors shouldn't have to care about, e.g.,
                 // when a parenthesized token tree matched in one macro expansion is matched as
@@ -372,16 +363,11 @@ fn check_expr(&mut self, cx: &EarlyContext, e: &ast::Expr) {
     }
 
     fn check_stmt(&mut self, cx: &EarlyContext, s: &ast::Stmt) {
-        let (value, msg) = match s.node {
-            ast::StmtKind::Local(ref local) => {
-                match local.init {
-                    Some(ref value) => (value, "assigned value"),
-                    None => return,
-                }
+        if let ast::StmtKind::Local(ref local) = s.node {
+            if let Some(ref value) = local.init {
+                self.check_unused_parens_core(cx, &value, "assigned value", false);
             }
-            _ => return,
-        };
-        self.check_unused_parens_core(cx, &value, msg, false);
+        }
     }
 }
 
@@ -414,9 +400,8 @@ fn check_use_tree(&self, cx: &EarlyContext, use_tree: &ast::UseTree, item: &ast:
                     let orig_ident = items[0].0.prefix.segments.last().unwrap().ident;
                     if orig_ident.name == keywords::SelfValue.name() {
                         return;
-                    } else {
-                        node_ident = rename.unwrap_or(orig_ident);
                     }
+                    node_ident = rename.unwrap_or(orig_ident);
                 }
                 ast::UseTreeKind::Glob => {
                     node_ident = ast::Ident::from_str("*");
index 22b135bee492ac9e6a7e904e8bd4321c1723de1e..53a190efb58355b484c19f6dee7be91fc8cf8a28 100644 (file)
@@ -15,9 +15,9 @@
 use rustc::hir::def_id::DefId;
 use rustc::middle::region::ScopeTree;
 use rustc::mir::{
-    self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, FakeReadCause, Field, Local,
-    LocalDecl, LocalKind, Location, Operand, Place, PlaceProjection, ProjectionElem, Rvalue,
-    Statement, StatementKind, TerminatorKind, VarBindingForm,
+    self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, Field, Local,
+    LocalDecl, LocalKind, Location, Operand, Place, PlaceProjection, ProjectionElem,
+    Rvalue, Statement, StatementKind, TerminatorKind, VarBindingForm,
 };
 use rustc::ty;
 use rustc::util::ppaux::with_highlight_region_for_bound_region;
@@ -262,7 +262,7 @@ pub(super) fn report_move_out_while_borrowed(
         move_spans.var_span_label(&mut err, "move occurs due to use in closure");
 
         self.explain_why_borrow_contains_point(context, borrow, None)
-            .emit(self.infcx.tcx, &mut err);
+            .add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "");
         err.buffer(&mut self.errors_buffer);
     }
 
@@ -299,7 +299,7 @@ pub(super) fn report_use_while_mutably_borrowed(
         });
 
         self.explain_why_borrow_contains_point(context, borrow, None)
-            .emit(self.infcx.tcx, &mut err);
+            .add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "");
         err.buffer(&mut self.errors_buffer);
     }
 
@@ -319,6 +319,8 @@ pub(super) fn report_conflicting_borrow(
         let desc_place = self.describe_place(place).unwrap_or("_".to_owned());
         let tcx = self.infcx.tcx;
 
+        let first_borrow_desc;
+
         // FIXME: supply non-"" `opt_via` when appropriate
         let mut err = match (
             gen_borrow_kind,
@@ -328,8 +330,23 @@ pub(super) fn report_conflicting_borrow(
             "immutable",
             "mutable",
         ) {
-            (BorrowKind::Shared, lft, _, BorrowKind::Mut { .. }, _, rgt)
-            | (BorrowKind::Mut { .. }, _, lft, BorrowKind::Shared, rgt, _) => {
+            (BorrowKind::Shared, lft, _, BorrowKind::Mut { .. }, _, rgt) => {
+                first_borrow_desc = "mutable ";
+                tcx.cannot_reborrow_already_borrowed(
+                    span,
+                    &desc_place,
+                    "",
+                    lft,
+                    issued_span,
+                    "it",
+                    rgt,
+                    "",
+                    None,
+                    Origin::Mir,
+                )
+            }
+            (BorrowKind::Mut { .. }, _, lft, BorrowKind::Shared, rgt, _) => {
+                first_borrow_desc = "immutable ";
                 tcx.cannot_reborrow_already_borrowed(
                     span,
                     &desc_place,
@@ -345,6 +362,7 @@ pub(super) fn report_conflicting_borrow(
             }
 
             (BorrowKind::Mut { .. }, _, _, BorrowKind::Mut { .. }, _, _) => {
+                first_borrow_desc = "first ";
                 tcx.cannot_mutably_borrow_multiply(
                     span,
                     &desc_place,
@@ -357,6 +375,7 @@ pub(super) fn report_conflicting_borrow(
             }
 
             (BorrowKind::Unique, _, _, BorrowKind::Unique, _, _) => {
+                first_borrow_desc = "first ";
                 tcx.cannot_uniquely_borrow_by_two_closures(
                     span,
                     &desc_place,
@@ -384,18 +403,22 @@ pub(super) fn report_conflicting_borrow(
                 return;
             }
 
-            (BorrowKind::Unique, _, _, _, _, _) => tcx.cannot_uniquely_borrow_by_one_closure(
-                span,
-                &desc_place,
-                "",
-                issued_span,
-                "it",
-                "",
-                None,
-                Origin::Mir,
-            ),
+            (BorrowKind::Unique, _, _, _, _, _) => {
+                first_borrow_desc = "first ";
+                tcx.cannot_uniquely_borrow_by_one_closure(
+                    span,
+                    &desc_place,
+                    "",
+                    issued_span,
+                    "it",
+                    "",
+                    None,
+                    Origin::Mir,
+                )
+            },
 
             (BorrowKind::Shared, lft, _, BorrowKind::Unique, _, _) => {
+                first_borrow_desc = "first ";
                 tcx.cannot_reborrow_already_uniquely_borrowed(
                     span,
                     &desc_place,
@@ -409,6 +432,7 @@ pub(super) fn report_conflicting_borrow(
             }
 
             (BorrowKind::Mut { .. }, _, lft, BorrowKind::Unique, _, _) => {
+                first_borrow_desc = "first ";
                 tcx.cannot_reborrow_already_uniquely_borrowed(
                     span,
                     &desc_place,
@@ -459,7 +483,7 @@ pub(super) fn report_conflicting_borrow(
         }
 
         self.explain_why_borrow_contains_point(context, issued_borrow, None)
-            .emit(self.infcx.tcx, &mut err);
+            .add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, first_borrow_desc);
 
         err.buffer(&mut self.errors_buffer);
     }
@@ -614,7 +638,7 @@ fn report_local_value_does_not_live_long_enough(
 
             if let BorrowExplanation::MustBeValidFor(..) = explanation {
             } else {
-                explanation.emit(self.infcx.tcx, &mut err);
+                explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "");
             }
         } else {
             err.span_label(borrow_span, "borrowed value does not live long enough");
@@ -625,7 +649,7 @@ fn report_local_value_does_not_live_long_enough(
 
             borrow_spans.args_span_label(&mut err, "value captured here");
 
-            explanation.emit(self.infcx.tcx, &mut err);
+            explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "");
         }
 
         err
@@ -685,7 +709,7 @@ pub(super) fn report_borrow_conflicts_with_destructor(
             _ => {}
         }
 
-        explanation.emit(self.infcx.tcx, &mut err);
+        explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "");
 
         err.buffer(&mut self.errors_buffer);
     }
@@ -746,13 +770,13 @@ fn report_temporary_value_does_not_live_long_enough(
         match explanation {
             BorrowExplanation::UsedLater(..)
             | BorrowExplanation::UsedLaterInLoop(..)
-            | BorrowExplanation::UsedLaterWhenDropped(..) => {
+            | BorrowExplanation::UsedLaterWhenDropped { .. } => {
                 // Only give this note and suggestion if it could be relevant.
                 err.note("consider using a `let` binding to create a longer lived value");
             }
             _ => {}
         }
-        explanation.emit(self.infcx.tcx, &mut err);
+        explanation.add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "");
 
         borrow_spans.args_span_label(&mut err, "value captured here");
 
@@ -889,7 +913,7 @@ pub(super) fn report_illegal_mutation_of_borrowed(
         loan_spans.var_span_label(&mut err, "borrow occurs due to use in closure");
 
         self.explain_why_borrow_contains_point(context, loan, None)
-            .emit(self.infcx.tcx, &mut err);
+            .add_explanation_to_diagnostic(self.infcx.tcx, self.mir, &mut err, "");
 
         err.buffer(&mut self.errors_buffer);
     }
@@ -1262,21 +1286,6 @@ pub fn is_place_thread_local(&self, place: &Place<'tcx>) -> bool {
         }
     }
 
-    /// Returns the `FakeReadCause` at this location if it is a `FakeRead` statement.
-    pub(super) fn retrieve_fake_read_cause_for_location(
-        &self,
-        location: &Location,
-    ) -> Option<FakeReadCause> {
-        let stmt = self.mir.basic_blocks()[location.block]
-            .statements
-            .get(location.statement_index)?;
-        if let StatementKind::FakeRead(cause, _) = stmt.kind {
-            Some(cause)
-        } else {
-            None
-        }
-    }
-
     fn classify_drop_access_kind(&self, place: &Place<'tcx>) -> StorageDeadOrDrop<'tcx> {
         let tcx = self.infcx.tcx;
         match place {
@@ -1780,9 +1789,11 @@ fn get_name_for_ty(&self, ty: ty::Ty<'tcx>, counter: usize) -> String {
         // lifetimes without names with the value `'0`.
         match ty.sty {
             ty::TyKind::Ref(ty::RegionKind::ReLateBound(_, br), _, _)
-            | ty::TyKind::Ref(ty::RegionKind::ReSkolemized(_, br), _, _) => {
-                with_highlight_region_for_bound_region(*br, counter, || format!("{}", ty))
-            }
+            | ty::TyKind::Ref(
+                ty::RegionKind::RePlaceholder(ty::Placeholder { name: br, .. }),
+                _,
+                _,
+            ) => with_highlight_region_for_bound_region(*br, counter, || format!("{}", ty)),
             _ => format!("{}", ty),
         }
     }
@@ -1792,7 +1803,8 @@ fn get_name_for_ty(&self, ty: ty::Ty<'tcx>, counter: usize) -> String {
     fn get_region_name_for_ty(&self, ty: ty::Ty<'tcx>, counter: usize) -> String {
         match ty.sty {
             ty::TyKind::Ref(region, _, _) => match region {
-                ty::RegionKind::ReLateBound(_, br) | ty::RegionKind::ReSkolemized(_, br) => {
+                ty::RegionKind::ReLateBound(_, br)
+                | ty::RegionKind::RePlaceholder(ty::Placeholder { name: br, .. }) => {
                     with_highlight_region_for_bound_region(*br, counter, || format!("{}", region))
                 }
                 _ => format!("{}", region),
index 6ecbc5ee727c1ddb1ef7b047175442b91d7ade13..0943b36440aa67c7fc2f2f65c814d22f1c76e750 100644 (file)
@@ -316,7 +316,10 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
             }
 
             let span = local_decl.source_info.span;
-            let mut_span = tcx.sess.source_map().span_until_non_whitespace(span);
+            if span.compiler_desugaring_kind().is_some() {
+                // If the `mut` arises as part of a desugaring, we should ignore it.
+                continue;
+            }
 
             let mut err = tcx.struct_span_lint_node(
                 UNUSED_MUT,
@@ -324,6 +327,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
                 span,
                 "variable does not need to be mutable",
             );
+            let mut_span = tcx.sess.source_map().span_until_non_whitespace(span);
             err.span_suggestion_short_with_applicability(
                 mut_span,
                 "remove this `mut`",
@@ -667,6 +671,7 @@ fn visit_terminator_entry(
                 ref args,
                 ref destination,
                 cleanup: _,
+                from_hir_call: _,
             } => {
                 self.consume_operand(ContextKind::CallOperator.new(loc), (func, span), flow_state);
                 for arg in args {
index 1c55806872d57ce0430b609a63ce5f858bbc93e7..693cfea3c95f0d4b3cbabdaa44d944abfb407c83 100644 (file)
@@ -9,6 +9,8 @@
 // except according to those terms.
 
 use core::unicode::property::Pattern_White_Space;
+use std::fmt::{self, Display};
+
 use rustc::mir::*;
 use rustc::ty;
 use rustc_errors::{DiagnosticBuilder,Applicability};
 
 use borrow_check::MirBorrowckCtxt;
 use borrow_check::prefixes::PrefixSet;
-use dataflow::move_paths::{IllegalMoveOrigin, IllegalMoveOriginKind};
-use dataflow::move_paths::{LookupResult, MoveError, MovePathIndex};
+use dataflow::move_paths::{
+    IllegalMoveOrigin, IllegalMoveOriginKind, InitLocation,
+    LookupResult, MoveError, MovePathIndex,
+};
 use util::borrowck_errors::{BorrowckErrors, Origin};
 
 // Often when desugaring a pattern match we may have many individual moves in
@@ -61,6 +65,22 @@ enum GroupedMoveError<'tcx> {
     },
 }
 
+enum BorrowedContentSource {
+    Arc,
+    Rc,
+    Other,
+}
+
+impl Display for BorrowedContentSource {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            BorrowedContentSource::Arc => write!(f, "an `Arc`"),
+            BorrowedContentSource::Rc => write!(f, "an `Rc`"),
+            BorrowedContentSource::Other => write!(f, "borrowed content"),
+        }
+    }
+}
+
 impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
     pub(crate) fn report_move_errors(&mut self, move_errors: Vec<(Place<'tcx>, MoveError<'tcx>)>) {
         let grouped_errors = self.group_move_errors(move_errors);
@@ -305,9 +325,12 @@ fn report(&mut self, error: GroupedMoveError<'tcx>) {
 
                                 diag
                             }
-                            _ => self.infcx.tcx.cannot_move_out_of(
-                                span, "borrowed content", origin
-                            ),
+                            _ => {
+                                let source = self.borrowed_content_source(place);
+                                self.infcx.tcx.cannot_move_out_of(
+                                    span, &format!("{}", source), origin
+                                )
+                            },
                         }
                     }
                     IllegalMoveOriginKind::InteriorOfTypeWithDestructor { container_ty: ty } => {
@@ -471,4 +494,94 @@ fn add_move_error_details(
             );
         }
     }
+
+    fn borrowed_content_source(&self, place: &Place<'tcx>) -> BorrowedContentSource {
+        // Look up the provided place and work out the move path index for it,
+        // we'll use this to work back through where this value came from and check whether it
+        // was originally part of an `Rc` or `Arc`.
+        let initial_mpi = match self.move_data.rev_lookup.find(place) {
+            LookupResult::Exact(mpi) | LookupResult::Parent(Some(mpi)) => mpi,
+            _ => return BorrowedContentSource::Other,
+        };
+
+        let mut queue = vec![initial_mpi];
+        let mut visited = Vec::new();
+        debug!("borrowed_content_source: queue={:?}", queue);
+        while let Some(mpi) = queue.pop() {
+            debug!(
+                "borrowed_content_source: mpi={:?} queue={:?} visited={:?}",
+                mpi, queue, visited
+            );
+
+            // Don't visit the same path twice.
+            if visited.contains(&mpi) {
+                continue;
+            }
+            visited.push(mpi);
+
+            for i in &self.move_data.init_path_map[mpi] {
+                let init = &self.move_data.inits[*i];
+                debug!("borrowed_content_source: init={:?}", init);
+                // We're only interested in statements that initialized a value, not the
+                // initializations from arguments.
+                let loc = match init.location {
+                    InitLocation::Statement(stmt) => stmt,
+                    _ => continue,
+                };
+
+                let bbd = &self.mir[loc.block];
+                let is_terminator = bbd.statements.len() == loc.statement_index;
+                debug!("borrowed_content_source: loc={:?} is_terminator={:?}", loc, is_terminator);
+                if !is_terminator {
+                    let stmt = &bbd.statements[loc.statement_index];
+                    debug!("borrowed_content_source: stmt={:?}", stmt);
+                    // We're only interested in assignments (in particular, where the
+                    // assignment came from - was it an `Rc` or `Arc`?).
+                    if let StatementKind::Assign(_, box Rvalue::Ref(_, _, source)) = &stmt.kind {
+                        let ty = source.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx);
+                        let ty = match ty.sty {
+                            ty::TyKind::Ref(_, ty, _) => ty,
+                            _ => ty,
+                        };
+                        debug!("borrowed_content_source: ty={:?}", ty);
+
+                        if ty.is_arc() {
+                            return BorrowedContentSource::Arc;
+                        } else if ty.is_rc() {
+                            return BorrowedContentSource::Rc;
+                        } else {
+                            queue.push(init.path);
+                        }
+                    }
+                } else if let Some(Terminator {
+                    kind: TerminatorKind::Call { args, .. },
+                    ..
+                }) = &bbd.terminator {
+                    for arg in args {
+                        let source = match arg {
+                            Operand::Copy(place) | Operand::Move(place) => place,
+                            _ => continue,
+                        };
+
+                        let ty = source.ty(self.mir, self.infcx.tcx).to_ty(self.infcx.tcx);
+                        let ty = match ty.sty {
+                            ty::TyKind::Ref(_, ty, _) => ty,
+                            _ => ty,
+                        };
+                        debug!("borrowed_content_source: ty={:?}", ty);
+
+                        if ty.is_arc() {
+                            return BorrowedContentSource::Arc;
+                        } else if ty.is_rc() {
+                            return BorrowedContentSource::Rc;
+                        } else {
+                            queue.push(init.path);
+                        }
+                    }
+                }
+            }
+        }
+
+        BorrowedContentSource::Other
+    }
 }
index 8d1caec2d72d36392dbd129f0537ecdc55e46538..e55469436abf0a72b08541f9d4097ae143a4a30c 100644 (file)
 // except according to those terms.
 
 use borrow_check::borrow_set::BorrowData;
+use borrow_check::error_reporting::UseSpans;
 use borrow_check::nll::region_infer::Cause;
 use borrow_check::{Context, MirBorrowckCtxt, WriteKind};
-use rustc::ty::{Region, TyCtxt};
-use rustc::mir::{FakeReadCause, Location, Place, TerminatorKind};
+use rustc::ty::{self, Region, TyCtxt};
+use rustc::mir::{FakeReadCause, Local, Location, Mir, Operand};
+use rustc::mir::{Place, StatementKind, TerminatorKind};
 use rustc_errors::DiagnosticBuilder;
 use syntax_pos::Span;
-use syntax_pos::symbol::Symbol;
 
 mod find_use;
 
 pub(in borrow_check) enum BorrowExplanation<'tcx> {
-    UsedLater(bool, Option<FakeReadCause>, Span),
-    UsedLaterInLoop(bool, Span),
-    UsedLaterWhenDropped(Span, Symbol, bool),
+    UsedLater(LaterUseKind, Span),
+    UsedLaterInLoop(LaterUseKind, Span),
+    UsedLaterWhenDropped {
+        drop_loc: Location,
+        dropped_local: Local,
+        should_note_order: bool,
+    },
     MustBeValidFor(Region<'tcx>),
     Unexplained,
 }
 
+#[derive(Clone, Copy)]
+pub(in borrow_check) enum LaterUseKind {
+    ClosureCapture,
+    Call,
+    FakeLetRead,
+    Other,
+}
+
 impl<'tcx> BorrowExplanation<'tcx> {
-    pub(in borrow_check) fn emit<'cx, 'gcx>(
+    pub(in borrow_check) fn add_explanation_to_diagnostic<'cx, 'gcx>(
         &self,
         tcx: TyCtxt<'cx, 'gcx, 'tcx>,
-        err: &mut DiagnosticBuilder<'_>
+        mir: &Mir<'tcx>,
+        err: &mut DiagnosticBuilder<'_>,
+        borrow_desc: &str,
     ) {
         match *self {
-            BorrowExplanation::UsedLater(is_in_closure, fake_read_cause, var_or_use_span) => {
-                let message = if is_in_closure {
-                    "borrow later captured here by closure"
-                } else if let Some(FakeReadCause::ForLet) = fake_read_cause {
-                    "borrow later stored here"
-                } else {
-                    "borrow later used here"
+            BorrowExplanation::UsedLater(later_use_kind, var_or_use_span) => {
+                let message = match later_use_kind {
+                    LaterUseKind::ClosureCapture => "borrow later captured here by closure",
+                    LaterUseKind::Call =>  "borrow later used by call",
+                    LaterUseKind::FakeLetRead => "borrow later stored here",
+                    LaterUseKind::Other => "borrow later used here",
                 };
-                err.span_label(var_or_use_span, message);
+                err.span_label(var_or_use_span, format!("{}{}", borrow_desc, message));
             },
-            BorrowExplanation::UsedLaterInLoop(is_in_closure, var_or_use_span) => {
-                let message = if is_in_closure {
-                    "borrow captured here by closure, in later iteration of loop"
-                } else {
-                    "borrow used here, in later iteration of loop"
+            BorrowExplanation::UsedLaterInLoop(later_use_kind, var_or_use_span) => {
+                let message = match later_use_kind {
+                    LaterUseKind::ClosureCapture => {
+                        "borrow captured here by closure, in later iteration of loop"
+                    },
+                    LaterUseKind::Call =>  "borrow used by call, in later iteration of loop",
+                    LaterUseKind::FakeLetRead => "borrow later stored here",
+                    LaterUseKind::Other => "borrow used here, in later iteration of loop",
                 };
-                err.span_label(var_or_use_span, message);
+                err.span_label(var_or_use_span, format!("{}{}", borrow_desc, message));
             },
-            BorrowExplanation::UsedLaterWhenDropped(span, local_name, should_note_order) => {
-                err.span_label(
-                    span,
-                    format!("borrow later used here, when `{}` is dropped", local_name),
-                );
+            BorrowExplanation::UsedLaterWhenDropped { drop_loc, dropped_local,
+                                                      should_note_order } =>
+            {
+                let local_decl = &mir.local_decls[dropped_local];
+                let (dtor_desc, type_desc) = match local_decl.ty.sty {
+                    // If type is an ADT that implements Drop, then
+                    // simplify output by reporting just the ADT name.
+                    ty::Adt(adt, _substs) if adt.has_dtor(tcx) && !adt.is_box() =>
+                        ("`Drop` code", format!("type `{}`", tcx.item_path_str(adt.did))),
+
+                    // Otherwise, just report the whole type (and use
+                    // the intentionally fuzzy phrase "destructor")
+                    ty::Closure(..) =>
+                        ("destructor", format!("closure")),
+                    ty::Generator(..) =>
+                        ("destructor", format!("generator")),
+
+                    _ => ("destructor", format!("type `{}`", local_decl.ty)),
+                };
+
+                match local_decl.name {
+                    Some(local_name) => {
+                        let message =
+                            format!("{B}borrow might be used here, when `{LOC}` is dropped \
+                                     and runs the {DTOR} for {TYPE}",
+                                    B=borrow_desc, LOC=local_name, TYPE=type_desc, DTOR=dtor_desc);
+                        err.span_label(mir.source_info(drop_loc).span, message);
+
+                        if should_note_order {
+                            err.note(
+                                "values in a scope are dropped \
+                                 in the opposite order they are defined",
+                            );
+                        }
+                    }
+                    None => {
+                        err.span_label(local_decl.source_info.span,
+                                       format!("a temporary with access to the {B}borrow \
+                                                is created here ...",
+                                               B=borrow_desc));
+                        let message =
+                            format!("... and the {B}borrow might be used here, \
+                                     when that temporary is dropped \
+                                     and runs the {DTOR} for {TYPE}",
+                                    B=borrow_desc, TYPE=type_desc, DTOR=dtor_desc);
+                        err.span_label(mir.source_info(drop_loc).span, message);
+
+                        if let Some(info) = &local_decl.is_block_tail {
+                            // FIXME: use span_suggestion instead, highlighting the
+                            // whole block tail expression.
+                            let msg = if info.tail_result_is_ignored {
+                                "The temporary is part of an expression at the end of a block. \
+                                 Consider adding semicolon after the expression so its temporaries \
+                                 are dropped sooner, before the local variables declared by the \
+                                 block are dropped."
+                            } else {
+                                "The temporary is part of an expression at the end of a block. \
+                                 Consider forcing this temporary to be dropped sooner, before \
+                                 the block's local variables are dropped. \
+                                 For example, you could save the expression's value in a new \
+                                 local variable `x` and then make `x` be the expression \
+                                 at the end of the block."
+                            };
 
-                if should_note_order {
-                    err.note(
-                        "values in a scope are dropped \
-                         in the opposite order they are defined",
-                    );
+                            err.note(msg);
+                        }
+                    }
                 }
-            },
+            }
+
             BorrowExplanation::MustBeValidFor(region) => {
                 tcx.note_and_explain_free_region(
                     err,
-                    "borrowed value must be valid for ",
+                    &format!("{}{}", borrow_desc, "borrowed value must be valid for "),
                     region,
                     "...",
                 );
@@ -79,7 +153,7 @@ pub(in borrow_check) fn emit<'cx, 'gcx>(
 }
 
 impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
-    /// Adds annotations to `err` explaining *why* the borrow contains the
+    /// Returns structured explanation for *why* the borrow contains the
     /// point from `context`. This is key for the "3-point errors"
     /// [described in the NLL RFC][d].
     ///
@@ -90,7 +164,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
     /// - `kind_place`: if Some, this describes the statement that triggered the error.
     ///   - first half is the kind of write, if any, being performed
     ///   - second half is the place being accessed
-    /// - `err`: where the error annotations are going to be added
     ///
     /// [d]: https://rust-lang.github.io/rfcs/2094-nll.html#leveraging-intuition-framing-errors-in-terms-of-points
     pub(in borrow_check) fn explain_why_borrow_contains_point(
@@ -100,8 +173,8 @@ pub(in borrow_check) fn explain_why_borrow_contains_point(
         kind_place: Option<(WriteKind, &Place<'tcx>)>,
     ) -> BorrowExplanation<'tcx> {
         debug!(
-            "find_why_borrow_contains_point(context={:?}, borrow={:?})",
-            context, borrow,
+            "explain_why_borrow_contains_point(context={:?}, borrow={:?}, kind_place={:?})",
+            context, borrow, kind_place
         );
 
         let regioncx = &self.nonlexical_regioncx;
@@ -127,45 +200,41 @@ pub(in borrow_check) fn explain_why_borrow_contains_point(
                     .or_else(|| self.borrow_spans(span, location));
 
                 if self.is_borrow_location_in_loop(context.loc) {
-                    BorrowExplanation::UsedLaterInLoop(spans.for_closure(), spans.var_or_use())
+                    let later_use = self.later_use_kind(spans, location);
+                    BorrowExplanation::UsedLaterInLoop(later_use.0, later_use.1)
                 } else {
                     // Check if the location represents a `FakeRead`, and adapt the error
                     // message to the `FakeReadCause` it is from: in particular,
                     // the ones inserted in optimized `let var = <expr>` patterns.
-                    BorrowExplanation::UsedLater(
-                        spans.for_closure(),
-                        self.retrieve_fake_read_cause_for_location(&location),
-                        spans.var_or_use()
-                    )
+                    let later_use = self.later_use_kind(spans, location);
+                    BorrowExplanation::UsedLater(later_use.0, later_use.1)
                 }
             }
 
-            Some(Cause::DropVar(local, location)) => match &mir.local_decls[local].name {
-                Some(local_name) => {
-                    let mut should_note_order = false;
-                    if let Some((WriteKind::StorageDeadOrDrop, place)) = kind_place {
-                        if let Place::Local(borrowed_local) = place {
-                            let dropped_local_scope = mir.local_decls[local].visibility_scope;
-                            let borrowed_local_scope =
-                                mir.local_decls[*borrowed_local].visibility_scope;
-
-                            if mir.is_sub_scope(borrowed_local_scope, dropped_local_scope)
-                                && local != *borrowed_local
-                            {
-                                should_note_order = true;
-                            }
-                        }
-                    }
+             Some(Cause::DropVar(local, location)) => {
+                 let mut should_note_order = false;
+                 if mir.local_decls[local].name.is_some() {
+                     if let Some((WriteKind::StorageDeadOrDrop, place)) = kind_place {
+                         if let Place::Local(borrowed_local) = place {
+                             let dropped_local_scope = mir.local_decls[local].visibility_scope;
+                             let borrowed_local_scope =
+                                 mir.local_decls[*borrowed_local].visibility_scope;
 
-                    BorrowExplanation::UsedLaterWhenDropped(
-                        mir.source_info(location).span,
-                        *local_name,
-                        should_note_order
-                    )
-                },
+                             if mir.is_sub_scope(borrowed_local_scope, dropped_local_scope)
+                                 && local != *borrowed_local
+                             {
+                                 should_note_order = true;
+                             }
+                         }
+                     }
+                 }
 
-                None => BorrowExplanation::Unexplained,
-            },
+                 BorrowExplanation::UsedLaterWhenDropped {
+                     drop_loc: location,
+                     dropped_local: local,
+                     should_note_order,
+                 }
+            }
 
             None => if let Some(region) = regioncx.to_error_region(region_sub) {
                 BorrowExplanation::MustBeValidFor(region)
@@ -246,4 +315,43 @@ fn is_borrow_location_in_loop(
 
         false
     }
+
+    fn later_use_kind(&self, use_spans: UseSpans, location: Location) -> (LaterUseKind, Span) {
+        use self::LaterUseKind::*;
+
+        let block = &self.mir.basic_blocks()[location.block];
+        match use_spans {
+            UseSpans::ClosureUse { var_span, .. } => (LaterUseKind::ClosureCapture, var_span),
+            UseSpans::OtherUse(span) => {
+                (if let Some(stmt) = block.statements.get(location.statement_index) {
+                    match stmt.kind {
+                        StatementKind::FakeRead(FakeReadCause::ForLet, _) => FakeLetRead,
+                        _ => Other,
+                    }
+                } else {
+                    assert_eq!(location.statement_index, block.statements.len());
+                    match block.terminator().kind {
+                        TerminatorKind::Call { ref func, from_hir_call: true, .. } => {
+                            // Just point to the function, to reduce the chance
+                            // of overlapping spans.
+                            let function_span = match func {
+                                Operand::Constant(c) => c.span,
+                                Operand::Copy(Place::Local(l)) | Operand::Move(Place::Local(l)) => {
+                                    let local_decl = &self.mir.local_decls[*l];
+                                    if local_decl.name.is_none() {
+                                        local_decl.source_info.span
+                                    } else {
+                                        span
+                                    }
+                                },
+                                _ => span,
+                            };
+                            return (Call, function_span);
+                        },
+                        _ => Other,
+                    }
+                }, span)
+            }
+        }
+    }
 }
index f19c102adcfe9d08db44cc197bc4bc6de47a1689..a9b5531bae519141a6f830bbfc5b78d7618fb190 100644 (file)
@@ -203,6 +203,7 @@ fn visit_terminator(
                 ref args,
                 ref destination,
                 cleanup: _,
+                from_hir_call: _,
             } => {
                 self.consume_operand(ContextKind::CallOperator.new(location), func);
                 for arg in args {
index b9f22c7402a07eb42f3793fd7fe516ca82593280..723b0e6fff6f8d4219d6c17814f6cf7eb19541e8 100644 (file)
@@ -107,6 +107,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
     // Run the MIR type-checker.
     let MirTypeckResults {
         constraints,
+        placeholder_indices,
         universal_region_relations,
     } = type_check::type_check(
         infcx,
@@ -122,6 +123,8 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
         elements,
     );
 
+    let placeholder_indices = Rc::new(placeholder_indices);
+
     if let Some(all_facts) = &mut all_facts {
         all_facts
             .universal_region
@@ -150,6 +153,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
     let mut regioncx = RegionInferenceContext::new(
         var_origins,
         universal_regions,
+        placeholder_indices,
         universal_region_relations,
         mir,
         outlives_constraints,
index be05e006608a26da38adaa291e9c7dbfb0cf68b9..3a545d9adbfcee457a062295a505d9f1803f9f83 100644 (file)
@@ -274,7 +274,7 @@ fn give_name_from_error_region(
             ty::ReLateBound(..)
             | ty::ReScope(..)
             | ty::ReVar(..)
-            | ty::ReSkolemized(..)
+            | ty::RePlaceholder(..)
             | ty::ReEmpty
             | ty::ReErased
             | ty::ReClosureBound(..)
index 2dbb5cd9deb144437a38fb9d9cbd9e236489f217..4a8f011b606b739e6796223498abd09180c41431 100644 (file)
@@ -11,7 +11,7 @@
 use super::universal_regions::UniversalRegions;
 use borrow_check::nll::constraints::graph::NormalConstraintGraph;
 use borrow_check::nll::constraints::{ConstraintSccIndex, ConstraintSet, OutlivesConstraint};
-use borrow_check::nll::region_infer::values::{RegionElement, ToElementIndex};
+use borrow_check::nll::region_infer::values::{PlaceholderIndices, RegionElement, ToElementIndex};
 use borrow_check::nll::type_check::free_region_relations::UniversalRegionRelations;
 use borrow_check::nll::type_check::Locations;
 use rustc::hir::def_id::DefId;
@@ -183,6 +183,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     pub(crate) fn new(
         var_infos: VarInfos,
         universal_regions: Rc<UniversalRegions<'tcx>>,
+        placeholder_indices: Rc<PlaceholderIndices>,
         universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
         _mir: &Mir<'tcx>,
         outlives_constraints: ConstraintSet,
@@ -196,19 +197,13 @@ pub(crate) fn new(
             .map(|info| RegionDefinition::new(info.universe, info.origin))
             .collect();
 
-        // Compute the max universe used anywhere amongst the regions.
-        let max_universe = definitions
-            .iter()
-            .map(|d| d.universe)
-            .max()
-            .unwrap_or(ty::UniverseIndex::ROOT);
-
         let constraints = Rc::new(outlives_constraints); // freeze constraints
         let constraint_graph = Rc::new(constraints.graph(definitions.len()));
         let fr_static = universal_regions.fr_static;
         let constraint_sccs = Rc::new(constraints.compute_sccs(&constraint_graph, fr_static));
 
-        let mut scc_values = RegionValues::new(elements, universal_regions.len(), max_universe);
+        let mut scc_values =
+            RegionValues::new(elements, universal_regions.len(), &placeholder_indices);
 
         for region in liveness_constraints.rows() {
             let scc = constraint_sccs.scc(region);
@@ -329,17 +324,14 @@ fn init_free_and_bound_regions(&mut self) {
                     self.scc_values.add_element(scc, variable);
                 }
 
-                NLLRegionVariableOrigin::BoundRegion(ui) => {
-                    // Each placeholder region X outlives its
-                    // associated universe but nothing else. Every
-                    // placeholder region is always in a universe that
-                    // contains `ui` -- but when placeholder regions
-                    // are placed into an SCC, that SCC may include
-                    // things from other universes that do not include
-                    // `ui`.
+                NLLRegionVariableOrigin::Placeholder(placeholder) => {
+                    // Each placeholder region is only visible from
+                    // its universe `ui` and its superuniverses. So we
+                    // can't just add it into `scc` unless the
+                    // universe of the scc can name this region.
                     let scc_universe = self.scc_universes[scc];
-                    if ui.is_subset_of(scc_universe) {
-                        self.scc_values.add_element(scc, ui);
+                    if placeholder.universe.is_subset_of(scc_universe) {
+                        self.scc_values.add_element(scc, placeholder);
                     } else {
                         self.add_incompatible_universe(scc);
                     }
@@ -544,8 +536,8 @@ fn universe_compatible(&self, scc_b: ConstraintSccIndex, scc_a: ConstraintSccInd
         // B's value, and check whether all of them are nameable
         // from universe_a
         self.scc_values
-            .subuniverses_contained_in(scc_b)
-            .all(|u| u.is_subset_of(universe_a))
+            .placeholders_contained_in(scc_b)
+            .all(|p| p.universe.is_subset_of(universe_a))
     }
 
     /// Extend `scc` so that it can outlive some placeholder region
@@ -1076,8 +1068,8 @@ fn check_universal_regions<'gcx>(
                     );
                 }
 
-                NLLRegionVariableOrigin::BoundRegion(universe) => {
-                    self.check_bound_universal_region(infcx, mir, mir_def_id, fr, universe);
+                NLLRegionVariableOrigin::Placeholder(placeholder) => {
+                    self.check_bound_universal_region(infcx, mir, mir_def_id, fr, placeholder);
                 }
 
                 NLLRegionVariableOrigin::Existential => {
@@ -1113,7 +1105,7 @@ fn check_universal_region<'gcx>(
         assert!(self.scc_universes[longer_fr_scc] == ty::UniverseIndex::ROOT);
         debug_assert!(
             self.scc_values
-                .subuniverses_contained_in(longer_fr_scc)
+                .placeholders_contained_in(longer_fr_scc)
                 .next()
                 .is_none()
         );
@@ -1181,9 +1173,12 @@ fn check_bound_universal_region<'gcx>(
         mir: &Mir<'tcx>,
         _mir_def_id: DefId,
         longer_fr: RegionVid,
-        universe: ty::UniverseIndex,
+        placeholder: ty::Placeholder,
     ) {
-        debug!("check_bound_universal_region(fr={:?})", longer_fr);
+        debug!(
+            "check_bound_universal_region(fr={:?}, placeholder={:?})",
+            longer_fr, placeholder,
+        );
 
         let longer_fr_scc = self.constraint_sccs.scc(longer_fr);
 
@@ -1196,7 +1191,7 @@ fn check_bound_universal_region<'gcx>(
                 .find(|element| match element {
                     RegionElement::Location(_) => true,
                     RegionElement::RootUniversalRegion(_) => true,
-                    RegionElement::SubUniversalRegion(ui) => *ui != universe,
+                    RegionElement::PlaceholderRegion(placeholder1) => placeholder != *placeholder1,
                 })
         } {
             Some(v) => v,
@@ -1207,10 +1202,10 @@ fn check_bound_universal_region<'gcx>(
         let error_region = match error_element {
             RegionElement::Location(l) => self.find_sub_region_live_at(longer_fr, l),
             RegionElement::RootUniversalRegion(r) => r,
-            RegionElement::SubUniversalRegion(error_ui) => self.definitions
+            RegionElement::PlaceholderRegion(error_placeholder) => self.definitions
                 .iter_enumerated()
                 .filter_map(|(r, definition)| match definition.origin {
-                    NLLRegionVariableOrigin::BoundRegion(ui) if error_ui == ui => Some(r),
+                    NLLRegionVariableOrigin::Placeholder(p) if p == error_placeholder => Some(r),
                     _ => None,
                 })
                 .next()
index 8dc41a9b2d32d13df61fc6af0403527c6b51a8d9..07372c19c46c936040bd8bf44f8615f7c5f90fab 100644 (file)
@@ -11,6 +11,7 @@
 use rustc::mir::{BasicBlock, Location, Mir};
 use rustc::ty::{self, RegionVid};
 use rustc_data_structures::bit_set::{HybridBitSet, SparseBitMatrix};
+use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::indexed_vec::Idx;
 use rustc_data_structures::indexed_vec::IndexVec;
 use std::fmt::Debug;
@@ -31,8 +32,7 @@
 impl RegionValueElements {
     crate fn new(mir: &Mir<'_>) -> Self {
         let mut num_points = 0;
-        let statements_before_block: IndexVec<BasicBlock, usize> = mir
-            .basic_blocks()
+        let statements_before_block: IndexVec<BasicBlock, usize> = mir.basic_blocks()
             .iter()
             .map(|block_data| {
                 let v = num_points;
@@ -48,7 +48,7 @@ impl RegionValueElements {
 
         let mut basic_blocks = IndexVec::with_capacity(num_points);
         for (bb, bb_data) in mir.basic_blocks().iter_enumerated() {
-            basic_blocks.extend((0 .. bb_data.statements.len() + 1).map(|_| bb));
+            basic_blocks.extend((0..bb_data.statements.len() + 1).map(|_| bb));
         }
 
         Self {
@@ -85,7 +85,10 @@ impl RegionValueElements {
         let block = self.basic_blocks[index];
         let start_index = self.statements_before_block[block];
         let statement_index = index.index() - start_index;
-        Location { block, statement_index }
+        Location {
+            block,
+            statement_index,
+        }
     }
 
     /// Sometimes we get point-indices back from bitsets that may be
@@ -103,13 +106,15 @@ impl RegionValueElements {
         index: PointIndex,
         stack: &mut Vec<PointIndex>,
     ) {
-        let Location { block, statement_index } = self.to_location(index);
+        let Location {
+            block,
+            statement_index,
+        } = self.to_location(index);
         if statement_index == 0 {
             // If this is a basic block head, then the predecessors are
             // the the terminators of other basic blocks
             stack.extend(
-                mir
-                    .predecessors_for(block)
+                mir.predecessors_for(block)
                     .iter()
                     .map(|&pred_bb| mir.terminator_loc(pred_bb))
                     .map(|pred_loc| self.point_from_location(pred_loc)),
@@ -127,10 +132,7 @@ impl RegionValueElements {
     pub struct PointIndex { DEBUG_FORMAT = "PointIndex({})" }
 }
 
-/// A single integer representing a (non-zero) `UniverseIndex`.
-/// Computed just by subtracting one from `UniverseIndex`; this is
-/// because the `0` value for `UniverseIndex` represents the root
-/// universe, and we don't need/want a bit for that one.
+/// A single integer representing a `ty::Placeholder`.
 newtype_index! {
     pub struct PlaceholderIndex { DEBUG_FORMAT = "PlaceholderIndex({})" }
 }
@@ -148,7 +150,7 @@ pub struct PlaceholderIndex { DEBUG_FORMAT = "PlaceholderIndex({})" }
 
     /// A subuniverse from a subuniverse (e.g., instantiated from a
     /// `for<'a> fn(&'a u32)` type).
-    SubUniversalRegion(ty::UniverseIndex),
+    PlaceholderRegion(ty::Placeholder),
 }
 
 /// When we initially compute liveness, we use a bit matrix storing
@@ -185,7 +187,10 @@ impl<N: Idx> LivenessValues<N> {
     /// Adds all the elements in the given bit array into the given
     /// region. Returns true if any of them are newly added.
     crate fn add_elements(&mut self, row: N, locations: &HybridBitSet<PointIndex>) -> bool {
-        debug!("LivenessValues::add_elements(row={:?}, locations={:?})", row, locations);
+        debug!(
+            "LivenessValues::add_elements(row={:?}, locations={:?})",
+            row, locations
+        );
         self.points.union_into_row(row, locations)
     }
 
@@ -214,6 +219,52 @@ impl<N: Idx> LivenessValues<N> {
     }
 }
 
+/// Maps from `ty::Placeholder` values that are used in the rest of
+/// rustc to the internal `PlaceholderIndex` values that are used in
+/// NLL.
+#[derive(Default)]
+crate struct PlaceholderIndices {
+    to_index: FxHashMap<ty::Placeholder, PlaceholderIndex>,
+    from_index: IndexVec<PlaceholderIndex, ty::Placeholder>,
+}
+
+impl PlaceholderIndices {
+    crate fn insert(&mut self, placeholder: ty::Placeholder) -> PlaceholderIndex {
+        let PlaceholderIndices {
+            to_index,
+            from_index,
+        } = self;
+        *to_index
+            .entry(placeholder)
+            .or_insert_with(|| from_index.push(placeholder))
+    }
+
+    crate fn lookup_index(&self, placeholder: ty::Placeholder) -> PlaceholderIndex {
+        self.to_index[&placeholder]
+    }
+
+    crate fn lookup_placeholder(&self, placeholder: PlaceholderIndex) -> ty::Placeholder {
+        self.from_index[placeholder]
+    }
+
+    crate fn len(&self) -> usize {
+        self.from_index.len()
+    }
+}
+
+impl ::std::iter::FromIterator<ty::Placeholder> for PlaceholderIndices {
+    fn from_iter<I>(iter: I) -> Self
+    where
+        I: IntoIterator<Item = ty::Placeholder>,
+    {
+        let mut result = Self::default();
+        iter.into_iter().for_each(|p| {
+            result.insert(p);
+        });
+        result
+    }
+}
+
 /// Stores the full values for a set of regions (in contrast to
 /// `LivenessValues`, which only stores those points in the where a
 /// region is live). The full value for a region may contain points in
@@ -235,6 +286,7 @@ impl<N: Idx> LivenessValues<N> {
 #[derive(Clone)]
 crate struct RegionValues<N: Idx> {
     elements: Rc<RegionValueElements>,
+    placeholder_indices: Rc<PlaceholderIndices>,
     points: SparseBitMatrix<N, PointIndex>,
     free_regions: SparseBitMatrix<N, RegionVid>,
 
@@ -250,12 +302,13 @@ impl<N: Idx> RegionValues<N> {
     crate fn new(
         elements: &Rc<RegionValueElements>,
         num_universal_regions: usize,
-        max_universe: ty::UniverseIndex,
+        placeholder_indices: &Rc<PlaceholderIndices>,
     ) -> Self {
-        let num_placeholders = max_universe.as_usize();
+        let num_placeholders = placeholder_indices.len();
         Self {
             elements: elements.clone(),
             points: SparseBitMatrix::new(elements.num_points),
+            placeholder_indices: placeholder_indices.clone(),
             free_regions: SparseBitMatrix::new(num_universal_regions),
             placeholders: SparseBitMatrix::new(num_placeholders),
         }
@@ -313,14 +366,11 @@ impl<N: Idx> RegionValues<N> {
 
     /// Returns the locations contained within a given region `r`.
     crate fn locations_outlived_by<'a>(&'a self, r: N) -> impl Iterator<Item = Location> + 'a {
-        self.points
-            .row(r)
-            .into_iter()
-            .flat_map(move |set| {
-                set.iter()
-                    .take_while(move |&p| self.elements.point_in_range(p))
-                    .map(move |p| self.elements.to_location(p))
-            })
+        self.points.row(r).into_iter().flat_map(move |set| {
+            set.iter()
+                .take_while(move |&p| self.elements.point_in_range(p))
+                .map(move |p| self.elements.to_location(p))
+        })
     }
 
     /// Returns just the universal regions that are contained in a given region's value.
@@ -335,32 +385,30 @@ impl<N: Idx> RegionValues<N> {
     }
 
     /// Returns all the elements contained in a given region's value.
-    crate fn subuniverses_contained_in<'a>(
+    crate fn placeholders_contained_in<'a>(
         &'a self,
         r: N,
-    ) -> impl Iterator<Item = ty::UniverseIndex> + 'a {
+    ) -> impl Iterator<Item = ty::Placeholder> + 'a {
         self.placeholders
             .row(r)
             .into_iter()
             .flat_map(|set| set.iter())
-            .map(|p| ty::UniverseIndex::from_u32((p.index() + 1) as u32))
+            .map(move |p| self.placeholder_indices.lookup_placeholder(p))
     }
 
     /// Returns all the elements contained in a given region's value.
     crate fn elements_contained_in<'a>(&'a self, r: N) -> impl Iterator<Item = RegionElement> + 'a {
         let points_iter = self.locations_outlived_by(r).map(RegionElement::Location);
 
-        let free_regions_iter = self
-            .universal_regions_outlived_by(r)
+        let free_regions_iter = self.universal_regions_outlived_by(r)
             .map(RegionElement::RootUniversalRegion);
 
-        let subuniverses_iter = self
-            .subuniverses_contained_in(r)
-            .map(RegionElement::SubUniversalRegion);
+        let placeholder_universes_iter = self.placeholders_contained_in(r)
+            .map(RegionElement::PlaceholderRegion);
 
         points_iter
             .chain(free_regions_iter)
-            .chain(subuniverses_iter)
+            .chain(placeholder_universes_iter)
     }
 
     /// Returns a "pretty" string value of the region. Meant for debugging.
@@ -397,14 +445,14 @@ fn contained_in_row<N: Idx>(self, values: &RegionValues<N>, row: N) -> bool {
     }
 }
 
-impl ToElementIndex for ty::UniverseIndex {
+impl ToElementIndex for ty::Placeholder {
     fn add_to_row<N: Idx>(self, values: &mut RegionValues<N>, row: N) -> bool {
-        let index = PlaceholderIndex::new(self.as_usize() - 1);
+        let index = values.placeholder_indices.lookup_index(self);
         values.placeholders.insert(row, index)
     }
 
     fn contained_in_row<N: Idx>(self, values: &RegionValues<N>, row: N) -> bool {
-        let index = PlaceholderIndex::new(self.as_usize() - 1);
+        let index = values.placeholder_indices.lookup_index(self);
         values.placeholders.contains(row, index)
     }
 }
@@ -467,7 +515,7 @@ fn region_value_str(elements: impl IntoIterator<Item = RegionElement>) -> String
                 result.push_str(&format!("{:?}", fr));
             }
 
-            RegionElement::SubUniversalRegion(ur) => {
+            RegionElement::PlaceholderRegion(placeholder) => {
                 if let Some((location1, location2)) = open_location {
                     push_sep(&mut result);
                     push_location_range(&mut result, location1, location2);
@@ -475,7 +523,7 @@ fn region_value_str(elements: impl IntoIterator<Item = RegionElement>) -> String
                 }
 
                 push_sep(&mut result);
-                result.push_str(&format!("{:?}", ur));
+                result.push_str(&format!("{:?}", placeholder));
             }
         }
     }
index ef4cc3452b1ef9e1222f463e1cc019c085a82243..99ac80862b13e695a28ac1990bfcc41b9adb0cff 100644 (file)
@@ -15,7 +15,9 @@
 use borrow_check::location::LocationTable;
 use borrow_check::nll::constraints::{ConstraintCategory, ConstraintSet, OutlivesConstraint};
 use borrow_check::nll::facts::AllFacts;
-use borrow_check::nll::region_infer::values::{LivenessValues, RegionValueElements};
+use borrow_check::nll::region_infer::values::LivenessValues;
+use borrow_check::nll::region_infer::values::PlaceholderIndices;
+use borrow_check::nll::region_infer::values::RegionValueElements;
 use borrow_check::nll::region_infer::{ClosureRegionRequirementsExt, TypeTest};
 use borrow_check::nll::renumber;
 use borrow_check::nll::type_check::free_region_relations::{
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::subst::Subst;
 use rustc::ty::{self, CanonicalTy, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind};
-use std::{fmt, iter};
 use std::rc::Rc;
+use std::{fmt, iter};
 use syntax_pos::{Span, DUMMY_SP};
 use transform::{MirPass, MirSource};
 
-use rustc_data_structures::fx::FxHashSet;
 use either::Either;
+use rustc_data_structures::fx::FxHashSet;
 
 macro_rules! span_mirbug {
     ($context:expr, $elem:expr, $($message:tt)*) => ({
@@ -128,6 +130,7 @@ pub(crate) fn type_check<'gcx, 'tcx>(
         outlives_constraints: ConstraintSet::default(),
         type_tests: Vec::default(),
     };
+    let mut placeholder_indices = PlaceholderIndices::default();
 
     let CreateResult {
         universal_region_relations,
@@ -147,6 +150,7 @@ pub(crate) fn type_check<'gcx, 'tcx>(
         borrow_set,
         all_facts,
         constraints: &mut constraints,
+        placeholder_indices: &mut placeholder_indices,
     };
 
     type_check_internal(
@@ -162,12 +166,15 @@ pub(crate) fn type_check<'gcx, 'tcx>(
             cx.equate_inputs_and_outputs(mir, universal_regions, &normalized_inputs_and_output);
             liveness::generate(cx, mir, elements, flow_inits, move_data, location_table);
 
-            cx.borrowck_context.as_mut().map(|bcx| translate_outlives_facts(bcx));
+            cx.borrowck_context
+                .as_mut()
+                .map(|bcx| translate_outlives_facts(bcx));
         },
     );
 
     MirTypeckResults {
         constraints,
+        placeholder_indices,
         universal_region_relations,
     }
 }
@@ -210,21 +217,25 @@ fn type_check_internal<'a, 'gcx, 'tcx, R>(
 fn translate_outlives_facts(cx: &mut BorrowCheckContext) {
     if let Some(facts) = cx.all_facts {
         let location_table = cx.location_table;
-        facts.outlives.extend(
-            cx.constraints.outlives_constraints.iter().flat_map(|constraint: &OutlivesConstraint| {
-                if let Some(from_location) = constraint.locations.from_location() {
-                    Either::Left(iter::once((
-                        constraint.sup,
-                        constraint.sub,
-                        location_table.mid_index(from_location),
-                    )))
-                } else {
-                    Either::Right(location_table.all_points().map(move |location| {
-                       (constraint.sup, constraint.sub, location)
-                    }))
-                }
-            })
-        );
+        facts
+            .outlives
+            .extend(cx.constraints.outlives_constraints.iter().flat_map(
+                |constraint: &OutlivesConstraint| {
+                    if let Some(from_location) = constraint.locations.from_location() {
+                        Either::Left(iter::once((
+                            constraint.sup,
+                            constraint.sub,
+                            location_table.mid_index(from_location),
+                        )))
+                    } else {
+                        Either::Right(
+                            location_table
+                                .all_points()
+                                .map(move |location| (constraint.sup, constraint.sub, location)),
+                        )
+                    }
+                },
+            ));
     }
 }
 
@@ -718,10 +729,12 @@ struct BorrowCheckContext<'a, 'tcx: 'a> {
     all_facts: &'a mut Option<AllFacts>,
     borrow_set: &'a BorrowSet<'tcx>,
     constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
+    placeholder_indices: &'a mut PlaceholderIndices,
 }
 
 crate struct MirTypeckResults<'tcx> {
     crate constraints: MirTypeckRegionConstraints<'tcx>,
+    crate placeholder_indices: PlaceholderIndices,
     crate universal_region_relations: Rc<UniversalRegionRelations<'tcx>>,
 }
 
index 13d59c3ba29c6707f52a3f2bbe7129dbc7252667..4e8dbf8498e2a643b421333590d132e72f04ff37 100644 (file)
@@ -146,18 +146,27 @@ trait TypeRelatingDelegate<'tcx> {
     /// delegate.
     fn push_outlives(&mut self, sup: ty::Region<'tcx>, sub: ty::Region<'tcx>);
 
-    /// Creates a new region variable representing an instantiated
-    /// higher-ranked region; this will be either existential or
-    /// universal depending on the context.  So e.g. if you have
-    /// `for<'a> fn(..) <: for<'b> fn(..)`, then we will first
-    /// instantiate `'b` with a universally quantitifed region and
-    /// then `'a` with an existentially quantified region (the order
-    /// is important so that the existential region `'a` can see the
-    /// universal one).
-    fn next_region_var(
-        &mut self,
-        universally_quantified: UniversallyQuantified,
-    ) -> ty::Region<'tcx>;
+    /// Creates a new universe index. Used when instantiating placeholders.
+    fn next_subuniverse(&mut self) -> ty::UniverseIndex;
+
+    /// Creates a new region variable representing a higher-ranked
+    /// region that is instantiated existentially. This creates an
+    /// inference variable, typically.
+    ///
+    /// So e.g. if you have `for<'a> fn(..) <: for<'b> fn(..)`, then
+    /// we will invoke this method to instantiate `'a` with an
+    /// inference variable (though `'b` would be instantiated first,
+    /// as a placeholder).
+    fn next_existential_region_var(&mut self) -> ty::Region<'tcx>;
+
+    /// Creates a new region variable representing a
+    /// higher-ranked region that is instantiated universally.
+    /// This creates a new region placeholder, typically.
+    ///
+    /// So e.g. if you have `for<'a> fn(..) <: for<'b> fn(..)`, then
+    /// we will invoke this method to instantiate `'b` with a
+    /// placeholder region.
+    fn next_placeholder_region(&mut self, placeholder: ty::Placeholder) -> ty::Region<'tcx>;
 
     /// Creates a new existential region in the given universe. This
     /// is used when handling subtyping and type variables -- if we
@@ -197,15 +206,20 @@ fn new(
 }
 
 impl TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, '_, 'tcx> {
-    fn next_region_var(
-        &mut self,
-        universally_quantified: UniversallyQuantified,
-    ) -> ty::Region<'tcx> {
-        let origin = if universally_quantified.0 {
-            NLLRegionVariableOrigin::BoundRegion(self.infcx.create_subuniverse())
-        } else {
-            NLLRegionVariableOrigin::Existential
-        };
+    fn next_subuniverse(&mut self) -> ty::UniverseIndex {
+        self.infcx.create_subuniverse()
+    }
+
+    fn next_existential_region_var(&mut self) -> ty::Region<'tcx> {
+        let origin = NLLRegionVariableOrigin::Existential;
+        self.infcx.next_nll_region_var(origin)
+    }
+
+    fn next_placeholder_region(&mut self, placeholder: ty::Placeholder) -> ty::Region<'tcx> {
+        let origin = NLLRegionVariableOrigin::Placeholder(placeholder);
+        if let Some(borrowck_context) = &mut self.borrowck_context {
+            borrowck_context.placeholder_indices.insert(placeholder);
+        }
         self.infcx.next_nll_region_var(origin)
     }
 
@@ -286,12 +300,37 @@ fn create_scope(
         universally_quantified: UniversallyQuantified,
     ) -> BoundRegionScope<'tcx> {
         let mut scope = BoundRegionScope::default();
+
+        // Create a callback that creates (via the delegate) either an
+        // existential or placeholder region as needed.
+        let mut next_region = {
+            let delegate = &mut self.delegate;
+            let mut lazy_universe = None;
+            move |br: ty::BoundRegion| {
+                if universally_quantified.0 {
+                    // The first time this closure is called, create a
+                    // new universe for the placeholders we will make
+                    // from here out.
+                    let universe = lazy_universe.unwrap_or_else(|| {
+                        let universe = delegate.next_subuniverse();
+                        lazy_universe = Some(universe);
+                        universe
+                    });
+
+                    let placeholder = ty::Placeholder { universe, name: br };
+                    delegate.next_placeholder_region(placeholder)
+                } else {
+                    delegate.next_existential_region_var()
+                }
+            }
+        };
+
         value.skip_binder().visit_with(&mut ScopeInstantiator {
-            delegate: &mut self.delegate,
+            next_region: &mut next_region,
             target_index: ty::INNERMOST,
-            universally_quantified,
             bound_region_scope: &mut scope,
         });
+
         scope
     }
 
@@ -604,21 +643,14 @@ fn binders<T>(
 /// binder depth, and finds late-bound regions targeting the
 /// `for<..`>.  For each of those, it creates an entry in
 /// `bound_region_scope`.
-struct ScopeInstantiator<'me, 'tcx: 'me, D>
-where
-    D: TypeRelatingDelegate<'tcx> + 'me,
-{
-    delegate: &'me mut D,
+struct ScopeInstantiator<'me, 'tcx: 'me> {
+    next_region: &'me mut dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
     // The debruijn index of the scope we are instantiating.
     target_index: ty::DebruijnIndex,
-    universally_quantified: UniversallyQuantified,
     bound_region_scope: &'me mut BoundRegionScope<'tcx>,
 }
 
-impl<'me, 'tcx, D> TypeVisitor<'tcx> for ScopeInstantiator<'me, 'tcx, D>
-where
-    D: TypeRelatingDelegate<'tcx>,
-{
+impl<'me, 'tcx> TypeVisitor<'tcx> for ScopeInstantiator<'me, 'tcx> {
     fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> bool {
         self.target_index.shift_in(1);
         t.super_visit_with(self);
@@ -629,9 +661,8 @@ fn visit_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> bool {
 
     fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
         let ScopeInstantiator {
-            universally_quantified,
             bound_region_scope,
-            delegate,
+            next_region,
             ..
         } = self;
 
@@ -640,7 +671,7 @@ fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool {
                 bound_region_scope
                     .map
                     .entry(*br)
-                    .or_insert_with(|| delegate.next_region_var(*universally_quantified));
+                    .or_insert_with(|| next_region(*br));
             }
 
             _ => {}
index c4cb7958fd3c35865cf6eef19165b5c206227ff0..b754d63f7183bbb990e53394ea858db3d482d723 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use build::{BlockAnd, BlockAndExtension, Builder};
+use build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
 use build::ForGuard::OutsideGuard;
 use build::matches::ArmHasGuard;
 use hair::*;
@@ -93,6 +93,7 @@ fn ast_block_stmts(&mut self,
             let Stmt { kind, opt_destruction_scope } = this.hir.mirror(stmt);
             match kind {
                 StmtKind::Expr { scope, expr } => {
+                    this.block_context.push(BlockFrame::Statement { ignores_expr_result: true });
                     unpack!(block = this.in_opt_scope(
                         opt_destruction_scope.map(|de|(de, source_info)), block, |this| {
                             let si = (scope, source_info);
@@ -109,6 +110,13 @@ fn ast_block_stmts(&mut self,
                     initializer,
                     lint_level
                 } => {
+                    let ignores_expr_result = if let PatternKind::Wild = *pattern.kind {
+                        true
+                    } else {
+                        false
+                    };
+                    this.block_context.push(BlockFrame::Statement { ignores_expr_result });
+
                     // Enter the remainder scope, i.e. the bindings' destruction scope.
                     this.push_scope((remainder_scope, source_info));
                     let_scope_stack.push(remainder_scope);
@@ -155,19 +163,40 @@ fn ast_block_stmts(&mut self,
                     }
                 }
             }
+
+            let popped = this.block_context.pop();
+            assert!(popped.map_or(false, |bf|bf.is_statement()));
         }
+
         // Then, the block may have an optional trailing expression which is a “return” value
-        // of the block.
+        // of the block, which is stored into `destination`.
+        let tcx = this.hir.tcx();
+        let destination_ty = destination.ty(&this.local_decls, tcx).to_ty(tcx);
         if let Some(expr) = expr {
+            let tail_result_is_ignored = destination_ty.is_unit() ||
+                match this.block_context.last() {
+                    // no context: conservatively assume result is read
+                    None => false,
+
+                    // sub-expression: block result feeds into some computation
+                    Some(BlockFrame::SubExpr) => false,
+
+                    // otherwise: use accumualated is_ignored state.
+                    Some(BlockFrame::TailExpr { tail_result_is_ignored: ignored }) |
+                    Some(BlockFrame::Statement { ignores_expr_result: ignored }) => *ignored,
+                };
+            this.block_context.push(BlockFrame::TailExpr { tail_result_is_ignored });
+
             unpack!(block = this.into(destination, block, expr));
+            let popped = this.block_context.pop();
+
+            assert!(popped.map_or(false, |bf|bf.is_tail_expr()));
         } else {
             // If a block has no trailing expression, then it is given an implicit return type.
             // This return type is usually `()`, unless the block is diverging, in which case the
             // return type is `!`. For the unit type, we need to actually return the unit, but in
             // the case of `!`, no return value is required, as the block will never return.
-            let tcx = this.hir.tcx();
-            let ty = destination.ty(&this.local_decls, tcx).to_ty(tcx);
-            if ty.is_unit() {
+            if destination_ty.is_unit() {
                 // We only want to assign an implicit `()` as the return value of the block if the
                 // block does not diverge. (Otherwise, we may try to assign a unit to a `!`-type.)
                 this.cfg.push_assign_unit(block, source_info, destination);
index a2dcce6adcb6e1b4c9a4fad429f2c7db34c86ed5..e0bf02c6739e3839354feeb79a8f375b0ec87629 100644 (file)
@@ -10,7 +10,7 @@
 
 //! See docs in build/expr/mod.rs
 
-use build::{BlockAnd, BlockAndExtension, Builder};
+use build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
 use hair::*;
 use rustc::middle::region;
 use rustc::mir::*;
@@ -59,14 +59,30 @@ fn expr_as_temp(
         }
 
         let expr_ty = expr.ty;
-        let temp = if mutability == Mutability::Not {
-            this.local_decls
-                .push(LocalDecl::new_immutable_temp(expr_ty, expr_span))
-        } else {
-            this.local_decls
-                .push(LocalDecl::new_temp(expr_ty, expr_span))
-        };
+        let temp = {
+            let mut local_decl = LocalDecl::new_temp(expr_ty, expr_span);
+            if mutability == Mutability::Not {
+                local_decl = local_decl.immutable();
+            }
+
+            debug!("creating temp {:?} with block_context: {:?}", local_decl, this.block_context);
+            // Find out whether this temp is being created within the
+            // tail expression of a block whose result is ignored.
+            for bf in this.block_context.iter().rev() {
+                match bf {
+                    BlockFrame::SubExpr => continue,
+                    BlockFrame::Statement { .. } => break,
+                    &BlockFrame::TailExpr { tail_result_is_ignored } => {
+                        local_decl = local_decl.block_tail(BlockTailInfo {
+                            tail_result_is_ignored
+                        });
+                        break;
+                    }
+                }
+            }
 
+            this.local_decls.push(local_decl)
+        };
         if !expr_ty.is_never() {
             this.cfg.push(
                 block,
index 9ea3805fdc65210dbae7a0f87ede997f4afe9992..4f5ed34a46133622488aca3670bc13b646621b0a 100644 (file)
@@ -11,7 +11,7 @@
 //! See docs in build/expr/mod.rs
 
 use build::expr::category::{Category, RvalueFunc};
-use build::{BlockAnd, BlockAndExtension, Builder};
+use build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
 use hair::*;
 use rustc::mir::*;
 use rustc::ty;
@@ -39,7 +39,17 @@ pub fn into_expr(
         let expr_span = expr.span;
         let source_info = this.source_info(expr_span);
 
-        match expr.kind {
+        let expr_is_block_or_scope = match expr.kind {
+            ExprKind::Block { .. } => true,
+            ExprKind::Scope { .. } => true,
+            _ => false,
+        };
+
+        if !expr_is_block_or_scope {
+            this.block_context.push(BlockFrame::SubExpr);
+        }
+
+        let block_and = match expr.kind {
             ExprKind::Scope {
                 region_scope,
                 lint_level,
@@ -264,7 +274,7 @@ pub fn into_expr(
                 );
                 exit_block.unit()
             }
-            ExprKind::Call { ty, fun, args } => {
+            ExprKind::Call { ty, fun, args, from_hir_call } => {
                 // FIXME(canndrew): This is_never should probably be an is_uninhabited
                 let diverges = expr.ty.is_never();
                 let intrinsic = match ty.sty {
@@ -302,6 +312,7 @@ pub fn into_expr(
                         visibility_scope: source_info.scope,
                         internal: true,
                         is_user_variable: None,
+                        is_block_tail: None,
                     });
                     let ptr_temp = Place::Local(ptr_temp);
                     let block = unpack!(this.into(&ptr_temp, block, ptr));
@@ -326,6 +337,7 @@ pub fn into_expr(
                             } else {
                                 Some((destination.clone(), success))
                             },
+                            from_hir_call,
                         },
                     );
                     success.unit()
@@ -413,6 +425,13 @@ pub fn into_expr(
                     .push_assign(block, source_info, destination, rvalue);
                 block.unit()
             }
+        };
+
+        if !expr_is_block_or_scope {
+            let popped = this.block_context.pop();
+            assert!(popped.is_some());
         }
+
+        block_and
     }
 }
index 32f09599ace82fd2e04913a1afa99d3989f8e3b3..d2b39f088b65e8c401ae5a35dd01214a82d6acaa 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use build::scope::BreakableScope;
-use build::{BlockAnd, BlockAndExtension, Builder};
+use build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
 use hair::*;
 use rustc::mir::*;
 
@@ -20,6 +20,7 @@ pub fn stmt_expr(&mut self, mut block: BasicBlock, expr: Expr<'tcx>) -> BlockAnd
         let source_info = this.source_info(expr.span);
         // Handle a number of expressions that don't need a destination at all. This
         // avoids needing a mountain of temporary `()` variables.
+        let expr2 = expr.clone();
         match expr.kind {
             ExprKind::Scope {
                 region_scope,
@@ -40,19 +41,23 @@ pub fn stmt_expr(&mut self, mut block: BasicBlock, expr: Expr<'tcx>) -> BlockAnd
                 // is better for borrowck interaction with overloaded
                 // operators like x[j] = x[i].
 
+                debug!("stmt_expr Assign block_context.push(SubExpr) : {:?}", expr2);
+                this.block_context.push(BlockFrame::SubExpr);
+
                 // Generate better code for things that don't need to be
                 // dropped.
                 if this.hir.needs_drop(lhs.ty) {
                     let rhs = unpack!(block = this.as_local_operand(block, rhs));
                     let lhs = unpack!(block = this.as_place(block, lhs));
                     unpack!(block = this.build_drop_and_replace(block, lhs_span, lhs, rhs));
-                    block.unit()
                 } else {
                     let rhs = unpack!(block = this.as_local_rvalue(block, rhs));
                     let lhs = unpack!(block = this.as_place(block, lhs));
                     this.cfg.push_assign(block, source_info, &lhs, rhs);
-                    block.unit()
                 }
+
+                this.block_context.pop();
+                block.unit()
             }
             ExprKind::AssignOp { op, lhs, rhs } => {
                 // FIXME(#28160) there is an interesting semantics
@@ -66,6 +71,9 @@ pub fn stmt_expr(&mut self, mut block: BasicBlock, expr: Expr<'tcx>) -> BlockAnd
                 let lhs = this.hir.mirror(lhs);
                 let lhs_ty = lhs.ty;
 
+                debug!("stmt_expr AssignOp block_context.push(SubExpr) : {:?}", expr2);
+                this.block_context.push(BlockFrame::SubExpr);
+
                 // As above, RTL.
                 let rhs = unpack!(block = this.as_local_operand(block, rhs));
                 let lhs = unpack!(block = this.as_place(block, lhs));
@@ -85,6 +93,7 @@ pub fn stmt_expr(&mut self, mut block: BasicBlock, expr: Expr<'tcx>) -> BlockAnd
                 );
                 this.cfg.push_assign(block, source_info, &lhs, result);
 
+                this.block_context.pop();
                 block.unit()
             }
             ExprKind::Continue { label } => {
@@ -114,7 +123,10 @@ pub fn stmt_expr(&mut self, mut block: BasicBlock, expr: Expr<'tcx>) -> BlockAnd
                     (break_block, region_scope, break_destination.clone())
                 };
                 if let Some(value) = value {
-                    unpack!(block = this.into(&destination, block, value))
+                    debug!("stmt_expr Break val block_context.push(SubExpr) : {:?}", expr2);
+                    this.block_context.push(BlockFrame::SubExpr);
+                    unpack!(block = this.into(&destination, block, value));
+                    this.block_context.pop();
                 } else {
                     this.cfg.push_assign_unit(block, source_info, &destination)
                 }
@@ -123,7 +135,13 @@ pub fn stmt_expr(&mut self, mut block: BasicBlock, expr: Expr<'tcx>) -> BlockAnd
             }
             ExprKind::Return { value } => {
                 block = match value {
-                    Some(value) => unpack!(this.into(&Place::Local(RETURN_PLACE), block, value)),
+                    Some(value) => {
+                        debug!("stmt_expr Return val block_context.push(SubExpr) : {:?}", expr2);
+                        this.block_context.push(BlockFrame::SubExpr);
+                        let result = unpack!(this.into(&Place::Local(RETURN_PLACE), block, value));
+                        this.block_context.pop();
+                        result
+                    }
                     None => {
                         this.cfg
                             .push_assign_unit(block, source_info, &Place::Local(RETURN_PLACE));
@@ -140,6 +158,8 @@ pub fn stmt_expr(&mut self, mut block: BasicBlock, expr: Expr<'tcx>) -> BlockAnd
                 outputs,
                 inputs,
             } => {
+                debug!("stmt_expr InlineAsm block_context.push(SubExpr) : {:?}", expr2);
+                this.block_context.push(BlockFrame::SubExpr);
                 let outputs = outputs
                     .into_iter()
                     .map(|output| unpack!(block = this.as_place(block, output)))
@@ -161,6 +181,7 @@ pub fn stmt_expr(&mut self, mut block: BasicBlock, expr: Expr<'tcx>) -> BlockAnd
                         },
                     },
                 );
+                this.block_context.pop();
                 block.unit()
             }
             _ => {
index e40ed51f7d3544677832cf48b6fd564b6b90b4ec..656c78a46ed78c84d75ce5366cdc21c004fec938 100644 (file)
@@ -1485,6 +1485,7 @@ fn declare_binding(
             source_info,
             visibility_scope,
             internal: false,
+            is_block_tail: None,
             is_user_variable: Some(ClearCrossCrate::Set(BindingForm::Var(VarBindingForm {
                 binding_mode,
                 // hypothetically, `visit_bindings` could try to unzip
@@ -1518,6 +1519,7 @@ fn declare_binding(
                 visibility_scope,
                 // FIXME: should these secretly injected ref_for_guard's be marked as `internal`?
                 internal: false,
+                is_block_tail: None,
                 is_user_variable: Some(ClearCrossCrate::Set(BindingForm::RefForGuard)),
             });
             LocalsForNode::ForGuard {
index caef3ef80dbc2c43ef26420a10f9943faa360656..a8713286f18ecc721e8f31f7393acce2ccd77f85 100644 (file)
@@ -361,6 +361,7 @@ pub fn perform_test(&mut self,
                         args: vec![val, expect],
                         destination: Some((eq_result.clone(), eq_block)),
                         cleanup: Some(cleanup),
+                        from_hir_call: false,
                     });
 
                     // check the result
index 3dbd3bbb41573b8834aa03ec6567c8c93d39a7c2..9e78932bffea6d638b3b5b4594af01997f50dccf 100644 (file)
@@ -281,6 +281,57 @@ fn liberated_closure_env_ty<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
     tcx.liberate_late_bound_regions(closure_def_id, &closure_env_ty)
 }
 
+#[derive(Debug, PartialEq, Eq)]
+pub enum BlockFrame {
+    /// Evaluation is currently within a statement.
+    ///
+    /// Examples include:
+    ///  1. `EXPR;`
+    ///  2. `let _ = EXPR;`
+    ///  3. `let x = EXPR;`
+    Statement {
+        /// If true, then statement discards result from evaluating
+        /// the expression (such as examples 1 and 2 above).
+        ignores_expr_result: bool
+    },
+
+    /// Evaluation is currently within the tail expression of a block.
+    ///
+    /// Example: `{ STMT_1; STMT_2; EXPR }`
+    TailExpr {
+        /// If true, then the surrounding context of the block ignores
+        /// the result of evaluating the block's tail expression.
+        ///
+        /// Example: `let _ = { STMT_1; EXPR };`
+        tail_result_is_ignored: bool
+    },
+
+    /// Generic mark meaning that the block occurred as a subexpression
+    /// where the result might be used.
+    ///
+    /// Examples: `foo(EXPR)`, `match EXPR { ... }`
+    SubExpr,
+}
+
+impl BlockFrame {
+    fn is_tail_expr(&self) -> bool {
+        match *self {
+            BlockFrame::TailExpr { .. } => true,
+
+            BlockFrame::Statement { .. } |
+            BlockFrame::SubExpr => false,
+        }
+    }
+    fn is_statement(&self) -> bool {
+        match *self {
+            BlockFrame::Statement { .. } => true,
+
+            BlockFrame::TailExpr { .. } |
+            BlockFrame::SubExpr => false,
+        }
+    }
+ }
+
 struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     hir: Cx<'a, 'gcx, 'tcx>,
     cfg: CFG<'tcx>,
@@ -292,6 +343,20 @@ struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     /// see the `scope` module for more details
     scopes: Vec<scope::Scope<'tcx>>,
 
+    /// the block-context: each time we build the code within an hair::Block,
+    /// we push a frame here tracking whether we are building a statement or
+    /// if we are pushing the tail expression of the block. This is used to
+    /// embed information in generated temps about whether they were created
+    /// for a block tail expression or not.
+    ///
+    /// It would be great if we could fold this into `self.scopes`
+    /// somehow; but right now I think that is very tightly tied to
+    /// the code generation in ways that we cannot (or should not)
+    /// start just throwing new entries onto that vector in order to
+    /// distinguish the context of EXPR1 from the context of EXPR2 in
+    /// `{ STMTS; EXPR1 } + EXPR2`
+    block_context: Vec<BlockFrame>,
+
     /// The current unsafe block in scope, even if it is hidden by
     /// a PushUnsafeBlock
     unpushed_unsafe: Safety,
@@ -695,6 +760,7 @@ fn new(hir: Cx<'a, 'gcx, 'tcx>,
             fn_span: span,
             arg_count,
             scopes: vec![],
+            block_context: vec![],
             source_scopes: IndexVec::new(),
             source_scope: OUTERMOST_SOURCE_SCOPE,
             source_scope_local_data: IndexVec::new(),
@@ -781,6 +847,7 @@ fn args_and_body(&mut self,
                 name,
                 internal: false,
                 is_user_variable: None,
+                is_block_tail: None,
             });
         }
 
index 1e362e6f0dccfeb55b816d62192216370f1d1589..da4bd780eb4faa9b78eb2ad4ca5102eb9e943184 100644 (file)
@@ -795,7 +795,7 @@ fn propagate_bits_into_graph_successors_of(
                     self.propagate_bits_into_entry_set_for(in_out, *target, dirty_list);
                 }
             }
-            mir::TerminatorKind::Call { cleanup, ref destination, func: _, args: _ } => {
+            mir::TerminatorKind::Call { cleanup, ref destination, .. } => {
                 if let Some(unwind) = cleanup {
                     if !self.dead_unwinds.contains(bb) {
                         self.propagate_bits_into_entry_set_for(in_out, unwind, dirty_list);
index 2884b15ca47db2bdce009f5380b9d83c81861039..32b1187011672cbb5cbd8662c8bee9c21ea0bea4 100644 (file)
@@ -380,7 +380,13 @@ fn gather_terminator(&mut self, term: &Terminator<'tcx>) {
                 self.gather_operand(value);
                 self.gather_init(location, InitKind::Deep);
             }
-            TerminatorKind::Call { ref func, ref args, ref destination, cleanup: _ } => {
+            TerminatorKind::Call {
+                ref func,
+                ref args,
+                ref destination,
+                cleanup: _,
+                from_hir_call: _,
+            } => {
                 self.gather_operand(func);
                 for arg in args {
                     self.gather_operand(arg);
index f94f1a1a8c8fededb17db6ab4b8ff33adca4c540..8d50fbbdc6b35dd3d23ebd1591d61193986a0344 100644 (file)
@@ -21,6 +21,7 @@
 use rustc::hir;
 use rustc::hir::def_id::LocalDefId;
 use rustc::mir::{BorrowKind};
+use syntax_pos::Span;
 
 impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
     type Output = Expr<'tcx>;
@@ -232,9 +233,9 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
 
     let kind = match expr.node {
         // Here comes the interesting stuff:
-        hir::ExprKind::MethodCall(.., ref args) => {
+        hir::ExprKind::MethodCall(_, method_span, ref args) => {
             // Rewrite a.b(c) into UFCS form like Trait::b(a, c)
-            let expr = method_callee(cx, expr, None);
+            let expr = method_callee(cx, expr, method_span,None);
             let args = args.iter()
                 .map(|e| e.to_ref())
                 .collect();
@@ -242,6 +243,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                 ty: expr.ty,
                 fun: expr.to_ref(),
                 args,
+                from_hir_call: true,
             }
         }
 
@@ -254,7 +256,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
 
                 // rewrite f(u, v) into FnOnce::call_once(f, (u, v))
 
-                let method = method_callee(cx, expr, None);
+                let method = method_callee(cx, expr, fun.span,None);
 
                 let arg_tys = args.iter().map(|e| cx.tables().expr_ty_adjusted(e));
                 let tupled_args = Expr {
@@ -268,6 +270,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                     ty: method.ty,
                     fun: method.to_ref(),
                     args: vec![fun.to_ref(), tupled_args.to_ref()],
+                    from_hir_call: true,
                 }
             } else {
                 let adt_data = if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) =
@@ -321,6 +324,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                         ty: cx.tables().node_id_to_type(fun.hir_id),
                         fun: fun.to_ref(),
                         args: args.to_ref(),
+                        from_hir_call: true,
                     }
                 }
             }
@@ -828,6 +832,7 @@ fn user_annotated_ty_for_adt(
 fn method_callee<'a, 'gcx, 'tcx>(
     cx: &mut Cx<'a, 'gcx, 'tcx>,
     expr: &hir::Expr,
+    span: Span,
     overloaded_callee: Option<(DefId, &'tcx Substs<'tcx>)>,
 ) -> Expr<'tcx> {
     let temp_lifetime = cx.region_scope_tree.temporary_scope(expr.hir_id.local_id);
@@ -848,7 +853,7 @@ fn method_callee<'a, 'gcx, 'tcx>(
     Expr {
         temp_lifetime,
         ty,
-        span: expr.span,
+        span,
         kind: ExprKind::Literal {
             literal: ty::Const::zero_sized(cx.tcx(), ty),
             user_ty,
@@ -1109,11 +1114,12 @@ fn overloaded_operator<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                                        expr: &'tcx hir::Expr,
                                        args: Vec<ExprRef<'tcx>>)
                                        -> ExprKind<'tcx> {
-    let fun = method_callee(cx, expr, None);
+    let fun = method_callee(cx, expr, expr.span, None);
     ExprKind::Call {
         ty: fun.ty,
         fun: fun.to_ref(),
         args,
+        from_hir_call: false,
     }
 }
 
@@ -1148,7 +1154,7 @@ fn overloaded_place<'a, 'gcx, 'tcx>(
     // construct the complete expression `foo()` for the overloaded call,
     // which will yield the &T type
     let temp_lifetime = cx.region_scope_tree.temporary_scope(expr.hir_id.local_id);
-    let fun = method_callee(cx, expr, overloaded_callee);
+    let fun = method_callee(cx, expr, expr.span, overloaded_callee);
     let ref_expr = Expr {
         temp_lifetime,
         ty: ref_ty,
@@ -1157,6 +1163,7 @@ fn overloaded_place<'a, 'gcx, 'tcx>(
             ty: fun.ty,
             fun: fun.to_ref(),
             args,
+            from_hir_call: false,
         },
     };
 
index 9258845ad06a74535c9a7167e1277512f224248d..eb73a2021484b0f7a5ad60b20b38ff130b50dd05 100644 (file)
@@ -150,6 +150,9 @@ pub enum ExprKind<'tcx> {
         ty: Ty<'tcx>,
         fun: ExprRef<'tcx>,
         args: Vec<ExprRef<'tcx>>,
+        // Whether this is from a call in HIR, rather than from an overloaded
+        // operator. True for overloaded function call.
+        from_hir_call: bool,
     },
     Deref {
         arg: ExprRef<'tcx>,
index 11e27a597fbcab9a1efcfb954956a6d68e994563..222d1164667d360177ac0a612d4fb8eaeea85a33 100644 (file)
@@ -971,7 +971,7 @@ fn check_relocation_edges(&self, ptr: Pointer, size: Size) -> EvalResult<'tcx> {
 
 /// Undefined bytes
 impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
-    // FIXME(solson): This is a very naive, slow version.
+    // FIXME: Add a fast version for the common, nonoverlapping case
     fn copy_undef_mask(
         &mut self,
         src: Pointer,
index 3f5a05f9d0ed8381d0540cb1d84ca157e1344ac7..f0ea93bfffd3e7cbaebbdd72cebd2e8d78cacc80 100644 (file)
@@ -382,6 +382,7 @@ pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String) {
             }
             ty::Error |
             ty::Infer(_) |
+            ty::UnnormalizedProjection(..) |
             ty::Projection(..) |
             ty::Param(_) |
             ty::GeneratorWitness(_) |
index 7ba72366af73630907c228f317ae50594513d21a..4b26094b9fc2843748c3bd33acaebce31a17e62d 100644 (file)
@@ -140,13 +140,15 @@ enum CallKind {
 fn temp_decl(mutability: Mutability, ty: Ty, span: Span) -> LocalDecl {
     let source_info = SourceInfo { scope: OUTERMOST_SOURCE_SCOPE, span };
     LocalDecl {
-        mutability, ty,
+        mutability,
+        ty,
         user_ty: None,
         name: None,
         source_info,
         visibility_scope: source_info.scope,
         internal: false,
         is_user_variable: None,
+        is_block_tail: None,
     }
 }
 
@@ -468,6 +470,7 @@ fn make_clone_call(
             args: vec![Operand::Move(ref_loc)],
             destination: Some((dest, next)),
             cleanup: Some(cleanup),
+            from_hir_call: true,
         }, false);
     }
 
@@ -766,7 +769,8 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             Some(BasicBlock::new(3))
         } else {
             None
-        }
+        },
+        from_hir_call: true,
     }, false);
 
     if let Adjustment::RefMut = rcvr_adjustment {
index 62adbf1bdf7db91961c16001f7b3fc30213644cd..c2ae6832cc09f9f2c80fb038ef4c5760c8135e0b 100644 (file)
@@ -308,6 +308,7 @@ fn replace_result_variable<'tcx>(
         source_info,
         visibility_scope: source_info.scope,
         internal: false,
+        is_block_tail: None,
         is_user_variable: None,
     };
     let new_ret_local = Local::new(mir.local_decls.len());
@@ -662,6 +663,7 @@ fn create_generator_drop_shim<'a, 'tcx>(
         source_info,
         visibility_scope: source_info.scope,
         internal: false,
+        is_block_tail: None,
         is_user_variable: None,
     };
 
@@ -679,6 +681,7 @@ fn create_generator_drop_shim<'a, 'tcx>(
         source_info,
         visibility_scope: source_info.scope,
         internal: false,
+        is_block_tail: None,
         is_user_variable: None,
     };
 
index b2ddbe04d755f7073f79fa3e090f25fd6b325dd3..bd7d9d367618be73f1bc77ce12513fae40d64087 100644 (file)
@@ -121,6 +121,7 @@ fn lower_128bit_ops<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, mir: &mut Mir<
                             args: vec![lhs, rhs],
                             destination: Some((place, bb)),
                             cleanup: None,
+                            from_hir_call: false,
                         },
                     });
             }
index 34339b0634194906755684650f0942deb6a91f88..f4efe33da7080f07cd086649baa0f03c2f3432b1 100644 (file)
@@ -258,7 +258,7 @@ fn promote_temp(&mut self, temp: Local) -> Local {
             };
 
             match terminator.kind {
-                TerminatorKind::Call { mut func, mut args, .. } => {
+                TerminatorKind::Call { mut func, mut args, from_hir_call, .. } => {
                     self.visit_operand(&mut func, loc);
                     for arg in &mut args {
                         self.visit_operand(arg, loc);
@@ -272,7 +272,8 @@ fn promote_temp(&mut self, temp: Local) -> Local {
                             func,
                             args,
                             cleanup: None,
-                            destination: Some((Place::Local(new_temp), new_target))
+                            destination: Some((Place::Local(new_temp), new_target)),
+                            from_hir_call,
                         },
                         ..terminator
                     };
index 98420115d75d73afae9ee9bdd9b4913be9d563f3..aa559c96ec6682b179c1c976f151aefb52e776ad 100644 (file)
@@ -318,6 +318,7 @@ fn check_terminator(
         TerminatorKind::Call {
             func,
             args,
+            from_hir_call: _,
             destination: _,
             cleanup: _,
         } => {
index 9b8165181cc1d04687252913b5425464e6c32e10..1dca367ffdf5f621b04a8f02f9d9a29ee790f1f3 100644 (file)
@@ -545,8 +545,9 @@ fn destructor_call_block<'a>(&mut self, (succ, unwind): (BasicBlock, Unwind))
                     args: vec![Operand::Move(Place::Local(ref_place))],
                     destination: Some((unit_temp, succ)),
                     cleanup: unwind.into_option(),
+                    from_hir_call: true,
                 },
-                source_info: self.source_info
+                source_info: self.source_info,
             }),
             is_cleanup: unwind.is_cleanup(),
         };
@@ -903,7 +904,8 @@ fn unelaborated_free_block<'a>(
             func: Operand::function_handle(tcx, free_func, substs, self.source_info.span),
             args: args,
             destination: Some((unit_temp, target)),
-            cleanup: None
+            cleanup: None,
+            from_hir_call: false,
         }; // FIXME(#43234)
         let free_block = self.new_block(unwind, call);
 
index 837340f70fce757c35a998a321cfb77f1b19b97b..3a8e84a3280c6dd3ca30b17a74004a7926db0191 100644 (file)
@@ -10,6 +10,7 @@ crate-type = ["dylib"]
 test = false
 
 [dependencies]
+bitflags = "1.0"
 log = "0.4"
 syntax = { path = "../libsyntax" }
 rustc = { path = "../librustc" }
index ece0188fa626d15f599f899ef564e5d434bf4386..a93cc7ad7518a7715893afef241826515a097859 100644 (file)
@@ -17,6 +17,8 @@
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_sort_by_cached_key)]
 
+#[macro_use]
+extern crate bitflags;
 #[macro_use]
 extern crate log;
 #[macro_use]
@@ -1012,7 +1014,8 @@ pub struct ModuleData<'a> {
     normal_ancestor_id: DefId,
 
     resolutions: RefCell<FxHashMap<(Ident, Namespace), &'a RefCell<NameResolution<'a>>>>,
-    legacy_macro_resolutions: RefCell<Vec<(Ident, MacroKind, ParentScope<'a>, Option<Def>)>>,
+    legacy_macro_resolutions: RefCell<Vec<(Ident, MacroKind, ParentScope<'a>,
+                                           Option<&'a NameBinding<'a>>)>>,
     macro_resolutions: RefCell<Vec<(Box<[Ident]>, Span)>>,
     builtin_attrs: RefCell<Vec<(Ident, ParentScope<'a>)>>,
 
@@ -1210,10 +1213,6 @@ fn def_ignoring_ambiguity(&self) -> Def {
         }
     }
 
-    fn get_macro<'b: 'a>(&self, resolver: &mut Resolver<'a, 'b>) -> Lrc<SyntaxExtension> {
-        resolver.get_macro(self.def_ignoring_ambiguity())
-    }
-
     // We sometimes need to treat variants as `pub` for backwards compatibility
     fn pseudo_vis(&self) -> ty::Visibility {
         if self.is_variant() && self.def().def_id().is_local() {
@@ -3664,8 +3663,8 @@ fn resolve_path_with_parent_scope(
                 self.resolve_ident_in_module(module, ident, ns, record_used, path_span)
             } else if opt_ns == Some(MacroNS) {
                 assert!(ns == TypeNS);
-                self.resolve_lexical_macro_path_segment(ident, ns, None, parent_scope, record_used,
-                                                        record_used, path_span).map(|(b, _)| b)
+                self.early_resolve_ident_in_lexical_scope(ident, ns, None, parent_scope,
+                                                          record_used, record_used, path_span)
             } else {
                 let record_used_id =
                     if record_used { crate_lint.node_id().or(Some(CRATE_NODE_ID)) } else { None };
index ff6e8a96f30ba645be1452eb36f39f374b9f6387..c31b558dedea03452bebb1a0010ec62f01465332 100644 (file)
@@ -11,7 +11,7 @@
 use {AmbiguityError, CrateLint, Resolver, ResolutionError, is_known_tool, resolve_error};
 use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult, ToNameBinding};
 use ModuleOrUniformRoot;
-use Namespace::{self, TypeNS, MacroNS};
+use Namespace::{self, *};
 use build_reduced_graph::{BuildReducedGraphVisitor, IsMacroExport};
 use resolve_imports::ImportResolver;
 use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX, DefIndex,
@@ -22,9 +22,9 @@
 use syntax::ast::{self, Name, Ident};
 use syntax::attr;
 use syntax::errors::DiagnosticBuilder;
-use syntax::ext::base::{self, Determinacy, MultiModifier, MultiDecorator};
+use syntax::ext::base::{self, Determinacy};
 use syntax::ext::base::{MacroKind, SyntaxExtension, Resolver as SyntaxResolver};
-use syntax::ext::expand::{AstFragment, Invocation, InvocationKind, TogetherWith};
+use syntax::ext::expand::{AstFragment, Invocation, InvocationKind};
 use syntax::ext::hygiene::{self, Mark};
 use syntax::ext::tt::macro_rules;
 use syntax::feature_gate::{self, feature_err, emit_feature_err, is_builtin_attr_name, GateIssue};
@@ -43,9 +43,6 @@
 use std::mem;
 use rustc_data_structures::sync::Lrc;
 
-#[derive(Clone, Copy)]
-crate struct FromPrelude(bool);
-
 #[derive(Clone)]
 pub struct InvocationData<'a> {
     def_index: DefIndex,
@@ -245,27 +242,10 @@ fn resolve_imports(&mut self) {
     // Resolves attribute and derive legacy macros from `#![plugin(..)]`.
     fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec<ast::Attribute>, allow_derive: bool)
                               -> Option<ast::Attribute> {
-        for i in 0..attrs.len() {
-            let name = attrs[i].name();
-
-            if self.session.plugin_attributes.borrow().iter()
-                    .any(|&(ref attr_nm, _)| name == &**attr_nm) {
-                attr::mark_known(&attrs[i]);
-            }
-
-            match self.builtin_macros.get(&name).cloned() {
-                Some(binding) => match *binding.get_macro(self) {
-                    MultiModifier(..) | MultiDecorator(..) | SyntaxExtension::AttrProcMacro(..) => {
-                        return Some(attrs.remove(i))
-                    }
-                    _ => {}
-                },
-                None => {}
-            }
+        if !allow_derive {
+            return None;
         }
 
-        if !allow_derive { return None }
-
         // Check for legacy derives
         for i in 0..attrs.len() {
             let name = attrs[i].name();
@@ -333,29 +313,24 @@ fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec<ast::Attribute>, allow_deri
 
     fn resolve_macro_invocation(&mut self, invoc: &Invocation, invoc_id: Mark, force: bool)
                                 -> Result<Option<Lrc<SyntaxExtension>>, Determinacy> {
-        let (path, kind, derives_in_scope, together_with) = match invoc.kind {
+        let (path, kind, derives_in_scope, after_derive) = match invoc.kind {
             InvocationKind::Attr { attr: None, .. } =>
                 return Ok(None),
-            InvocationKind::Attr { attr: Some(ref attr), ref traits, together_with, .. } =>
-                (&attr.path, MacroKind::Attr, traits.clone(), together_with),
+            InvocationKind::Attr { attr: Some(ref attr), ref traits, after_derive, .. } =>
+                (&attr.path, MacroKind::Attr, traits.clone(), after_derive),
             InvocationKind::Bang { ref mac, .. } =>
-                (&mac.node.path, MacroKind::Bang, Vec::new(), TogetherWith::None),
+                (&mac.node.path, MacroKind::Bang, Vec::new(), false),
             InvocationKind::Derive { ref path, .. } =>
-                (path, MacroKind::Derive, Vec::new(), TogetherWith::None),
+                (path, MacroKind::Derive, Vec::new(), false),
         };
 
         let parent_scope = self.invoc_parent_scope(invoc_id, derives_in_scope);
         let (def, ext) = self.resolve_macro_to_def(path, kind, &parent_scope, force)?;
 
         if let Def::Macro(def_id, _) = def {
-            match together_with {
-                TogetherWith::Derive =>
-                    self.session.span_err(invoc.span(),
-                        "macro attributes must be placed before `#[derive]`"),
-                TogetherWith::TestBench if !self.session.features_untracked().plugin =>
-                    self.session.span_err(invoc.span(),
-                        "macro attributes cannot be used together with `#[test]` or `#[bench]`"),
-                _ => {}
+            if after_derive {
+                self.session.span_err(invoc.span(),
+                                      "macro attributes must be placed before `#[derive]`");
             }
             self.macro_defs.insert(invoc.expansion_data.mark, def_id);
             let normal_module_def_id =
@@ -520,37 +495,34 @@ pub fn resolve_macro_to_def_inner(
                     Err(Determinacy::Determined)
                 },
             };
+
             parent_scope.module.macro_resolutions.borrow_mut()
                 .push((path.into_boxed_slice(), span));
-            return def;
-        }
 
-        let result = if let Some(legacy_binding) = self.resolve_legacy_scope(path[0], Some(kind),
-                                                                             parent_scope, false) {
-            Ok(legacy_binding.def())
+            def
         } else {
-            match self.resolve_lexical_macro_path_segment(path[0], MacroNS, Some(kind),
-                                                          parent_scope, false, force, span) {
-                Ok((binding, _)) => Ok(binding.def_ignoring_ambiguity()),
+            let binding = self.early_resolve_ident_in_lexical_scope(
+                path[0], MacroNS, Some(kind), parent_scope, false, force, span
+            );
+            match binding {
+                Ok(..) => {}
+                Err(Determinacy::Determined) => self.found_unresolved_macro = true,
                 Err(Determinacy::Undetermined) => return Err(Determinacy::Undetermined),
-                Err(Determinacy::Determined) => {
-                    self.found_unresolved_macro = true;
-                    Err(Determinacy::Determined)
-                }
             }
-        };
 
-        parent_scope.module.legacy_macro_resolutions.borrow_mut()
-            .push((path[0], kind, parent_scope.clone(), result.ok()));
+            parent_scope.module.legacy_macro_resolutions.borrow_mut()
+                .push((path[0], kind, parent_scope.clone(), binding.ok()));
 
-        result
+            binding.map(|binding| binding.def_ignoring_ambiguity())
+        }
     }
 
-    // Resolve the initial segment of a non-global macro path
-    // (e.g. `foo` in `foo::bar!(); or `foo!();`).
+    // Resolve an identifier in lexical scope.
     // This is a variation of `fn resolve_ident_in_lexical_scope` that can be run during
     // expansion and import resolution (perhaps they can be merged in the future).
-    crate fn resolve_lexical_macro_path_segment(
+    // The function is used for resolving initial segments of macro paths (e.g. `foo` in
+    // `foo::bar!(); or `foo!();`) and can be used for "uniform path" imports in the future.
+    crate fn early_resolve_ident_in_lexical_scope(
         &mut self,
         mut ident: Ident,
         ns: Namespace,
@@ -559,12 +531,12 @@ pub fn resolve_macro_to_def_inner(
         record_used: bool,
         force: bool,
         path_span: Span,
-    ) -> Result<(&'a NameBinding<'a>, FromPrelude), Determinacy> {
+    ) -> Result<&'a NameBinding<'a>, Determinacy> {
         // General principles:
         // 1. Not controlled (user-defined) names should have higher priority than controlled names
         //    built into the language or standard library. This way we can add new names into the
         //    language or standard library without breaking user code.
-        // 2. "Closed set" below means new names can appear after the current resolution attempt.
+        // 2. "Closed set" below means new names cannot appear after the current resolution attempt.
         // Places to search (in order of decreasing priority):
         // (Type NS)
         // 1. FIXME: Ribs (type parameters), there's no necessary infrastructure yet
@@ -575,24 +547,58 @@ pub fn resolve_macro_to_def_inner(
         // 4. Tool modules (closed, controlled right now, but not in the future).
         // 5. Standard library prelude (de-facto closed, controlled).
         // 6. Language prelude (closed, controlled).
+        // (Value NS)
+        // 1. FIXME: Ribs (local variables), there's no necessary infrastructure yet
+        //    (open set, not controlled).
+        // 2. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents
+        //    (open, not controlled).
+        // 3. Standard library prelude (de-facto closed, controlled).
         // (Macro NS)
-        // 0. Derive helpers (open, not controlled). All ambiguities with other names
+        // 1-3. Derive helpers (open, not controlled). All ambiguities with other names
         //    are currently reported as errors. They should be higher in priority than preludes
         //    and probably even names in modules according to the "general principles" above. They
         //    also should be subject to restricted shadowing because are effectively produced by
         //    derives (you need to resolve the derive first to add helpers into scope), but they
         //    should be available before the derive is expanded for compatibility.
         //    It's mess in general, so we are being conservative for now.
-        // 1. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents
-        //    (open, not controlled).
-        // 2. `macro_use` prelude (open, the open part is from macro expansions, not controlled).
-        // 2a. User-defined prelude from macro-use
+        // 1-3. `macro_rules` (open, not controlled), loop through legacy scopes. Have higher
+        //    priority than prelude macros, but create ambiguities with macros in modules.
+        // 1-3. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents
+        //    (open, not controlled). Have higher priority than prelude macros, but create
+        //    ambiguities with `macro_rules`.
+        // 4. `macro_use` prelude (open, the open part is from macro expansions, not controlled).
+        // 4a. User-defined prelude from macro-use
         //    (open, the open part is from macro expansions, not controlled).
-        // 2b. Standard library prelude is currently implemented as `macro-use` (closed, controlled)
-        // 3. Language prelude: builtin macros (closed, controlled, except for legacy plugins).
-        // 4. Language prelude: builtin attributes (closed, controlled).
+        // 4b. Standard library prelude is currently implemented as `macro-use` (closed, controlled)
+        // 5. Language prelude: builtin macros (closed, controlled, except for legacy plugins).
+        // 6. Language prelude: builtin attributes (closed, controlled).
+        // 4-6. Legacy plugin helpers (open, not controlled). Similar to derive helpers,
+        //    but introduced by legacy plugins using `register_attribute`. Priority is somewhere
+        //    in prelude, not sure where exactly (creates ambiguities with any other prelude names).
+
+        enum WhereToResolve<'a> {
+            DeriveHelpers,
+            MacroRules(LegacyScope<'a>),
+            Module(Module<'a>),
+            MacroUsePrelude,
+            BuiltinMacros,
+            BuiltinAttrs,
+            LegacyPluginHelpers,
+            ExternPrelude,
+            ToolPrelude,
+            StdLibPrelude,
+            BuiltinTypes,
+        }
+
+        bitflags! {
+            struct Flags: u8 {
+                const DERIVE_HELPERS = 1 << 0;
+                const MACRO_RULES    = 1 << 1;
+                const MODULE         = 1 << 2;
+                const PRELUDE        = 1 << 3;
+            }
+        }
 
-        assert!(ns == TypeNS  || ns == MacroNS);
         assert!(force || !record_used); // `record_used` implies `force`
         ident = ident.modern();
 
@@ -607,25 +613,38 @@ pub fn resolve_macro_to_def_inner(
         // }
         // So we have to save the innermost solution and continue searching in outer scopes
         // to detect potential ambiguities.
-        let mut innermost_result: Option<(&NameBinding, FromPrelude)> = None;
-
-        enum WhereToResolve<'a> {
-            Module(Module<'a>),
-            MacroUsePrelude,
-            BuiltinMacros,
-            BuiltinAttrs,
-            DeriveHelpers,
-            ExternPrelude,
-            ToolPrelude,
-            StdLibPrelude,
-            BuiltinTypes,
-        }
+        let mut innermost_result: Option<(&NameBinding, Flags, /* conflicts with */ Flags)> = None;
 
         // Go through all the scopes and try to resolve the name.
         let mut where_to_resolve = WhereToResolve::DeriveHelpers;
         let mut use_prelude = !parent_scope.module.no_implicit_prelude;
         loop {
             let result = match where_to_resolve {
+                WhereToResolve::DeriveHelpers => {
+                    let mut result = Err(Determinacy::Determined);
+                    for derive in &parent_scope.derives {
+                        let parent_scope = ParentScope { derives: Vec::new(), ..*parent_scope };
+                        if let Ok((_, ext)) = self.resolve_macro_to_def(derive, MacroKind::Derive,
+                                                                        &parent_scope, force) {
+                            if let SyntaxExtension::ProcMacroDerive(_, helper_attrs, _) = &*ext {
+                                if helper_attrs.contains(&ident.name) {
+                                    let binding =
+                                        (Def::NonMacroAttr(NonMacroAttrKind::DeriveHelper),
+                                        ty::Visibility::Public, derive.span, Mark::root())
+                                        .to_name_binding(self.arenas);
+                                    result = Ok((binding, Flags::DERIVE_HELPERS, Flags::all()));
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                    result
+                }
+                WhereToResolve::MacroRules(legacy_scope) => match legacy_scope {
+                    LegacyScope::Binding(legacy_binding) if ident == legacy_binding.ident =>
+                        Ok((legacy_binding.binding, Flags::MACRO_RULES, Flags::empty())),
+                    _ => Err(Determinacy::Determined),
+                }
                 WhereToResolve::Module(module) => {
                     let orig_current_module = mem::replace(&mut self.current_module, module);
                     let binding = self.resolve_ident_in_module_unadjusted(
@@ -637,17 +656,17 @@ enum WhereToResolve<'a> {
                         path_span,
                     );
                     self.current_module = orig_current_module;
-                    binding.map(|binding| (binding, FromPrelude(false)))
+                    binding.map(|binding| (binding, Flags::MODULE, Flags::empty()))
                 }
                 WhereToResolve::MacroUsePrelude => {
                     match self.macro_use_prelude.get(&ident.name).cloned() {
-                        Some(binding) => Ok((binding, FromPrelude(true))),
+                        Some(binding) => Ok((binding, Flags::PRELUDE, Flags::empty())),
                         None => Err(Determinacy::Determined),
                     }
                 }
                 WhereToResolve::BuiltinMacros => {
                     match self.builtin_macros.get(&ident.name).cloned() {
-                        Some(binding) => Ok((binding, FromPrelude(true))),
+                        Some(binding) => Ok((binding, Flags::PRELUDE, Flags::empty())),
                         None => Err(Determinacy::Determined),
                     }
                 }
@@ -656,30 +675,21 @@ enum WhereToResolve<'a> {
                         let binding = (Def::NonMacroAttr(NonMacroAttrKind::Builtin),
                                        ty::Visibility::Public, ident.span, Mark::root())
                                        .to_name_binding(self.arenas);
-                        Ok((binding, FromPrelude(true)))
+                        Ok((binding, Flags::PRELUDE, Flags::empty()))
                     } else {
                         Err(Determinacy::Determined)
                     }
                 }
-                WhereToResolve::DeriveHelpers => {
-                    let mut result = Err(Determinacy::Determined);
-                    for derive in &parent_scope.derives {
-                        let parent_scope = ParentScope { derives: Vec::new(), ..*parent_scope };
-                        if let Ok((_, ext)) = self.resolve_macro_to_def(derive, MacroKind::Derive,
-                                                                        &parent_scope, force) {
-                            if let SyntaxExtension::ProcMacroDerive(_, helper_attrs, _) = &*ext {
-                                if helper_attrs.contains(&ident.name) {
-                                    let binding =
-                                        (Def::NonMacroAttr(NonMacroAttrKind::DeriveHelper),
-                                        ty::Visibility::Public, derive.span, Mark::root())
-                                        .to_name_binding(self.arenas);
-                                    result = Ok((binding, FromPrelude(false)));
-                                    break;
-                                }
-                            }
-                        }
+                WhereToResolve::LegacyPluginHelpers => {
+                    if self.session.plugin_attributes.borrow().iter()
+                                                     .any(|(name, _)| ident.name == &**name) {
+                        let binding = (Def::NonMacroAttr(NonMacroAttrKind::LegacyPluginHelper),
+                                       ty::Visibility::Public, ident.span, Mark::root())
+                                       .to_name_binding(self.arenas);
+                        Ok((binding, Flags::PRELUDE, Flags::PRELUDE))
+                    } else {
+                        Err(Determinacy::Determined)
                     }
-                    result
                 }
                 WhereToResolve::ExternPrelude => {
                     if use_prelude && self.session.extern_prelude.contains(&ident.name) {
@@ -691,7 +701,7 @@ enum WhereToResolve<'a> {
 
                         let binding = (crate_root, ty::Visibility::Public,
                                        ident.span, Mark::root()).to_name_binding(self.arenas);
-                        Ok((binding, FromPrelude(true)))
+                        Ok((binding, Flags::PRELUDE, Flags::empty()))
                     } else {
                         Err(Determinacy::Determined)
                     }
@@ -700,7 +710,7 @@ enum WhereToResolve<'a> {
                     if use_prelude && is_known_tool(ident.name) {
                         let binding = (Def::ToolMod, ty::Visibility::Public,
                                        ident.span, Mark::root()).to_name_binding(self.arenas);
-                        Ok((binding, FromPrelude(true)))
+                        Ok((binding, Flags::PRELUDE, Flags::empty()))
                     } else {
                         Err(Determinacy::Determined)
                     }
@@ -717,46 +727,60 @@ enum WhereToResolve<'a> {
                                 false,
                                 path_span,
                             ) {
-                                result = Ok((binding, FromPrelude(true)));
+                                result = Ok((binding, Flags::PRELUDE, Flags::empty()));
                             }
                         }
                     }
                     result
                 }
                 WhereToResolve::BuiltinTypes => {
-                    if let Some(prim_ty) =
-                            self.primitive_type_table.primitive_types.get(&ident.name).cloned() {
-                        let binding = (Def::PrimTy(prim_ty), ty::Visibility::Public,
-                                       ident.span, Mark::root()).to_name_binding(self.arenas);
-                        Ok((binding, FromPrelude(true)))
-                    } else {
-                        Err(Determinacy::Determined)
+                    match self.primitive_type_table.primitive_types.get(&ident.name).cloned() {
+                        Some(prim_ty) => {
+                            let binding = (Def::PrimTy(prim_ty), ty::Visibility::Public,
+                                           ident.span, Mark::root()).to_name_binding(self.arenas);
+                            Ok((binding, Flags::PRELUDE, Flags::empty()))
+                        }
+                        None => Err(Determinacy::Determined)
                     }
                 }
             };
 
             macro_rules! continue_search { () => {
                 where_to_resolve = match where_to_resolve {
+                    WhereToResolve::DeriveHelpers =>
+                        WhereToResolve::MacroRules(parent_scope.legacy),
+                    WhereToResolve::MacroRules(legacy_scope) => match legacy_scope {
+                        LegacyScope::Binding(binding) =>
+                            WhereToResolve::MacroRules(binding.parent_legacy_scope),
+                        LegacyScope::Invocation(invocation) =>
+                            WhereToResolve::MacroRules(invocation.output_legacy_scope.get()),
+                        LegacyScope::Empty => WhereToResolve::Module(parent_scope.module),
+                        LegacyScope::Uninitialized => unreachable!(),
+                    }
                     WhereToResolve::Module(module) => {
                         match self.hygienic_lexical_parent(module, &mut ident.span) {
                             Some(parent_module) => WhereToResolve::Module(parent_module),
                             None => {
                                 use_prelude = !module.no_implicit_prelude;
-                                if ns == MacroNS {
-                                    WhereToResolve::MacroUsePrelude
-                                } else {
-                                    WhereToResolve::ExternPrelude
+                                match ns {
+                                    TypeNS => WhereToResolve::ExternPrelude,
+                                    ValueNS => WhereToResolve::StdLibPrelude,
+                                    MacroNS => WhereToResolve::MacroUsePrelude,
                                 }
                             }
                         }
                     }
                     WhereToResolve::MacroUsePrelude => WhereToResolve::BuiltinMacros,
                     WhereToResolve::BuiltinMacros => WhereToResolve::BuiltinAttrs,
-                    WhereToResolve::BuiltinAttrs => break, // nowhere else to search
-                    WhereToResolve::DeriveHelpers => WhereToResolve::Module(parent_scope.module),
+                    WhereToResolve::BuiltinAttrs => WhereToResolve::LegacyPluginHelpers,
+                    WhereToResolve::LegacyPluginHelpers => break, // nowhere else to search
                     WhereToResolve::ExternPrelude => WhereToResolve::ToolPrelude,
                     WhereToResolve::ToolPrelude => WhereToResolve::StdLibPrelude,
-                    WhereToResolve::StdLibPrelude => WhereToResolve::BuiltinTypes,
+                    WhereToResolve::StdLibPrelude => match ns {
+                        TypeNS => WhereToResolve::BuiltinTypes,
+                        ValueNS => break, // nowhere else to search
+                        MacroNS => unreachable!(),
+                    }
                     WhereToResolve::BuiltinTypes => break, // nowhere else to search
                 };
 
@@ -764,33 +788,36 @@ macro_rules! continue_search { () => {
             }}
 
             match result {
-                Ok(result) => {
-                    if sub_namespace_mismatch(kind, result.0.macro_kind()) {
+                Ok((binding, flags, ambig_flags)) => {
+                    if sub_namespace_mismatch(kind, binding.macro_kind()) {
                         continue_search!();
                     }
 
                     if !record_used {
-                        return Ok(result);
+                        return Ok(binding);
                     }
 
-                    if let Some(innermost_result) = innermost_result {
+                    if let Some((innermost_binding, innermost_flags, innermost_ambig_flags))
+                            = innermost_result {
                         // Found another solution, if the first one was "weak", report an error.
-                        let (def, innermost_def) = (result.0.def(), innermost_result.0.def());
-                        if def != innermost_def &&
-                           (innermost_result.0.is_glob_import() ||
-                            innermost_result.0.may_appear_after(parent_scope.expansion, result.0) ||
-                            innermost_def == Def::NonMacroAttr(NonMacroAttrKind::DeriveHelper) ||
-                            def == Def::NonMacroAttr(NonMacroAttrKind::DeriveHelper)) {
+                        if binding.def() != innermost_binding.def() &&
+                           (innermost_binding.is_glob_import() ||
+                            innermost_binding.may_appear_after(parent_scope.expansion, binding) ||
+                            innermost_flags.intersects(ambig_flags) ||
+                            flags.intersects(innermost_ambig_flags) ||
+                            (innermost_flags.contains(Flags::MACRO_RULES) &&
+                             flags.contains(Flags::MODULE) &&
+                             !self.disambiguate_legacy_vs_modern(innermost_binding, binding))) {
                             self.ambiguity_errors.push(AmbiguityError {
                                 ident,
-                                b1: innermost_result.0,
-                                b2: result.0,
+                                b1: innermost_binding,
+                                b2: binding,
                             });
-                            return Ok(innermost_result);
+                            return Ok(innermost_binding);
                         }
                     } else {
                         // Found the first solution.
-                        innermost_result = Some(result);
+                        innermost_result = Some((binding, flags, ambig_flags));
                     }
 
                     continue_search!();
@@ -803,8 +830,8 @@ macro_rules! continue_search { () => {
         }
 
         // The first found solution was the only one, return it.
-        if let Some(innermost_result) = innermost_result {
-            return Ok(innermost_result);
+        if let Some((binding, ..)) = innermost_result {
+            return Ok(binding);
         }
 
         let determinacy = Determinacy::determined(force);
@@ -816,92 +843,12 @@ macro_rules! continue_search { () => {
             let binding = (Def::NonMacroAttr(NonMacroAttrKind::Custom),
                            ty::Visibility::Public, ident.span, Mark::root())
                            .to_name_binding(self.arenas);
-            Ok((binding, FromPrelude(true)))
+            Ok(binding)
         } else {
             Err(determinacy)
         }
     }
 
-    fn resolve_legacy_scope(
-        &mut self,
-        ident: Ident,
-        kind: Option<MacroKind>,
-        parent_scope: &ParentScope<'a>,
-        record_used: bool,
-    ) -> Option<&'a NameBinding<'a>> {
-        if sub_namespace_mismatch(kind, Some(MacroKind::Bang)) {
-            return None;
-        }
-
-        let ident = ident.modern();
-
-        // This is *the* result, resolution from the scope closest to the resolved identifier.
-        // However, sometimes this result is "weak" because it comes from a macro expansion,
-        // and in this case it cannot shadow names from outer scopes, e.g.
-        // macro_rules! m { ... } // solution in outer scope
-        // {
-        //     define_m!(); // generates another `macro_rules! m` - innermost solution
-        //                  // weak, cannot shadow the outer `m`, need to report ambiguity error
-        //     m!();
-        // }
-        // So we have to save the innermost solution and continue searching in outer scopes
-        // to detect potential ambiguities.
-        let mut innermost_result: Option<&NameBinding> = None;
-
-        // Go through all the scopes and try to resolve the name.
-        let mut where_to_resolve = parent_scope.legacy;
-        loop {
-            let result = match where_to_resolve {
-                LegacyScope::Binding(legacy_binding) if ident == legacy_binding.ident =>
-                    Some(legacy_binding.binding),
-                _ => None,
-            };
-
-            macro_rules! continue_search { () => {
-                where_to_resolve = match where_to_resolve {
-                    LegacyScope::Empty => break, // nowhere else to search
-                    LegacyScope::Binding(binding) => binding.parent_legacy_scope,
-                    LegacyScope::Invocation(invocation) => invocation.output_legacy_scope.get(),
-                    LegacyScope::Uninitialized => unreachable!(),
-                };
-
-                continue;
-            }}
-
-            match result {
-                Some(result) => {
-                    if !record_used {
-                        return Some(result);
-                    }
-
-                    if let Some(innermost_result) = innermost_result {
-                        // Found another solution, if the first one was "weak", report an error.
-                        if result.def() != innermost_result.def() &&
-                           innermost_result.may_appear_after(parent_scope.expansion, result) {
-                            self.ambiguity_errors.push(AmbiguityError {
-                                ident,
-                                b1: innermost_result,
-                                b2: result,
-                            });
-                            return Some(innermost_result);
-                        }
-                    } else {
-                        // Found the first solution.
-                        innermost_result = Some(result);
-                    }
-
-                    continue_search!();
-                }
-                None => {
-                    continue_search!();
-                }
-            }
-        }
-
-        // The first found solution was the only one (or there was no solution at all), return it.
-        innermost_result
-    }
-
     pub fn finalize_current_module_macro_resolutions(&mut self) {
         let module = self.current_module;
         for &(ref path, span) in module.macro_resolutions.borrow().iter() {
@@ -916,80 +863,52 @@ pub fn finalize_current_module_macro_resolutions(&mut self) {
 
         let legacy_macro_resolutions =
             mem::replace(&mut *module.legacy_macro_resolutions.borrow_mut(), Vec::new());
-        for (ident, kind, parent_scope, def) in legacy_macro_resolutions {
-            let span = ident.span;
-            let legacy_resolution = self.resolve_legacy_scope(
-                ident, Some(kind), &parent_scope, true
+        for (ident, kind, parent_scope, initial_binding) in legacy_macro_resolutions {
+            let binding = self.early_resolve_ident_in_lexical_scope(
+                ident, MacroNS, Some(kind), &parent_scope, true, true, ident.span
             );
-            let resolution = self.resolve_lexical_macro_path_segment(
-                ident, MacroNS, Some(kind), &parent_scope, true, true, span
-            );
-
-            let check_consistency = |this: &Self, new_def: Def| {
-                if let Some(def) = def {
-                    if this.ambiguity_errors.is_empty() && new_def != def && new_def != Def::Err {
-                        // Make sure compilation does not succeed if preferred macro resolution
-                        // has changed after the macro had been expanded. In theory all such
-                        // situations should be reported as ambiguity errors, so this is span-bug.
-                        span_bug!(span, "inconsistent resolution for a macro");
+            match binding {
+                Ok(binding) => {
+                    let def = binding.def_ignoring_ambiguity();
+                    if let Some(initial_binding) = initial_binding {
+                        self.record_use(ident, MacroNS, initial_binding);
+                        let initial_def = initial_binding.def_ignoring_ambiguity();
+                        if self.ambiguity_errors.is_empty() &&
+                           def != initial_def && def != Def::Err {
+                            // Make sure compilation does not succeed if preferred macro resolution
+                            // has changed after the macro had been expanded. In theory all such
+                            // situations should be reported as ambiguity errors, so this is a bug.
+                            span_bug!(ident.span, "inconsistent resolution for a macro");
+                        }
+                    } else {
+                        // It's possible that the macro was unresolved (indeterminate) and silently
+                        // expanded into a dummy fragment for recovery during expansion.
+                        // Now, post-expansion, the resolution may succeed, but we can't change the
+                        // past and need to report an error.
+                        let msg = format!("cannot determine resolution for the {} `{}`",
+                                          kind.descr(), ident);
+                        let msg_note = "import resolution is stuck, try simplifying macro imports";
+                        self.session.struct_span_err(ident.span, &msg).note(msg_note).emit();
                     }
-                } else {
-                    // It's possible that the macro was unresolved (indeterminate) and silently
-                    // expanded into a dummy fragment for recovery during expansion.
-                    // Now, post-expansion, the resolution may succeed, but we can't change the
-                    // past and need to report an error.
-                    let msg =
-                        format!("cannot determine resolution for the {} `{}`", kind.descr(), ident);
-                    let msg_note = "import resolution is stuck, try simplifying macro imports";
-                    this.session.struct_span_err(span, &msg).note(msg_note).emit();
                 }
-            };
-
-            match (legacy_resolution, resolution) {
-                (None, Err(_)) => {
-                    assert!(def.is_none());
+                Err(..) => {
+                    assert!(initial_binding.is_none());
                     let bang = if kind == MacroKind::Bang { "!" } else { "" };
                     let msg =
                         format!("cannot find {} `{}{}` in this scope", kind.descr(), ident, bang);
-                    let mut err = self.session.struct_span_err(span, &msg);
-                    self.suggest_macro_name(&ident.as_str(), kind, &mut err, span);
+                    let mut err = self.session.struct_span_err(ident.span, &msg);
+                    self.suggest_macro_name(&ident.as_str(), kind, &mut err, ident.span);
                     err.emit();
-                },
-                (Some(legacy_binding), Ok((binding, FromPrelude(from_prelude))))
-                        if legacy_binding.def() != binding.def_ignoring_ambiguity() &&
-                           (!from_prelude &&
-                            !self.disambiguate_legacy_vs_modern(legacy_binding, binding) ||
-                            legacy_binding.may_appear_after(parent_scope.expansion, binding)) => {
-                    self.report_ambiguity_error(ident, legacy_binding, binding);
-                },
-                // OK, non-macro-expanded legacy wins over prelude even if defs are different
-                // Also, non-macro-expanded legacy wins over modern from the same module
-                // Also, legacy and modern can co-exist if their defs are same
-                (Some(legacy_binding), Ok(_)) |
-                // OK, unambiguous resolution
-                (Some(legacy_binding), Err(_)) => {
-                    check_consistency(self, legacy_binding.def());
-                }
-                // OK, unambiguous resolution
-                (None, Ok((binding, FromPrelude(from_prelude)))) => {
-                    check_consistency(self, binding.def_ignoring_ambiguity());
-                    if from_prelude {
-                        self.record_use(ident, MacroNS, binding);
-                    }
                 }
-            };
+            }
         }
 
         let builtin_attrs = mem::replace(&mut *module.builtin_attrs.borrow_mut(), Vec::new());
         for (ident, parent_scope) in builtin_attrs {
-            let resolve_legacy = |this: &mut Self| this.resolve_legacy_scope(
-                ident, Some(MacroKind::Attr), &parent_scope, true
-            );
-            let resolve_modern = |this: &mut Self| this.resolve_lexical_macro_path_segment(
+            let binding = self.early_resolve_ident_in_lexical_scope(
                 ident, MacroNS, Some(MacroKind::Attr), &parent_scope, true, true, ident.span
-            ).map(|(binding, _)| binding).ok();
-
-            if let Some(binding) = resolve_legacy(self).or_else(|| resolve_modern(self)) {
+            );
+            if let Ok(binding) = binding {
                 if binding.def_ignoring_ambiguity() !=
                         Def::NonMacroAttr(NonMacroAttrKind::Builtin) {
                     let builtin_binding = (Def::NonMacroAttr(NonMacroAttrKind::Builtin),
index 333131398151affa682ca0c4292e83302f0ebfcf..6e9877b1ab66d2591c385991b07e7013bc6dd414 100644 (file)
@@ -334,7 +334,7 @@ pub fn resolve_ident_in_module_unadjusted(&mut self,
         // expansion. With restricted shadowing names from globs and macro expansions cannot
         // shadow names from outer scopes, so we can freely fallback from module search to search
         // in outer scopes. To continue search in outer scopes we have to lie a bit and return
-        // `Determined` to `resolve_lexical_macro_path_segment` even if the correct answer
+        // `Determined` to `early_resolve_ident_in_lexical_scope` even if the correct answer
         // for in-module resolution could be `Undetermined`.
         if restricted_shadowing {
             return Err(Determined);
index e3ec2e6b9ce02b48dfabce331ed39510f7f6d2ff..2996fe03200428cb8ead7057131aa1f186bbf367 100644 (file)
@@ -272,6 +272,8 @@ fn dtorck_constraint_for_ty<'a, 'gcx, 'tcx>(
             overflows: vec![],
         }),
 
+        ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
+
         ty::Infer(..) | ty::Error => {
             // By the time this code runs, all type variables ought to
             // be fully resolved.
index 00c6ebafec0d5b4132438f076878396dac8ba32e..28d2ae413de6d2375694cdf125c28ac7f9c8a2f5 100644 (file)
@@ -1338,10 +1338,7 @@ pub fn def_to_ty(&self,
         match path.def {
             Def::Existential(did) => {
                 // check for desugared impl trait
-                if ty::is_impl_trait_defn(tcx, did).is_some() {
-                    let lifetimes = &path.segments[0].args.as_ref().unwrap().args;
-                    return self.impl_trait_ty_to_ty(did, lifetimes);
-                }
+                assert!(ty::is_impl_trait_defn(tcx, did).is_none());
                 let item_segment = path.segments.split_last().unwrap();
                 self.prohibit_generics(item_segment.1);
                 let substs = self.ast_path_substs_for_ty(span, did, item_segment.0);
@@ -1462,6 +1459,10 @@ pub fn ast_ty_to_ty(&self, ast_ty: &hir::Ty) -> Ty<'tcx> {
                 });
                 self.def_to_ty(opt_self_ty, path, false)
             }
+            hir::TyKind::Def(item_id, ref lifetimes) => {
+                let did = tcx.hir.local_def_id(item_id.id);
+                self.impl_trait_ty_to_ty(did, lifetimes)
+            },
             hir::TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => {
                 debug!("ast_ty_to_ty: qself={:?} segment={:?}", qself, segment);
                 let ty = self.ast_ty_to_ty(qself);
index 564ecae15dc35ba9001ecddfb79cfa3dc120f233..285fed9544ddbe10c1645a6a1eaf11635d57d953 100644 (file)
@@ -124,6 +124,7 @@ fn pointer_kind(&self, t: Ty<'tcx>, span: Span) ->
             ty::Foreign(..) => Some(PointerKind::Thin),
             // We should really try to normalize here.
             ty::Projection(ref pi) => Some(PointerKind::OfProjection(pi)),
+            ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
             ty::Opaque(def_id, substs) => Some(PointerKind::OfOpaque(def_id, substs)),
             ty::Param(ref p) => Some(PointerKind::OfParam(p)),
             // Insufficient type information.
index 29770dc12eb3349e9fa249ce118afa75efa3e21f..695812faafff10bed688e8c16ff30c80b2215fa8 100644 (file)
@@ -128,14 +128,14 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // We create a mapping `dummy_substs` that maps from the impl type
     // parameters to fresh types and regions. For type parameters,
     // this is the identity transform, but we could as well use any
-    // skolemized types. For regions, we convert from bound to free
+    // placeholder types. For regions, we convert from bound to free
     // regions (Note: but only early-bound regions, i.e., those
     // declared on the impl or used in type parameter bounds).
     //
     //     impl_to_skol_substs = {'i => 'i0, U => U0, N => N0 }
     //
     // Now we can apply skol_substs to the type of the impl method
-    // to yield a new function type in terms of our fresh, skolemized
+    // to yield a new function type in terms of our fresh, placeholder
     // types:
     //
     //     <'b> fn(t: &'i0 U0, m: &'b) -> Foo
@@ -163,15 +163,15 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // We do this by creating a parameter environment which contains a
     // substitution corresponding to impl_to_skol_substs. We then build
     // trait_to_skol_substs and use it to convert the predicates contained
-    // in the trait_m.generics to the skolemized form.
+    // in the trait_m.generics to the placeholder form.
     //
     // Finally we register each of these predicates as an obligation in
     // a fresh FulfillmentCtxt, and invoke select_all_or_error.
 
-    // Create mapping from impl to skolemized.
+    // Create mapping from impl to placeholder.
     let impl_to_skol_substs = Substs::identity_for_item(tcx, impl_m.def_id);
 
-    // Create mapping from trait to skolemized.
+    // Create mapping from trait to placeholder.
     let trait_to_skol_substs = impl_to_skol_substs.rebase_onto(tcx,
                                                                impl_m.container.id(),
                                                                trait_to_impl_substs);
@@ -212,7 +212,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     hybrid_preds.predicates.extend(
         trait_m_predicates.instantiate_own(tcx, trait_to_skol_substs).predicates);
 
-    // Construct trait parameter environment and then shift it into the skolemized viewpoint.
+    // Construct trait parameter environment and then shift it into the placeholder viewpoint.
     // The key step here is to update the caller_bounds's predicates to be
     // the new hybrid bounds we computed.
     let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_node_id);
@@ -259,7 +259,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // any associated types appearing in the fn arguments or return
         // type.
 
-        // Compute skolemized form of impl and trait method tys.
+        // Compute placeholder form of impl and trait method tys.
         let tcx = infcx.tcx;
 
         let (impl_sig, _) =
@@ -894,7 +894,7 @@ pub fn compare_const_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // method.
         let impl_c_node_id = tcx.hir.as_local_node_id(impl_c.def_id).unwrap();
 
-        // Compute skolemized form of impl and trait const tys.
+        // Compute placeholder form of impl and trait const tys.
         let impl_ty = tcx.type_of(impl_c.def_id);
         let trait_ty = tcx.type_of(trait_c.def_id).subst(tcx, trait_to_impl_substs);
         let mut cause = ObligationCause::misc(impl_c_span, impl_c_node_id);
index 17e0b0431da6e426ffdc9e14ad509db9d68d6c3a..f96c85ae7ae3fc497036a0e1a19cb0ecfa097384 100644 (file)
@@ -1637,9 +1637,39 @@ fn explicit_predicates_of<'a, 'tcx>(
     def_id: DefId,
 ) -> ty::GenericPredicates<'tcx> {
     use rustc::hir::*;
+    use rustc_data_structures::fx::FxHashSet;
 
     debug!("explicit_predicates_of(def_id={:?})", def_id);
 
+    /// A data structure with unique elements, which preserves order of insertion.
+    /// Preserving the order of insertion is important here so as not to break
+    /// compile-fail UI tests.
+    struct UniquePredicates<'tcx> {
+        predicates: Vec<(ty::Predicate<'tcx>, Span)>,
+        uniques: FxHashSet<(ty::Predicate<'tcx>, Span)>,
+    }
+
+    impl<'tcx> UniquePredicates<'tcx> {
+        fn new() -> Self {
+            UniquePredicates {
+                predicates: vec![],
+                uniques: FxHashSet::default(),
+            }
+        }
+
+        fn push(&mut self, value: (ty::Predicate<'tcx>, Span)) {
+            if self.uniques.insert(value) {
+                self.predicates.push(value);
+            }
+        }
+
+        fn extend<I: IntoIterator<Item = (ty::Predicate<'tcx>, Span)>>(&mut self, iter: I) {
+            for value in iter {
+                self.push(value);
+            }
+        }
+    }
+
     let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
     let node = tcx.hir.get(node_id);
 
@@ -1649,7 +1679,7 @@ fn explicit_predicates_of<'a, 'tcx>(
     let icx = ItemCtxt::new(tcx, def_id);
     let no_generics = hir::Generics::empty();
 
-    let mut predicates = vec![];
+    let mut predicates = UniquePredicates::new();
 
     let ast_generics = match node {
         Node::TraitItem(item) => &item.generics,
@@ -1744,7 +1774,7 @@ fn explicit_predicates_of<'a, 'tcx>(
     // on a trait we need to add in the supertrait bounds and bounds found on
     // associated types.
     if let Some((_trait_ref, _)) = is_trait {
-        predicates = tcx.super_predicates_of(def_id).predicates;
+        predicates.extend(tcx.super_predicates_of(def_id).predicates);
     }
 
     // In default impls, we can assume that the self type implements
@@ -1895,6 +1925,8 @@ fn explicit_predicates_of<'a, 'tcx>(
         }))
     }
 
+    let mut predicates = predicates.predicates;
+
     // Subtle: before we store the predicates into the tcx, we
     // sort them so that predicates like `T: Foo<Item=U>` come
     // before uses of `U`.  This avoids false ambiguity errors
index 6bf7a3501bed997b092bdafbdc8e2b0c5b1530a2..96b75c4792d759486f8966789592149271d3a2d3 100644 (file)
@@ -170,7 +170,7 @@ fn is_free_region<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, region: Region<'_>) -> bool
         | RegionKind::ReCanonical(..)
         | RegionKind::ReScope(..)
         | RegionKind::ReVar(..)
-        | RegionKind::ReSkolemized(..)
+        | RegionKind::RePlaceholder(..)
         | RegionKind::ReFree(..) => {
             bug!("unexpected region in outlives inference: {:?}", region);
         }
index 95544da0b8e0da47ba6b68c1d4f6fe67fba07440..32a591777db5b57362ea53be5499f71d118d1cd6 100644 (file)
@@ -336,6 +336,7 @@ fn add_constraints_from_ty(&mut self,
                 // types, where we use Error as the Self type
             }
 
+            ty::UnnormalizedProjection(..) |
             ty::GeneratorWitness(..) |
             ty::Infer(..) => {
                 bug!("unexpected type encountered in \
@@ -430,7 +431,7 @@ fn add_constraints_from_region(&mut self,
             ty::ReClosureBound(..) |
             ty::ReScope(..) |
             ty::ReVar(..) |
-            ty::ReSkolemized(..) |
+            ty::RePlaceholder(..) |
             ty::ReEmpty |
             ty::ReErased => {
                 // We don't expect to see anything but 'static or bound
index 371b631723a39bb35beea29188331c330892e215..ddabef96c7c5e5e2031db9d70515457c943bbd85 100644 (file)
@@ -1258,7 +1258,7 @@ fn clean(&self, cx: &DocContext) -> Option<Lifetime> {
             ty::ReFree(..) |
             ty::ReScope(..) |
             ty::ReVar(..) |
-            ty::ReSkolemized(..) |
+            ty::RePlaceholder(..) |
             ty::ReEmpty |
             ty::ReClosureBound(_) |
             ty::ReCanonical(_) |
@@ -2416,6 +2416,14 @@ fn clean(&self, cx: &DocContext) -> Type {
                 Array(box ty.clean(cx), length)
             },
             TyKind::Tup(ref tys) => Tuple(tys.clean(cx)),
+            TyKind::Def(item_id, _) => {
+                let item = cx.tcx.hir.expect_item(item_id.id);
+                if let hir::ItemKind::Existential(ref ty) = item.node {
+                    ImplTrait(ty.bounds.clean(cx))
+                } else {
+                    unreachable!()
+                }
+            }
             TyKind::Path(hir::QPath::Resolved(None, ref path)) => {
                 if let Some(new_ty) = cx.ty_substs.borrow().get(&path.def).cloned() {
                     return new_ty;
@@ -2425,14 +2433,6 @@ fn clean(&self, cx: &DocContext) -> Type {
                     if let Some(bounds) = cx.impl_trait_bounds.borrow_mut().remove(&did) {
                         return ImplTrait(bounds);
                     }
-                } else if let Def::Existential(did) = path.def {
-                    // This block is for returned impl trait only.
-                    if let Some(node_id) = cx.tcx.hir.as_local_node_id(did) {
-                        let item = cx.tcx.hir.expect_item(node_id);
-                        if let hir::ItemKind::Existential(ref ty) = item.node {
-                            return ImplTrait(ty.bounds.clean(cx));
-                        }
-                    }
                 }
 
                 let mut alias = None;
@@ -2737,6 +2737,7 @@ fn clean(&self, cx: &DocContext) -> Type {
 
             ty::Closure(..) | ty::Generator(..) => Tuple(vec![]), // FIXME(pcwalton)
 
+            ty::UnnormalizedProjection(..) => panic!("UnnormalizedProjection"),
             ty::GeneratorWitness(..) => panic!("GeneratorWitness"),
             ty::Infer(..) => panic!("Infer"),
             ty::Error => panic!("Error"),
index ee811f3379239d4b560a9472f5c18477108be92e..58ac46d22717bc7dd0af46b28d11b7335a5ce9f1 100644 (file)
@@ -97,7 +97,6 @@ h1, h2, h3:not(.impl):not(.method):not(.type):not(.tymethod):not(.important), h4
 h1.fqn {
        border-bottom: 1px dashed;
        margin-top: 0;
-       overflow: auto;
 }
 h2, h3:not(.impl):not(.method):not(.type):not(.tymethod), h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant) {
        border-bottom: 1px solid;
index 3de4a1bd4170b62a454a5091fe05a6e4cdec29ed..7a5353bb60ff634c68c58cb65811abcaea1beda4 100644 (file)
@@ -217,6 +217,35 @@ fn type_id(&self) -> TypeId where Self: 'static {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, E: Error + 'a> From<E> for Box<dyn Error + 'a> {
+    /// Converts a type of [`Error`] into a box of dyn [`Error`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::error::Error;
+    /// use std::fmt;
+    /// use std::mem;
+    ///
+    /// #[derive(Debug)]
+    /// struct AnError;
+    ///
+    /// impl fmt::Display for AnError {
+    ///     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    ///         write!(f , "An error")
+    ///     }
+    /// }
+    ///
+    /// impl Error for AnError {
+    ///     fn description(&self) -> &str {
+    ///         "Description of an error"
+    ///     }
+    /// }
+    ///
+    /// let an_error = AnError;
+    /// assert!(0 == mem::size_of_val(&an_error));
+    /// let a_boxed_error = Box::<Error>::from(an_error);
+    /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
+    /// ```
     fn from(err: E) -> Box<dyn Error + 'a> {
         Box::new(err)
     }
@@ -224,6 +253,41 @@ fn from(err: E) -> Box<dyn Error + 'a> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, E: Error + Send + Sync + 'a> From<E> for Box<dyn Error + Send + Sync + 'a> {
+    /// Converts a type of [`Error`] + [`Send`] + [`Sync`] into a box of dyn [`Error`] +
+    /// [`Send`] + [`Sync`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::error::Error;
+    /// use std::fmt;
+    /// use std::mem;
+    ///
+    /// #[derive(Debug)]
+    /// struct AnError;
+    ///
+    /// impl fmt::Display for AnError {
+    ///     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    ///         write!(f , "An error")
+    ///     }
+    /// }
+    ///
+    /// impl Error for AnError {
+    ///     fn description(&self) -> &str {
+    ///         "Description of an error"
+    ///     }
+    /// }
+    ///
+    /// unsafe impl Send for AnError {}
+    ///
+    /// unsafe impl Sync for AnError {}
+    ///
+    /// let an_error = AnError;
+    /// assert!(0 == mem::size_of_val(&an_error));
+    /// let a_boxed_error = Box::<Error + Send + Sync>::from(an_error);
+    /// assert!(
+    ///     mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
+    /// ```
     fn from(err: E) -> Box<dyn Error + Send + Sync + 'a> {
         Box::new(err)
     }
@@ -231,6 +295,19 @@ fn from(err: E) -> Box<dyn Error + Send + Sync + 'a> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl From<String> for Box<dyn Error + Send + Sync> {
+    /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::error::Error;
+    /// use std::mem;
+    ///
+    /// let a_string_error = "a string error".to_string();
+    /// let a_boxed_error = Box::<Error + Send + Sync>::from(a_string_error);
+    /// assert!(
+    ///     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);
@@ -251,6 +328,18 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 
 #[stable(feature = "string_box_error", since = "1.6.0")]
 impl From<String> for Box<dyn Error> {
+    /// Converts a [`String`] into a box of dyn [`Error`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::error::Error;
+    /// use std::mem;
+    ///
+    /// let a_string_error = "a string error".to_string();
+    /// let a_boxed_error = Box::<Error>::from(a_string_error);
+    /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
+    /// ```
     fn from(str_err: String) -> Box<dyn Error> {
         let err1: Box<dyn Error + Send + Sync> = From::from(str_err);
         let err2: Box<dyn Error> = err1;
@@ -260,6 +349,19 @@ fn from(str_err: String) -> Box<dyn Error> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, 'b> From<&'b str> for Box<dyn Error + Send + Sync + 'a> {
+    /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::error::Error;
+    /// use std::mem;
+    ///
+    /// let a_str_error = "a str error";
+    /// let a_boxed_error = Box::<Error + Send + Sync>::from(a_str_error);
+    /// assert!(
+    ///     mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
+    /// ```
     fn from(err: &'b str) -> Box<dyn Error + Send + Sync + 'a> {
         From::from(String::from(err))
     }
@@ -267,6 +369,18 @@ fn from(err: &'b str) -> Box<dyn Error + Send + Sync + 'a> {
 
 #[stable(feature = "string_box_error", since = "1.6.0")]
 impl<'a> From<&'a str> for Box<dyn Error> {
+    /// Converts a [`str`] into a box of dyn [`Error`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::error::Error;
+    /// use std::mem;
+    ///
+    /// let a_str_error = "a str error";
+    /// let a_boxed_error = Box::<Error>::from(a_str_error);
+    /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
+    /// ```
     fn from(err: &'a str) -> Box<dyn Error> {
         From::from(String::from(err))
     }
@@ -274,6 +388,20 @@ fn from(err: &'a str) -> Box<dyn Error> {
 
 #[stable(feature = "cow_box_error", since = "1.22.0")]
 impl<'a, 'b> From<Cow<'b, str>> for Box<dyn Error + Send + Sync + 'a> {
+    /// Converts a [`Cow`] into a box of dyn [`Error`] + [`Send`] + [`Sync`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::error::Error;
+    /// use std::mem;
+    /// use std::borrow::Cow;
+    ///
+    /// let a_cow_str_error = Cow::from("a str error");
+    /// let a_boxed_error = Box::<Error + Send + Sync>::from(a_cow_str_error);
+    /// assert!(
+    ///     mem::size_of::<Box<dyn Error + Send + Sync>>() == mem::size_of_val(&a_boxed_error))
+    /// ```
     fn from(err: Cow<'b, str>) -> Box<dyn Error + Send + Sync + 'a> {
         From::from(String::from(err))
     }
@@ -281,6 +409,19 @@ fn from(err: Cow<'b, str>) -> Box<dyn Error + Send + Sync + 'a> {
 
 #[stable(feature = "cow_box_error", since = "1.22.0")]
 impl<'a> From<Cow<'a, str>> for Box<dyn Error> {
+    /// Converts a [`Cow`] into a box of dyn [`Error`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::error::Error;
+    /// use std::mem;
+    /// use std::borrow::Cow;
+    ///
+    /// let a_cow_str_error = Cow::from("a str error");
+    /// let a_boxed_error = Box::<Error>::from(a_cow_str_error);
+    /// assert!(mem::size_of::<Box<dyn Error>>() == mem::size_of_val(&a_boxed_error))
+    /// ```
     fn from(err: Cow<'a, str>) -> Box<dyn Error> {
         From::from(String::from(err))
     }
index afe0b67e33020aeb3a743bb32997549def92c7dd..c58bd364cedaba7857e9f607aedc464bcff11bab 100644 (file)
 #![feature(const_cstr_unchecked)]
 #![feature(core_intrinsics)]
 #![feature(dropck_eyepatch)]
+#![feature(duration_as_u128)]
 #![feature(exact_size_is_empty)]
 #![feature(external_doc)]
 #![feature(fixed_size_array)]
index df085a7f450b099640410acceff6427440379882..a0590a800d3cc77494ccf1a8c07a13487b2917c3 100644 (file)
@@ -515,11 +515,11 @@ fn get(&mut self) -> &(dyn Any + Send) {
     rust_panic(&mut RewrapBox(msg))
 }
 
-/// A private no-mangle function on which to slap yer breakpoints.
+/// An unmangled function (through `rustc_std_internal_symbol`) on which to slap
+/// yer breakpoints.
 #[inline(never)]
-#[no_mangle]
-#[allow(private_no_mangle_fns)] // yes we get it, but we like breakpoints
-pub fn rust_panic(mut msg: &mut dyn BoxMeUp) -> ! {
+#[cfg_attr(not(test), rustc_std_internal_symbol)]
+fn rust_panic(mut msg: &mut dyn BoxMeUp) -> ! {
     let code = unsafe {
         let obj = &mut msg as *mut &mut dyn BoxMeUp;
         __rust_start_panic(obj as usize)
index e12ef8d9eda2de71ad030275addf8a9c492b5265..d69ebc17622720200a1db22eb5262621e99946ce 100644 (file)
 
 //! Useful synchronization primitives.
 //!
-//! This module contains useful safe and unsafe synchronization primitives.
-//! Most of the primitives in this module do not provide any sort of locking
-//! and/or blocking at all, but rather provide the necessary tools to build
-//! other types of concurrent primitives.
+//! ## The need for synchronization
+//!
+//! Conceptually, a Rust program is a series of operations which will
+//! be executed on a computer. The timeline of events happening in the
+//! program is consistent with the order of the operations in the code.
+//!
+//! Consider the following code, operating on some global static variables:
+//!
+//! ```rust
+//! static mut A: u32 = 0;
+//! static mut B: u32 = 0;
+//! static mut C: u32 = 0;
+//!
+//! fn main() {
+//!     unsafe {
+//!         A = 3;
+//!         B = 4;
+//!         A = A + B;
+//!         C = B;
+//!         println!("{} {} {}", A, B, C);
+//!         C = A;
+//!     }
+//! }
+//! ```
+//!
+//! It appears as if some variables stored in memory are changed, an addition
+//! is performed, result is stored in `A` and the variable `C` is
+//! modified twice.
+//!
+//! When only a single thread is involved, the results are as expected:
+//! the line `7 4 4` gets printed.
+//!
+//! As for what happens behind the scenes, when optimizations are enabled the
+//! final generated machine code might look very different from the code:
+//!
+//! - The first store to `C` might be moved before the store to `A` or `B`,
+//!   _as if_ we had written `C = 4; A = 3; B = 4`.
+//!
+//! - Assignment of `A + B` to `A` might be removed, since the sum can be stored
+//!   in a temporary location until it gets printed, with the global variable
+//!   never getting updated.
+//!
+//! - The final result could be determined just by looking at the code
+//!   at compile time, so [constant folding] might turn the whole
+//!   block into a simple `println!("7 4 4")`.
+//!
+//! The compiler is allowed to perform any combination of these
+//! optimizations, as long as the final optimized code, when executed,
+//! produces the same results as the one without optimizations.
+//!
+//! Due to the [concurrency] involved in modern computers, assumptions
+//! about the program's execution order are often wrong. Access to
+//! global variables can lead to nondeterministic results, **even if**
+//! compiler optimizations are disabled, and it is **still possible**
+//! to introduce synchronization bugs.
+//!
+//! Note that thanks to Rust's safety guarantees, accessing global (static)
+//! variables requires `unsafe` code, assuming we don't use any of the
+//! synchronization primitives in this module.
+//!
+//! [constant folding]: https://en.wikipedia.org/wiki/Constant_folding
+//! [concurrency]: https://en.wikipedia.org/wiki/Concurrency_(computer_science)
+//!
+//! ## Out-of-order execution
+//!
+//! Instructions can execute in a different order from the one we define, due to
+//! various reasons:
+//!
+//! - The **compiler** reordering instructions: If the compiler can issue an
+//!   instruction at an earlier point, it will try to do so. For example, it
+//!   might hoist memory loads at the top of a code block, so that the CPU can
+//!   start [prefetching] the values from memory.
+//!
+//!   In single-threaded scenarios, this can cause issues when writing
+//!   signal handlers or certain kinds of low-level code.
+//!   Use [compiler fences] to prevent this reordering.
+//!
+//! - A **single processor** executing instructions [out-of-order]:
+//!   Modern CPUs are capable of [superscalar] execution,
+//!   i.e. multiple instructions might be executing at the same time,
+//!   even though the machine code describes a sequential process.
+//!
+//!   This kind of reordering is handled transparently by the CPU.
+//!
+//! - A **multiprocessor** system executing multiple hardware threads
+//!   at the same time: In multi-threaded scenarios, you can use two
+//!   kinds of primitives to deal with synchronization:
+//!   - [memory fences] to ensure memory accesses are made visibile to
+//!   other CPUs in the right order.
+//!   - [atomic operations] to ensure simultaneous access to the same
+//!   memory location doesn't lead to undefined behavior.
+//!
+//! [prefetching]: https://en.wikipedia.org/wiki/Cache_prefetching
+//! [compiler fences]: crate::sync::atomic::compiler_fence
+//! [out-of-order]: https://en.wikipedia.org/wiki/Out-of-order_execution
+//! [superscalar]: https://en.wikipedia.org/wiki/Superscalar_processor
+//! [memory fences]: crate::sync::atomic::fence
+//! [atomic operations]: crate::sync::atomic
+//!
+//! ## Higher-level synchronization objects
+//!
+//! Most of the low-level synchronization primitives are quite error-prone and
+//! inconvenient to use, which is why the standard library also exposes some
+//! higher-level synchronization objects.
+//!
+//! These abstractions can be built out of lower-level primitives.
+//! For efficiency, the sync objects in the standard library are usually
+//! implemented with help from the operating system's kernel, which is
+//! able to reschedule the threads while they are blocked on acquiring
+//! a lock.
+//!
+//! The following is an overview of the available synchronization
+//! objects:
+//!
+//! - [`Arc`]: Atomically Reference-Counted pointer, which can be used
+//!   in multithreaded environments to prolong the lifetime of some
+//!   data until all the threads have finished using it.
+//!
+//! - [`Barrier`]: Ensures multiple threads will wait for each other
+//!   to reach a point in the program, before continuing execution all
+//!   together.
+//!
+//! - [`Condvar`]: Condition Variable, providing the ability to block
+//!   a thread while waiting for an event to occur.
+//!
+//! - [`mpsc`]: Multi-producer, single-consumer queues, used for
+//!   message-based communication. Can provide a lightweight
+//!   inter-thread synchronisation mechanism, at the cost of some
+//!   extra memory.
+//!
+//! - [`Mutex`]: Mutual Exclusion mechanism, which ensures that at
+//!   most one thread at a time is able to access some data.
+//!
+//! - [`Once`]: Used for thread-safe, one-time initialization of a
+//!   global variable.
+//!
+//! - [`RwLock`]: Provides a mutual exclusion mechanism which allows
+//!   multiple readers at the same time, while allowing only one
+//!   writer at a time. In some cases, this can be more efficient than
+//!   a mutex.
+//!
+//! [`Arc`]: crate::sync::Arc
+//! [`Barrier`]: crate::sync::Barrier
+//! [`Condvar`]: crate::sync::Condvar
+//! [`mpsc`]: crate::sync::mpsc
+//! [`Mutex`]: crate::sync::Mutex
+//! [`Once`]: crate::sync::Once
+//! [`RwLock`]: crate::sync::RwLock
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
diff --git a/src/libstd/sys/wasm/condvar_atomics.rs b/src/libstd/sys/wasm/condvar_atomics.rs
new file mode 100644 (file)
index 0000000..5c55fd0
--- /dev/null
@@ -0,0 +1,104 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use arch::wasm32::atomic;
+use cmp;
+use mem;
+use sync::atomic::{AtomicUsize, Ordering::SeqCst};
+use sys::mutex::Mutex;
+use time::Duration;
+
+pub struct Condvar {
+    cnt: AtomicUsize,
+}
+
+// Condition variables are implemented with a simple counter internally that is
+// likely to cause spurious wakeups. Blocking on a condition variable will first
+// read the value of the internal counter, unlock the given mutex, and then
+// block if and only if the counter's value is still the same. Notifying a
+// condition variable will modify the counter (add one for now) and then wake up
+// a thread waiting on the address of the counter.
+//
+// A thread waiting on the condition variable will as a result avoid going to
+// sleep if it's notified after the lock is unlocked but before it fully goes to
+// sleep. A sleeping thread is guaranteed to be woken up at some point as it can
+// only be woken up with a call to `wake`.
+//
+// Note that it's possible for 2 or more threads to be woken up by a call to
+// `notify_one` with this implementation. That can happen where the modification
+// of `cnt` causes any threads in the middle of `wait` to avoid going to sleep,
+// and the subsequent `wake` may wake up a thread that's actually blocking. We
+// consider this a spurious wakeup, though, which all users of condition
+// variables must already be prepared to handle. As a result, this source of
+// spurious wakeups is currently though to be ok, although it may be problematic
+// later on if it causes too many spurious wakeups.
+
+impl Condvar {
+    pub const fn new() -> Condvar {
+        Condvar { cnt: AtomicUsize::new(0) }
+    }
+
+    #[inline]
+    pub unsafe fn init(&mut self) {
+        // nothing to do
+    }
+
+    pub unsafe fn notify_one(&self) {
+        self.cnt.fetch_add(1, SeqCst);
+        atomic::wake(self.ptr(), 1);
+    }
+
+    #[inline]
+    pub unsafe fn notify_all(&self) {
+        self.cnt.fetch_add(1, SeqCst);
+        atomic::wake(self.ptr(), -1); // -1 == "wake everyone"
+    }
+
+    pub unsafe fn wait(&self, mutex: &Mutex) {
+        // "atomically block and unlock" implemented by loading our current
+        // counter's value, unlocking the mutex, and blocking if the counter
+        // still has the same value.
+        //
+        // Notifications happen by incrementing the counter and then waking a
+        // thread. Incrementing the counter after we unlock the mutex will
+        // prevent us from sleeping and otherwise the call to `wake` will
+        // wake us up once we're asleep.
+        let ticket = self.cnt.load(SeqCst) as i32;
+        mutex.unlock();
+        let val = atomic::wait_i32(self.ptr(), ticket, -1);
+        // 0 == woken, 1 == not equal to `ticket`, 2 == timeout (shouldn't happen)
+        debug_assert!(val == 0 || val == 1);
+        mutex.lock();
+    }
+
+    pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
+        let ticket = self.cnt.load(SeqCst) as i32;
+        mutex.unlock();
+        let nanos = dur.as_nanos();
+        let nanos = cmp::min(i64::max_value() as u128, nanos);
+
+        // If the return value is 2 then a timeout happened, so we return
+        // `false` as we weren't actually notified.
+        let ret = atomic::wait_i32(self.ptr(), ticket, nanos as i64) != 2;
+        mutex.lock();
+        return ret
+    }
+
+    #[inline]
+    pub unsafe fn destroy(&self) {
+        // nothing to do
+    }
+
+    #[inline]
+    fn ptr(&self) -> *mut i32 {
+        assert_eq!(mem::size_of::<usize>(), mem::size_of::<i32>());
+        &self.cnt as *const AtomicUsize as *mut i32
+    }
+}
index c02e5e809c8bb33cb81553eec35607420553fbd4..e11b4d71aaeea90cf01cee2b66eb99cc2423d90e 100644 (file)
 #[cfg(feature = "backtrace")]
 pub mod backtrace;
 pub mod cmath;
-pub mod condvar;
 pub mod env;
 pub mod fs;
 pub mod memchr;
-pub mod mutex;
 pub mod net;
 pub mod os;
 pub mod os_str;
 pub mod path;
 pub mod pipe;
 pub mod process;
-pub mod rwlock;
 pub mod stack_overflow;
 pub mod thread;
-pub mod thread_local;
 pub mod time;
 pub mod stdio;
 
+cfg_if! {
+    if #[cfg(target_feature = "atomics")] {
+        #[path = "condvar_atomics.rs"]
+        pub mod condvar;
+        #[path = "mutex_atomics.rs"]
+        pub mod mutex;
+        #[path = "rwlock_atomics.rs"]
+        pub mod rwlock;
+        #[path = "thread_local_atomics.rs"]
+        pub mod thread_local;
+    } else {
+        pub mod condvar;
+        pub mod mutex;
+        pub mod rwlock;
+        pub mod thread_local;
+    }
+}
+
 #[cfg(not(test))]
 pub fn init() {
 }
diff --git a/src/libstd/sys/wasm/mutex_atomics.rs b/src/libstd/sys/wasm/mutex_atomics.rs
new file mode 100644 (file)
index 0000000..ced6c17
--- /dev/null
@@ -0,0 +1,163 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use arch::wasm32::atomic;
+use cell::UnsafeCell;
+use mem;
+use sync::atomic::{AtomicUsize, AtomicU64, Ordering::SeqCst};
+
+pub struct Mutex {
+    locked: AtomicUsize,
+}
+
+// Mutexes have a pretty simple implementation where they contain an `i32`
+// internally that is 0 when unlocked and 1 when the mutex is locked.
+// Acquisition has a fast path where it attempts to cmpxchg the 0 to a 1, and
+// if it fails it then waits for a notification. Releasing a lock is then done
+// by swapping in 0 and then notifying any waiters, if present.
+
+impl Mutex {
+    pub const fn new() -> Mutex {
+        Mutex { locked: AtomicUsize::new(0) }
+    }
+
+    #[inline]
+    pub unsafe fn init(&mut self) {
+        // nothing to do
+    }
+
+    pub unsafe fn lock(&self) {
+        while !self.try_lock() {
+            let val = atomic::wait_i32(
+                self.ptr(),
+                1,  // we expect our mutex is locked
+                -1, // wait infinitely
+            );
+            // we should have either woke up (0) or got a not-equal due to a
+            // race (1). We should never time out (2)
+            debug_assert!(val == 0 || val == 1);
+        }
+    }
+
+    pub unsafe fn unlock(&self) {
+        let prev = self.locked.swap(0, SeqCst);
+        debug_assert_eq!(prev, 1);
+        atomic::wake(self.ptr(), 1); // wake up one waiter, if any
+    }
+
+    #[inline]
+    pub unsafe fn try_lock(&self) -> bool {
+        self.locked.compare_exchange(0, 1, SeqCst, SeqCst).is_ok()
+    }
+
+    #[inline]
+    pub unsafe fn destroy(&self) {
+        // nothing to do
+    }
+
+    #[inline]
+    fn ptr(&self) -> *mut i32 {
+        assert_eq!(mem::size_of::<usize>(), mem::size_of::<i32>());
+        &self.locked as *const AtomicUsize as *mut isize as *mut i32
+    }
+}
+
+pub struct ReentrantMutex {
+    owner: AtomicU64,
+    recursions: UnsafeCell<u32>,
+}
+
+unsafe impl Send for ReentrantMutex {}
+unsafe impl Sync for ReentrantMutex {}
+
+// Reentrant mutexes are similarly implemented to mutexs above except that
+// instead of "1" meaning unlocked we use the id of a thread to represent
+// whether it has locked a mutex. That way we have an atomic counter which
+// always holds the id of the thread that currently holds the lock (or 0 if the
+// lock is unlocked).
+//
+// Once a thread acquires a lock recursively, which it detects by looking at
+// the value that's already there, it will update a local `recursions` counter
+// in a nonatomic fashion (as we hold the lock). The lock is then fully
+// released when this recursion counter reaches 0.
+
+impl ReentrantMutex {
+    pub unsafe fn uninitialized() -> ReentrantMutex {
+        ReentrantMutex {
+            owner: AtomicU64::new(0),
+            recursions: UnsafeCell::new(0),
+        }
+    }
+
+    pub unsafe fn init(&mut self) {
+        // nothing to do...
+    }
+
+    pub unsafe fn lock(&self) {
+        let me = thread_id();
+        while let Err(owner) = self._try_lock(me) {
+            let val = atomic::wait_i64(self.ptr(), owner as i64, -1);
+            debug_assert!(val == 0 || val == 1);
+        }
+    }
+
+    #[inline]
+    pub unsafe fn try_lock(&self) -> bool {
+        self._try_lock(thread_id()).is_ok()
+    }
+
+    #[inline]
+    unsafe fn _try_lock(&self, id: u64) -> Result<(), u64> {
+        let id = id.checked_add(1).unwrap(); // make sure `id` isn't 0
+        match self.owner.compare_exchange(0, id, SeqCst, SeqCst) {
+            // we transitioned from unlocked to locked
+            Ok(_) => {
+                debug_assert_eq!(*self.recursions.get(), 0);
+                Ok(())
+            }
+
+            // we currently own this lock, so let's update our count and return
+            // true.
+            Err(n) if n == id => {
+                *self.recursions.get() += 1;
+                Ok(())
+            }
+
+            // Someone else owns the lock, let our caller take care of it
+            Err(other) => Err(other),
+        }
+    }
+
+    pub unsafe fn unlock(&self) {
+        // If we didn't ever recursively lock the lock then we fully unlock the
+        // mutex and wake up a waiter, if any. Otherwise we decrement our
+        // recursive counter and let some one else take care of the zero.
+        match *self.recursions.get() {
+            0 => {
+                self.owner.swap(0, SeqCst);
+                atomic::wake(self.ptr() as *mut i32, 1); // wake up one waiter, if any
+            }
+            ref mut n => *n -= 1,
+        }
+    }
+
+    pub unsafe fn destroy(&self) {
+        // nothing to do...
+    }
+
+    #[inline]
+    fn ptr(&self) -> *mut i64 {
+        &self.owner as *const AtomicU64 as *mut i64
+    }
+}
+
+fn thread_id() -> u64 {
+    panic!("thread ids not implemented on wasm with atomics yet")
+}
diff --git a/src/libstd/sys/wasm/rwlock_atomics.rs b/src/libstd/sys/wasm/rwlock_atomics.rs
new file mode 100644 (file)
index 0000000..3623333
--- /dev/null
@@ -0,0 +1,161 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use cell::UnsafeCell;
+use sys::mutex::Mutex;
+use sys::condvar::Condvar;
+
+pub struct RWLock {
+    lock: Mutex,
+    cond: Condvar,
+    state: UnsafeCell<State>,
+}
+
+enum State {
+    Unlocked,
+    Reading(usize),
+    Writing,
+}
+
+unsafe impl Send for RWLock {}
+unsafe impl Sync for RWLock {}
+
+// This rwlock implementation is a relatively simple implementation which has a
+// condition variable for readers/writers as well as a mutex protecting the
+// internal state of the lock. A current downside of the implementation is that
+// unlocking the lock will notify *all* waiters rather than just readers or just
+// writers. This can cause lots of "thundering stampede" problems. While
+// hopefully correct this implementation is very likely to want to be changed in
+// the future.
+
+impl RWLock {
+    pub const fn new() -> RWLock {
+        RWLock {
+            lock: Mutex::new(),
+            cond: Condvar::new(),
+            state: UnsafeCell::new(State::Unlocked),
+        }
+    }
+
+    #[inline]
+    pub unsafe fn read(&self) {
+        self.lock.lock();
+        while !(*self.state.get()).inc_readers() {
+            self.cond.wait(&self.lock);
+        }
+        self.lock.unlock();
+    }
+
+    #[inline]
+    pub unsafe fn try_read(&self) -> bool {
+        self.lock.lock();
+        let ok = (*self.state.get()).inc_readers();
+        self.lock.unlock();
+        return ok
+    }
+
+    #[inline]
+    pub unsafe fn write(&self) {
+        self.lock.lock();
+        while !(*self.state.get()).inc_writers() {
+            self.cond.wait(&self.lock);
+        }
+        self.lock.unlock();
+    }
+
+    #[inline]
+    pub unsafe fn try_write(&self) -> bool {
+        self.lock.lock();
+        let ok = (*self.state.get()).inc_writers();
+        self.lock.unlock();
+        return ok
+    }
+
+    #[inline]
+    pub unsafe fn read_unlock(&self) {
+        self.lock.lock();
+        let notify = (*self.state.get()).dec_readers();
+        self.lock.unlock();
+        if notify {
+            // FIXME: should only wake up one of these some of the time
+            self.cond.notify_all();
+        }
+    }
+
+    #[inline]
+    pub unsafe fn write_unlock(&self) {
+        self.lock.lock();
+        (*self.state.get()).dec_writers();
+        self.lock.unlock();
+        // FIXME: should only wake up one of these some of the time
+        self.cond.notify_all();
+    }
+
+    #[inline]
+    pub unsafe fn destroy(&self) {
+        self.lock.destroy();
+        self.cond.destroy();
+    }
+}
+
+impl State {
+    fn inc_readers(&mut self) -> bool {
+        match *self {
+            State::Unlocked => {
+                *self = State::Reading(1);
+                true
+            }
+            State::Reading(ref mut cnt) => {
+                *cnt += 1;
+                true
+            }
+            State::Writing => false
+        }
+    }
+
+    fn inc_writers(&mut self) -> bool {
+        match *self {
+            State::Unlocked => {
+                *self = State::Writing;
+                true
+            }
+            State::Reading(_) |
+            State::Writing => false
+        }
+    }
+
+    fn dec_readers(&mut self) -> bool {
+        let zero = match *self {
+            State::Reading(ref mut cnt) => {
+                *cnt -= 1;
+                *cnt == 0
+            }
+            State::Unlocked |
+            State::Writing => invalid(),
+        };
+        if zero {
+            *self = State::Unlocked;
+        }
+        zero
+    }
+
+    fn dec_writers(&mut self) {
+        match *self {
+            State::Writing => {}
+            State::Unlocked |
+            State::Reading(_) => invalid(),
+        }
+        *self = State::Unlocked;
+    }
+}
+
+fn invalid() -> ! {
+    panic!("inconsistent rwlock");
+}
index 8173a62421117d4bb11b034a1bcee3978458a84c..bef6c1f34905e8b84e56cd5d5778e84a8ca6e153 100644 (file)
@@ -33,10 +33,31 @@ pub fn set_name(_name: &CStr) {
         // nope
     }
 
+    #[cfg(not(target_feature = "atomics"))]
     pub fn sleep(_dur: Duration) {
         panic!("can't sleep");
     }
 
+    #[cfg(target_feature = "atomics")]
+    pub fn sleep(dur: Duration) {
+        use arch::wasm32::atomic;
+        use cmp;
+
+        // Use an atomic wait to block the current thread artificially with a
+        // timeout listed. Note that we should never be notified (return value
+        // of 0) or our comparison should never fail (return value of 1) so we
+        // should always only resume execution through a timeout (return value
+        // 2).
+        let mut nanos = dur.as_nanos();
+        while nanos > 0 {
+            let amt = cmp::min(i64::max_value() as u128, nanos);
+            let mut x = 0;
+            let val = unsafe { atomic::wait_i32(&mut x, 0, amt as i64) };
+            debug_assert_eq!(val, 2);
+            nanos -= amt;
+        }
+    }
+
     pub fn join(self) {
         match self.0 {}
     }
diff --git a/src/libstd/sys/wasm/thread_local_atomics.rs b/src/libstd/sys/wasm/thread_local_atomics.rs
new file mode 100644 (file)
index 0000000..1394013
--- /dev/null
@@ -0,0 +1,32 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub type Key = usize;
+
+pub unsafe fn create(_dtor: Option<unsafe extern fn(*mut u8)>) -> Key {
+    panic!("TLS on wasm with atomics not implemented yet");
+}
+
+pub unsafe fn set(_key: Key, _value: *mut u8) {
+    panic!("TLS on wasm with atomics not implemented yet");
+}
+
+pub unsafe fn get(_key: Key) -> *mut u8 {
+    panic!("TLS on wasm with atomics not implemented yet");
+}
+
+pub unsafe fn destroy(_key: Key) {
+    panic!("TLS on wasm with atomics not implemented yet");
+}
+
+#[inline]
+pub fn requires_synchronized_create() -> bool {
+    false
+}
index 52322e98d46f9cd0e7e3e57b3b0e98a7fe14967a..9e06384f5a804e574124136419bba662902f37ac 100644 (file)
@@ -220,14 +220,6 @@ pub struct Invocation {
     pub expansion_data: ExpansionData,
 }
 
-// Needed for feature-gating attributes used after derives or together with test/bench
-#[derive(Clone, Copy, PartialEq)]
-pub enum TogetherWith {
-    None,
-    Derive,
-    TestBench,
-}
-
 pub enum InvocationKind {
     Bang {
         mac: ast::Mac,
@@ -238,7 +230,8 @@ pub enum InvocationKind {
         attr: Option<ast::Attribute>,
         traits: Vec<Path>,
         item: Annotatable,
-        together_with: TogetherWith,
+        // We temporarily report errors for attribute macros placed after derives
+        after_derive: bool,
     },
     Derive {
         path: Path,
@@ -645,8 +638,8 @@ fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) {
         let (kind, gate) = match *item {
             Annotatable::Item(ref item) => {
                 match item.node {
-                    ItemKind::Mod(_) if self.cx.ecfg.proc_macro_mod() => return,
-                    ItemKind::Mod(_) => ("modules", "proc_macro_mod"),
+                    ItemKind::Mod(_) if self.cx.ecfg.proc_macro_hygiene() => return,
+                    ItemKind::Mod(_) => ("modules", "proc_macro_hygiene"),
                     _ => return,
                 }
             }
@@ -654,9 +647,9 @@ fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) {
             Annotatable::ImplItem(_) => return,
             Annotatable::ForeignItem(_) => return,
             Annotatable::Stmt(_) |
-            Annotatable::Expr(_) if self.cx.ecfg.proc_macro_expr() => return,
-            Annotatable::Stmt(_) => ("statements", "proc_macro_expr"),
-            Annotatable::Expr(_) => ("expressions", "proc_macro_expr"),
+            Annotatable::Expr(_) if self.cx.ecfg.proc_macro_hygiene() => return,
+            Annotatable::Stmt(_) => ("statements", "proc_macro_hygiene"),
+            Annotatable::Expr(_) => ("expressions", "proc_macro_hygiene"),
         };
         emit_feature_err(
             self.cx.parse_sess,
@@ -668,7 +661,7 @@ fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) {
     }
 
     fn gate_proc_macro_expansion(&self, span: Span, fragment: &Option<AstFragment>) {
-        if self.cx.ecfg.proc_macro_gen() {
+        if self.cx.ecfg.proc_macro_hygiene() {
             return
         }
         let fragment = match fragment {
@@ -691,7 +684,7 @@ fn visit_item(&mut self, i: &'ast ast::Item) {
                 if let ast::ItemKind::MacroDef(_) = i.node {
                     emit_feature_err(
                         self.parse_sess,
-                        "proc_macro_gen",
+                        "proc_macro_hygiene",
                         self.span,
                         GateIssue::Language,
                         &format!("procedural macros cannot expand to macro definitions"),
@@ -885,12 +878,12 @@ fn gate_proc_macro_expansion_kind(&self, span: Span, kind: AstFragmentKind) {
             AstFragmentKind::ImplItems => return,
             AstFragmentKind::ForeignItems => return,
         };
-        if self.cx.ecfg.proc_macro_non_items() {
+        if self.cx.ecfg.proc_macro_hygiene() {
             return
         }
         emit_feature_err(
             self.cx.parse_sess,
-            "proc_macro_non_items",
+            "proc_macro_hygiene",
             span,
             GateIssue::Language,
             &format!("procedural macros cannot be expanded to {}", kind),
@@ -1008,9 +1001,7 @@ pub fn parse_ast_fragment(&mut self, kind: AstFragmentKind, macro_legacy_warning
             AstFragmentKind::ForeignItems => {
                 let mut items = SmallVec::new();
                 while self.token != token::Eof {
-                    if let Some(item) = self.parse_foreign_item()? {
-                        items.push(item);
-                    }
+                    items.push(self.parse_foreign_item()?);
                 }
                 AstFragment::ForeignItems(items)
             }
@@ -1084,19 +1075,17 @@ fn collect_attr(&mut self,
                     traits: Vec<Path>,
                     item: Annotatable,
                     kind: AstFragmentKind,
-                    together_with: TogetherWith)
+                    after_derive: bool)
                     -> AstFragment {
-        self.collect(kind, InvocationKind::Attr { attr, traits, item, together_with })
+        self.collect(kind, InvocationKind::Attr { attr, traits, item, after_derive })
     }
 
-    fn find_attr_invoc(&self, attrs: &mut Vec<ast::Attribute>, together_with: &mut TogetherWith)
+    fn find_attr_invoc(&self, attrs: &mut Vec<ast::Attribute>, after_derive: &mut bool)
                        -> Option<ast::Attribute> {
         let attr = attrs.iter()
                         .position(|a| {
                             if a.path == "derive" {
-                                *together_with = TogetherWith::Derive
-                            } else if a.path == "rustc_test_marker2" {
-                                *together_with = TogetherWith::TestBench
+                                *after_derive = true;
                             }
                             !attr::is_known(a) && !is_builtin_attr(a)
                         })
@@ -1109,19 +1098,15 @@ fn find_attr_invoc(&self, attrs: &mut Vec<ast::Attribute>, together_with: &mut T
                                  "non-builtin inner attributes are unstable");
             }
         }
-        if together_with == &TogetherWith::None &&
-           attrs.iter().any(|a| a.path == "rustc_test_marker2") {
-            *together_with = TogetherWith::TestBench;
-        }
         attr
     }
 
     /// If `item` is an attr invocation, remove and return the macro attribute and derive traits.
     fn classify_item<T>(&mut self, mut item: T)
-                        -> (Option<ast::Attribute>, Vec<Path>, T, TogetherWith)
+                        -> (Option<ast::Attribute>, Vec<Path>, T, /* after_derive */ bool)
         where T: HasAttrs,
     {
-        let (mut attr, mut traits, mut together_with) = (None, Vec::new(), TogetherWith::None);
+        let (mut attr, mut traits, mut after_derive) = (None, Vec::new(), false);
 
         item = item.map_attrs(|mut attrs| {
             if let Some(legacy_attr_invoc) = self.cx.resolver.find_legacy_attr_invoc(&mut attrs,
@@ -1130,20 +1115,20 @@ fn classify_item<T>(&mut self, mut item: T)
                 return attrs;
             }
 
-            attr = self.find_attr_invoc(&mut attrs, &mut together_with);
+            attr = self.find_attr_invoc(&mut attrs, &mut after_derive);
             traits = collect_derives(&mut self.cx, &mut attrs);
             attrs
         });
 
-        (attr, traits, item, together_with)
+        (attr, traits, item, after_derive)
     }
 
     /// Alternative of `classify_item()` that ignores `#[derive]` so invocations fallthrough
     /// to the unused-attributes lint (making it an error on statements and expressions
     /// is a breaking change)
     fn classify_nonitem<T: HasAttrs>(&mut self, mut item: T)
-                                     -> (Option<ast::Attribute>, T, TogetherWith) {
-        let (mut attr, mut together_with) = (None, TogetherWith::None);
+                                     -> (Option<ast::Attribute>, T, /* after_derive */ bool) {
+        let (mut attr, mut after_derive) = (None, false);
 
         item = item.map_attrs(|mut attrs| {
             if let Some(legacy_attr_invoc) = self.cx.resolver.find_legacy_attr_invoc(&mut attrs,
@@ -1152,11 +1137,11 @@ fn classify_nonitem<T: HasAttrs>(&mut self, mut item: T)
                 return attrs;
             }
 
-            attr = self.find_attr_invoc(&mut attrs, &mut together_with);
+            attr = self.find_attr_invoc(&mut attrs, &mut after_derive);
             attrs
         });
 
-        (attr, item, together_with)
+        (attr, item, after_derive)
     }
 
     fn configure<T: HasAttrs>(&mut self, node: T) -> Option<T> {
@@ -1195,7 +1180,7 @@ fn fold_expr(&mut self, expr: P<ast::Expr>) -> P<ast::Expr> {
         expr.node = self.cfg.configure_expr_kind(expr.node);
 
         // ignore derives so they remain unused
-        let (attr, expr, together_with) = self.classify_nonitem(expr);
+        let (attr, expr, after_derive) = self.classify_nonitem(expr);
 
         if attr.is_some() {
             // collect the invoc regardless of whether or not attributes are permitted here
@@ -1204,7 +1189,7 @@ fn fold_expr(&mut self, expr: P<ast::Expr>) -> P<ast::Expr> {
 
             // AstFragmentKind::Expr requires the macro to emit an expression
             return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)),
-                                     AstFragmentKind::Expr, together_with).make_expr();
+                                     AstFragmentKind::Expr, after_derive).make_expr();
         }
 
         if let ast::ExprKind::Mac(mac) = expr.node {
@@ -1220,13 +1205,13 @@ fn fold_opt_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
         expr.node = self.cfg.configure_expr_kind(expr.node);
 
         // ignore derives so they remain unused
-        let (attr, expr, together_with) = self.classify_nonitem(expr);
+        let (attr, expr, after_derive) = self.classify_nonitem(expr);
 
         if attr.is_some() {
             attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a));
 
             return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)),
-                                     AstFragmentKind::OptExpr, together_with).make_opt_expr();
+                                     AstFragmentKind::OptExpr, after_derive).make_opt_expr();
         }
 
         if let ast::ExprKind::Mac(mac) = expr.node {
@@ -1258,18 +1243,18 @@ fn fold_pat(&mut self, pat: P<ast::Pat>) -> P<ast::Pat> {
 
         // we'll expand attributes on expressions separately
         if !stmt.is_expr() {
-            let (attr, derives, stmt_, together_with) = if stmt.is_item() {
+            let (attr, derives, stmt_, after_derive) = if stmt.is_item() {
                 self.classify_item(stmt)
             } else {
                 // ignore derives on non-item statements so it falls through
                 // to the unused-attributes lint
-                let (attr, stmt, together_with) = self.classify_nonitem(stmt);
-                (attr, vec![], stmt, together_with)
+                let (attr, stmt, after_derive) = self.classify_nonitem(stmt);
+                (attr, vec![], stmt, after_derive)
             };
 
             if attr.is_some() || !derives.is_empty() {
                 return self.collect_attr(attr, derives, Annotatable::Stmt(P(stmt_)),
-                                         AstFragmentKind::Stmts, together_with).make_stmts();
+                                         AstFragmentKind::Stmts, after_derive).make_stmts();
             }
 
             stmt = stmt_;
@@ -1311,10 +1296,10 @@ fn fold_block(&mut self, block: P<Block>) -> P<Block> {
     fn fold_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
         let item = configure!(self, item);
 
-        let (attr, traits, item, together_with) = self.classify_item(item);
+        let (attr, traits, item, after_derive) = self.classify_item(item);
         if attr.is_some() || !traits.is_empty() {
             return self.collect_attr(attr, traits, Annotatable::Item(item),
-                                     AstFragmentKind::Items, together_with).make_items();
+                                     AstFragmentKind::Items, after_derive).make_items();
         }
 
         match item.node {
@@ -1386,10 +1371,10 @@ fn fold_block(&mut self, block: P<Block>) -> P<Block> {
     fn fold_trait_item(&mut self, item: ast::TraitItem) -> SmallVec<[ast::TraitItem; 1]> {
         let item = configure!(self, item);
 
-        let (attr, traits, item, together_with) = self.classify_item(item);
+        let (attr, traits, item, after_derive) = self.classify_item(item);
         if attr.is_some() || !traits.is_empty() {
             return self.collect_attr(attr, traits, Annotatable::TraitItem(P(item)),
-                                     AstFragmentKind::TraitItems, together_with).make_trait_items()
+                                     AstFragmentKind::TraitItems, after_derive).make_trait_items()
         }
 
         match item.node {
@@ -1405,10 +1390,10 @@ fn fold_block(&mut self, block: P<Block>) -> P<Block> {
     fn fold_impl_item(&mut self, item: ast::ImplItem) -> SmallVec<[ast::ImplItem; 1]> {
         let item = configure!(self, item);
 
-        let (attr, traits, item, together_with) = self.classify_item(item);
+        let (attr, traits, item, after_derive) = self.classify_item(item);
         if attr.is_some() || !traits.is_empty() {
             return self.collect_attr(attr, traits, Annotatable::ImplItem(P(item)),
-                                     AstFragmentKind::ImplItems, together_with).make_impl_items();
+                                     AstFragmentKind::ImplItems, after_derive).make_impl_items();
         }
 
         match item.node {
@@ -1440,11 +1425,11 @@ fn fold_foreign_mod(&mut self, foreign_mod: ast::ForeignMod) -> ast::ForeignMod
     fn fold_foreign_item(&mut self, foreign_item: ast::ForeignItem)
         -> SmallVec<[ast::ForeignItem; 1]>
     {
-        let (attr, traits, foreign_item, together_with) = self.classify_item(foreign_item);
+        let (attr, traits, foreign_item, after_derive) = self.classify_item(foreign_item);
 
         if attr.is_some() || !traits.is_empty() {
             return self.collect_attr(attr, traits, Annotatable::ForeignItem(P(foreign_item)),
-                                     AstFragmentKind::ForeignItems, together_with)
+                                     AstFragmentKind::ForeignItems, after_derive)
                                      .make_foreign_items();
         }
 
@@ -1612,10 +1597,7 @@ fn enable_allow_internal_unstable = allow_internal_unstable,
         fn enable_custom_derive = custom_derive,
         fn enable_format_args_nl = format_args_nl,
         fn macros_in_extern_enabled = macros_in_extern,
-        fn proc_macro_mod = proc_macro_mod,
-        fn proc_macro_gen = proc_macro_gen,
-        fn proc_macro_expr = proc_macro_expr,
-        fn proc_macro_non_items = proc_macro_non_items,
+        fn proc_macro_hygiene = proc_macro_hygiene,
     }
 
     fn enable_custom_inner_attributes(&self) -> bool {
index adbe2f9d4393f52f1f6ef426b56a778b6f8d0fbd..3b4e00a515d3ea305c5731441c5983b072f35502 100644 (file)
@@ -441,10 +441,7 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
 
     // Allows macro invocations on modules expressions and statements and
     // procedural macros to expand to non-items.
-    (active, proc_macro_mod, "1.27.0", Some(54727), None),
-    (active, proc_macro_expr, "1.27.0", Some(54727), None),
-    (active, proc_macro_non_items, "1.27.0", Some(54727), None),
-    (active, proc_macro_gen, "1.27.0", Some(54727), None),
+    (active, proc_macro_hygiene, "1.30.0", Some(54727), None),
 
     // #[doc(alias = "...")]
     (active, doc_alias, "1.27.0", Some(50146), None),
@@ -541,6 +538,14 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
      Some("merged into `#![feature(slice_patterns)]`")),
     (removed, macro_reexport, "1.0.0", Some(29638), None,
      Some("subsumed by `pub use`")),
+    (removed, proc_macro_mod, "1.27.0", Some(54727), None,
+     Some("subsumed by `#![feature(proc_macro_hygiene)]`")),
+    (removed, proc_macro_expr, "1.27.0", Some(54727), None,
+     Some("subsumed by `#![feature(proc_macro_hygiene)]`")),
+    (removed, proc_macro_non_items, "1.27.0", Some(54727), None,
+     Some("subsumed by `#![feature(proc_macro_hygiene)]`")),
+    (removed, proc_macro_gen, "1.27.0", Some(54727), None,
+     Some("subsumed by `#![feature(proc_macro_hygiene)]`")),
 );
 
 declare_features! (
@@ -990,10 +995,6 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
                                      "the `#[rustc_test_marker]` attribute \
                                       is used internally to track tests",
                                      cfg_fn!(rustc_attrs))),
-    ("rustc_test_marker2", Normal, Gated(Stability::Unstable,
-                                         "rustc_attrs",
-                                         "temporarily used by rustc to report some errors",
-                                         cfg_fn!(rustc_attrs))),
     ("rustc_transparent_macro", Whitelisted, Gated(Stability::Unstable,
                                                    "rustc_attrs",
                                                    "used internally for testing macro hygiene",
index 5571a18b5962518ed1de26e47a55cbac4249fb06..d653ed819fddde9ed1f5549566312940f045f928 100644 (file)
@@ -1777,7 +1777,26 @@ fn parse_arg_general(&mut self, require_name: bool) -> PResult<'a, Arg> {
                    require_name);
             let pat = self.parse_pat()?;
 
-            self.expect(&token::Colon)?;
+            if let Err(mut err) = self.expect(&token::Colon) {
+                // 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)
+                }) {
+                    let ident = self.parse_ident().unwrap();
+                    let span = pat.span.with_hi(ident.span.hi());
+
+                    err.span_suggestion_with_applicability(
+                        span,
+                        "declare the type after the parameter binding",
+                        String::from("<identifier>: <type>"),
+                        Applicability::HasPlaceholders,
+                    );
+                }
+
+                return Err(err);
+            }
+
             (pat, self.parse_ty()?)
         } else {
             debug!("parse_arg_general ident_to_pat");
@@ -6718,10 +6737,9 @@ fn parse_item_foreign_mod(&mut self,
         attrs.extend(self.parse_inner_attributes()?);
 
         let mut foreign_items = vec![];
-        while let Some(item) = self.parse_foreign_item()? {
-            foreign_items.push(item);
+        while !self.eat(&token::CloseDelim(token::Brace)) {
+            foreign_items.push(self.parse_foreign_item()?);
         }
-        self.expect(&token::CloseDelim(token::Brace))?;
 
         let prev_span = self.prev_span;
         let m = ast::ForeignMod {
@@ -7305,8 +7323,8 @@ fn parse_item_implementation(
     }
 
     /// Parse a foreign item.
-    crate fn parse_foreign_item(&mut self) -> PResult<'a, Option<ForeignItem>> {
-        maybe_whole!(self, NtForeignItem, |ni| Some(ni));
+    crate fn parse_foreign_item(&mut self) -> PResult<'a, ForeignItem> {
+        maybe_whole!(self, NtForeignItem, |ni| ni);
 
         let attrs = self.parse_outer_attributes()?;
         let lo = self.span;
@@ -7326,20 +7344,20 @@ fn parse_item_implementation(
                     ).emit();
             }
             self.bump(); // `static` or `const`
-            return Ok(Some(self.parse_item_foreign_static(visibility, lo, attrs)?));
+            return Ok(self.parse_item_foreign_static(visibility, lo, attrs)?);
         }
         // FOREIGN FUNCTION ITEM
         if self.check_keyword(keywords::Fn) {
-            return Ok(Some(self.parse_item_foreign_fn(visibility, lo, attrs)?));
+            return Ok(self.parse_item_foreign_fn(visibility, lo, attrs)?);
         }
         // FOREIGN TYPE ITEM
         if self.check_keyword(keywords::Type) {
-            return Ok(Some(self.parse_item_foreign_type(visibility, lo, attrs)?));
+            return Ok(self.parse_item_foreign_type(visibility, lo, attrs)?);
         }
 
         match self.parse_assoc_macro_invoc("extern", Some(&visibility), &mut false)? {
             Some(mac) => {
-                Ok(Some(
+                Ok(
                     ForeignItem {
                         ident: keywords::Invalid.ident(),
                         span: lo.to(self.prev_span),
@@ -7348,14 +7366,14 @@ fn parse_item_implementation(
                         vis: visibility,
                         node: ForeignItemKind::Macro(mac),
                     }
-                ))
+                )
             }
             None => {
-                if !attrs.is_empty() {
+                if !attrs.is_empty()  {
                     self.expected_item_err(&attrs);
                 }
 
-                Ok(None)
+                self.unexpected()
             }
         }
     }
index f2acdb3f469d1e9b5f6587e749565ebaa409a8b9..83a05921510b4d2dcc37a0d9b1aabedf46a8156f 100644 (file)
@@ -2228,6 +2228,9 @@ fn print_expr_outer_attr_style(&mut self,
                 self.word_nbsp("async")?;
                 self.print_capture_clause(capture_clause)?;
                 self.s.space()?;
+                // cbox/ibox in analogy to the `ExprKind::Block` arm above
+                self.cbox(INDENT_UNIT)?;
+                self.ibox(0)?;
                 self.print_block_with_attrs(blk, attrs)?;
             }
             ast::ExprKind::Assign(ref lhs, ref rhs) => {
index 8ddfb1d9cba224c7aa077042a6b14e1ac30e5d47..be3485cfa7cc23a5e2c8a40e3a22e42ac4822f39 100644 (file)
@@ -49,7 +49,7 @@ pub fn expand_test_or_bench(
     // If we're not in test configuration, remove the annotated item
     if !cx.ecfg.should_test { return vec![]; }
 
-    let mut item =
+    let item =
         if let Annotatable::Item(i) = item { i }
         else {
             cx.parse_sess.span_diagnostic.span_fatal(item.span(),
@@ -192,12 +192,6 @@ pub fn expand_test_or_bench(
 
     debug!("Synthetic test item:\n{}\n", pprust::item_to_string(&test_const));
 
-    // Temporarily add another marker to the original item for error reporting
-    let marker2 = cx.attribute(
-        attr_sp, cx.meta_word(attr_sp, Symbol::intern("rustc_test_marker2"))
-    );
-    item.attrs.push(marker2);
-
     vec![
         // Access to libtest under a gensymed name
         Annotatable::Item(test_extern),
index 05c2f61c384e2097a3a4c648344114fc4ac983be..fe825c93788c841ac1872e8351a62c37a5f78427 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 05c2f61c384e2097a3a4c648344114fc4ac983be
+Subproject commit fe825c93788c841ac1872e8351a62c37a5f78427
diff --git a/src/test/codegen/export-no-mangle.rs b/src/test/codegen/export-no-mangle.rs
new file mode 100644 (file)
index 0000000..3546284
--- /dev/null
@@ -0,0 +1,29 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type = "lib"]
+
+mod private {
+    // CHECK: @FOO =
+    #[no_mangle]
+    pub static FOO: u32 = 3;
+
+    // CHECK: @BAR =
+    #[export_name = "BAR"]
+    static BAR: u32 = 3;
+
+    // CHECK: void @foo()
+    #[no_mangle]
+    pub extern fn foo() {}
+
+    // CHECK: void @bar()
+    #[export_name = "bar"]
+    extern fn bar() {}
+}
diff --git a/src/test/codegen/external-no-mangle-fns.rs b/src/test/codegen/external-no-mangle-fns.rs
new file mode 100644 (file)
index 0000000..3f092b8
--- /dev/null
@@ -0,0 +1,63 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -O
+// `#[no_mangle]`d functions always have external linkage, i.e. no `internal` in their `define`s
+
+#![crate_type = "lib"]
+#![no_std]
+
+// CHECK: define void @a()
+#[no_mangle]
+fn a() {}
+
+// CHECK: define void @b()
+#[no_mangle]
+pub fn b() {}
+
+mod private {
+    // CHECK: define void @c()
+    #[no_mangle]
+    fn c() {}
+
+    // CHECK: define void @d()
+    #[no_mangle]
+    pub fn d() {}
+}
+
+const HIDDEN: () = {
+    // CHECK: define void @e()
+    #[no_mangle]
+    fn e() {}
+
+    // CHECK: define void @f()
+    #[no_mangle]
+    pub fn f() {}
+};
+
+// The surrounding item should not accidentally become external
+// CHECK: define internal {{.*}} void @_ZN22external_no_mangle_fns1x
+#[inline(never)]
+fn x() {
+    // CHECK: define void @g()
+    #[no_mangle]
+    fn g() {
+        x();
+    }
+
+    // CHECK: define void @h()
+    #[no_mangle]
+    pub fn h() {}
+
+    // side effect to keep `x` around
+    unsafe {
+        core::ptr::read_volatile(&42);
+    }
+}
diff --git a/src/test/codegen/external-no-mangle-statics.rs b/src/test/codegen/external-no-mangle-statics.rs
new file mode 100644 (file)
index 0000000..59d8296
--- /dev/null
@@ -0,0 +1,88 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -O
+// `#[no_mangle]`d static variables always have external linkage, i.e. no `internal` in their
+// definitions
+
+#![crate_type = "lib"]
+#![no_std]
+
+// CHECK: @A = local_unnamed_addr constant
+#[no_mangle]
+static A: u8 = 0;
+
+// CHECK: @B = local_unnamed_addr global
+#[no_mangle]
+static mut B: u8 = 0;
+
+// CHECK: @C = local_unnamed_addr constant
+#[no_mangle]
+pub static C: u8 = 0;
+
+// CHECK: @D = local_unnamed_addr global
+#[no_mangle]
+pub static mut D: u8 = 0;
+
+mod private {
+    // CHECK: @E = local_unnamed_addr constant
+    #[no_mangle]
+    static E: u8 = 0;
+
+    // CHECK: @F = local_unnamed_addr global
+    #[no_mangle]
+    static mut F: u8 = 0;
+
+    // CHECK: @G = local_unnamed_addr constant
+    #[no_mangle]
+    pub static G: u8 = 0;
+
+    // CHECK: @H = local_unnamed_addr global
+    #[no_mangle]
+    pub static mut H: u8 = 0;
+}
+
+const HIDDEN: () = {
+    // CHECK: @I = local_unnamed_addr constant
+    #[no_mangle]
+    static I: u8 = 0;
+
+    // CHECK: @J = local_unnamed_addr global
+    #[no_mangle]
+    static mut J: u8 = 0;
+
+    // CHECK: @K = local_unnamed_addr constant
+    #[no_mangle]
+    pub static K: u8 = 0;
+
+    // CHECK: @L = local_unnamed_addr global
+    #[no_mangle]
+    pub static mut L: u8 = 0;
+};
+
+// The surrounding item should not accidentally become external
+fn x() {
+    // CHECK: @M = local_unnamed_addr constant
+    #[no_mangle]
+    static M: fn() = x;
+
+    // CHECK: @N = local_unnamed_addr global
+    #[no_mangle]
+    static mut N: u8 = 0;
+
+    // CHECK: @O = local_unnamed_addr constant
+    #[no_mangle]
+    pub static O: u8 = 0;
+
+    // CHECK: @P = local_unnamed_addr global
+    #[no_mangle]
+    pub static mut P: u8 = 0;
+}
+// CHECK: define internal void @_ZN26external_no_mangle_statics1x{{.*$}}
index 3235ef0bb3335134f6a250aa0d618b6b042504c1..b146e106aa10406a59bc868b9b62dc152774fb6b 100644 (file)
 #![crate_type = "rlib"]
 #![feature(thread_local)]
 
-// CHECK: @STATIC_VAR_1 = internal thread_local unnamed_addr global <{ [32 x i8] }> zeroinitializer, section "__DATA,__thread_bss", align 4
+// CHECK: @STATIC_VAR_1 = thread_local local_unnamed_addr global <{ [32 x i8] }> zeroinitializer, section "__DATA,__thread_bss", align 4
 #[no_mangle]
-#[allow(private_no_mangle_statics)]
 #[thread_local]
 static mut STATIC_VAR_1: [u32; 8] = [0; 8];
 
-// CHECK: @STATIC_VAR_2 = internal thread_local unnamed_addr global <{ [32 x i8] }> <{{[^>]*}}>, section "__DATA,__thread_data", align 4
+// CHECK: @STATIC_VAR_2 = thread_local local_unnamed_addr global <{ [32 x i8] }> <{{[^>]*}}>, section "__DATA,__thread_data", align 4
 #[no_mangle]
-#[allow(private_no_mangle_statics)]
 #[thread_local]
 static mut STATIC_VAR_2: [u32; 8] = [4; 8];
 
index b2f43489523d1859ce824bcea7cf953d64bf841c..5ddca4763260d51798018de4ee223feed846a73f 100644 (file)
@@ -20,8 +20,8 @@ fn main() {
 fn foo() {
     let _a = Box::new(3);
     bar();
-// CHECK-LABEL: foo
-// CHECK: call {{.*}} void @bar
+// CHECK-LABEL: define void @foo
+// CHECK: call void @bar
 }
 
 #[inline(never)]
index 91b72510e3e540fb63738ee2b8e9c3325d0ecf98..f52c251c14d7bd4a105bee20a36f8108e84a21c1 100644 (file)
@@ -13,7 +13,7 @@
 
 //! Attributes producing expressions in invalid locations
 
-#![feature(stmt_expr_attributes, proc_macro_expr)]
+#![feature(stmt_expr_attributes, proc_macro_hygiene)]
 
 extern crate attr_stmt_expr;
 use attr_stmt_expr::{duplicate, no_output};
index 52b2a473ecd75c277d18b5ce64c790e55056894f..1344156b3053cabf57ef61064f3ad26dc93da025 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:attr-stmt-expr.rs
 // ignore-stage1
 
-#![feature(proc_macro_expr)]
+#![feature(proc_macro_hygiene)]
 
 extern crate attr_stmt_expr;
 use attr_stmt_expr::{expect_let, expect_print_stmt, expect_expr, expect_print_expr};
index 6e9d231ea99a4513468f702429d22510eac99489..60e533d3ea8d29f2397dd75583505509be2912ee 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:bang_proc_macro2.rs
 // ignore-stage1
 
-#![feature(proc_macro_non_items)]
+#![feature(proc_macro_hygiene)]
 #![allow(unused_macros)]
 
 extern crate bang_proc_macro2;
index c07e6e31d6287f684b5e2bed0beb8aa8e3fcf160..5049a474dd215064a695fb7885d6734f9372e847 100644 (file)
@@ -9,11 +9,7 @@
 // except according to those terms.
 
 // aux-build:proc-macro-gates.rs
-// gate-test-proc_macro_non_items
-// gate-test-proc_macro_mod line
-// gate-test-proc_macro_expr
-// gate-test-proc_macro_mod
-// gate-test-proc_macro_gen
+// gate-test-proc_macro_hygiene
 
 #![feature(stmt_expr_attributes)]
 
index 6899caa7153bb57c091ec13be5d5cec186b76c72..cc3286fe70512881c31a834e2d0446b54a2d4d40 100644 (file)
@@ -10,7 +10,7 @@
 
 // compile-flags: -Z parse-only
 
-// error-pattern:expected one of `(`, `fn`, `static`, `type`, or `}` here
+// error-pattern:expected one of `(`, `fn`, `static`, or `type`
 extern {
     pub pub fn foo();
 }
diff --git a/src/test/pretty/issue-54752-async-block.rs b/src/test/pretty/issue-54752-async-block.rs
new file mode 100644 (file)
index 0000000..6930ee1
--- /dev/null
@@ -0,0 +1,7 @@
+#![feature(async_await)]
+#![allow(unused_parens)]
+
+// edition:2018
+// pp-exact
+
+fn main() { let _a = (async  { }); }
index 27387332c1c1f50b0a7c4f5f8fbb3ff8eba44a3e..f0a9e95ed5af589e75898c473559d3235023e9c0 100644 (file)
@@ -20,8 +20,8 @@ pub fn main() {
         let path = Path::new("libdylib.so");
         let a = DynamicLibrary::open(Some(&path)).unwrap();
         assert!(a.symbol::<isize>("fun1").is_ok());
-        assert!(a.symbol::<isize>("fun2").is_err());
-        assert!(a.symbol::<isize>("fun3").is_err());
+        assert!(a.symbol::<isize>("fun2").is_ok());
+        assert!(a.symbol::<isize>("fun3").is_ok());
         assert!(a.symbol::<isize>("fun4").is_ok());
         assert!(a.symbol::<isize>("fun5").is_ok());
     }
index a267016efc2e354c924e8a1a46329049536cfb3c..741bce921e67e60922a114165920291ac5bd46b1 100644 (file)
@@ -25,6 +25,8 @@ CRATE := cortex-m
 CRATE_URL := https://github.com/rust-embedded/cortex-m
 CRATE_SHA1 := a448e9156e2cb1e556e5441fd65426952ef4b927 # 0.5.0
 
+export RUSTFLAGS := --cap-lints=allow
+
 all:
        env
        mkdir -p $(WORK_DIR)
diff --git a/src/test/run-make/wasm-export-all-symbols/Makefile b/src/test/run-make/wasm-export-all-symbols/Makefile
new file mode 100644 (file)
index 0000000..07379b7
--- /dev/null
@@ -0,0 +1,16 @@
+-include ../../run-make-fulldeps/tools.mk
+
+ifeq ($(TARGET),wasm32-unknown-unknown)
+all:
+       $(RUSTC) bar.rs --target wasm32-unknown-unknown
+       $(RUSTC) foo.rs --target wasm32-unknown-unknown
+       $(NODE) verify.js $(TMPDIR)/foo.wasm
+       $(RUSTC) bar.rs --target wasm32-unknown-unknown -O
+       $(RUSTC) foo.rs --target wasm32-unknown-unknown -O
+       $(NODE) verify.js $(TMPDIR)/foo.wasm
+       $(RUSTC) foo.rs --target wasm32-unknown-unknown -C lto
+       $(NODE) verify.js $(TMPDIR)/foo.wasm
+else
+all:
+endif
+
diff --git a/src/test/run-make/wasm-export-all-symbols/bar.rs b/src/test/run-make/wasm-export-all-symbols/bar.rs
new file mode 100644 (file)
index 0000000..5d4ce06
--- /dev/null
@@ -0,0 +1,14 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type = "rlib"]
+
+#[no_mangle]
+pub extern fn foo() {}
diff --git a/src/test/run-make/wasm-export-all-symbols/foo.rs b/src/test/run-make/wasm-export-all-symbols/foo.rs
new file mode 100644 (file)
index 0000000..fc1ed31
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type = "cdylib"]
+
+extern crate bar;
diff --git a/src/test/run-make/wasm-export-all-symbols/verify.js b/src/test/run-make/wasm-export-all-symbols/verify.js
new file mode 100644 (file)
index 0000000..5a505ea
--- /dev/null
@@ -0,0 +1,32 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+const fs = require('fs');
+const process = require('process');
+const assert = require('assert');
+const buffer = fs.readFileSync(process.argv[2]);
+
+let m = new WebAssembly.Module(buffer);
+let list = WebAssembly.Module.exports(m);
+console.log('exports', list);
+
+const my_exports = {};
+let nexports = 0;
+for (const entry of list) {
+  if (entry.kind !== 'function')
+    continue;
+  my_exports[entry.name] = true;
+  nexports += 1;
+}
+
+if (nexports != 1)
+  throw new Error("should only have one function export");
+if (my_exports.foo === undefined)
+  throw new Error("`foo` wasn't defined");
index 94c5b208a370799733b8416904bec1b8dcff0053..e7545f954daab00a0378a713646f6bcd0c49b5be 100644 (file)
@@ -11,7 +11,7 @@
 // no-prefer-dynamic
 
 #![crate_type = "proc-macro"]
-#![feature(proc_macro_non_items)]
+#![feature(proc_macro_hygiene)]
 
 extern crate proc_macro;
 
index b54543c73fbd21147e053ff0ffeb31a22fdc21aa..caf56dabf796adf00bfe288e3c9eb30ed448330d 100644 (file)
@@ -11,7 +11,7 @@
 // no-prefer-dynamic
 
 #![crate_type = "proc-macro"]
-#![feature(proc_macro_non_items, proc_macro_quote)]
+#![feature(proc_macro_hygiene, proc_macro_quote)]
 
 extern crate proc_macro;
 
index 7a15a4cb3a2e8ee9d853e475c45287aae93692a4..4ea3d0d0d0a07245bbc85fefb246f7421aac44c6 100644 (file)
@@ -39,7 +39,7 @@ pub fn test() {
     let lib = DynamicLibrary::open(None).unwrap();
     unsafe {
         assert!(lib.symbol::<isize>("foo").is_ok());
-        assert!(lib.symbol::<isize>("baz").is_err());
-        assert!(lib.symbol::<isize>("bar").is_err());
+        assert!(lib.symbol::<isize>("baz").is_ok());
+        assert!(lib.symbol::<isize>("bar").is_ok());
     }
 }
index b9c565a9d3c23c590726725405e4f1bbf209aeff..847db0098fffc622bab245e248b531c5ec3c64ac 100644 (file)
@@ -11,7 +11,7 @@
 // no-prefer-dynamic
 
 #![crate_type = "proc-macro"]
-#![feature(proc_macro_non_items)]
+#![feature(proc_macro_hygiene)]
 
 extern crate proc_macro;
 
index c3e7787cf7f30e216e95a26084452f9dc200848b..f51a6aae068a121903fe8a357a4fd01923cc34e9 100644 (file)
@@ -19,8 +19,8 @@
 #[macro_use] #[no_link]
 extern crate macro_crate_test;
 
-#[derive(PartialEq, Clone, Debug)]
 #[rustc_into_multi_foo]
+#[derive(PartialEq, Clone, Debug)]
 fn foo() -> AnotherFakeTypeThatHadBetterGoAway {}
 
 // Check that the `#[into_multi_foo]`-generated `foo2` is configured away
index 4c36f097ec1149f810d6f3387647035f28668591..d438adda151fa25360565d63634b157255a5aeec 100644 (file)
@@ -12,7 +12,7 @@
 // aux-build:cond_plugin.rs
 // ignore-stage1
 
-#![feature(proc_macro_non_items)]
+#![feature(proc_macro_hygiene)]
 
 extern crate cond_plugin;
 
index 1005a6bfc50c7fa00f29428bb52162bd25506df2..f967ef56bb8f0bb1bdfb4d1d2a573793747d9a34 100644 (file)
@@ -13,7 +13,7 @@
 // aux-build:hello_macro.rs
 // ignore-stage1
 
-#![feature(proc_macro_non_items, proc_macro_gen)]
+#![feature(proc_macro_hygiene)]
 
 extern crate hello_macro;
 
index b5272e6608bbfd31d47d7ca7407d3ea94092f66c..8a3452f24d24708c0cb94be099c038814dd23e65 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:attr-stmt-expr.rs
 // ignore-stage1
 
-#![feature(stmt_expr_attributes, proc_macro_expr)]
+#![feature(stmt_expr_attributes, proc_macro_hygiene)]
 
 extern crate attr_stmt_expr;
 use attr_stmt_expr::{expect_let, expect_print_stmt, expect_expr, expect_print_expr,
index a84e029f9d87d22dc56dd9ce2f46f6625c67633c..77d0d9339feffe17cd382a6217d31a201e9215a1 100644 (file)
@@ -10,7 +10,7 @@
 
 // no-prefer-dynamic
 
-#![feature(proc_macro_non_items, proc_macro_quote)]
+#![feature(proc_macro_hygiene, proc_macro_quote)]
 #![crate_type = "proc-macro"]
 
 extern crate proc_macro;
index 43c1d5fcc8d4996a653e383322d17cde24771941..551ac3863e1ab44fe25bfba1f2da9976e810f8a8 100644 (file)
@@ -10,7 +10,7 @@
 
 // no-prefer-dynamic
 
-#![feature(proc_macro_quote, proc_macro_non_items)]
+#![feature(proc_macro_quote, proc_macro_hygiene)]
 #![crate_type = "proc-macro"]
 
 extern crate proc_macro as proc_macro_renamed; // This does not break `quote!`
index 955b6ab986d07b3575e819f1c6b7804f97a5af92..10fe015555557072fb3857eb3b348c30809e8577 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:bang-macro.rs
 // ignore-stage1
 
-#![feature(proc_macro_non_items)]
+#![feature(proc_macro_hygiene)]
 
 extern crate bang_macro;
 use bang_macro::rewrite;
index 9d2120e6764f74ac9653232f5d5f549b87e48059..b27c806f04717a8d55a330c539c7824135efb82d 100644 (file)
@@ -13,7 +13,7 @@
 // aux-build:call-site.rs
 // ignore-stage1
 
-#![feature(proc_macro_non_items)]
+#![feature(proc_macro_hygiene)]
 
 extern crate call_site;
 use call_site::*;
index 6601d66e586a3aa7e961ccdd47e0772dab59393e..07ad4f288d8948f5804e4f0cc0c2992903100336 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:count_compound_ops.rs
 // ignore-stage1
 
-#![feature(proc_macro_non_items)]
+#![feature(proc_macro_hygiene)]
 
 extern crate count_compound_ops;
 use count_compound_ops::count_compound_ops;
index 2d15b4e60b4261e0820b99f1b01c109ef5232e51..cf18bb247c7696ecafe9529af65c470e47d39cec 100644 (file)
@@ -13,7 +13,7 @@
 // aux-build:hygiene_example.rs
 // ignore-stage1
 
-#![feature(proc_macro_non_items)]
+#![feature(proc_macro_hygiene)]
 
 extern crate hygiene_example;
 use hygiene_example::hello;
index a793d069d1448b8551eca130d8258daaf4a55d1a..ccd729badebb908864ed46bd669c9ad218f45af6 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:negative-token.rs
 // ignore-stage1
 
-#![feature(proc_macro_non_items)]
+#![feature(proc_macro_hygiene)]
 
 extern crate negative_token;
 
index c9d7b0423ec5929c643639a146809c2056066508..27e0c23561f5759bc5568ff4fd98886ab59a9e87 100644 (file)
@@ -12,7 +12,7 @@
 // ignore-stage1
 // ignore-cross-compile
 
-#![feature(proc_macro_non_items)]
+#![feature(proc_macro_hygiene)]
 
 extern crate proc_macro_def;
 
index d10c11644d5b949cca7cfcd45b0d8f59824fcbc9..cb9f5ca698dd7b1326201bd675fc41c035111528 100644 (file)
@@ -11,6 +11,7 @@
 // run-pass
 // ignore-windows
 // ignore-macos
+// ignore-wasm32-bare common linkage not implemented right now
 
 #![feature(linkage)]
 
index 24fb400150aa851712ddb171ebee0e4f906bb1f8..3dac45139ac0febb500f6faf6c54ff2e839c9675 100644 (file)
@@ -10,8 +10,8 @@
 
 #![allow(dead_code)]
 // Regression test for #37154: the problem here was that the cache
-// results in a false error because it was caching skolemized results
-// even after those skolemized regions had been popped.
+// results in a false error because it was caching placeholder results
+// even after those placeholder regions had been popped.
 
 trait Foo {
     fn method(&self) {}
index 553cd86e6203858edb6e1a4f820041075418a1fe..7b1eecd1558659f4665d2978d9839febc9074710 100644 (file)
@@ -1,9 +1,5 @@
 // aux-build:attr_proc_macro.rs
-// compile-flags:--test
 
-#![feature(test)]
-
-extern crate test;
 extern crate attr_proc_macro;
 use attr_proc_macro::*;
 
 #[attr_proc_macro] //~ ERROR macro attributes must be placed before `#[derive]`
 struct After;
 
-#[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]`
-#[test]
-fn test_before() {}
-
-#[test]
-#[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]`
-fn test_after() {}
-
-#[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]`
-#[bench]
-fn bench_before(b: &mut test::Bencher) {}
-
-#[bench]
-#[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]`
-fn bench_after(b: &mut test::Bencher) {}
+fn main() {}
index 841fc630b227089d20ef9f6613432e3686554d19..a4f165cd1b52c65470e116dbed27a4c33152c9b3 100644 (file)
@@ -1,32 +1,8 @@
 error: macro attributes must be placed before `#[derive]`
-  --> $DIR/attribute-order-restricted.rs:15:1
+  --> $DIR/attribute-order-restricted.rs:11:1
    |
 LL | #[attr_proc_macro] //~ ERROR macro attributes must be placed before `#[derive]`
    | ^^^^^^^^^^^^^^^^^^
 
-error: macro attributes cannot be used together with `#[test]` or `#[bench]`
-  --> $DIR/attribute-order-restricted.rs:18:1
-   |
-LL | #[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]`
-   | ^^^^^^^^^^^^^^^^^^
-
-error: macro attributes cannot be used together with `#[test]` or `#[bench]`
-  --> $DIR/attribute-order-restricted.rs:23:1
-   |
-LL | #[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]`
-   | ^^^^^^^^^^^^^^^^^^
-
-error: macro attributes cannot be used together with `#[test]` or `#[bench]`
-  --> $DIR/attribute-order-restricted.rs:26:1
-   |
-LL | #[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]`
-   | ^^^^^^^^^^^^^^^^^^
-
-error: macro attributes cannot be used together with `#[test]` or `#[bench]`
-  --> $DIR/attribute-order-restricted.rs:31:1
-   |
-LL | #[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]`
-   | ^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 5 previous errors
+error: aborting due to previous error
 
index 6879848d269b0cb7d3e68e84102cb6e5b53fe716..ff6464a7a3a70fdee854028d6a4e1c3fd54efa9b 100644 (file)
@@ -10,7 +10,7 @@
 
 // aux-build:lifetimes.rs
 
-#![feature(proc_macro_non_items)]
+#![feature(proc_macro_hygiene)]
 
 extern crate lifetimes;
 
index 9a54696d1f076a80b608f3fc7203a352a36244a1..d7713f48e703b8574f95cf47b28a852ad6247b88 100644 (file)
@@ -11,7 +11,7 @@
 // compile-pass
 // aux-build:bang_proc_macro.rs
 
-#![feature(proc_macro_non_items)]
+#![feature(proc_macro_hygiene)]
 
 #[macro_use]
 extern crate bang_proc_macro;
index 940ec016a5a3f2741a472a0f0ddd99a8a314925b..63a95ce211d7ada864adbbe8fe6e7f592b837a3f 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:multispan.rs
 // ignore-stage1
 
-#![feature(proc_macro_non_items)]
+#![feature(proc_macro_hygiene)]
 
 extern crate multispan;
 
index 18f5b0f506cc2f7b9e78aa49ec730ff4b6fcac4c..7c30a8e328aa5ecb92df3fd00608daa782bac5ff 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:parent-source-spans.rs
 // ignore-stage1
 
-#![feature(decl_macro, proc_macro_non_items)]
+#![feature(decl_macro, proc_macro_hygiene)]
 
 extern crate parent_source_spans;
 
index f6b0e90da001440838c59f06db17b8f5fa8bbc15..dd81b1017ebc31dfa740e1eb949e7eaba1f7e067 100644 (file)
@@ -11,7 +11,7 @@
 // aux-build:three-equals.rs
 // ignore-stage1
 
-#![feature(proc_macro_non_items)]
+#![feature(proc_macro_hygiene)]
 
 extern crate three_equals;
 
index a9abc79400e67892147d8ae2735fe6eab16a0fb4..72fda9079d636282fe834afcb0c3287ecc693449 100644 (file)
@@ -10,7 +10,7 @@ LL |     outside_closure_1(a); //[ast]~ ERROR cannot borrow `*a` as mutable beca
    |                       ^ borrow occurs here
 ...
 LL |     drop(bar);
-   |          --- borrow later used here
+   |          --- first borrow later used here
 
 error[E0501]: cannot borrow `*a` as immutable because previous closure requires unique access
   --> $DIR/E0501.rs:31:23
@@ -24,7 +24,7 @@ LL |     outside_closure_2(a); //[ast]~ ERROR cannot borrow `*a` as immutable be
    |                       ^ borrow occurs here
 ...
 LL |     drop(bar);
-   |          --- borrow later used here
+   |          --- first borrow later used here
 
 error: aborting due to 2 previous errors
 
index a9abc79400e67892147d8ae2735fe6eab16a0fb4..72fda9079d636282fe834afcb0c3287ecc693449 100644 (file)
@@ -10,7 +10,7 @@ LL |     outside_closure_1(a); //[ast]~ ERROR cannot borrow `*a` as mutable beca
    |                       ^ borrow occurs here
 ...
 LL |     drop(bar);
-   |          --- borrow later used here
+   |          --- first borrow later used here
 
 error[E0501]: cannot borrow `*a` as immutable because previous closure requires unique access
   --> $DIR/E0501.rs:31:23
@@ -24,7 +24,7 @@ LL |     outside_closure_2(a); //[ast]~ ERROR cannot borrow `*a` as immutable be
    |                       ^ borrow occurs here
 ...
 LL |     drop(bar);
-   |          --- borrow later used here
+   |          --- first borrow later used here
 
 error: aborting due to 2 previous errors
 
index 98762a0f6cfffd52ce58a613b4eac0ade01128e6..545a60f6770d9471d24ffd0230fc4c8c0de8c17a 100644 (file)
@@ -44,7 +44,7 @@ LL | |     +
 LL | |     &f;  //~ ERROR: cannot borrow `f` as immutable because it is also borrowed as mutable
    | |     ^-
    | |_____||
-   |       |borrow later used here
+   |       |mutable borrow later used here
    |       immutable borrow occurs here
 
 error[E0502]: cannot borrow `f` as mutable because it is also borrowed as immutable
@@ -59,7 +59,7 @@ LL | |     +
 LL | |     &mut f;  //~ ERROR: cannot borrow `f` as mutable because it is also borrowed as immutable
    | |     ^^^^^-
    | |_____|____|
-   |       |    borrow later used here
+   |       |    immutable borrow later used here
    |       mutable borrow occurs here
 
 error: aborting due to 6 previous errors
index 855488e1eef1b59ac4c92e36f989120d20ac1c1c..873581d91057dd8017fbf8937c76233edd7f4a6b 100644 (file)
@@ -17,7 +17,7 @@ LL |     let a = &x.0;
 LL |     let b = &mut x.0; //~ ERROR cannot borrow `x.0` as mutable because it is also borrowed as
    |             ^^^^^^^^ mutable borrow occurs here
 LL |     a.use_ref();
-   |     - borrow later used here
+   |     - immutable borrow later used here
 
 error[E0499]: cannot borrow `x.0` as mutable more than once at a time
   --> $DIR/borrow-tuple-fields.rs:33:13
@@ -27,7 +27,7 @@ LL |     let a = &mut x.0;
 LL |     let b = &mut x.0; //~ ERROR cannot borrow `x.0` as mutable more than once at a time
    |             ^^^^^^^^ second mutable borrow occurs here
 LL |     a.use_ref();
-   |     - borrow later used here
+   |     - first borrow later used here
 
 error[E0505]: cannot move out of `x` because it is borrowed
   --> $DIR/borrow-tuple-fields.rs:38:13
@@ -47,7 +47,7 @@ LL |     let a = &x.0;
 LL |     let b = &mut x.0; //~ ERROR cannot borrow `x.0` as mutable because it is also borrowed as
    |             ^^^^^^^^ mutable borrow occurs here
 LL |     a.use_ref();
-   |     - borrow later used here
+   |     - immutable borrow later used here
 
 error[E0499]: cannot borrow `x.0` as mutable more than once at a time
   --> $DIR/borrow-tuple-fields.rs:48:13
@@ -57,7 +57,7 @@ LL |     let a = &mut x.0;
 LL |     let b = &mut x.0; //~ ERROR cannot borrow `x.0` as mutable more than once at a time
    |             ^^^^^^^^ second mutable borrow occurs here
 LL |     a.use_mut();
-   |     - borrow later used here
+   |     - first borrow later used here
 
 error: aborting due to 6 previous errors
 
index 963a89ed44da6dc00d49a3d59ae2362b97cd53c7..4d61840d9e84a7feb9207bc6d212c3cc944315d6 100644 (file)
@@ -8,7 +8,7 @@ LL |         Y(ref mut b, _) => b //~ ERROR cannot borrow
    |           ^^^^^^^^^ second mutable borrow occurs here
 ...
 LL |     *a += 1;
-   |     ------- borrow later used here
+   |     ------- first borrow later used here
 
 error: aborting due to previous error
 
index f06822f7bb6e4ae0bf116a0352aecc05cb02f8e3..f36741e9a02270de4f6930fb81bfa415d2d074ad 100644 (file)
@@ -8,7 +8,7 @@ LL |         (ref mut b, _) => b //~ ERROR cannot borrow
    |          ^^^^^^^^^ second mutable borrow occurs here
 ...
 LL |     *a += 1;
-   |     ------- borrow later used here
+   |     ------- first borrow later used here
 
 error: aborting due to previous error
 
index 05197205e814c0b931e2030dc242e85669ab93d3..17722bf226d82992f403f2493ca45280f0f52743 100644 (file)
@@ -8,7 +8,7 @@ LL |       Foo::Y(ref mut b, _) => b, //~ ERROR cannot borrow
    |              ^^^^^^^^^ second mutable borrow occurs here
 ...
 LL |     *a += 1;
-   |     ------- borrow later used here
+   |     ------- first borrow later used here
 
 error: aborting due to previous error
 
index f4568d7c9eb8aae16f764f15360a283392cbd27e..2dda17b38bbf325fb21eadd23dc8f69855a510a7 100644 (file)
@@ -8,19 +8,19 @@ LL |     p[0] = 5; //~ ERROR cannot borrow
    |     ^ mutable borrow occurs here
 LL | 
 LL |     println!("{}", *q);
-   |                    -- borrow later used here
+   |                    -- immutable borrow later used here
 
 error[E0502]: cannot borrow `p` as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-assign-comp-idx.rs:37:9
    |
-LL |     borrow(
-LL | |         &p,
-   | |         -- immutable borrow occurs here
-LL | |         || p[0] = 5); //~ ERROR cannot borrow `p` as mutable
-   | |_________^^_-_______- borrow later used here
-   |           |  |
-   |           |  second borrow occurs due to use of `p` in closure
-   |           mutable borrow occurs here
+LL |     borrow(
+   |     ------ immutable borrow later used by call
+LL |         &p,
+   |         -- immutable borrow occurs here
+LL |         || p[0] = 5); //~ ERROR cannot borrow `p` as mutable
+   |         ^^ - second borrow occurs due to use of `p` in closure
+   |         |
+   |         mutable borrow occurs here
 
 error: aborting due to 2 previous errors
 
index eb26676cde24b32faf3ec62367ecff0c7338c3d5..f4ae5eaba16f8c322047370710a04c2f099b0c88 100644 (file)
@@ -1,21 +1,15 @@
 error[E0499]: cannot borrow `x` as mutable more than once at a time
   --> $DIR/borrowck-autoref-3261.rs:25:9
    |
-LL |       (&mut x).with(
-   |       --------
-   |       |
-   |  _____first mutable borrow occurs here
-   | |
-LL | |         |opt| { //~ ERROR cannot borrow `x` as mutable more than once at a time
-   | |         ^^^^^ second mutable borrow occurs here
-LL | |             match opt {
-LL | |                 &Either::Right(ref f) => {
-LL | |                     x = X(Either::Left((0, 0)));
-   | |                     - second borrow occurs due to use of `x` in closure
-...  |
-LL | |             }
-LL | |         })
-   | |__________- borrow later used here
+LL |     (&mut x).with(
+   |     -------- ---- first borrow later used by call
+   |     |
+   |     first mutable borrow occurs here
+LL |         |opt| { //~ ERROR cannot borrow `x` as mutable more than once at a time
+   |         ^^^^^ second mutable borrow occurs here
+...
+LL |                     x = X(Either::Left((0, 0)));
+   |                     - second borrow occurs due to use of `x` in closure
 
 error: aborting due to previous error
 
index 73f533a6b96991f6770374dcf3a4a756c346772b..77c637b7b4e97b844fdcdfb418b83b6bce3b5dc2 100644 (file)
@@ -1,24 +1,22 @@
 error[E0502]: cannot borrow `a` as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-bad-nested-calls-free.rs:35:17
    |
-LL | /     add(
-LL | |         &*a,
-   | |         --- immutable borrow occurs here
-LL | |         rewrite(&mut a)); //~ ERROR cannot borrow
-   | |_________________^^^^^^_- borrow later used here
-   |                   |
-   |                   mutable borrow occurs here
+LL |     add(
+   |     --- immutable borrow later used by call
+LL |         &*a,
+   |         --- immutable borrow occurs here
+LL |         rewrite(&mut a)); //~ ERROR cannot borrow
+   |                 ^^^^^^ mutable borrow occurs here
 
 error[E0502]: cannot borrow `a` as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-bad-nested-calls-free.rs:42:17
    |
-LL | /     add(
-LL | |         &*a,
-   | |         --- immutable borrow occurs here
-LL | |         rewrite(&mut a)); //~ ERROR cannot borrow
-   | |_________________^^^^^^_- borrow later used here
-   |                   |
-   |                   mutable borrow occurs here
+LL |     add(
+   |     --- immutable borrow later used by call
+LL |         &*a,
+   |         --- immutable borrow occurs here
+LL |         rewrite(&mut a)); //~ ERROR cannot borrow
+   |                 ^^^^^^ mutable borrow occurs here
 
 error: aborting due to 2 previous errors
 
index ecb70068fed30f22c171009f2066ab5c72f51c92..d3ee9b2b2b2b54674fad99c5a9a984fd859ea740 100644 (file)
@@ -1,24 +1,22 @@
 error[E0505]: cannot move out of `a` because it is borrowed
   --> $DIR/borrowck-bad-nested-calls-move.rs:35:9
    |
-LL | /     add(
-LL | |         &*a,
-   | |         --- borrow of `*a` occurs here
-LL | |         a); //~ ERROR cannot move
-   | |_________^- borrow later used here
-   |           |
-   |           move out of `a` occurs here
+LL |     add(
+   |     --- borrow later used by call
+LL |         &*a,
+   |         --- borrow of `*a` occurs here
+LL |         a); //~ ERROR cannot move
+   |         ^ move out of `a` occurs here
 
 error[E0505]: cannot move out of `a` because it is borrowed
   --> $DIR/borrowck-bad-nested-calls-move.rs:42:9
    |
-LL | /     add(
-LL | |         &*a,
-   | |         --- borrow of `*a` occurs here
-LL | |         a); //~ ERROR cannot move
-   | |_________^- borrow later used here
-   |           |
-   |           move out of `a` occurs here
+LL |     add(
+   |     --- borrow later used by call
+LL |         &*a,
+   |         --- borrow of `*a` occurs here
+LL |         a); //~ ERROR cannot move
+   |         ^ move out of `a` occurs here
 
 error: aborting due to 2 previous errors
 
index 603f4d63f7f4a78505c6ef8f094a98f4ff5124ba..a368ef5b254af875ef3bec63c41e4aadda2da729 100644 (file)
@@ -6,7 +6,7 @@ LL |     let bar1 = &mut foo.bar1;
 LL |     let _bar2 = &mut foo.bar1;  //~ ERROR cannot borrow
    |                 ^^^^^^^^^^^^^ second mutable borrow occurs here
 LL |     *bar1;
-   |     ----- borrow later used here
+   |     ----- first borrow later used here
 
 error[E0502]: cannot borrow `foo.bar1` as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-borrow-from-owned-ptr.rs:36:17
@@ -16,7 +16,7 @@ LL |     let bar1 = &mut foo.bar1;
 LL |     let _bar2 = &foo.bar1;  //~ ERROR cannot borrow
    |                 ^^^^^^^^^ immutable borrow occurs here
 LL |     *bar1;
-   |     ----- borrow later used here
+   |     ----- mutable borrow later used here
 
 error[E0502]: cannot borrow `foo.bar1` as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-borrow-from-owned-ptr.rs:43:17
@@ -26,7 +26,7 @@ LL |     let bar1 = &foo.bar1;
 LL |     let _bar2 = &mut foo.bar1;  //~ ERROR cannot borrow
    |                 ^^^^^^^^^^^^^ mutable borrow occurs here
 LL |     *bar1;
-   |     ----- borrow later used here
+   |     ----- immutable borrow later used here
 
 error[E0499]: cannot borrow `foo.bar1` as mutable more than once at a time
   --> $DIR/borrowck-borrow-from-owned-ptr.rs:73:21
@@ -38,7 +38,7 @@ LL |         Foo { bar1: ref mut _bar1, bar2: _ } => {}
    |                     ^^^^^^^^^^^^^ second mutable borrow occurs here
 ...
 LL |     *bar1;
-   |     ----- borrow later used here
+   |     ----- first borrow later used here
 
 error[E0502]: cannot borrow `foo.bar1` as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-borrow-from-owned-ptr.rs:82:17
@@ -49,7 +49,7 @@ LL |     let _foo1 = &foo.bar1; //~ ERROR cannot borrow
    |                 ^^^^^^^^^ immutable borrow occurs here
 LL |     let _foo2 = &*foo; //~ ERROR cannot borrow
 LL |     *bar1;
-   |     ----- borrow later used here
+   |     ----- mutable borrow later used here
 
 error[E0502]: cannot borrow `*foo` as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-borrow-from-owned-ptr.rs:83:17
@@ -60,7 +60,7 @@ LL |     let _foo1 = &foo.bar1; //~ ERROR cannot borrow
 LL |     let _foo2 = &*foo; //~ ERROR cannot borrow
    |                 ^^^^^ immutable borrow occurs here
 LL |     *bar1;
-   |     ----- borrow later used here
+   |     ----- mutable borrow later used here
 
 error[E0499]: cannot borrow `foo.bar1` as mutable more than once at a time
   --> $DIR/borrowck-borrow-from-owned-ptr.rs:90:17
@@ -70,7 +70,7 @@ LL |     let bar1 = &mut foo.bar1.int1;
 LL |     let _foo1 = &mut foo.bar1; //~ ERROR cannot borrow
    |                 ^^^^^^^^^^^^^ second mutable borrow occurs here
 LL |     *bar1;
-   |     ----- borrow later used here
+   |     ----- first borrow later used here
 
 error[E0499]: cannot borrow `*foo` as mutable more than once at a time
   --> $DIR/borrowck-borrow-from-owned-ptr.rs:97:17
@@ -80,7 +80,7 @@ LL |     let bar1 = &mut foo.bar1.int1;
 LL |     let _foo2 = &mut *foo; //~ ERROR cannot borrow
    |                 ^^^^^^^^^ second mutable borrow occurs here
 LL |     *bar1;
-   |     ----- borrow later used here
+   |     ----- first borrow later used here
 
 error[E0502]: cannot borrow `foo.bar1` as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-borrow-from-owned-ptr.rs:104:17
@@ -90,7 +90,7 @@ LL |     let bar1 = &foo.bar1.int1;
 LL |     let _foo1 = &mut foo.bar1; //~ ERROR cannot borrow
    |                 ^^^^^^^^^^^^^ mutable borrow occurs here
 LL |     *bar1;
-   |     ----- borrow later used here
+   |     ----- immutable borrow later used here
 
 error[E0502]: cannot borrow `*foo` as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-borrow-from-owned-ptr.rs:111:17
@@ -100,7 +100,7 @@ LL |     let bar1 = &foo.bar1.int1;
 LL |     let _foo2 = &mut *foo; //~ ERROR cannot borrow
    |                 ^^^^^^^^^ mutable borrow occurs here
 LL |     *bar1;
-   |     ----- borrow later used here
+   |     ----- immutable borrow later used here
 
 error[E0596]: cannot borrow `foo.bar1` as mutable, as `foo` is not declared as mutable
   --> $DIR/borrowck-borrow-from-owned-ptr.rs:132:16
index 3a215f2336aefec6d294a0aeb1090e45056b8202..d02cf6381d264199eaeaa900a0ceb1006218b80f 100644 (file)
@@ -6,7 +6,7 @@ LL |     let bar1 = &mut foo.bar1;
 LL |     let _bar2 = &mut foo.bar1;  //~ ERROR cannot borrow
    |                 ^^^^^^^^^^^^^ second mutable borrow occurs here
 LL |     *bar1;
-   |     ----- borrow later used here
+   |     ----- first borrow later used here
 
 error[E0502]: cannot borrow `foo.bar1` as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-borrow-from-stack-variable.rs:35:17
@@ -16,7 +16,7 @@ LL |     let bar1 = &mut foo.bar1;
 LL |     let _bar2 = &foo.bar1;  //~ ERROR cannot borrow
    |                 ^^^^^^^^^ immutable borrow occurs here
 LL |     *bar1;
-   |     ----- borrow later used here
+   |     ----- mutable borrow later used here
 
 error[E0502]: cannot borrow `foo.bar1` as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-borrow-from-stack-variable.rs:42:17
@@ -26,7 +26,7 @@ LL |     let bar1 = &foo.bar1;
 LL |     let _bar2 = &mut foo.bar1;  //~ ERROR cannot borrow
    |                 ^^^^^^^^^^^^^ mutable borrow occurs here
 LL |     *bar1;
-   |     ----- borrow later used here
+   |     ----- immutable borrow later used here
 
 error[E0499]: cannot borrow `foo.bar1` as mutable more than once at a time
   --> $DIR/borrowck-borrow-from-stack-variable.rs:71:21
@@ -38,7 +38,7 @@ LL |         Foo { bar1: ref mut _bar1, bar2: _ } => {} //
    |                     ^^^^^^^^^^^^^ second mutable borrow occurs here
 ...
 LL |     *bar1;
-   |     ----- borrow later used here
+   |     ----- first borrow later used here
 
 error[E0502]: cannot borrow `foo.bar1` as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-borrow-from-stack-variable.rs:80:17
@@ -49,7 +49,7 @@ LL |     let _foo1 = &foo.bar1; //~ ERROR cannot borrow
    |                 ^^^^^^^^^ immutable borrow occurs here
 LL |     let _foo2 = &foo; //~ ERROR cannot borrow
 LL |     *bar1;
-   |     ----- borrow later used here
+   |     ----- mutable borrow later used here
 
 error[E0502]: cannot borrow `foo` as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-borrow-from-stack-variable.rs:81:17
@@ -60,7 +60,7 @@ LL |     let _foo1 = &foo.bar1; //~ ERROR cannot borrow
 LL |     let _foo2 = &foo; //~ ERROR cannot borrow
    |                 ^^^^ immutable borrow occurs here
 LL |     *bar1;
-   |     ----- borrow later used here
+   |     ----- mutable borrow later used here
 
 error[E0499]: cannot borrow `foo.bar1` as mutable more than once at a time
   --> $DIR/borrowck-borrow-from-stack-variable.rs:88:17
@@ -70,7 +70,7 @@ LL |     let bar1 = &mut foo.bar1.int1;
 LL |     let _foo1 = &mut foo.bar1; //~ ERROR cannot borrow
    |                 ^^^^^^^^^^^^^ second mutable borrow occurs here
 LL |     *bar1;
-   |     ----- borrow later used here
+   |     ----- first borrow later used here
 
 error[E0499]: cannot borrow `foo` as mutable more than once at a time
   --> $DIR/borrowck-borrow-from-stack-variable.rs:95:17
@@ -80,7 +80,7 @@ LL |     let bar1 = &mut foo.bar1.int1;
 LL |     let _foo2 = &mut foo; //~ ERROR cannot borrow
    |                 ^^^^^^^^ second mutable borrow occurs here
 LL |     *bar1;
-   |     ----- borrow later used here
+   |     ----- first borrow later used here
 
 error[E0502]: cannot borrow `foo.bar1` as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-borrow-from-stack-variable.rs:102:17
@@ -90,7 +90,7 @@ LL |     let bar1 = &foo.bar1.int1;
 LL |     let _foo1 = &mut foo.bar1; //~ ERROR cannot borrow
    |                 ^^^^^^^^^^^^^ mutable borrow occurs here
 LL |     *bar1;
-   |     ----- borrow later used here
+   |     ----- immutable borrow later used here
 
 error[E0502]: cannot borrow `foo` as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-borrow-from-stack-variable.rs:109:17
@@ -100,7 +100,7 @@ LL |     let bar1 = &foo.bar1.int1;
 LL |     let _foo2 = &mut foo; //~ ERROR cannot borrow
    |                 ^^^^^^^^ mutable borrow occurs here
 LL |     *bar1;
-   |     ----- borrow later used here
+   |     ----- immutable borrow later used here
 
 error[E0596]: cannot borrow `foo.bar1` as mutable, as `foo` is not declared as mutable
   --> $DIR/borrowck-borrow-from-stack-variable.rs:130:16
index 8c30e6ac002077c470d95be1586d947b29d5f058..fb04b3b93dc5d95fdae64e36e9230cc2cb468330 100644 (file)
@@ -15,7 +15,7 @@ LL |     let t1 = &mut *t0;
 LL |     let p: &isize = &**t0; //~ ERROR cannot borrow
    |                     ^^^^^ immutable borrow occurs here
 LL |     **t1 = 22;
-   |     --------- borrow later used here
+   |     --------- mutable borrow later used here
 
 error[E0596]: cannot borrow `**t0` as mutable, as it is behind a `&` reference
   --> $DIR/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs:29:26
index 9c3d0b170d90e28162e048a79b7dec16845b878b..65c4a392887da3b54c028a91cd12c72787c47cf7 100644 (file)
@@ -6,7 +6,7 @@ LL |     let y = x.f1();
 LL |     x.f2(); //~ ERROR cannot borrow `*x` as mutable
    |     ^ second mutable borrow occurs here
 LL |     y.use_ref();
-   |     - borrow later used here
+   |     - first borrow later used here
 
 error: aborting due to previous error
 
index f24d0ed046a5790b07f4a054e6f0a402ee880b04..814fb7bbedc7156ec0367bf58af6ee95049494ca 100644 (file)
@@ -11,7 +11,7 @@ LL |     let c2 = || x * 5; //[ast]~ ERROR cannot borrow `x`
    |              immutable borrow occurs here
 LL |     //[mir]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable
 LL |     drop(c1);
-   |          -- borrow later used here
+   |          -- mutable borrow later used here
 
 error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-closures-mut-and-imm.rs:39:14
@@ -26,7 +26,7 @@ LL |     let c2 = || get(&x); //[ast]~ ERROR cannot borrow `x`
    |              immutable borrow occurs here
 LL |                          //[mir]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable
 LL |     drop(c1);
-   |          -- borrow later used here
+   |          -- mutable borrow later used here
 
 error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-closures-mut-and-imm.rs:47:14
@@ -41,7 +41,7 @@ LL |     let c2 = || x * 5; //[ast]~ ERROR cannot borrow `x`
    |              immutable borrow occurs here
 LL |                        //[mir]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable
 LL |     drop(c1);
-   |          -- borrow later used here
+   |          -- mutable borrow later used here
 
 error[E0506]: cannot assign to `x` because it is borrowed
   --> $DIR/borrowck-closures-mut-and-imm.rs:55:5
@@ -108,7 +108,7 @@ LL |     let c2 = || *x.f = 5; //[ast]~ ERROR cannot borrow `x` as mutable
    |              mutable borrow occurs here
 LL |                           //[mir]~^ ERROR cannot borrow `x` as mutable because it is also borrowed as immutable
 LL |     drop(c1);
-   |          -- borrow later used here
+   |          -- immutable borrow later used here
 
 error: aborting due to 8 previous errors
 
index f24d0ed046a5790b07f4a054e6f0a402ee880b04..814fb7bbedc7156ec0367bf58af6ee95049494ca 100644 (file)
@@ -11,7 +11,7 @@ LL |     let c2 = || x * 5; //[ast]~ ERROR cannot borrow `x`
    |              immutable borrow occurs here
 LL |     //[mir]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable
 LL |     drop(c1);
-   |          -- borrow later used here
+   |          -- mutable borrow later used here
 
 error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-closures-mut-and-imm.rs:39:14
@@ -26,7 +26,7 @@ LL |     let c2 = || get(&x); //[ast]~ ERROR cannot borrow `x`
    |              immutable borrow occurs here
 LL |                          //[mir]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable
 LL |     drop(c1);
-   |          -- borrow later used here
+   |          -- mutable borrow later used here
 
 error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-closures-mut-and-imm.rs:47:14
@@ -41,7 +41,7 @@ LL |     let c2 = || x * 5; //[ast]~ ERROR cannot borrow `x`
    |              immutable borrow occurs here
 LL |                        //[mir]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable
 LL |     drop(c1);
-   |          -- borrow later used here
+   |          -- mutable borrow later used here
 
 error[E0506]: cannot assign to `x` because it is borrowed
   --> $DIR/borrowck-closures-mut-and-imm.rs:55:5
@@ -108,7 +108,7 @@ LL |     let c2 = || *x.f = 5; //[ast]~ ERROR cannot borrow `x` as mutable
    |              mutable borrow occurs here
 LL |                           //[mir]~^ ERROR cannot borrow `x` as mutable because it is also borrowed as immutable
 LL |     drop(c1);
-   |          -- borrow later used here
+   |          -- immutable borrow later used here
 
 error: aborting due to 8 previous errors
 
index c96799c85f20606117e71831f46ff5106b1ba233..fea61420b19387855af7b701eae807fc32606631 100644 (file)
@@ -10,7 +10,7 @@ LL |     let c2 = to_fn_mut(|| x = 5); //~ ERROR cannot borrow `x` as mutable mo
    |                        |
    |                        second mutable borrow occurs here
 LL |     c1;
-   |     -- borrow later used here
+   |     -- first borrow later used here
 
 error[E0499]: cannot borrow `x` as mutable more than once at a time
   --> $DIR/borrowck-closures-two-mut-fail.rs:37:24
@@ -24,7 +24,7 @@ LL |     let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as muta
    |                        |
    |                        second mutable borrow occurs here
 LL |     c1;
-   |     -- borrow later used here
+   |     -- first borrow later used here
 
 error[E0499]: cannot borrow `x` as mutable more than once at a time
   --> $DIR/borrowck-closures-two-mut-fail.rs:44:24
@@ -38,7 +38,7 @@ LL |     let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as muta
    |                        |
    |                        second mutable borrow occurs here
 LL |     c1;
-   |     -- borrow later used here
+   |     -- first borrow later used here
 
 error[E0499]: cannot borrow `x` as mutable more than once at a time
   --> $DIR/borrowck-closures-two-mut-fail.rs:51:24
@@ -53,7 +53,7 @@ LL |     let c2 = to_fn_mut(|| { let _y = to_fn_mut(|| set(&mut x)); }); // (nes
    |                        second mutable borrow occurs here
 LL |     //~^ ERROR cannot borrow `x` as mutable more than once
 LL |     c1;
-   |     -- borrow later used here
+   |     -- first borrow later used here
 
 error[E0499]: cannot borrow `x` as mutable more than once at a time
   --> $DIR/borrowck-closures-two-mut-fail.rs:63:24
@@ -68,7 +68,7 @@ LL |     let c2 = to_fn_mut(|| set(&mut *x.f));
    |                        second mutable borrow occurs here
 LL |     //~^ ERROR cannot borrow `x` as mutable more than once
 LL |     c1;
-   |     -- borrow later used here
+   |     -- first borrow later used here
 
 error: aborting due to 5 previous errors
 
index 6186c3839193d0dd3aa23c038fd71befd8371997..bbfe37702364e276c164849aced70439df0c2778 100644 (file)
@@ -86,7 +86,7 @@ LL |     let c2 = to_fn_mut(|| x = 5); //~ ERROR cannot borrow `x` as mutable mo
    |                        second mutable borrow occurs here
 LL |     //~| ERROR cannot borrow `x` as mutable more than once
 LL |     drop((c1, c2));
-   |           -- borrow later used here
+   |           -- first borrow later used here
 
 error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir)
   --> $DIR/borrowck-closures-two-mut.rs:36:24
@@ -101,7 +101,7 @@ LL |     let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as muta
    |                        second mutable borrow occurs here
 LL |     //~| ERROR cannot borrow `x` as mutable more than once
 LL |     drop((c1, c2));
-   |           -- borrow later used here
+   |           -- first borrow later used here
 
 error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir)
   --> $DIR/borrowck-closures-two-mut.rs:44:24
@@ -116,7 +116,7 @@ LL |     let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as muta
    |                        second mutable borrow occurs here
 LL |     //~| ERROR cannot borrow `x` as mutable more than once
 LL |     drop((c1, c2));
-   |           -- borrow later used here
+   |           -- first borrow later used here
 
 error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir)
   --> $DIR/borrowck-closures-two-mut.rs:52:24
@@ -131,7 +131,7 @@ LL |     let c2 = to_fn_mut(|| { let _y = to_fn_mut(|| set(&mut x)); }); // (nes
    |                        second mutable borrow occurs here
 ...
 LL |     drop((c1, c2));
-   |           -- borrow later used here
+   |           -- first borrow later used here
 
 error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir)
   --> $DIR/borrowck-closures-two-mut.rs:65:24
@@ -146,7 +146,7 @@ LL |     let c2 = to_fn_mut(|| set(&mut *x.f));
    |                        second mutable borrow occurs here
 ...
 LL |     drop((c1, c2));
-   |           -- borrow later used here
+   |           -- first borrow later used here
 
 error: aborting due to 10 previous errors
 
index b8f17570a6471309dd978410e0e6881d3165a5bd..aca4f309257e7effc23086a08d73788c4a660e1c 100644 (file)
@@ -6,7 +6,7 @@ LL |         let p = &this.x;
 LL |         &mut this.x; //~ ERROR cannot borrow
    |         ^^^^^^^^^^^ mutable borrow occurs here
 LL |         p.use_ref();
-   |         - borrow later used here
+   |         - immutable borrow later used here
 
 error: aborting due to previous error
 
index 17519ccb1438dded93710c0d229dc3533c02a84c..231ae53fe82bf97484dfbf112c1372e557d6b38a 100644 (file)
@@ -10,7 +10,7 @@ LL |     let c2 = || set(x); //~ ERROR closure requires unique access to `x`
    |              |
    |              closure construction occurs here
 LL |     c1;
-   |     -- borrow later used here
+   |     -- first borrow later used here
 
 error[E0500]: closure requires unique access to `x` but it is already borrowed
   --> $DIR/borrowck-closures-unique.rs:42:14
@@ -24,7 +24,7 @@ LL |     let c2 = || { get(x); set(x); }; //~ ERROR closure requires unique acce
    |              |
    |              closure construction occurs here
 LL |     c1;
-   |     -- borrow later used here
+   |     -- first borrow later used here
 
 error[E0524]: two closures require unique access to `x` at the same time
   --> $DIR/borrowck-closures-unique.rs:48:14
@@ -38,7 +38,7 @@ LL |     let c2 = || set(x); //~ ERROR two closures require unique access to `x`
    |              |
    |              second closure is constructed here
 LL |     c1;
-   |     -- borrow later used here
+   |     -- first borrow later used here
 
 error[E0594]: cannot assign to `x`, as it is not declared as mutable
   --> $DIR/borrowck-closures-unique.rs:57:38
index dc73929989ce1f8c7add66b513d5081a5edeaaf2..90eb7fda0263cbad2be05a15ea187ffec03f3749 100644 (file)
@@ -7,10 +7,9 @@ LL |     ptr = box Foo { x: ptr.x + 1 };
    |     --- first borrow occurs due to use of `ptr` in closure
 LL |   };
 LL |   test(&*ptr); //~ ERROR cannot borrow `*ptr`
-   |   -----^^^^^-
-   |   |    |
-   |   |    immutable borrow occurs here
-   |   borrow later used here
+   |   ---- ^^^^^ immutable borrow occurs here
+   |   |
+   |   mutable borrow later used by call
 
 error: aborting due to previous error
 
index e417dadf6df163efebbf9d4694bee5095f00a1dd..ac6cfac2a165f61a4822904969b3c39263d74227 100644 (file)
@@ -7,7 +7,7 @@ LL |             &mut x; //[ast]~ ERROR cannot borrow `**x` as mutable more than
    |             ^^^^^^ second mutable borrow occurs here
 LL |                     //[mir]~^ ERROR cannot borrow `x` as mutable more than once at a time
 LL |             *y = 1;
-   |             ------ borrow later used here
+   |             ------ first borrow later used here
 
 error[E0499]: cannot borrow `x` as mutable more than once at a time
   --> $DIR/borrowck-describe-lvalue.rs:307:20
@@ -18,7 +18,7 @@ LL |                    &mut x; //[ast]~ ERROR cannot borrow `**x` as mutable mo
    |                    ^^^^^^ second mutable borrow occurs here
 LL |                    //[mir]~^ ERROR cannot borrow `x` as mutable more than once at a time
 LL |                    *y = 1;
-   |                    ------ borrow later used here
+   |                    ------ first borrow later used here
 
 error: unsatisfied lifetime constraints
   --> $DIR/borrowck-describe-lvalue.rs:305:16
@@ -269,7 +269,7 @@ LL |             E::A(ref ax) =>
    |                  ^^^^^^ immutable borrow occurs here
 ...
 LL |         drop(x);
-   |              - borrow later used here
+   |              - mutable borrow later used here
 
 error[E0502]: cannot borrow `e.x` as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-describe-lvalue.rs:207:23
@@ -281,7 +281,7 @@ LL |             E::B { x: ref bx } =>
    |                       ^^^^^^ immutable borrow occurs here
 ...
 LL |         drop(x);
-   |              - borrow later used here
+   |              - mutable borrow later used here
 
 error[E0502]: cannot borrow `s.y.0` as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-describe-lvalue.rs:221:22
@@ -293,7 +293,7 @@ LL |             S  { y: (ref y0, _), .. } =>
    |                      ^^^^^^ immutable borrow occurs here
 ...
 LL |         drop(x);
-   |              - borrow later used here
+   |              - mutable borrow later used here
 
 error[E0502]: cannot borrow `s.x.y` as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-describe-lvalue.rs:228:28
@@ -305,7 +305,7 @@ LL |             S  { x: F { y: ref x0, .. }, .. } =>
    |                            ^^^^^^ immutable borrow occurs here
 ...
 LL |         drop(x);
-   |              - borrow later used here
+   |              - mutable borrow later used here
 
 error[E0503]: cannot use `*v` because it was mutably borrowed
   --> $DIR/borrowck-describe-lvalue.rs:271:9
@@ -339,7 +339,7 @@ LL |             &[_, F {x: ref xf, ..}] => println!("{}", xf),
    |                        ^^^^^^ immutable borrow occurs here
 ...
 LL |         drop(x);
-   |              - borrow later used here
+   |              - mutable borrow later used here
 
 error[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-describe-lvalue.rs:245:29
@@ -350,7 +350,7 @@ LL |             let p: &'a u8 = &*block.current;
    |                             ^^^^^^^^^^^^^^^ immutable borrow occurs here
 ...
 LL |             drop(x);
-   |                  - borrow later used here
+   |                  - mutable borrow later used here
 
 error[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-describe-lvalue.rs:260:33
@@ -361,7 +361,7 @@ LL |             let p : *const u8 = &*(*block).current;
    |                                 ^^^^^^^^^^^^^^^^^^ immutable borrow occurs here
 ...
 LL |             drop(x);
-   |                  - borrow later used here
+   |                  - mutable borrow later used here
 
 error[E0382]: use of moved value: `x`
   --> $DIR/borrowck-describe-lvalue.rs:318:22
index e417dadf6df163efebbf9d4694bee5095f00a1dd..ac6cfac2a165f61a4822904969b3c39263d74227 100644 (file)
@@ -7,7 +7,7 @@ LL |             &mut x; //[ast]~ ERROR cannot borrow `**x` as mutable more than
    |             ^^^^^^ second mutable borrow occurs here
 LL |                     //[mir]~^ ERROR cannot borrow `x` as mutable more than once at a time
 LL |             *y = 1;
-   |             ------ borrow later used here
+   |             ------ first borrow later used here
 
 error[E0499]: cannot borrow `x` as mutable more than once at a time
   --> $DIR/borrowck-describe-lvalue.rs:307:20
@@ -18,7 +18,7 @@ LL |                    &mut x; //[ast]~ ERROR cannot borrow `**x` as mutable mo
    |                    ^^^^^^ second mutable borrow occurs here
 LL |                    //[mir]~^ ERROR cannot borrow `x` as mutable more than once at a time
 LL |                    *y = 1;
-   |                    ------ borrow later used here
+   |                    ------ first borrow later used here
 
 error: unsatisfied lifetime constraints
   --> $DIR/borrowck-describe-lvalue.rs:305:16
@@ -269,7 +269,7 @@ LL |             E::A(ref ax) =>
    |                  ^^^^^^ immutable borrow occurs here
 ...
 LL |         drop(x);
-   |              - borrow later used here
+   |              - mutable borrow later used here
 
 error[E0502]: cannot borrow `e.x` as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-describe-lvalue.rs:207:23
@@ -281,7 +281,7 @@ LL |             E::B { x: ref bx } =>
    |                       ^^^^^^ immutable borrow occurs here
 ...
 LL |         drop(x);
-   |              - borrow later used here
+   |              - mutable borrow later used here
 
 error[E0502]: cannot borrow `s.y.0` as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-describe-lvalue.rs:221:22
@@ -293,7 +293,7 @@ LL |             S  { y: (ref y0, _), .. } =>
    |                      ^^^^^^ immutable borrow occurs here
 ...
 LL |         drop(x);
-   |              - borrow later used here
+   |              - mutable borrow later used here
 
 error[E0502]: cannot borrow `s.x.y` as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-describe-lvalue.rs:228:28
@@ -305,7 +305,7 @@ LL |             S  { x: F { y: ref x0, .. }, .. } =>
    |                            ^^^^^^ immutable borrow occurs here
 ...
 LL |         drop(x);
-   |              - borrow later used here
+   |              - mutable borrow later used here
 
 error[E0503]: cannot use `*v` because it was mutably borrowed
   --> $DIR/borrowck-describe-lvalue.rs:271:9
@@ -339,7 +339,7 @@ LL |             &[_, F {x: ref xf, ..}] => println!("{}", xf),
    |                        ^^^^^^ immutable borrow occurs here
 ...
 LL |         drop(x);
-   |              - borrow later used here
+   |              - mutable borrow later used here
 
 error[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-describe-lvalue.rs:245:29
@@ -350,7 +350,7 @@ LL |             let p: &'a u8 = &*block.current;
    |                             ^^^^^^^^^^^^^^^ immutable borrow occurs here
 ...
 LL |             drop(x);
-   |                  - borrow later used here
+   |                  - mutable borrow later used here
 
 error[E0502]: cannot borrow `*block.current` as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-describe-lvalue.rs:260:33
@@ -361,7 +361,7 @@ LL |             let p : *const u8 = &*(*block).current;
    |                                 ^^^^^^^^^^^^^^^^^^ immutable borrow occurs here
 ...
 LL |             drop(x);
-   |                  - borrow later used here
+   |                  - mutable borrow later used here
 
 error[E0382]: use of moved value: `x`
   --> $DIR/borrowck-describe-lvalue.rs:318:22
index fb300d32b05e9e5ee0ddfbadf454a59b7fe27176..6ac5fef1416afd277ba6fa8d036fd4e2907ce6a3 100644 (file)
@@ -62,7 +62,7 @@ LL |     let p = &mut x.a;
 LL |     let q = &mut x.a; //~ ERROR cannot borrow `x.a` as mutable more than once at a time
    |             ^^^^^^^^ second mutable borrow occurs here
 LL |     drop(*p);
-   |          -- borrow later used here
+   |          -- first borrow later used here
 
 error[E0382]: use of moved value: `x.b`
   --> $DIR/borrowck-field-sensitivity.rs:66:10
index b7803cbc804aecb8fb0b898653ccd69f325ccb56..a6487ede6f838ba64e5974fc8d1318df7af2f97b 100644 (file)
@@ -5,7 +5,7 @@ LL |     for &x in &vector {
    |               -------
    |               |
    |               immutable borrow occurs here
-   |               borrow used here, in later iteration of loop
+   |               immutable borrow used here, in later iteration of loop
 LL |         let cap = vector.capacity();
 LL |         vector.extend(repeat(0));      //~ ERROR cannot borrow
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
@@ -17,7 +17,7 @@ LL |     for &x in &vector {
    |               -------
    |               |
    |               immutable borrow occurs here
-   |               borrow used here, in later iteration of loop
+   |               immutable borrow used here, in later iteration of loop
 ...
 LL |         vector[1] = 5;   //~ ERROR cannot borrow
    |         ^^^^^^ mutable borrow occurs here
index e403b076ab40662311f0d19706a22d5b0798136a..123d475f1c09f7f6fdb6e67635416b42255f4080 100644 (file)
@@ -1,34 +1,28 @@
 error[E0501]: cannot borrow `*f` as mutable because previous closure requires unique access
   --> $DIR/borrowck-insert-during-each.rs:26:3
    |
-LL |      f.foo(
-   |   ___^
-   |  |___|
-   | ||
-LL | ||         |a| { //~ ERROR closure requires unique access to `f`
-   | ||         --- closure construction occurs here
-LL | ||             f.n.insert(*a);
-   | ||             - first borrow occurs due to use of `f` in closure
-LL | ||         })
-   | ||          ^
-   | ||__________|
-   | |___________borrow occurs here
-   |             borrow later used here
-
-error[E0500]: closure requires unique access to `f` but it is already borrowed
-  --> $DIR/borrowck-insert-during-each.rs:27:9
-   |
 LL |     f.foo(
-   |     -
-   |     |
-   |  ___borrow occurs here
+   |     ^ --- first borrow later used by call
+   |  ___|
    | |
 LL | |         |a| { //~ ERROR closure requires unique access to `f`
-   | |         ^^^ closure construction occurs here
+   | |         --- closure construction occurs here
 LL | |             f.n.insert(*a);
-   | |             - second borrow occurs due to use of `f` in closure
+   | |             - first borrow occurs due to use of `f` in closure
 LL | |         })
-   | |__________- borrow later used here
+   | |__________^ borrow occurs here
+
+error[E0500]: closure requires unique access to `f` but it is already borrowed
+  --> $DIR/borrowck-insert-during-each.rs:27:9
+   |
+LL |   f.foo(
+   |   - --- first borrow later used by call
+   |   |
+   |   borrow occurs here
+LL |         |a| { //~ ERROR closure requires unique access to `f`
+   |         ^^^ closure construction occurs here
+LL |             f.n.insert(*a);
+   |             - second borrow occurs due to use of `f` in closure
 
 error: aborting due to 2 previous errors
 
index 0f0eed4a051dd7dfb710508976c8f6db6a5f5b53..f1c33a596cbbab1802e286d7c8a07e1ff3e2ecdd 100644 (file)
@@ -7,7 +7,7 @@ LL |     }
 LL |     borrow_mut(&mut *v); //~ ERROR cannot borrow
    |                ^^^^^^^ mutable borrow occurs here
 LL |     _w.use_ref();
-   |     -- borrow later used here
+   |     -- immutable borrow later used here
 
 error: aborting due to previous error
 
index 81aa1e2c9602e79672f0ee47d877aa67f035e0a1..388fc9c5fa8acd976911a2ebb7180eb76cd7dd23 100644 (file)
@@ -8,13 +8,13 @@ LL |         borrow(&*v); //~ ERROR cannot borrow
    |                ^^^ immutable borrow occurs here
 LL |     }
 LL |     *x = box 5;
-   |     -- borrow used here, in later iteration of loop
+   |     -- mutable borrow used here, in later iteration of loop
 
 error[E0502]: cannot borrow `*v` as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-lend-flow-loop.rs:109:16
    |
 LL |         **x += 1;
-   |         -------- borrow used here, in later iteration of loop
+   |         -------- mutable borrow used here, in later iteration of loop
 LL |         borrow(&*v); //~ ERROR cannot borrow
    |                ^^^ immutable borrow occurs here
 LL |         if cond2 {
index 7ebc2ce47cd9039441c1410525c2b99ab82525b8..e97ba68cd5cf6fb95e3f5302d2c92478f0f7860e 100644 (file)
@@ -6,7 +6,7 @@ LL |     let _w = &v;
 LL |     borrow_mut(&mut *v); //~ ERROR cannot borrow
    |                ^^^^^^^ mutable borrow occurs here
 LL |     _w.use_ref();
-   |     -- borrow later used here
+   |     -- immutable borrow later used here
 
 error: aborting due to previous error
 
index 5c3cd46a87d9c5d8bed394d2231cba1b352c2577..b181fcf8b540330577363f0e8767aa5f493f8184 100644 (file)
@@ -1,18 +1,14 @@
 error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-loan-blocks-mut-uniq.rs:20:12
    |
-LL |       borrow(&*v,
-   |       -      --- immutable borrow occurs here
-   |  _____|
-   | |
-LL | |            |w| { //~ ERROR cannot borrow `v` as mutable
-   | |            ^^^ mutable borrow occurs here
-LL | |             v = box 4;
-   | |             - second borrow occurs due to use of `v` in closure
-LL | |             assert_eq!(*v, 3);
-LL | |             assert_eq!(*w, 4);
-LL | |         })
-   | |__________- borrow later used here
+LL |     borrow(&*v,
+   |     ------ --- immutable borrow occurs here
+   |     |
+   |     immutable borrow later used by call
+LL |            |w| { //~ ERROR cannot borrow `v` as mutable
+   |            ^^^ mutable borrow occurs here
+LL |             v = box 4;
+   |             - second borrow occurs due to use of `v` in closure
 
 error: aborting due to previous error
 
index b7c871625870c0f22ed018070b123bab2d3cf197..6f08c13caa4082d812044788ebd56708516bcbf6 100644 (file)
@@ -20,7 +20,7 @@ LL |     p.times(3); //~ ERROR cannot borrow `p`
    |     ^ immutable borrow occurs here
 LL | 
 LL |     *q + 3; // OK to use the new alias `q`
-   |     -- borrow later used here
+   |     -- mutable borrow later used here
 
 error: aborting due to 2 previous errors
 
index a5b81027c2fc4e698ead23711a2c96a0669a214d..18c2d67f6b01e23e099f8957713649984f4d8749 100644 (file)
@@ -1,15 +1,13 @@
 error[E0502]: cannot borrow `p` as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-loan-rcvr.rs:34:14
    |
-LL |       p.blockm(|| { //~ ERROR cannot borrow `p` as mutable
-   |       -        ^^ mutable borrow occurs here
-   |       |
-   |  _____immutable borrow occurs here
-   | |
-LL | |         p.x = 10;
-   | |         - second borrow occurs due to use of `p` in closure
-LL | |     })
-   | |______- borrow later used here
+LL |     p.blockm(|| { //~ ERROR cannot borrow `p` as mutable
+   |     - ------ ^^ mutable borrow occurs here
+   |     | |
+   |     | immutable borrow later used by call
+   |     immutable borrow occurs here
+LL |         p.x = 10;
+   |         - second borrow occurs due to use of `p` in closure
 
 error[E0502]: cannot borrow `p` as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-loan-rcvr.rs:45:5
@@ -20,7 +18,7 @@ LL |     p.impurem(); //~ ERROR cannot borrow
    |     ^ immutable borrow occurs here
 LL | 
 LL |     l.x += 1;
-   |     -------- borrow later used here
+   |     -------- mutable borrow later used here
 
 error: aborting due to 2 previous errors
 
index 492e90914ea70efd1f7e34cdf72030fc414f59a7..2b22a125d3f43a55ca4c47ba4bacf1f37962a954 100644 (file)
@@ -1,15 +1,14 @@
 error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-loan-vec-content.rs:28:9
    |
-LL | /     takes_imm_elt(
-LL | |         &v[0],
-   | |          - immutable borrow occurs here
-LL | |         || { //~ ERROR cannot borrow `v` as mutable
-   | |         ^^ mutable borrow occurs here
-LL | |             v[1] = 4;
-   | |             - second borrow occurs due to use of `v` in closure
-LL | |         })
-   | |__________- borrow later used here
+LL |     takes_imm_elt(
+   |     ------------- immutable borrow later used by call
+LL |         &v[0],
+   |          - immutable borrow occurs here
+LL |         || { //~ ERROR cannot borrow `v` as mutable
+   |         ^^ mutable borrow occurs here
+LL |             v[1] = 4;
+   |             - second borrow occurs due to use of `v` in closure
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.ast.nll.stderr b/src/test/ui/borrowck/borrowck-move-out-of-overloaded-auto-deref.ast.nll.stderr
new file mode 100644 (file)
index 0000000..d58beab
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0507]: cannot move out of an `Rc`
+  --> $DIR/borrowck-move-out-of-overloaded-auto-deref.rs:17:14
+   |
+LL |     let _x = Rc::new(vec![1, 2]).into_iter();
+   |              ^^^^^^^^^^^^^^^^^^^ cannot move out of an `Rc`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0507`.
index 94f7eba63a1ca71699f7b5b75aa5d592d0fcb888..d58beabb3038af551493e03d3d7a35312c100b9f 100644 (file)
@@ -1,8 +1,8 @@
-error[E0507]: cannot move out of borrowed content
+error[E0507]: cannot move out of an `Rc`
   --> $DIR/borrowck-move-out-of-overloaded-auto-deref.rs:17:14
    |
 LL |     let _x = Rc::new(vec![1, 2]).into_iter();
-   |              ^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content
+   |              ^^^^^^^^^^^^^^^^^^^ cannot move out of an `Rc`
 
 error: aborting due to previous error
 
index b9c47e6e8cfe92f410a2c2c328e164ee7049c1e9..c9c8cf104ce2e769fa4aa36749ce6b14f9c1894f 100644 (file)
@@ -1,10 +1,10 @@
-error[E0507]: cannot move out of borrowed content
+error[E0507]: cannot move out of an `Rc`
   --> $DIR/borrowck-move-out-of-overloaded-deref.rs:14:14
    |
 LL |     let _x = *Rc::new("hi".to_string());
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |              |
-   |              cannot move out of borrowed content
+   |              cannot move out of an `Rc`
    |              help: consider removing the `*`: `Rc::new("hi".to_string())`
 
 error: aborting due to previous error
index 19ec9cf7ded60d492d4a009e294760f8c9e40cfc..5301ee7a403fe4c13f9d2aac66b63dbb3003273e 100644 (file)
@@ -4,7 +4,7 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time
 LL |             1 => { addr.push(&mut x); } //[ast]~ ERROR [E0499]
    |                    ----      ^^^^^^ second mutable borrow occurs here
    |                    |
-   |                    borrow used here, in later iteration of loop
+   |                    first borrow used here, in later iteration of loop
 ...
 LL |             _ => { addr.push(&mut x); } //[ast]~ ERROR [E0499]
    |                              ------ first mutable borrow occurs here
@@ -13,7 +13,7 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time
   --> $DIR/borrowck-mut-borrow-linear-errors.rs:25:30
    |
 LL |             1 => { addr.push(&mut x); } //[ast]~ ERROR [E0499]
-   |                    ---- borrow used here, in later iteration of loop
+   |                    ---- first borrow used here, in later iteration of loop
 LL |             //[mir]~^ ERROR [E0499]
 LL |             2 => { addr.push(&mut x); } //[ast]~ ERROR [E0499]
    |                              ^^^^^^ second mutable borrow occurs here
index 19ec9cf7ded60d492d4a009e294760f8c9e40cfc..5301ee7a403fe4c13f9d2aac66b63dbb3003273e 100644 (file)
@@ -4,7 +4,7 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time
 LL |             1 => { addr.push(&mut x); } //[ast]~ ERROR [E0499]
    |                    ----      ^^^^^^ second mutable borrow occurs here
    |                    |
-   |                    borrow used here, in later iteration of loop
+   |                    first borrow used here, in later iteration of loop
 ...
 LL |             _ => { addr.push(&mut x); } //[ast]~ ERROR [E0499]
    |                              ------ first mutable borrow occurs here
@@ -13,7 +13,7 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time
   --> $DIR/borrowck-mut-borrow-linear-errors.rs:25:30
    |
 LL |             1 => { addr.push(&mut x); } //[ast]~ ERROR [E0499]
-   |                    ---- borrow used here, in later iteration of loop
+   |                    ---- first borrow used here, in later iteration of loop
 LL |             //[mir]~^ ERROR [E0499]
 LL |             2 => { addr.push(&mut x); } //[ast]~ ERROR [E0499]
    |                              ^^^^^^ second mutable borrow occurs here
index 0684e787bae7f3a2146f60e561371ec03e985892..57f9a2c1778d36f077bed6139e0393d5bc5b169e 100644 (file)
@@ -7,7 +7,7 @@ LL |     let mut t2 = &mut t0;   //~ ERROR cannot borrow `t0`
    |                  ^^^^^^^ mutable borrow occurs here
 LL |     **t2 += 1;              // Mutates `*t0`
 LL |     p.use_ref();
-   |     - borrow later used here
+   |     - immutable borrow later used here
 
 error[E0499]: cannot borrow `t0` as mutable more than once at a time
   --> $DIR/borrowck-mut-borrow-of-mut-base-ptr.rs:29:18
@@ -18,7 +18,7 @@ LL |     let mut t2 = &mut t0;       //~ ERROR cannot borrow `t0`
    |                  ^^^^^^^ second mutable borrow occurs here
 LL |     **t2 += 1;                  // Mutates `*t0` but not through `*p`
 LL |     p.use_mut();
-   |     - borrow later used here
+   |     - first borrow later used here
 
 error: aborting due to 2 previous errors
 
index e4e2dfe86bd83d693a90569e3013f7843fd6c590..8a9aaa9d8958c049c7d75732443713ed480a48af 100644 (file)
@@ -6,7 +6,7 @@ LL |     let y = x.borrowed();
 LL |     let z = x.mut_borrowed(); //~ ERROR cannot borrow
    |             ^^^^^^^^^^^^^^^^ mutable borrow occurs here
 LL |     y.use_ref();
-   |     - borrow later used here
+   |     - immutable borrow later used here
 
 error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-object-lifetime.rs:36:13
@@ -16,7 +16,7 @@ LL |     let y = x.borrowed();
 LL |     let z = &mut x; //~ ERROR cannot borrow
    |             ^^^^^^ mutable borrow occurs here
 LL |     y.use_ref();
-   |     - borrow later used here
+   |     - immutable borrow later used here
 
 error: aborting due to 2 previous errors
 
index 994492d8575c9f65e6205595beead5d90e5f2152..fd4c380ea05d29c0c9075ad0617943d0d9fec09e 100644 (file)
@@ -6,7 +6,7 @@ LL |     let p = &mut f[&s];
 LL |     let q = &f[&s]; //~ ERROR cannot borrow
    |              ^ immutable borrow occurs here
 LL |     p.use_mut();
-   |     - borrow later used here
+   |     - mutable borrow later used here
 
 error[E0499]: cannot borrow `*f` as mutable more than once at a time
   --> $DIR/borrowck-overloaded-index-autoderef.rs:53:18
@@ -16,7 +16,7 @@ LL |     let p = &mut f[&s];
 LL |     let q = &mut f[&s]; //~ ERROR cannot borrow
    |                  ^ second mutable borrow occurs here
 LL |     p.use_mut();
-   |     - borrow later used here
+   |     - first borrow later used here
 
 error[E0499]: cannot borrow `f.foo` as mutable more than once at a time
   --> $DIR/borrowck-overloaded-index-autoderef.rs:63:18
@@ -26,7 +26,7 @@ LL |     let p = &mut f.foo[&s];
 LL |     let q = &mut f.foo[&s]; //~ ERROR cannot borrow
    |                  ^^^^^ second mutable borrow occurs here
 LL |     p.use_mut();
-   |     - borrow later used here
+   |     - first borrow later used here
 
 error[E0502]: cannot borrow `f.foo` as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-overloaded-index-autoderef.rs:75:18
@@ -36,7 +36,7 @@ LL |     let p = &f.foo[&s];
 LL |     let q = &mut f.foo[&s]; //~ ERROR cannot borrow
    |                  ^^^^^ mutable borrow occurs here
 LL |     p.use_ref();
-   |     - borrow later used here
+   |     - immutable borrow later used here
 
 error[E0506]: cannot assign to `f.foo` because it is borrowed
   --> $DIR/borrowck-overloaded-index-autoderef.rs:81:5
index 3a2bfb18cb9e6dcd7f5310f416e8a02a0cfb82e2..7ff9285bcc0bba8aa913ee66a65b562481d5d6b6 100644 (file)
@@ -7,7 +7,7 @@ LL |     println!("{}", f[&s]);
    |                      ^^ immutable borrow occurs here
 ...
 LL |     drop(rs);
-   |          -- borrow later used here
+   |          -- mutable borrow later used here
 
 error[E0502]: cannot borrow `s` as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-overloaded-index-ref-index.rs:65:7
@@ -19,7 +19,7 @@ LL |     f[&s] = 10;
    |       ^^ immutable borrow occurs here
 ...
 LL |     drop(rs);
-   |          -- borrow later used here
+   |          -- mutable borrow later used here
 
 error[E0594]: cannot assign to data in a `&` reference
   --> $DIR/borrowck-overloaded-index-ref-index.rs:71:5
index 3a2bfb18cb9e6dcd7f5310f416e8a02a0cfb82e2..7ff9285bcc0bba8aa913ee66a65b562481d5d6b6 100644 (file)
@@ -7,7 +7,7 @@ LL |     println!("{}", f[&s]);
    |                      ^^ immutable borrow occurs here
 ...
 LL |     drop(rs);
-   |          -- borrow later used here
+   |          -- mutable borrow later used here
 
 error[E0502]: cannot borrow `s` as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-overloaded-index-ref-index.rs:65:7
@@ -19,7 +19,7 @@ LL |     f[&s] = 10;
    |       ^^ immutable borrow occurs here
 ...
 LL |     drop(rs);
-   |          -- borrow later used here
+   |          -- mutable borrow later used here
 
 error[E0594]: cannot assign to data in a `&` reference
   --> $DIR/borrowck-overloaded-index-ref-index.rs:71:5
index fa600f0559f17e63274796c5cdec189968804b35..a089f6d90f8752cef36e341c4e735712d4d11f95 100644 (file)
@@ -8,7 +8,7 @@ LL |     let z = &x; //~ ERROR cannot borrow
    |             ^^ immutable borrow occurs here
 ...
 LL |     y.use_mut();
-   |     - borrow later used here
+   |     - mutable borrow later used here
 
 error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-report-with-custom-diagnostic.rs:30:21
@@ -20,7 +20,7 @@ LL |             let z = &mut x; //~ ERROR cannot borrow
    |                     ^^^^^^ mutable borrow occurs here
 ...
 LL |             y.use_ref();
-   |             - borrow later used here
+   |             - immutable borrow later used here
 
 error[E0499]: cannot borrow `x` as mutable more than once at a time
   --> $DIR/borrowck-report-with-custom-diagnostic.rs:45:17
@@ -32,7 +32,7 @@ LL |         let z = &mut x; //~ ERROR cannot borrow
    |                 ^^^^^^ second mutable borrow occurs here
 ...
 LL |         y.use_mut();
-   |         - borrow later used here
+   |         - first borrow later used here
 
 error: aborting due to 3 previous errors
 
index 16d401ec7f9bf5403815999165689231735ba545..7f260910ab87a45bf2c7addc5ee93f5b5c0c7b28 100644 (file)
@@ -6,7 +6,7 @@ LL |     if let [ref first, ref second, ..] = *s {
 LL |         if let [_, ref mut  second2, ref mut third, ..] = *s { //~ERROR
    |                    ^^^^^^^^^^^^^^^^ mutable borrow occurs here
 LL |             nop(&[first, second, second2, third]);
-   |                          ------ borrow later used here
+   |                          ------ immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-slice-pattern-element-loan.rs:44:21
@@ -16,7 +16,7 @@ LL |     if let [.., ref fourth, ref third, _, ref first] = *s {
 LL |         if let [.., ref mut third2, _, _] = *s { //~ERROR
    |                     ^^^^^^^^^^^^^^ mutable borrow occurs here
 LL |             nop(&[first, third, third2, fourth]);
-   |                          ----- borrow later used here
+   |                          ----- immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-slice-pattern-element-loan.rs:55:20
@@ -27,7 +27,7 @@ LL |     if let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s {
 LL |         if let [_, ref mut from_begin1, ..] = *s { //~ERROR
    |                    ^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
 LL |             nop(&[from_begin1, from_end1, from_end3, from_end4]);
-   |                                                      --------- borrow later used here
+   |                                                      --------- immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-slice-pattern-element-loan.rs:58:23
@@ -38,7 +38,7 @@ LL |     if let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s {
 LL |         if let [_, _, ref mut from_begin2, ..] = *s { //~ERROR
    |                       ^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
 LL |             nop(&[from_begin2, from_end1, from_end3, from_end4]);
-   |                                           --------- borrow later used here
+   |                                           --------- immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-slice-pattern-element-loan.rs:61:26
@@ -49,7 +49,7 @@ LL |     if let [.., _, ref from_end4, ref from_end3, _, ref from_end1] = *s {
 LL |         if let [_, _, _, ref mut from_begin3, ..] = *s { //~ERROR
    |                          ^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
 LL |             nop(&[from_begin3, from_end1, from_end3, from_end4]);
-   |                                           --------- borrow later used here
+   |                                           --------- immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-slice-pattern-element-loan.rs:69:21
@@ -60,7 +60,7 @@ LL |     if let [ref from_begin0, ref from_begin1, _, ref from_begin3, _, ..] =
 LL |         if let [.., ref mut from_end2, _] = *s { //~ERROR
    |                     ^^^^^^^^^^^^^^^^^ mutable borrow occurs here
 LL |             nop(&[from_begin0, from_begin1, from_begin3, from_end2]);
-   |                                             ----------- borrow later used here
+   |                                             ----------- immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-slice-pattern-element-loan.rs:72:21
@@ -71,7 +71,7 @@ LL |     if let [ref from_begin0, ref from_begin1, _, ref from_begin3, _, ..] =
 LL |         if let [.., ref mut from_end3, _,  _] = *s { //~ERROR
    |                     ^^^^^^^^^^^^^^^^^ mutable borrow occurs here
 LL |             nop(&[from_begin0, from_begin1, from_begin3, from_end3]);
-   |                                             ----------- borrow later used here
+   |                                             ----------- immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-slice-pattern-element-loan.rs:75:21
@@ -82,7 +82,7 @@ LL |     if let [ref from_begin0, ref from_begin1, _, ref from_begin3, _, ..] =
 LL |         if let [.., ref mut from_end4, _, _, _] = *s { //~ERROR
    |                     ^^^^^^^^^^^^^^^^^ mutable borrow occurs here
 LL |             nop(&[from_begin0, from_begin1, from_begin3, from_end4]);
-   |                                ----------- borrow later used here
+   |                                ----------- immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-slice-pattern-element-loan.rs:92:20
@@ -92,7 +92,7 @@ LL |     if let [ref first, ref second, ..] = *s {
 LL |         if let [_, ref mut tail..] = *s { //~ERROR
    |                    ^^^^^^^^^^^^ mutable borrow occurs here
 LL |             nop(&[first, second]);
-   |                          ------ borrow later used here
+   |                          ------ immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-slice-pattern-element-loan.rs:110:17
@@ -102,7 +102,7 @@ LL |     if let [.., ref second, ref first] = *s {
 LL |         if let [ref mut tail.., _] = *s { //~ERROR
    |                 ^^^^^^^^^^^^ mutable borrow occurs here
 LL |             nop(&[first, second]);
-   |                          ------ borrow later used here
+   |                          ------ immutable borrow later used here
 
 error[E0502]: cannot borrow `s[..]` as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-slice-pattern-element-loan.rs:119:17
@@ -112,7 +112,7 @@ LL |     if let [_, _, _, ref s1..] = *s {
 LL |         if let [ref mut s2.., _, _, _] = *s { //~ERROR
    |                 ^^^^^^^^^^ mutable borrow occurs here
 LL |             nop_subslice(s1);
-   |                          -- borrow later used here
+   |                          -- immutable borrow later used here
 
 error: aborting due to 11 previous errors
 
index 5f605694c5bccaa9759a6c6408186335e97d0ed1..4fad30fd40d9d01bb0c02ed3891532080c62894e 100644 (file)
@@ -7,7 +7,7 @@ LL |     swap(&mut t0, &mut t1); //~ ERROR cannot borrow `t0`
    |          ^^^^^^^ mutable borrow occurs here
 LL |     *t1 = 22;
 LL |     p.use_ref();
-   |     - borrow later used here
+   |     - immutable borrow later used here
 
 error: aborting due to previous error
 
index 2f14826fa1253171753f86d81c7f2eb75b2a855d..781d693d5659711f6f63405a72364a6216279d98 100644 (file)
@@ -7,7 +7,7 @@ LL |             let rma = &mut u.a; //[ast]~ ERROR cannot borrow `u.a` as mutab
    |                       ^^^^^^^^ mutable borrow occurs here
 LL |                                 //[mir]~^ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable
 LL |             drop(ra);
-   |                  -- borrow later used here
+   |                  -- immutable borrow later used here
 
 error[E0506]: cannot assign to `u.a` because it is borrowed
   --> $DIR/borrowck-union-borrow.rs:43:13
@@ -29,7 +29,7 @@ LL |             let rmb = &mut u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`
    |                       ^^^^^^^^ mutable borrow occurs here
 LL |                                 //[mir]~^ ERROR cannot borrow `u.b` as mutable because it is also borrowed as immutable
 LL |             drop(ra);
-   |                  -- borrow later used here
+   |                  -- immutable borrow later used here
 
 error[E0506]: cannot assign to `u.b` because it is borrowed
   --> $DIR/borrowck-union-borrow.rs:66:13
@@ -51,7 +51,7 @@ LL |             let ra = &u.a; //[ast]~ ERROR cannot borrow `u.a` as immutable
    |                      ^^^^ immutable borrow occurs here
 LL |                          //[mir]~^ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable
 LL |             drop(rma);
-   |                  --- borrow later used here
+   |                  --- mutable borrow later used here
 
 error[E0503]: cannot use `u.a` because it was mutably borrowed
   --> $DIR/borrowck-union-borrow.rs:79:21
@@ -73,7 +73,7 @@ LL |             let rma2 = &mut u.a; //[ast]~ ERROR cannot borrow `u.a` as muta
    |                        ^^^^^^^^ second mutable borrow occurs here
 LL |                                  //[mir]~^ ERROR cannot borrow `u.a` as mutable more than once at a time
 LL |             drop(rma);
-   |                  --- borrow later used here
+   |                  --- first borrow later used here
 
 error[E0506]: cannot assign to `u.a` because it is borrowed
   --> $DIR/borrowck-union-borrow.rs:91:13
@@ -95,7 +95,7 @@ LL |             let rb = &u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as
    |                      ^^^^ immutable borrow occurs here
 LL |                            //[mir]~^ ERROR cannot borrow `u.b` as immutable because it is also borrowed as mutable
 LL |             drop(rma);
-   |                  --- borrow later used here
+   |                  --- mutable borrow later used here
 
 error[E0503]: cannot use `u.b` because it was mutably borrowed
   --> $DIR/borrowck-union-borrow.rs:104:21
@@ -117,7 +117,7 @@ LL |             let rmb2 = &mut u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b
    |                        ^^^^^^^^ second mutable borrow occurs here
 LL |                                  //[mir]~^ ERROR cannot borrow `u.b` as mutable more than once at a time
 LL |             drop(rma);
-   |                  --- borrow later used here
+   |                  --- first borrow later used here
 
 error[E0506]: cannot assign to `u.b` because it is borrowed
   --> $DIR/borrowck-union-borrow.rs:117:13
index 2f14826fa1253171753f86d81c7f2eb75b2a855d..781d693d5659711f6f63405a72364a6216279d98 100644 (file)
@@ -7,7 +7,7 @@ LL |             let rma = &mut u.a; //[ast]~ ERROR cannot borrow `u.a` as mutab
    |                       ^^^^^^^^ mutable borrow occurs here
 LL |                                 //[mir]~^ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable
 LL |             drop(ra);
-   |                  -- borrow later used here
+   |                  -- immutable borrow later used here
 
 error[E0506]: cannot assign to `u.a` because it is borrowed
   --> $DIR/borrowck-union-borrow.rs:43:13
@@ -29,7 +29,7 @@ LL |             let rmb = &mut u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`
    |                       ^^^^^^^^ mutable borrow occurs here
 LL |                                 //[mir]~^ ERROR cannot borrow `u.b` as mutable because it is also borrowed as immutable
 LL |             drop(ra);
-   |                  -- borrow later used here
+   |                  -- immutable borrow later used here
 
 error[E0506]: cannot assign to `u.b` because it is borrowed
   --> $DIR/borrowck-union-borrow.rs:66:13
@@ -51,7 +51,7 @@ LL |             let ra = &u.a; //[ast]~ ERROR cannot borrow `u.a` as immutable
    |                      ^^^^ immutable borrow occurs here
 LL |                          //[mir]~^ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable
 LL |             drop(rma);
-   |                  --- borrow later used here
+   |                  --- mutable borrow later used here
 
 error[E0503]: cannot use `u.a` because it was mutably borrowed
   --> $DIR/borrowck-union-borrow.rs:79:21
@@ -73,7 +73,7 @@ LL |             let rma2 = &mut u.a; //[ast]~ ERROR cannot borrow `u.a` as muta
    |                        ^^^^^^^^ second mutable borrow occurs here
 LL |                                  //[mir]~^ ERROR cannot borrow `u.a` as mutable more than once at a time
 LL |             drop(rma);
-   |                  --- borrow later used here
+   |                  --- first borrow later used here
 
 error[E0506]: cannot assign to `u.a` because it is borrowed
   --> $DIR/borrowck-union-borrow.rs:91:13
@@ -95,7 +95,7 @@ LL |             let rb = &u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as
    |                      ^^^^ immutable borrow occurs here
 LL |                            //[mir]~^ ERROR cannot borrow `u.b` as immutable because it is also borrowed as mutable
 LL |             drop(rma);
-   |                  --- borrow later used here
+   |                  --- mutable borrow later used here
 
 error[E0503]: cannot use `u.b` because it was mutably borrowed
   --> $DIR/borrowck-union-borrow.rs:104:21
@@ -117,7 +117,7 @@ LL |             let rmb2 = &mut u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b
    |                        ^^^^^^^^ second mutable borrow occurs here
 LL |                                  //[mir]~^ ERROR cannot borrow `u.b` as mutable more than once at a time
 LL |             drop(rma);
-   |                  --- borrow later used here
+   |                  --- first borrow later used here
 
 error[E0506]: cannot assign to `u.b` because it is borrowed
   --> $DIR/borrowck-union-borrow.rs:117:13
index a918550fabfc14fd315cba0f7b47313d5a11c813..29e079ee3330bde180364d5c4946e90726f79f1d 100644 (file)
@@ -6,7 +6,7 @@ LL |     let w = &mut v;
 LL |     borrow(&*v); //~ ERROR cannot borrow `*v`
    |            ^^^ immutable borrow occurs here
 LL |     w.use_mut();
-   |     - borrow later used here
+   |     - mutable borrow later used here
 
 error[E0502]: cannot borrow `*v` as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-uniq-via-lend.rs:63:12
@@ -16,7 +16,7 @@ LL |     x = &mut v;
 LL |     borrow(&*v); //~ ERROR cannot borrow `*v`
    |            ^^^ immutable borrow occurs here
 LL |     x.use_mut();
-   |     - borrow later used here
+   |     - mutable borrow later used here
 
 error: aborting due to 2 previous errors
 
index 9b73991ce30d865c01c5aa30e9c50b497e88c7e6..4614c5cf5a6f3feb1b4464d7a6657bcb62bf0c56 100644 (file)
@@ -5,7 +5,7 @@ LL |     let vb: &mut [isize] = &mut v;
    |                            ------ first mutable borrow occurs here
 ...
 LL |             v.push(tail[0] + tail[1]); //~ ERROR cannot borrow
-   |             ^      ------- borrow later used here
+   |             ^      ------- first borrow later used here
    |             |
    |             second mutable borrow occurs here
 
index 1ddca21320211857b61312294073fa5fad0e5a26..71e965777971ebcfe7ed41cd5213888ad2c5bb00 100644 (file)
@@ -6,7 +6,7 @@ LL |         Some(baz) => {
 LL |             bar.take(); //~ ERROR cannot borrow
    |             ^^^ second mutable borrow occurs here
 LL |             drop(baz);
-   |                  --- borrow later used here
+   |                  --- first borrow later used here
 
 error: aborting due to previous error
 
index 92225369c92711806bdc6a8bd65f132df1dcef5e..c6aa243b6cff7d26da06554bde3743acb0b99964 100644 (file)
@@ -4,7 +4,7 @@ error[E0499]: cannot borrow `*arg` as mutable more than once at a time
 LL |             (self.func)(arg) //~ ERROR cannot borrow
    |                         ^^^ mutable borrow starts here in previous iteration of loop
    |
-note: borrowed value must be valid for the lifetime 'a as defined on the impl at 17:6...
+note: first borrowed value must be valid for the lifetime 'a as defined on the impl at 17:6...
   --> $DIR/mut-borrow-in-loop.rs:17:6
    |
 LL | impl<'a, T : 'a> FuncWrapper<'a, T> {
@@ -16,7 +16,7 @@ error[E0499]: cannot borrow `*arg` as mutable more than once at a time
 LL |             (self.func)(arg) //~ ERROR cannot borrow
    |                         ^^^ mutable borrow starts here in previous iteration of loop
    |
-note: borrowed value must be valid for the lifetime 'a as defined on the impl at 17:6...
+note: first borrowed value must be valid for the lifetime 'a as defined on the impl at 17:6...
   --> $DIR/mut-borrow-in-loop.rs:17:6
    |
 LL | impl<'a, T : 'a> FuncWrapper<'a, T> {
@@ -28,7 +28,7 @@ error[E0499]: cannot borrow `*arg` as mutable more than once at a time
 LL |             (self.func)(arg) //~ ERROR cannot borrow
    |                         ^^^ mutable borrow starts here in previous iteration of loop
    |
-note: borrowed value must be valid for the lifetime 'a as defined on the impl at 17:6...
+note: first borrowed value must be valid for the lifetime 'a as defined on the impl at 17:6...
   --> $DIR/mut-borrow-in-loop.rs:17:6
    |
 LL | impl<'a, T : 'a> FuncWrapper<'a, T> {
index dd445c8c3a06bc242c2ccf41d6574012a141edf7..fd201d75106b4704e7659c0da09aef00d40077b8 100644 (file)
@@ -6,7 +6,7 @@ LL |     let first = &mut void;
 LL |     let second = &mut void; //~ ERROR cannot borrow
    |                  ^^^^^^^^^ second mutable borrow occurs here
 LL |     first.use_mut();
-   |     ----- borrow later used here
+   |     ----- first borrow later used here
 
 error[E0499]: cannot borrow `inner_void` as mutable more than once at a time
   --> $DIR/mut-borrow-outside-loop.rs:25:28
@@ -17,7 +17,7 @@ LL |         let inner_second = &mut inner_void; //~ ERROR cannot borrow
    |                            ^^^^^^^^^^^^^^^ second mutable borrow occurs here
 LL |         inner_second.use_mut();
 LL |         inner_first.use_mut();
-   |         ----------- borrow used here, in later iteration of loop
+   |         ----------- first borrow used here, in later iteration of loop
 
 error: aborting due to 2 previous errors
 
index 5a7f33e5b56a3d76eb1342e2f92288011154d6c2..ad1dc439c6d1555bba1001465db190ef0c4a82df 100644 (file)
@@ -7,7 +7,7 @@ LL |     { let z = &x; read(z); }
    |               ^^ immutable borrow occurs here
 LL |     //[nll_target]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable
 LL |     *y += 1;
-   |     ------- borrow later used here
+   |     ------- mutable borrow later used here
 
 error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
   --> $DIR/two-phase-activation-sharing-interference.rs:50:13
@@ -18,7 +18,7 @@ LL |     let z = &x;
    |             ^^ immutable borrow occurs here
 LL |     //[nll_target]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable
 LL |     *y += 1;
-   |     ------- borrow later used here
+   |     ------- mutable borrow later used here
 
 error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
   --> $DIR/two-phase-activation-sharing-interference.rs:61:13
@@ -29,7 +29,7 @@ LL |     let z = &x;
    |             ^^ immutable borrow occurs here
 ...
 LL |     *y += 1;
-   |     ------- borrow later used here
+   |     ------- mutable borrow later used here
 
 error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
   --> $DIR/two-phase-activation-sharing-interference.rs:72:14
@@ -40,7 +40,7 @@ LL |     let _z = &x;
    |              ^^ immutable borrow occurs here
 LL |     //[nll_target]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable
 LL |     *y += 1;
-   |     ------- borrow later used here
+   |     ------- mutable borrow later used here
 
 error: aborting due to 4 previous errors
 
index 942a38febdd499a2231789561f3da7f64e41b972..a3d3da94d54aae23d733c2fe5266ffdc9433abc1 100644 (file)
@@ -1,19 +1,13 @@
 error[E0502]: cannot borrow `vec` as mutable because it is also borrowed as immutable
   --> $DIR/two-phase-cannot-nest-mut-self-calls.rs:26:9
    |
-LL |       vec.get({
-   |       ---
-   |       |
-   |  _____immutable borrow occurs here
-   | |
-LL | |
-LL | |         vec.push(2);
-   | |         ^^^^^^^^^^^ mutable borrow occurs here
-LL | |         //~^ ERROR cannot borrow `vec` as mutable because it is also borrowed as immutable
-LL | |
-LL | |         0
-LL | |     });
-   | |______- borrow later used here
+LL |     vec.get({
+   |     --- --- immutable borrow later used by call
+   |     |
+   |     immutable borrow occurs here
+LL | 
+LL |         vec.push(2);
+   |         ^^^^^^^^^^^ mutable borrow occurs here
 
 error: aborting due to previous error
 
index a7e1dd95364533bb206d2b95b9b039c272c99f7d..a6d311a7b1de7d383cd8c56ebe20306a987878c0 100644 (file)
@@ -2,21 +2,20 @@ error[E0499]: cannot borrow `foo` as mutable more than once at a time
   --> $DIR/two-phase-multi-mut.rs:23:5
    |
 LL |     foo.method(&mut foo);
-   |     ^^^^^^^^^^^--------^
-   |     |          |
-   |     |          first mutable borrow occurs here
+   |     ^^^^------^--------^
+   |     |   |      |
+   |     |   |      first mutable borrow occurs here
+   |     |   first borrow later used by call
    |     second mutable borrow occurs here
-   |     borrow later used here
 
 error[E0499]: cannot borrow `foo` as mutable more than once at a time
   --> $DIR/two-phase-multi-mut.rs:23:16
    |
 LL |     foo.method(&mut foo);
-   |     -----------^^^^^^^^-
-   |     |          |
-   |     |          second mutable borrow occurs here
+   |     --- ------ ^^^^^^^^ second mutable borrow occurs here
+   |     |   |
+   |     |   first borrow later used by call
    |     first mutable borrow occurs here
-   |     borrow later used here
 
 error: aborting due to 2 previous errors
 
index a8651c0e741bf6ac88461deb023df2e3c13a92d9..a272d2cf019a7f7c92ff0911cfe36a0c818ac1f1 100644 (file)
@@ -2,11 +2,10 @@ error[E0499]: cannot borrow `*f` as mutable more than once at a time
   --> $DIR/two-phase-nonrecv-autoref.rs:70:11
    |
 LL |         f(f(10));
-   |         --^-----
-   |         | |
-   |         | second mutable borrow occurs here
+   |         - ^ second mutable borrow occurs here
+   |         |
    |         first mutable borrow occurs here
-   |         borrow later used here
+   |         first borrow later used by call
 
 error[E0382]: use of moved value: `*f`
   --> $DIR/two-phase-nonrecv-autoref.rs:79:11
@@ -20,11 +19,10 @@ error[E0499]: cannot borrow `*f` as mutable more than once at a time
   --> $DIR/two-phase-nonrecv-autoref.rs:86:11
    |
 LL |         f(f(10));
-   |         --^-----
-   |         | |
-   |         | second mutable borrow occurs here
+   |         - ^ second mutable borrow occurs here
+   |         |
    |         first mutable borrow occurs here
-   |         borrow later used here
+   |         first borrow later used by call
 
 error[E0161]: cannot move a value of type dyn std::ops::FnOnce(i32) -> i32: the size of dyn std::ops::FnOnce(i32) -> i32 cannot be statically determined
   --> $DIR/two-phase-nonrecv-autoref.rs:95:9
@@ -50,11 +48,10 @@ error[E0502]: cannot borrow `a` as immutable because it is also borrowed as muta
   --> $DIR/two-phase-nonrecv-autoref.rs:139:27
    |
 LL |     double_access(&mut a, &a);
-   |     ----------------------^^-
-   |     |             |       |
-   |     |             |       immutable borrow occurs here
+   |     ------------- ------  ^^ immutable borrow occurs here
+   |     |             |
    |     |             mutable borrow occurs here
-   |     borrow later used here
+   |     mutable borrow later used by call
 
 error[E0502]: cannot borrow `i` as immutable because it is also borrowed as mutable
   --> $DIR/two-phase-nonrecv-autoref.rs:167:7
@@ -64,7 +61,7 @@ LL |     i[i[3]] = 4;
    |     | |
    |     | immutable borrow occurs here
    |     mutable borrow occurs here
-   |     borrow later used here
+   |     mutable borrow later used here
 
 error[E0502]: cannot borrow `i` as immutable because it is also borrowed as mutable
   --> $DIR/two-phase-nonrecv-autoref.rs:173:7
@@ -74,7 +71,7 @@ LL |     i[i[3]] = i[4];
    |     | |
    |     | immutable borrow occurs here
    |     mutable borrow occurs here
-   |     borrow later used here
+   |     mutable borrow later used here
 
 error: aborting due to 9 previous errors
 
index a8651c0e741bf6ac88461deb023df2e3c13a92d9..a272d2cf019a7f7c92ff0911cfe36a0c818ac1f1 100644 (file)
@@ -2,11 +2,10 @@ error[E0499]: cannot borrow `*f` as mutable more than once at a time
   --> $DIR/two-phase-nonrecv-autoref.rs:70:11
    |
 LL |         f(f(10));
-   |         --^-----
-   |         | |
-   |         | second mutable borrow occurs here
+   |         - ^ second mutable borrow occurs here
+   |         |
    |         first mutable borrow occurs here
-   |         borrow later used here
+   |         first borrow later used by call
 
 error[E0382]: use of moved value: `*f`
   --> $DIR/two-phase-nonrecv-autoref.rs:79:11
@@ -20,11 +19,10 @@ error[E0499]: cannot borrow `*f` as mutable more than once at a time
   --> $DIR/two-phase-nonrecv-autoref.rs:86:11
    |
 LL |         f(f(10));
-   |         --^-----
-   |         | |
-   |         | second mutable borrow occurs here
+   |         - ^ second mutable borrow occurs here
+   |         |
    |         first mutable borrow occurs here
-   |         borrow later used here
+   |         first borrow later used by call
 
 error[E0161]: cannot move a value of type dyn std::ops::FnOnce(i32) -> i32: the size of dyn std::ops::FnOnce(i32) -> i32 cannot be statically determined
   --> $DIR/two-phase-nonrecv-autoref.rs:95:9
@@ -50,11 +48,10 @@ error[E0502]: cannot borrow `a` as immutable because it is also borrowed as muta
   --> $DIR/two-phase-nonrecv-autoref.rs:139:27
    |
 LL |     double_access(&mut a, &a);
-   |     ----------------------^^-
-   |     |             |       |
-   |     |             |       immutable borrow occurs here
+   |     ------------- ------  ^^ immutable borrow occurs here
+   |     |             |
    |     |             mutable borrow occurs here
-   |     borrow later used here
+   |     mutable borrow later used by call
 
 error[E0502]: cannot borrow `i` as immutable because it is also borrowed as mutable
   --> $DIR/two-phase-nonrecv-autoref.rs:167:7
@@ -64,7 +61,7 @@ LL |     i[i[3]] = 4;
    |     | |
    |     | immutable borrow occurs here
    |     mutable borrow occurs here
-   |     borrow later used here
+   |     mutable borrow later used here
 
 error[E0502]: cannot borrow `i` as immutable because it is also borrowed as mutable
   --> $DIR/two-phase-nonrecv-autoref.rs:173:7
@@ -74,7 +71,7 @@ LL |     i[i[3]] = i[4];
    |     | |
    |     | immutable borrow occurs here
    |     mutable borrow occurs here
-   |     borrow later used here
+   |     mutable borrow later used here
 
 error: aborting due to 9 previous errors
 
index 62a548af62b5ffeb4da71117e8860dcdb3157066..21f54881b004ab1cd0465e4f5100b3548b1af1db 100644 (file)
@@ -8,7 +8,7 @@ LL |         delay = &mut vec;
    |                 ^^^^^^^^ mutable borrow occurs here
 ...
 LL |         shared[0];
-   |         ------ borrow later used here
+   |         ------ immutable borrow later used here
 
 error: aborting due to previous error
 
index 26a6271bbdea20a2e7daba306cb5c750831e4fd2..4847f6cec86c9936d68dc45a6f850723967b4118 100644 (file)
@@ -1,19 +1,13 @@
 error[E0499]: cannot borrow `v` as mutable more than once at a time
   --> $DIR/two-phase-sneaky.rs:22:9
    |
-LL |       v[0].push_str({
-   |       -
-   |       |
-   |  _____first mutable borrow occurs here
-   | |
-LL | |
-LL | |         v.push(format!("foo"));
-   | |         ^ second mutable borrow occurs here
-LL | |         //~^   ERROR cannot borrow `v` as mutable more than once at a time [E0499]
-LL | |
-LL | |         "World!"
-LL | |     });
-   | |______- borrow later used here
+LL |     v[0].push_str({
+   |     -    -------- first borrow later used by call
+   |     |
+   |     first mutable borrow occurs here
+LL | 
+LL |         v.push(format!("foo"));
+   |         ^ second mutable borrow occurs here
 
 error: aborting due to previous error
 
index 1fcd902134113a6484b0cf019c547710543c4e5c..b1f947aceb5c86961c48d39b53ea88f4727ec5d2 100644 (file)
@@ -13,61 +13,57 @@ error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as im
   --> $DIR/two-phase-surprise-no-conflict.rs:79:17
    |
 LL |                 self.hash_expr(&self.cx_mut.body(eid).value);
-   |                 ^^^^^^^^^^^^^^^^-----------^^^^^^^^^^^^^^^^^
-   |                 |               |
-   |                 |               immutable borrow occurs here
+   |                 ^^^^^---------^^-----------^^^^^^^^^^^^^^^^^
+   |                 |    |          |
+   |                 |    |          immutable borrow occurs here
+   |                 |    immutable borrow later used by call
    |                 mutable borrow occurs here
-   |                 borrow later used here
 
 error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
   --> $DIR/two-phase-surprise-no-conflict.rs:151:51
    |
 LL |     reg.register_static(Box::new(TrivialPass::new(&mut reg.sess_mut)));
-   |     ----------------------------------------------^^^^^^^^^^^^^^^^^---
-   |     |                                             |
-   |     |                                             second mutable borrow occurs here
+   |     --- ---------------                           ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
+   |     |   |
+   |     |   first borrow later used by call
    |     first mutable borrow occurs here
-   |     borrow later used here
 
 error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
   --> $DIR/two-phase-surprise-no-conflict.rs:156:54
    |
 LL |     reg.register_bound(Box::new(TrivialPass::new_mut(&mut reg.sess_mut)));
-   |     -------------------------------------------------^^^^^^^^^^^^^^^^^---
-   |     |                                                |
-   |     |                                                second mutable borrow occurs here
+   |     --- --------------                               ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
+   |     |   |
+   |     |   first borrow later used by call
    |     first mutable borrow occurs here
-   |     borrow later used here
 
 error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
   --> $DIR/two-phase-surprise-no-conflict.rs:161:53
    |
 LL |     reg.register_univ(Box::new(TrivialPass::new_mut(&mut reg.sess_mut)));
-   |     ------------------------------------------------^^^^^^^^^^^^^^^^^---
-   |     |                                               |
-   |     |                                               second mutable borrow occurs here
+   |     --- -------------                               ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
+   |     |   |
+   |     |   first borrow later used by call
    |     first mutable borrow occurs here
-   |     borrow later used here
 
 error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
   --> $DIR/two-phase-surprise-no-conflict.rs:166:44
    |
 LL |     reg.register_ref(&TrivialPass::new_mut(&mut reg.sess_mut));
-   |     ---------------------------------------^^^^^^^^^^^^^^^^^--
-   |     |                                      |
-   |     |                                      second mutable borrow occurs here
+   |     --- ------------                       ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
+   |     |   |
+   |     |   first borrow later used by call
    |     first mutable borrow occurs here
-   |     borrow later used here
 
 error[E0502]: cannot borrow `*reg` as mutable because it is also borrowed as immutable
   --> $DIR/two-phase-surprise-no-conflict.rs:178:5
    |
 LL |     reg.register_bound(Box::new(CapturePass::new(&reg.sess_mut)));
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------------^^^
-   |     |                                            |
-   |     |                                            immutable borrow occurs here
+   |     ^^^^--------------^^^^^^^^^^^^^^^^^^^^^^^^^^^-------------^^^
+   |     |   |                                        |
+   |     |   |                                        immutable borrow occurs here
+   |     |   immutable borrow later used by call
    |     mutable borrow occurs here
-   |     borrow later used here
 
 error[E0502]: cannot borrow `*reg` as mutable because it is also borrowed as immutable
   --> $DIR/two-phase-surprise-no-conflict.rs:183:5
@@ -78,7 +74,7 @@ LL |     reg.register_univ(Box::new(CapturePass::new(&reg.sess_mut)));
    |     |                                           immutable borrow occurs here
    |     mutable borrow occurs here
    |
-note: borrowed value must be valid for the lifetime 'a as defined on the function body at 122:21...
+note: immutable borrowed value must be valid for the lifetime 'a as defined on the function body at 122:21...
   --> $DIR/two-phase-surprise-no-conflict.rs:122:21
    |
 LL | fn register_plugins<'a>(mk_reg: impl Fn() -> &'a mut Registry<'a>) {
@@ -88,31 +84,30 @@ error[E0502]: cannot borrow `*reg` as mutable because it is also borrowed as imm
   --> $DIR/two-phase-surprise-no-conflict.rs:188:5
    |
 LL |     reg.register_ref(&CapturePass::new(&reg.sess_mut));
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------------^^
-   |     |                                  |
-   |     |                                  immutable borrow occurs here
+   |     ^^^^------------^^^^^^^^^^^^^^^^^^^-------------^^
+   |     |   |                              |
+   |     |   |                              immutable borrow occurs here
+   |     |   immutable borrow later used by call
    |     mutable borrow occurs here
-   |     borrow later used here
 
 error[E0499]: cannot borrow `*reg` as mutable more than once at a time
   --> $DIR/two-phase-surprise-no-conflict.rs:200:5
    |
 LL |     reg.register_bound(Box::new(CapturePass::new_mut(&mut reg.sess_mut)));
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------^^^
-   |     |                                                |
-   |     |                                                first mutable borrow occurs here
+   |     ^^^^--------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------^^^
+   |     |   |                                            |
+   |     |   |                                            first mutable borrow occurs here
+   |     |   first borrow later used by call
    |     second mutable borrow occurs here
-   |     borrow later used here
 
 error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
   --> $DIR/two-phase-surprise-no-conflict.rs:200:54
    |
 LL |     reg.register_bound(Box::new(CapturePass::new_mut(&mut reg.sess_mut)));
-   |     -------------------------------------------------^^^^^^^^^^^^^^^^^---
-   |     |                                                |
-   |     |                                                second mutable borrow occurs here
+   |     --- --------------                               ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
+   |     |   |
+   |     |   first borrow later used by call
    |     first mutable borrow occurs here
-   |     borrow later used here
 
 error[E0499]: cannot borrow `*reg` as mutable more than once at a time
   --> $DIR/two-phase-surprise-no-conflict.rs:206:5
@@ -123,7 +118,7 @@ LL |     reg.register_univ(Box::new(CapturePass::new_mut(&mut reg.sess_mut)));
    |     |                                               first mutable borrow occurs here
    |     second mutable borrow occurs here
    |
-note: borrowed value must be valid for the lifetime 'a as defined on the function body at 122:21...
+note: first borrowed value must be valid for the lifetime 'a as defined on the function body at 122:21...
   --> $DIR/two-phase-surprise-no-conflict.rs:122:21
    |
 LL | fn register_plugins<'a>(mk_reg: impl Fn() -> &'a mut Registry<'a>) {
@@ -133,31 +128,29 @@ error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
   --> $DIR/two-phase-surprise-no-conflict.rs:206:53
    |
 LL |     reg.register_univ(Box::new(CapturePass::new_mut(&mut reg.sess_mut)));
-   |     ------------------------------------------------^^^^^^^^^^^^^^^^^---
-   |     |                                               |
-   |     |                                               second mutable borrow occurs here
+   |     --- -------------                               ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
+   |     |   |
+   |     |   first borrow later used by call
    |     first mutable borrow occurs here
-   |     borrow later used here
 
 error[E0499]: cannot borrow `*reg` as mutable more than once at a time
   --> $DIR/two-phase-surprise-no-conflict.rs:212:5
    |
 LL |     reg.register_ref(&CapturePass::new_mut(&mut reg.sess_mut));
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------^^
-   |     |                                      |
-   |     |                                      first mutable borrow occurs here
+   |     ^^^^------------^^^^^^^^^^^^^^^^^^^^^^^-----------------^^
+   |     |   |                                  |
+   |     |   |                                  first mutable borrow occurs here
+   |     |   first borrow later used by call
    |     second mutable borrow occurs here
-   |     borrow later used here
 
 error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
   --> $DIR/two-phase-surprise-no-conflict.rs:212:44
    |
 LL |     reg.register_ref(&CapturePass::new_mut(&mut reg.sess_mut));
-   |     ---------------------------------------^^^^^^^^^^^^^^^^^--
-   |     |                                      |
-   |     |                                      second mutable borrow occurs here
+   |     --- ------------                       ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
+   |     |   |
+   |     |   first borrow later used by call
    |     first mutable borrow occurs here
-   |     borrow later used here
 
 error: aborting due to 15 previous errors
 
index f4fc7e54f80e8d4da91689db6b0b008a38dcc091..06ac92b18e1b2716b672f4b81bd367c81a10f75e 100644 (file)
@@ -13,161 +13,145 @@ error[E0502]: cannot borrow `*self.cx` as immutable because it is also borrowed
   --> $DIR/two-phase-surprise-no-conflict.rs:64:33
    |
 LL |                 self.hash_expr(&self.cx.body(eid).value);
-   |                 ----------------^^^^^^^-----------------
-   |                 |               |
-   |                 |               immutable borrow occurs here
+   |                 ---- ---------  ^^^^^^^ immutable borrow occurs here
+   |                 |    |
+   |                 |    mutable borrow later used by call
    |                 mutable borrow occurs here
-   |                 borrow later used here
 
 error[E0502]: cannot borrow `*self.cx_mut` as immutable because it is also borrowed as mutable
   --> $DIR/two-phase-surprise-no-conflict.rs:79:33
    |
 LL |                 self.hash_expr(&self.cx_mut.body(eid).value);
-   |                 ----------------^^^^^^^^^^^-----------------
-   |                 |               |
-   |                 |               immutable borrow occurs here
+   |                 ---- ---------  ^^^^^^^^^^^ immutable borrow occurs here
+   |                 |    |
+   |                 |    mutable borrow later used by call
    |                 mutable borrow occurs here
-   |                 borrow later used here
 
 error[E0502]: cannot borrow `reg.sess_mut` as immutable because it is also borrowed as mutable
   --> $DIR/two-phase-surprise-no-conflict.rs:131:51
    |
 LL |     reg.register_static(Box::new(TrivialPass::new(&reg.sess_mut)));
-   |     ----------------------------------------------^^^^^^^^^^^^^---
-   |     |                                             |
-   |     |                                             immutable borrow occurs here
+   |     --- ---------------                           ^^^^^^^^^^^^^ immutable borrow occurs here
+   |     |   |
+   |     |   mutable borrow later used by call
    |     mutable borrow occurs here
-   |     borrow later used here
 
 error[E0502]: cannot borrow `reg.sess_mut` as immutable because it is also borrowed as mutable
   --> $DIR/two-phase-surprise-no-conflict.rs:135:50
    |
 LL |     reg.register_bound(Box::new(TrivialPass::new(&reg.sess_mut)));
-   |     ---------------------------------------------^^^^^^^^^^^^^---
-   |     |                                            |
-   |     |                                            immutable borrow occurs here
+   |     --- --------------                           ^^^^^^^^^^^^^ immutable borrow occurs here
+   |     |   |
+   |     |   mutable borrow later used by call
    |     mutable borrow occurs here
-   |     borrow later used here
 
 error[E0502]: cannot borrow `reg.sess_mut` as immutable because it is also borrowed as mutable
   --> $DIR/two-phase-surprise-no-conflict.rs:139:49
    |
 LL |     reg.register_univ(Box::new(TrivialPass::new(&reg.sess_mut)));
-   |     --------------------------------------------^^^^^^^^^^^^^---
-   |     |                                           |
-   |     |                                           immutable borrow occurs here
+   |     --- -------------                           ^^^^^^^^^^^^^ immutable borrow occurs here
+   |     |   |
+   |     |   mutable borrow later used by call
    |     mutable borrow occurs here
-   |     borrow later used here
 
 error[E0502]: cannot borrow `reg.sess_mut` as immutable because it is also borrowed as mutable
   --> $DIR/two-phase-surprise-no-conflict.rs:143:40
    |
 LL |     reg.register_ref(&TrivialPass::new(&reg.sess_mut));
-   |     -----------------------------------^^^^^^^^^^^^^--
-   |     |                                  |
-   |     |                                  immutable borrow occurs here
+   |     --- ------------                   ^^^^^^^^^^^^^ immutable borrow occurs here
+   |     |   |
+   |     |   mutable borrow later used by call
    |     mutable borrow occurs here
-   |     borrow later used here
 
 error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
   --> $DIR/two-phase-surprise-no-conflict.rs:151:51
    |
 LL |     reg.register_static(Box::new(TrivialPass::new(&mut reg.sess_mut)));
-   |     ----------------------------------------------^^^^^^^^^^^^^^^^^---
-   |     |                                             |
-   |     |                                             second mutable borrow occurs here
+   |     --- ---------------                           ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
+   |     |   |
+   |     |   first borrow later used by call
    |     first mutable borrow occurs here
-   |     borrow later used here
 
 error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
   --> $DIR/two-phase-surprise-no-conflict.rs:156:54
    |
 LL |     reg.register_bound(Box::new(TrivialPass::new_mut(&mut reg.sess_mut)));
-   |     -------------------------------------------------^^^^^^^^^^^^^^^^^---
-   |     |                                                |
-   |     |                                                second mutable borrow occurs here
+   |     --- --------------                               ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
+   |     |   |
+   |     |   first borrow later used by call
    |     first mutable borrow occurs here
-   |     borrow later used here
 
 error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
   --> $DIR/two-phase-surprise-no-conflict.rs:161:53
    |
 LL |     reg.register_univ(Box::new(TrivialPass::new_mut(&mut reg.sess_mut)));
-   |     ------------------------------------------------^^^^^^^^^^^^^^^^^---
-   |     |                                               |
-   |     |                                               second mutable borrow occurs here
+   |     --- -------------                               ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
+   |     |   |
+   |     |   first borrow later used by call
    |     first mutable borrow occurs here
-   |     borrow later used here
 
 error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
   --> $DIR/two-phase-surprise-no-conflict.rs:166:44
    |
 LL |     reg.register_ref(&TrivialPass::new_mut(&mut reg.sess_mut));
-   |     ---------------------------------------^^^^^^^^^^^^^^^^^--
-   |     |                                      |
-   |     |                                      second mutable borrow occurs here
+   |     --- ------------                       ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
+   |     |   |
+   |     |   first borrow later used by call
    |     first mutable borrow occurs here
-   |     borrow later used here
 
 error[E0502]: cannot borrow `reg.sess_mut` as immutable because it is also borrowed as mutable
   --> $DIR/two-phase-surprise-no-conflict.rs:178:50
    |
 LL |     reg.register_bound(Box::new(CapturePass::new(&reg.sess_mut)));
-   |     ---------------------------------------------^^^^^^^^^^^^^---
-   |     |                                            |
-   |     |                                            immutable borrow occurs here
+   |     --- --------------                           ^^^^^^^^^^^^^ immutable borrow occurs here
+   |     |   |
+   |     |   mutable borrow later used by call
    |     mutable borrow occurs here
-   |     borrow later used here
 
 error[E0502]: cannot borrow `reg.sess_mut` as immutable because it is also borrowed as mutable
   --> $DIR/two-phase-surprise-no-conflict.rs:183:49
    |
 LL |     reg.register_univ(Box::new(CapturePass::new(&reg.sess_mut)));
-   |     --------------------------------------------^^^^^^^^^^^^^---
-   |     |                                           |
-   |     |                                           immutable borrow occurs here
+   |     --- -------------                           ^^^^^^^^^^^^^ immutable borrow occurs here
+   |     |   |
+   |     |   mutable borrow later used by call
    |     mutable borrow occurs here
-   |     borrow later used here
 
 error[E0502]: cannot borrow `reg.sess_mut` as immutable because it is also borrowed as mutable
   --> $DIR/two-phase-surprise-no-conflict.rs:188:40
    |
 LL |     reg.register_ref(&CapturePass::new(&reg.sess_mut));
-   |     -----------------------------------^^^^^^^^^^^^^--
-   |     |                                  |
-   |     |                                  immutable borrow occurs here
+   |     --- ------------                   ^^^^^^^^^^^^^ immutable borrow occurs here
+   |     |   |
+   |     |   mutable borrow later used by call
    |     mutable borrow occurs here
-   |     borrow later used here
 
 error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
   --> $DIR/two-phase-surprise-no-conflict.rs:200:54
    |
 LL |     reg.register_bound(Box::new(CapturePass::new_mut(&mut reg.sess_mut)));
-   |     -------------------------------------------------^^^^^^^^^^^^^^^^^---
-   |     |                                                |
-   |     |                                                second mutable borrow occurs here
+   |     --- --------------                               ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
+   |     |   |
+   |     |   first borrow later used by call
    |     first mutable borrow occurs here
-   |     borrow later used here
 
 error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
   --> $DIR/two-phase-surprise-no-conflict.rs:206:53
    |
 LL |     reg.register_univ(Box::new(CapturePass::new_mut(&mut reg.sess_mut)));
-   |     ------------------------------------------------^^^^^^^^^^^^^^^^^---
-   |     |                                               |
-   |     |                                               second mutable borrow occurs here
+   |     --- -------------                               ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
+   |     |   |
+   |     |   first borrow later used by call
    |     first mutable borrow occurs here
-   |     borrow later used here
 
 error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
   --> $DIR/two-phase-surprise-no-conflict.rs:212:44
    |
 LL |     reg.register_ref(&CapturePass::new_mut(&mut reg.sess_mut));
-   |     ---------------------------------------^^^^^^^^^^^^^^^^^--
-   |     |                                      |
-   |     |                                      second mutable borrow occurs here
+   |     --- ------------                       ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here
+   |     |   |
+   |     |   first borrow later used by call
    |     first mutable borrow occurs here
-   |     borrow later used here
 
 error: aborting due to 17 previous errors
 
index d6673f6a8a6fb6b77b506d79f4438ac9f11378a4..4a3e14ac034721e712f53e07ad4fde770f20056f 100644 (file)
@@ -5,9 +5,8 @@ LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
-   = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
    = note: Implemented(Self: Bar) :- FromEnv(Self: Bar).
-   = note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Foo), WellFormed(Self: Foo).
+   = note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Foo).
 
 error: program clause dump
   --> $DIR/lower_env1.rs:19:1
@@ -16,11 +15,10 @@ LL | #[rustc_dump_env_program_clauses] //~ ERROR program clause dump
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
-   = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
    = note: Implemented(Self: Bar) :- FromEnv(Self: Bar).
    = note: Implemented(Self: Foo) :- FromEnv(Self: Foo).
    = note: Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized).
-   = note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Foo), WellFormed(Self: Foo).
+   = note: WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Foo).
    = note: WellFormed(Self: Foo) :- Implemented(Self: Foo).
    = note: WellFormed(Self: std::marker::Sized) :- Implemented(Self: std::marker::Sized).
 
index c0eeb63447d550e46ef119b01e0cff508a5743a8..76ed3bc31370e94827cb80532189ef79bafc0fe0 100644 (file)
@@ -7,7 +7,7 @@ LL |     let z = &mut x; //~ ERROR cannot borrow
    |             ^^^^^^ second mutable borrow occurs here
 LL |     z.use_mut();
 LL |     y.use_mut();
-   |     - borrow later used here
+   |     - first borrow later used here
 
 error: aborting due to previous error
 
index 52ce3787f5885c1932aa09e8017cc1c87cdf9941..d79405e9a59b2d2a5c96652c971fa084e93402ce 100644 (file)
@@ -2,11 +2,10 @@ error[E0499]: cannot borrow `v` as mutable more than once at a time
   --> $DIR/one_line.rs:13:12
    |
 LL |     v.push(v.pop().unwrap()); //~ ERROR cannot borrow
-   |     -------^----------------
-   |     |      |
-   |     |      second mutable borrow occurs here
+   |     - ---- ^ second mutable borrow occurs here
+   |     | |
+   |     | first borrow later used by call
    |     first mutable borrow occurs here
-   |     borrow later used here
 
 error: aborting due to previous error
 
index 29b6f0575627c6de4bf930a4b42bf9f1eececf73..60584e481c125f4724b799cf1fbd5cad99375be8 100644 (file)
@@ -7,7 +7,7 @@ LL |     let z = borrow_mut(x);
    |                        ^ second mutable borrow occurs here
 ...
 LL |     drop((y, z));
-   |           - borrow later used here
+   |           - first borrow later used here
 
 error[E0506]: cannot assign to `**x` because it is borrowed
   --> $DIR/coerce-overloaded-autoderef.rs:31:5
@@ -25,21 +25,20 @@ error[E0499]: cannot borrow `*x` as mutable more than once at a time
   --> $DIR/coerce-overloaded-autoderef.rs:38:20
    |
 LL |     borrow_mut2(x, x);
-   |     ---------------^-
-   |     |           |  |
-   |     |           |  second mutable borrow occurs here
+   |     ----------- -  ^ second mutable borrow occurs here
+   |     |           |
    |     |           first mutable borrow occurs here
-   |     borrow later used here
+   |     first borrow later used by call
 
 error[E0502]: cannot borrow `*x` as mutable because it is also borrowed as immutable
   --> $DIR/coerce-overloaded-autoderef.rs:44:5
    |
 LL |     borrow2(x, x);
-   |     ^^^^^^^^^^^-^
+   |     -------^^^^-^
    |     |          |
    |     |          immutable borrow occurs here
    |     mutable borrow occurs here
-   |     borrow later used here
+   |     immutable borrow later used by call
 
 error: aborting due to 4 previous errors
 
index 29b6f0575627c6de4bf930a4b42bf9f1eececf73..60584e481c125f4724b799cf1fbd5cad99375be8 100644 (file)
@@ -7,7 +7,7 @@ LL |     let z = borrow_mut(x);
    |                        ^ second mutable borrow occurs here
 ...
 LL |     drop((y, z));
-   |           - borrow later used here
+   |           - first borrow later used here
 
 error[E0506]: cannot assign to `**x` because it is borrowed
   --> $DIR/coerce-overloaded-autoderef.rs:31:5
@@ -25,21 +25,20 @@ error[E0499]: cannot borrow `*x` as mutable more than once at a time
   --> $DIR/coerce-overloaded-autoderef.rs:38:20
    |
 LL |     borrow_mut2(x, x);
-   |     ---------------^-
-   |     |           |  |
-   |     |           |  second mutable borrow occurs here
+   |     ----------- -  ^ second mutable borrow occurs here
+   |     |           |
    |     |           first mutable borrow occurs here
-   |     borrow later used here
+   |     first borrow later used by call
 
 error[E0502]: cannot borrow `*x` as mutable because it is also borrowed as immutable
   --> $DIR/coerce-overloaded-autoderef.rs:44:5
    |
 LL |     borrow2(x, x);
-   |     ^^^^^^^^^^^-^
+   |     -------^^^^-^
    |     |          |
    |     |          immutable borrow occurs here
    |     mutable borrow occurs here
-   |     borrow later used here
+   |     immutable borrow later used by call
 
 error: aborting due to 4 previous errors
 
index fbc49a7e91f8842fc4fe83e49b9d48e46b3f7888..0ca752b5ff9d36a583538b6bbba03571bbd5da83 100644 (file)
@@ -7,7 +7,7 @@ LL |     let z = borrow_mut(x);
    |                        ^ second mutable borrow occurs here
 ...
 LL |     drop((y, z));
-   |           - borrow later used here
+   |           - first borrow later used here
 
 error[E0506]: cannot assign to `**x` because it is borrowed
   --> $DIR/coerce-overloaded-autoderef.rs:31:5
@@ -25,21 +25,19 @@ error[E0499]: cannot borrow `*x` as mutable more than once at a time
   --> $DIR/coerce-overloaded-autoderef.rs:38:20
    |
 LL |     borrow_mut2(x, x);
-   |     ---------------^-
-   |     |           |  |
-   |     |           |  second mutable borrow occurs here
+   |     ----------- -  ^ second mutable borrow occurs here
+   |     |           |
    |     |           first mutable borrow occurs here
-   |     borrow later used here
+   |     first borrow later used by call
 
 error[E0502]: cannot borrow `*x` as immutable because it is also borrowed as mutable
   --> $DIR/coerce-overloaded-autoderef.rs:44:16
    |
 LL |     borrow2(x, x);
-   |     -----------^-
-   |     |       |  |
-   |     |       |  immutable borrow occurs here
+   |     ------- -  ^ immutable borrow occurs here
+   |     |       |
    |     |       mutable borrow occurs here
-   |     borrow later used here
+   |     mutable borrow later used by call
 
 error: aborting due to 4 previous errors
 
index 004c43a7343f802e19bb0d3963cd896e8f927ab1..8e29dccb8a709ee0f489bc6a65a96e31e0d238bf 100644 (file)
@@ -11,11 +11,10 @@ error[E0502]: cannot borrow `self` as mutable because it is also borrowed as imm
   --> $DIR/issue-34126.rs:16:18
    |
 LL |         self.run(&mut self); //~ ERROR cannot borrow
-   |         ---------^^^^^^^^^-
-   |         |        |
-   |         |        mutable borrow occurs here
+   |         ---- --- ^^^^^^^^^ mutable borrow occurs here
+   |         |    |
+   |         |    immutable borrow later used by call
    |         immutable borrow occurs here
-   |         borrow later used here
 
 error: aborting due to 2 previous errors
 
index b59f628c746bb775a76f56f29ad6be7eb9b2ff90..e0b7fc4eb905451ccc32be5023b989ad6d616176 100644 (file)
@@ -8,7 +8,7 @@ LL | }
    | -
    | |
    | `c_shortest` dropped here while still borrowed
-   | borrow later used here, when `dt` is dropped
+   | borrow might be used here, when `dt` is dropped and runs the `Drop` code for type `other::Dt`
    |
    = note: values in a scope are dropped in the opposite order they are defined
 
index ad460fcf55e57d4cda386772cd6a795d88c1cfad..97c1caa87f5c5e9d997397335f842ef4ab4c0fe8 100644 (file)
@@ -8,7 +8,7 @@ LL | }
    | -
    | |
    | `c_shortest` dropped here while still borrowed
-   | borrow later used here, when `dt` is dropped
+   | borrow might be used here, when `dt` is dropped and runs the `Drop` code for type `Dt`
    |
    = note: values in a scope are dropped in the opposite order they are defined
 
index 864fb2f2ea6f43934fd2b97cc0523c3a65bd45b5..4a6e42ef94a85dad316386acce2d4f4802bd03db 100644 (file)
@@ -8,7 +8,7 @@ LL | }
    | -
    | |
    | `c_shortest` dropped here while still borrowed
-   | borrow later used here, when `dt` is dropped
+   | borrow might be used here, when `dt` is dropped and runs the `Drop` code for type `Dt`
    |
    = note: values in a scope are dropped in the opposite order they are defined
 
index ffb322b85dc34232d46ced6e0748bc4de5db078d..b828a16756101d27f9ed66cdccabbb85013e5209 100644 (file)
@@ -7,7 +7,7 @@ LL | }
    | -
    | |
    | `v` dropped here while still borrowed
-   | borrow later used here, when `v` is dropped
+   | borrow might be used here, when `v` is dropped and runs the `Drop` code for type `Wrap`
 
 error: aborting due to previous error
 
index 89801693b763ce6fde3b245680ced87b24a6bbe5..39815ac6f1766f5c5ee0266bb36cfbf32297e350 100644 (file)
@@ -7,7 +7,7 @@ LL |     let mut a = &mut i; //~ ERROR E0499
    |                 ^^^^^^ second mutable borrow occurs here
 LL |     a.use_mut();
 LL |     x.use_mut();
-   |     - borrow later used here
+   |     - first borrow later used here
 
 error: aborting due to previous error
 
index 565f73616b9fe313b5e03134424ba85eab72a682..ce0827102469800fa9b9700a6132ab516ea5141f 100644 (file)
@@ -6,7 +6,7 @@ LL |     let ref y = a;
 LL |     bar(a); //~ ERROR E0502
    |     ^^^^^^ mutable borrow occurs here
 LL |     y.use_ref();
-   |     - borrow later used here
+   |     - immutable borrow later used here
 
 error: aborting due to previous error
 
index 31ba24b0004fb4e68dcf9ce41e408ca8b87c0fce..54a46f612b9ed645be11e7a1c7c787b842a1c7f3 100644 (file)
@@ -8,7 +8,7 @@ LL | }
    | -
    | |
    | `y` dropped here while still borrowed
-   | borrow later used here, when `x` is dropped
+   | borrow might be used here, when `x` is dropped and runs the `Drop` code for type `Foo`
    |
    = note: values in a scope are dropped in the opposite order they are defined
 
index dd235cb9c3aa99aca11448d031af4be7e1cd09f6..bbddbb7d679a8ded69b3119fba4dffbe869ad8a5 100644 (file)
@@ -393,7 +393,6 @@ mod no_mangle {
     mod inner { #![no_mangle="3500"] }
 
     #[no_mangle = "3500"] fn f() { }
-    //~^ WARN function is marked #[no_mangle], but not exported
 
     #[no_mangle = "3500"] struct S;
 
index fd38fb6f9764196d3fce28abd8c451c55edbf24e..3b31b411f3f56785f37b012850a1bf58c1dd7664 100644 (file)
@@ -173,13 +173,13 @@ LL |     #[deny(x5100)] impl S { }
    |            ^^^^^
 
 warning: macro_escape is a deprecated synonym for macro_use
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:501:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:500:1
    |
 LL | #[macro_escape]
    | ^^^^^^^^^^^^^^^
 
 warning: macro_escape is a deprecated synonym for macro_use
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:504:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:503:17
    |
 LL |     mod inner { #![macro_escape] }
    |                 ^^^^^^^^^^^^^^^^
@@ -523,720 +523,710 @@ warning: unused attribute
 LL | #[automatically_derived = "3600"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: function is marked #[no_mangle], but not exported
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:395:27
-   |
-LL |     #[no_mangle = "3500"] fn f() { }
-   |                           -^^^^^^^^^
-   |                           |
-   |                           help: try making it public: `pub`
-   |
-   = note: #[warn(private_no_mangle_fns)] on by default
-
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:408:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:407:17
    |
 LL |     mod inner { #![no_link="3400"] }
    |                 ^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:411:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:410:5
    |
 LL |     #[no_link = "3400"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:414:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:413:5
    |
 LL |     #[no_link = "3400"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:417:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:416:5
    |
 LL |     #[no_link = "3400"]type T = S;
    |     ^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:420:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:419:5
    |
 LL |     #[no_link = "3400"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:405:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:404:1
    |
 LL | #[no_link = "3400"]
    | ^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:427:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:426:17
    |
 LL |     mod inner { #![should_panic="3200"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:430:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:429:5
    |
 LL |     #[should_panic = "3200"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:433:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:432:5
    |
 LL |     #[should_panic = "3200"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:436:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:435:5
    |
 LL |     #[should_panic = "3200"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:439:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:438:5
    |
 LL |     #[should_panic = "3200"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:424:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:423:1
    |
 LL | #[should_panic = "3200"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:446:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:445:17
    |
 LL |     mod inner { #![ignore="3100"] }
    |                 ^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:449:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:448:5
    |
 LL |     #[ignore = "3100"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:452:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:451:5
    |
 LL |     #[ignore = "3100"] struct S;
    |     ^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:455:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:454:5
    |
 LL |     #[ignore = "3100"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:458:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:457:5
    |
 LL |     #[ignore = "3100"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:443:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:442:1
    |
 LL | #[ignore = "3100"]
    | ^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:465:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:464:17
    |
 LL |     mod inner { #![no_implicit_prelude="3000"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:468:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:467:5
    |
 LL |     #[no_implicit_prelude = "3000"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:471:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:470:5
    |
 LL |     #[no_implicit_prelude = "3000"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:474:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:473:5
    |
 LL |     #[no_implicit_prelude = "3000"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:477:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:476:5
    |
 LL |     #[no_implicit_prelude = "3000"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:462:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:461:1
    |
 LL | #[no_implicit_prelude = "3000"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:484:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:483:17
    |
 LL |     mod inner { #![reexport_test_harness_main="2900"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:487:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:486:5
    |
 LL |     #[reexport_test_harness_main = "2900"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:490:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:489:5
    |
 LL |     #[reexport_test_harness_main = "2900"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:493:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:492:5
    |
 LL |     #[reexport_test_harness_main = "2900"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:496:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:495:5
    |
 LL |     #[reexport_test_harness_main = "2900"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:481:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:480:1
    |
 LL | #[reexport_test_harness_main = "2900"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:507:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:506:5
    |
 LL |     #[macro_escape] fn f() { }
    |     ^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:510:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:509:5
    |
 LL |     #[macro_escape] struct S;
    |     ^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:513:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:512:5
    |
 LL |     #[macro_escape] type T = S;
    |     ^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:516:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:515:5
    |
 LL |     #[macro_escape] impl S { }
    |     ^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:524:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:523:17
    |
 LL |     mod inner { #![no_std="2600"] }
    |                 ^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:524:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:523:17
    |
 LL |     mod inner { #![no_std="2600"] }
    |                 ^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:528:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:527:5
    |
 LL |     #[no_std = "2600"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:528:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:527:5
    |
 LL |     #[no_std = "2600"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:532:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:531:5
    |
 LL |     #[no_std = "2600"] struct S;
    |     ^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:532:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:531:5
    |
 LL |     #[no_std = "2600"] struct S;
    |     ^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:536:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:535:5
    |
 LL |     #[no_std = "2600"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:536:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:535:5
    |
 LL |     #[no_std = "2600"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:540:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:539:5
    |
 LL |     #[no_std = "2600"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:540:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:539:5
    |
 LL |     #[no_std = "2600"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:520:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:519:1
    |
 LL | #[no_std = "2600"]
    | ^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:520:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:519:1
    |
 LL | #[no_std = "2600"]
    | ^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:679:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:678:17
    |
 LL |     mod inner { #![crate_name="0900"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:679:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:678:17
    |
 LL |     mod inner { #![crate_name="0900"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:683:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:682:5
    |
 LL |     #[crate_name = "0900"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:683:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:682:5
    |
 LL |     #[crate_name = "0900"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:687:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:686:5
    |
 LL |     #[crate_name = "0900"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:687:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:686:5
    |
 LL |     #[crate_name = "0900"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:691:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:690:5
    |
 LL |     #[crate_name = "0900"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:691:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:690:5
    |
 LL |     #[crate_name = "0900"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:695:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:694:5
    |
 LL |     #[crate_name = "0900"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:695:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:694:5
    |
 LL |     #[crate_name = "0900"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:675:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:674:1
    |
 LL | #[crate_name = "0900"]
    | ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:675:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:674:1
    |
 LL | #[crate_name = "0900"]
    | ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:704:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:703:17
    |
 LL |     mod inner { #![crate_type="0800"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:704:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:703:17
    |
 LL |     mod inner { #![crate_type="0800"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:708:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:707:5
    |
 LL |     #[crate_type = "0800"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:708:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:707:5
    |
 LL |     #[crate_type = "0800"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:712:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:711:5
    |
 LL |     #[crate_type = "0800"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:712:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:711:5
    |
 LL |     #[crate_type = "0800"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:716:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:715:5
    |
 LL |     #[crate_type = "0800"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:716:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:715:5
    |
 LL |     #[crate_type = "0800"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:720:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:719:5
    |
 LL |     #[crate_type = "0800"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:720:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:719:5
    |
 LL |     #[crate_type = "0800"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:700:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:699:1
    |
 LL | #[crate_type = "0800"]
    | ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:700:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:699:1
    |
 LL | #[crate_type = "0800"]
    | ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:729:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:728:17
    |
 LL |     mod inner { #![feature(x0600)] }
    |                 ^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:729:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:728:17
    |
 LL |     mod inner { #![feature(x0600)] }
    |                 ^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:733:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:732:5
    |
 LL |     #[feature(x0600)] fn f() { }
    |     ^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:733:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:732:5
    |
 LL |     #[feature(x0600)] fn f() { }
    |     ^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:737:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:736:5
    |
 LL |     #[feature(x0600)] struct S;
    |     ^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:737:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:736:5
    |
 LL |     #[feature(x0600)] struct S;
    |     ^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:741:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:740:5
    |
 LL |     #[feature(x0600)] type T = S;
    |     ^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:741:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:740:5
    |
 LL |     #[feature(x0600)] type T = S;
    |     ^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:745:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:744:5
    |
 LL |     #[feature(x0600)] impl S { }
    |     ^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:745:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:744:5
    |
 LL |     #[feature(x0600)] impl S { }
    |     ^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:725:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:724:1
    |
 LL | #[feature(x0600)]
    | ^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:725:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:724:1
    |
 LL | #[feature(x0600)]
    | ^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:755:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:754:17
    |
 LL |     mod inner { #![no_main="0400"] }
    |                 ^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:755:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:754:17
    |
 LL |     mod inner { #![no_main="0400"] }
    |                 ^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:759:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:758:5
    |
 LL |     #[no_main = "0400"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:759:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:758:5
    |
 LL |     #[no_main = "0400"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:763:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:762:5
    |
 LL |     #[no_main = "0400"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:763:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:762:5
    |
 LL |     #[no_main = "0400"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:767:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:766:5
    |
 LL |     #[no_main = "0400"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:767:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:766:5
    |
 LL |     #[no_main = "0400"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:771:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:770:5
    |
 LL |     #[no_main = "0400"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:771:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:770:5
    |
 LL |     #[no_main = "0400"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:751:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:750:1
    |
 LL | #[no_main = "0400"]
    | ^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:751:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:750:1
    |
 LL | #[no_main = "0400"]
    | ^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:793:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:792:17
    |
 LL |     mod inner { #![recursion_limit="0200"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:793:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:792:17
    |
 LL |     mod inner { #![recursion_limit="0200"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:797:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:796:5
    |
 LL |     #[recursion_limit="0200"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:797:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:796:5
    |
 LL |     #[recursion_limit="0200"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:801:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:800:5
    |
 LL |     #[recursion_limit="0200"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:801:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:800:5
    |
 LL |     #[recursion_limit="0200"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:805:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:804:5
    |
 LL |     #[recursion_limit="0200"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:805:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:804:5
    |
 LL |     #[recursion_limit="0200"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:809:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:808:5
    |
 LL |     #[recursion_limit="0200"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:809:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:808:5
    |
 LL |     #[recursion_limit="0200"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:789:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:788:1
    |
 LL | #[recursion_limit="0200"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:789:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:788:1
    |
 LL | #[recursion_limit="0200"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:818:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:817:17
    |
 LL |     mod inner { #![type_length_limit="0100"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:818:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:817:17
    |
 LL |     mod inner { #![type_length_limit="0100"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:822:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:821:5
    |
 LL |     #[type_length_limit="0100"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:822:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:821:5
    |
 LL |     #[type_length_limit="0100"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:826:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:825:5
    |
 LL |     #[type_length_limit="0100"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:826:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:825:5
    |
 LL |     #[type_length_limit="0100"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:830:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:829:5
    |
 LL |     #[type_length_limit="0100"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:830:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:829:5
    |
 LL |     #[type_length_limit="0100"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:834:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:833:5
    |
 LL |     #[type_length_limit="0100"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:834:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:833:5
    |
 LL |     #[type_length_limit="0100"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: unused attribute
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:814:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:813:1
    |
 LL | #[type_length_limit="0100"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be an inner attribute: add an exclamation mark: #![foo]
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:814:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:813:1
    |
 LL | #[type_length_limit="0100"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -1314,7 +1304,7 @@ LL | #![proc_macro_derive          = "2500"] //~ WARN unused attribute
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: compilation successful
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:845:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:844:1
    |
 LL | / fn main() { //~ ERROR compilation successful
 LL | |     println!("Hello World");
index 2488df7772b3f08383a50f1fb21b7751069b9fc6..9d1a52a8335433845b91259c589bdfd71f62c432 100644 (file)
@@ -2,10 +2,17 @@ error[E0597]: `a` does not live long enough
   --> $DIR/borrowing.rs:18:18
    |
 LL |         unsafe { (|| yield &a).resume() }
-   |                  ^^^^^^^^^^^^^ borrowed value does not live long enough
+   |                  ^^^^^^^^^^^^^
+   |                  |
+   |                  borrowed value does not live long enough
+   |                  a temporary with access to the borrow is created here ...
 LL |         //~^ ERROR: `a` does not live long enough
 LL |     };
-   |     - `a` dropped here while still borrowed
+   |     -- ... and the borrow might be used here, when that temporary is dropped and runs the destructor for generator
+   |     |
+   |     `a` dropped here while still borrowed
+   |
+   = note: The temporary is part of an expression at the end of a block. Consider forcing this temporary to be dropped sooner, before the block's local variables are dropped. For example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block.
 
 error[E0597]: `a` does not live long enough
   --> $DIR/borrowing.rs:24:9
index ef7e64ffd97ae251494a68b10e5b8548955c115b..2b95a5caf6da07b7667785355da936cd3eadb029 100644 (file)
@@ -8,7 +8,7 @@ LL | }
    | -
    | |
    | `*cell` dropped here while still borrowed
-   | borrow later used here, when `gen` is dropped
+   | borrow might be used here, when `gen` is dropped and runs the destructor for generator
    |
    = note: values in a scope are dropped in the opposite order they are defined
 
@@ -27,7 +27,7 @@ LL |   }
    |   -
    |   |
    |   `ref_` dropped here while still borrowed
-   |   borrow later used here, when `gen` is dropped
+   |   borrow might be used here, when `gen` is dropped and runs the destructor for generator
    |
    = note: values in a scope are dropped in the opposite order they are defined
 
index af79eb7ac054fb8b84862a58c04f3cd41f62f78d..d332df6e4ba4667bc7465d19853d3abe447596a8 100644 (file)
@@ -19,7 +19,7 @@ LL | |     };
 LL |       println!("{}", x[0]); //~ ERROR
    |                      ^ immutable borrow occurs here
 LL |       b.resume();
-   |       - borrow later used here
+   |       - mutable borrow later used here
 
 error: aborting due to 2 previous errors
 
index 14989079527415fc32f9f7c30e133e742bb63997..b5c392c51ece5cb77b2627f5d3ed020c4f64e954 100644 (file)
@@ -11,7 +11,7 @@ LL | |     };
 LL |       println!("{}", x); //~ ERROR
    |                      ^ borrow occurs here
 LL |       b.resume();
-   |       - borrow later used here
+   |       - first borrow later used here
 
 error: aborting due to previous error
 
index ec52d19cd1c5879d405ce330e802e226f99ffb1c..61a28bfd17b2e8a5ff2c8df648d6f34eea6fb9cc 100644 (file)
@@ -8,7 +8,7 @@ LL |     my_stuff.clear(); //~ ERROR cannot borrow
    |     ^^^^^^^^^^^^^^^^ mutable borrow occurs here
 LL | 
 LL |     println!("{}", *thing);
-   |                    ------ borrow later used here
+   |                    ------ immutable borrow later used here
 
 error: aborting due to previous error
 
index 943b684fe8d7703c836fd2853abdfd2bece43086..4cf87ee8dc75b7af983d75844b90ca8476c7ce02 100644 (file)
@@ -6,7 +6,7 @@ LL |     let mut it = my_stuff.iter();
 LL |     my_stuff.insert(1, 43); //~ ERROR cannot borrow
    |     ^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
 LL |     it;
-   |     -- borrow later used here
+   |     -- immutable borrow later used here
 
 error: aborting due to previous error
 
index 0697022932504a08f283ed5e9b1df39379445d94..10d028b05a78beae3b43141118cfa9cf656c3122 100644 (file)
@@ -7,7 +7,7 @@ LL |     foo.insert(); //~ ERROR cannot borrow
    |     ^^^
    |     |
    |     second mutable borrow occurs here
-   |     borrow later used here
+   |     first borrow later used here
 
 error: aborting due to previous error
 
index 56dfee1fe33c1e43bd826edadce36b94c0ab9267..4130ad7639fe288d215154256a6b4fff7291059d 100644 (file)
@@ -7,7 +7,7 @@ LL |     let S { 0: ref mut borrow2 } = s;
    |                ^^^^^^^^^^^^^^^ second mutable borrow occurs here
 ...
 LL |     borrow1.use_mut();
-   |     ------- borrow later used here
+   |     ------- first borrow later used here
 
 error: aborting due to previous error
 
index bbd75f30d6cb13ca69a05af3d2319dafc4133c03..6f051b40e8b65eaf2959e41f0ada2fc7625860b4 100644 (file)
@@ -71,4 +71,18 @@ fn main() {
 
     "##);
     //~^^^ ERROR: there is no argument named `foo`
+
+    // bad syntax in format string with multiple newlines, #53836
+    format!("first number: {}
+second number: {}
+third number: {}
+fourth number: {}
+fifth number: {}
+sixth number: {}
+seventh number: {}
+eighth number: {}
+ninth number: {
+tenth number: {}",
+        1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+    //~^^ ERROR: invalid format string
 }
index c8fd8bad19ba54402f1f3176ef4280ab4004288a..7e71707c22b16705c74bdd174d1e0f12fed88a9c 100644 (file)
@@ -204,5 +204,11 @@ error: there is no argument named `foo`
 LL |         {foo}
    |         ^^^^^
 
-error: aborting due to 27 previous errors
+error: invalid format string: expected `'}'`, found `'t'`
+  --> $DIR/ifmt-bad-arg.rs:85:1
+   |
+LL | tenth number: {}",
+   | ^ expected `}` in format string
+
+error: aborting due to 28 previous errors
 
diff --git a/src/test/ui/impl-trait/deprecated_annotation.rs b/src/test/ui/impl-trait/deprecated_annotation.rs
new file mode 100644 (file)
index 0000000..dd9f5fd
--- /dev/null
@@ -0,0 +1,19 @@
+// compile-pass
+
+#![deny(warnings)]
+
+#[deprecated]
+trait Deprecated {}
+
+#[deprecated]
+struct DeprecatedTy;
+
+#[allow(deprecated)]
+impl Deprecated for DeprecatedTy {}
+
+#[allow(deprecated)]
+fn foo() -> impl Deprecated { DeprecatedTy }
+
+fn main() {
+    foo();
+}
index e554bbb4f3146073d85a8c96baaf920da8c3db17..7e5ab0c5abe07596fa3cfaac5249cd1f18b62b47 100644 (file)
@@ -1,20 +1,3 @@
-error[E0659]: `panic` is ambiguous
-  --> $DIR/shadow_builtin_macros.rs:43:5
-   |
-LL |     panic!(); //~ ERROR `panic` is ambiguous
-   |     ^^^^^ ambiguous name
-   |
-note: `panic` could refer to the name defined here
-  --> $DIR/shadow_builtin_macros.rs:40:9
-   |
-LL |         macro_rules! panic { () => {} }
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-LL |     } }
-LL |     m!();
-   |     ----- in this macro invocation
-   = note: `panic` is also a builtin macro
-   = note: macro-expanded macros do not shadow
-
 error[E0659]: `panic` is ambiguous
   --> $DIR/shadow_builtin_macros.rs:25:14
    |
@@ -43,6 +26,23 @@ LL |     ::two_macros::m!(use foo::panic;);
    = note: `panic` is also a builtin macro
    = note: macro-expanded macro imports do not shadow
 
+error[E0659]: `panic` is ambiguous
+  --> $DIR/shadow_builtin_macros.rs:43:5
+   |
+LL |     panic!(); //~ ERROR `panic` is ambiguous
+   |     ^^^^^ ambiguous name
+   |
+note: `panic` could refer to the name defined here
+  --> $DIR/shadow_builtin_macros.rs:40:9
+   |
+LL |         macro_rules! panic { () => {} }
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     } }
+LL |     m!();
+   |     ----- in this macro invocation
+   = note: `panic` is also a builtin macro
+   = note: macro-expanded macros do not shadow
+
 error[E0659]: `n` is ambiguous
   --> $DIR/shadow_builtin_macros.rs:59:5
    |
index a7e6c9f2b3371b7c54e40c88da02248888e1de7d..4d4320083e4a47a25732116cc896c4d7147adf0d 100644 (file)
@@ -8,10 +8,9 @@ LL |         ptr = box Foo { x: ptr.x + 1 };
    |         --- first borrow occurs due to use of `ptr` in closure
 ...
 LL |     test(&*ptr);
-   |     -----^^^^^-
-   |     |    |
-   |     |    immutable borrow occurs here
-   |     borrow later used here
+   |     ---- ^^^^^ immutable borrow occurs here
+   |     |
+   |     mutable borrow later used by call
 
 error: aborting due to previous error
 
index 33c0eefbfaa289758d5a0a1d81b20e3d5750b64a..0d641ec8e891ad150a7b8d85a42291311cc364d9 100644 (file)
@@ -1,15 +1,12 @@
-error[E0308]: mismatched types
-  --> $DIR/issue-13058.rs:36:11
+error[E0621]: explicit lifetime required in the type of `cont`
+  --> $DIR/issue-13058.rs:24:21
    |
-LL |     check((3, 5));
-   |           ^^^^^^
-   |           |
-   |           expected reference, found tuple
-   |           help: consider borrowing here: `&(3, 5)`
-   |
-   = note: expected type `&_`
-              found type `({integer}, {integer})`
+LL | fn check<'r, I: Iterator<Item=usize>, T: Itble<'r, usize, I>>(cont: &T) -> bool
+   |                                                                     -- help: add explicit lifetime `'r` to the type of `cont`: `&'r T`
+LL | {
+LL |     let cont_iter = cont.iter();
+   |                     ^^^^^^^^^^^ lifetime `'r` required
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0621`.
index dbcf9998ad937c6956ff6f7e89141306ef48d92c..cabf02194776a1bde47e6575df8be52be5d774d4 100644 (file)
@@ -33,6 +33,5 @@ fn check<'r, I: Iterator<Item=usize>, T: Itble<'r, usize, I>>(cont: &T) -> bool
 }
 
 fn main() {
-    check((3, 5));
-//~^ ERROR mismatched types
+    check(&(3, 5));
 }
index 5e8319d26ad3ca42ba3277d07f7d35e619934535..ee39678736cddaeed08d61593e9355206735d818 100644 (file)
@@ -7,19 +7,6 @@ LL | {
 LL |     let cont_iter = cont.iter();
    |                          ^^^^ lifetime `'r` required
 
-error[E0308]: mismatched types
-  --> $DIR/issue-13058.rs:36:11
-   |
-LL |     check((3, 5));
-   |           ^^^^^^
-   |           |
-   |           expected reference, found tuple
-   |           help: consider borrowing here: `&(3, 5)`
-   |
-   = note: expected type `&_`
-              found type `({integer}, {integer})`
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors occurred: E0308, E0621.
-For more information about an error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0621`.
index b5ed33d07c5a5f3ad8b405ee2ac494b2894d32b5..c815ad9049f4ecefda9ad1236f1c82a94c15dffe 100644 (file)
@@ -2,11 +2,10 @@ error[E0499]: cannot borrow `*s` as mutable more than once at a time
   --> $DIR/issue-18566.rs:33:19
    |
 LL |     MyPtr(s).poke(s);
-   |     --------------^-
-   |     |     |       |
-   |     |     |       second mutable borrow occurs here
-   |     |     first mutable borrow occurs here
-   |     borrow later used here
+   |           -  ---- ^ second mutable borrow occurs here
+   |           |  |
+   |           |  first borrow later used by call
+   |           first mutable borrow occurs here
 
 error: aborting due to previous error
 
index 8acdc73bf0e6867c0f44c8f7ad31a43b333f17ae..023021eccb9312fdfab048c54a3e3918db4b4dd5 100644 (file)
@@ -11,7 +11,7 @@ LL |     c.push(Box::new(|| y = 0));
    |                     second mutable borrow occurs here
 LL | //~^ ERROR cannot borrow `y` as mutable more than once at a time
 LL | }
-   | - borrow later used here, when `c` is dropped
+   | - first borrow might be used here, when `c` is dropped and runs the destructor for type `std::cell::RefCell<std::vec::Vec<std::boxed::Box<dyn std::ops::FnMut()>>>`
 
 error[E0499]: cannot borrow `y` as mutable more than once at a time
   --> $DIR/issue-18783.rs:26:29
@@ -26,7 +26,7 @@ LL |     Push::push(&c, Box::new(|| y = 0));
    |                             second mutable borrow occurs here
 LL | //~^ ERROR cannot borrow `y` as mutable more than once at a time
 LL | }
-   | - borrow later used here, when `c` is dropped
+   | - first borrow might be used here, when `c` is dropped and runs the destructor for type `std::cell::RefCell<std::vec::Vec<std::boxed::Box<dyn std::ops::FnMut()>>>`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-24338.rs b/src/test/ui/issues/issue-24338.rs
new file mode 100644 (file)
index 0000000..0c5db8f
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+//
+// compile-pass
+
+trait DictLike<'a> {
+    type ItemsIterator: Iterator<Item=u8>;
+    fn get(c: Self::ItemsIterator) {
+        c.into_iter();
+    }
+}
+
+trait DictLike2<'a> {
+    type ItemsIterator: Iterator<Item=u8>;
+
+    fn items(&self) -> Self::ItemsIterator;
+
+    fn get(&self)  {
+        for _ in self.items() {}
+    }
+}
+
+fn main() {}
index bd48d0eeb7c42ec903c972b9d68bce96d22f01cc..f3d855feca2dc4cee09db0b9de6b8a2a3dcda68c 100644 (file)
@@ -7,10 +7,9 @@ LL |         $this.width.unwrap()
 LL |         let r = &mut *self;
    |                 ---------- borrow of `*self` occurs here
 LL |         r.get_size(width!(self))
-   |         ------------------------
-   |         |          |
-   |         |          in this macro invocation
-   |         borrow later used here
+   |           -------- ------------ in this macro invocation
+   |           |
+   |           borrow later used by call
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-28134.rs b/src/test/ui/issues/issue-28134.rs
new file mode 100644 (file)
index 0000000..333b073
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: --test
+
+#![test] //~ ERROR only functions may be used as tests
diff --git a/src/test/ui/issues/issue-28134.stderr b/src/test/ui/issues/issue-28134.stderr
new file mode 100644 (file)
index 0000000..cecbe5b
--- /dev/null
@@ -0,0 +1,8 @@
+error: only functions may be used as tests
+  --> $DIR/issue-28134.rs:13:1
+   |
+LL | #![test] //~ ERROR only functions may be used as tests
+   | ^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-29743.rs b/src/test/ui/issues/issue-29743.rs
new file mode 100644 (file)
index 0000000..e563bf0
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+//
+// compile-pass
+
+fn main() {
+    let mut i = [1, 2, 3];
+    i[i[0]] = 0;
+    i[i[0] - 1] = 0;
+}
index 39e3c218f408912d1956d972a6c74d28d43ee58c..5750b1761e5cc74b4f7c4e03f85625fa67c0edb4 100644 (file)
@@ -6,7 +6,7 @@ LL |     let _a = &collection;
 LL |     collection.swap(1, 2); //~ ERROR also borrowed as immutable
    |     ^^^^^^^^^^ mutable borrow occurs here
 LL |     _a.use_ref();
-   |     -- borrow later used here
+   |     -- immutable borrow later used here
 
 error: aborting due to previous error
 
index e528a84ebd1a5a23241bf3435bd8585ad4bea820..1512ea53a076550c6244b739d540d9aa41c11a3a 100644 (file)
@@ -8,7 +8,7 @@ LL |         let nref = &u.z.c;
    |                    ^^^^^^ immutable borrow occurs here
 LL |         //~^ ERROR cannot borrow `u.z.c` as immutable because it is also borrowed as mutable [E0502]
 LL |         println!("{} {}", mref, nref)
-   |                           ---- borrow later used here
+   |                           ---- mutable borrow later used here
 
 error: aborting due to previous error
 
index 4bdce85d18b5feff02dbd3340dd7a1ef64f9e79b..116cb3be6b50ce4f098e637ae49dcd1cffdcfe80 100644 (file)
@@ -3,9 +3,15 @@ error[E0502]: cannot borrow `heap` as immutable because it is also borrowed as m
    |
 LL |     let borrow = heap.peek_mut();
    |                  ---- mutable borrow occurs here
-...
+LL | 
+LL |     match (borrow, ()) {
+   |           ------------ a temporary with access to the mutable borrow is created here ...
+LL |         (Some(_), ()) => {
 LL |             println!("{:?}", heap); //~ ERROR cannot borrow `heap` as immutable
    |                              ^^^^ immutable borrow occurs here
+...
+LL |     };
+   |      - ... and the mutable borrow might be used here, when that temporary is dropped and runs the destructor for type `(std::option::Option<std::collections::binary_heap::PeekMut<'_, i32>>, ())`
 
 error: aborting due to previous error
 
index cd64dfa7a47dd291292e86fda10c9220c97dc4d3..8188c2c455e40ecb0772582717fcecf762592dbb 100644 (file)
@@ -11,7 +11,7 @@
 // compile-flags:-F private_no_mangle_fns -F no_mangle_const_items -F private_no_mangle_statics
 
 #[no_mangle]
-fn foo() { //~ ERROR function is marked #[no_mangle], but not exported
+fn foo() {
 }
 
 #[allow(dead_code)]
@@ -30,7 +30,7 @@ pub fn bar()  {
 
 #[allow(dead_code)]
 #[no_mangle]
-static PRIVATE_BAR: u64 = 1; //~ ERROR static is marked #[no_mangle], but not exported
+static PRIVATE_BAR: u64 = 1;
 
 
 fn main() {
index e7d49f339e6d88564e511870fb613a03e1d6b733..063915d5b5f9a6c368169b92612311f2a26402e1 100644 (file)
@@ -1,15 +1,10 @@
-error: function is marked #[no_mangle], but not exported
-  --> $DIR/lint-unexported-no-mangle.rs:14:1
+warning: lint `private_no_mangle_fns` has been removed: `no longer an warning, #[no_mangle] functions always exported`
    |
-LL |   fn foo() { //~ ERROR function is marked #[no_mangle], but not exported
-   |   ^
-   |   |
-   |  _help: try making it public: `pub`
-   | |
-LL | | }
-   | |_^
+   = note: requested on the command line with `-F private_no_mangle_fns`
+
+warning: lint `private_no_mangle_statics` has been removed: `no longer an warning, #[no_mangle] statics always exported`
    |
-   = note: requested on the command line with `-F private-no-mangle-fns`
+   = note: requested on the command line with `-F private_no_mangle_statics`
 
 error: const items should never be #[no_mangle]
   --> $DIR/lint-unexported-no-mangle.rs:19:1
@@ -29,15 +24,5 @@ LL | pub const PUB_FOO: u64 = 1; //~ ERROR const items should never be #[no_mang
    | |
    | help: try a static value: `pub static`
 
-error: static is marked #[no_mangle], but not exported
-  --> $DIR/lint-unexported-no-mangle.rs:33:1
-   |
-LL | static PRIVATE_BAR: u64 = 1; //~ ERROR static is marked #[no_mangle], but not exported
-   | -^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   | |
-   | help: try making it public: `pub`
-   |
-   = note: requested on the command line with `-F private-no-mangle-statics`
-
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
index 4da2700cb9fdb7221aea5f5294a70fc6849e055c..ff50b3b1ab68f6dd21d17d02a39c0c8914de4aee 100644 (file)
@@ -13,9 +13,6 @@
 #![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issue #43896
 #![feature(no_debug)]
 
-#[no_mangle] static SHENZHOU: usize = 1;
-//~^ WARN static is marked #[no_mangle]
-//~| HELP try making it public
 #[no_mangle] const DISCOVERY: usize = 1;
 //~^ ERROR const items should never be #[no_mangle]
 //~| HELP try a static value
@@ -27,27 +24,25 @@ pub fn defiant<T>(_t: T) {}
 
 #[no_mangle]
 fn rio_grande() {}
-//~^ WARN function is marked
-//~| HELP try making it public
 
 mod badlands {
     // The private-no-mangle lints shouldn't suggest inserting `pub` when the
     // item is already `pub` (but triggered the lint because, e.g., it's in a
     // private module). (Issue #47383)
-    #[no_mangle] pub static DAUNTLESS: bool = true;
-    //~^ WARN static is marked
-    //~| HELP try exporting the item with a `pub use` statement
-    #[no_mangle] pub fn val_jean() {}
-    //~^ WARN function is marked
-    //~| HELP try exporting the item with a `pub use` statement
+    #[no_mangle] pub const DAUNTLESS: bool = true;
+    //~^ ERROR const items should never be #[no_mangle]
+    //~| HELP try a static value
+    #[no_mangle] pub fn val_jean<T>() {}
+    //~^ WARN functions generic over types must be mangled
+    //~| HELP remove this attribute
 
     // ... but we can suggest just-`pub` instead of restricted
-    #[no_mangle] pub(crate) static VETAR: bool = true;
-    //~^ WARN static is marked
-    //~| HELP try making it public
-    #[no_mangle] pub(crate) fn crossfield() {}
-    //~^ WARN function is marked
-    //~| HELP try making it public
+    #[no_mangle] pub(crate) const VETAR: bool = true;
+    //~^ ERROR const items should never be #[no_mangle]
+    //~| HELP try a static value
+    #[no_mangle] pub(crate) fn crossfield<T>() {}
+    //~^ WARN functions generic over types must be mangled
+    //~| HELP remove this attribute
 }
 
 struct Equinox {
index 8e5dac8be78276b8f8c5ec1c3b71b81e38ed96ab..340a4a48512e2e0bd88fc6686c455da8b730b7b3 100644 (file)
@@ -1,5 +1,5 @@
 warning: unnecessary parentheses around assigned value
-  --> $DIR/suggestions.rs:64:21
+  --> $DIR/suggestions.rs:59:21
    |
 LL |         let mut a = (1);
    |                     ^^^ help: remove these parentheses
@@ -11,7 +11,7 @@ LL | #![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issu
    |                     ^^^^^^^^^^^^^
 
 warning: use of deprecated attribute `no_debug`: the `#[no_debug]` attribute was an experimental feature that has been deprecated due to lack of demand. See https://github.com/rust-lang/rust/issues/29721
-  --> $DIR/suggestions.rs:57:1
+  --> $DIR/suggestions.rs:52:1
    |
 LL | #[no_debug] // should suggest removal of deprecated attribute
    | ^^^^^^^^^^^ help: remove this attribute
@@ -19,7 +19,7 @@ LL | #[no_debug] // should suggest removal of deprecated attribute
    = note: #[warn(deprecated)] on by default
 
 warning: variable does not need to be mutable
-  --> $DIR/suggestions.rs:64:13
+  --> $DIR/suggestions.rs:59:13
    |
 LL |         let mut a = (1);
    |             ----^
@@ -33,7 +33,7 @@ LL | #![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issu
    |         ^^^^^^^^^^
 
 warning: variable does not need to be mutable
-  --> $DIR/suggestions.rs:70:13
+  --> $DIR/suggestions.rs:65:13
    |
 LL |            let mut
    |   _____________^
@@ -44,18 +44,8 @@ LL | ||             b = 1;
    |  |____________|
    |               help: remove this `mut`
 
-warning: static is marked #[no_mangle], but not exported
-  --> $DIR/suggestions.rs:16:14
-   |
-LL | #[no_mangle] static SHENZHOU: usize = 1;
-   |              -^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |              |
-   |              help: try making it public: `pub`
-   |
-   = note: #[warn(private_no_mangle_statics)] on by default
-
 error: const items should never be #[no_mangle]
-  --> $DIR/suggestions.rs:19:14
+  --> $DIR/suggestions.rs:16:14
    |
 LL | #[no_mangle] const DISCOVERY: usize = 1;
    |              -----^^^^^^^^^^^^^^^^^^^^^^
@@ -65,7 +55,7 @@ LL | #[no_mangle] const DISCOVERY: usize = 1;
    = note: #[deny(no_mangle_const_items)] on by default
 
 warning: functions generic over types must be mangled
-  --> $DIR/suggestions.rs:25:1
+  --> $DIR/suggestions.rs:22:1
    |
 LL | #[no_mangle]
    | ------------ help: remove this attribute
@@ -75,50 +65,40 @@ LL | pub fn defiant<T>(_t: T) {}
    |
    = note: #[warn(no_mangle_generic_items)] on by default
 
-warning: function is marked #[no_mangle], but not exported
-  --> $DIR/suggestions.rs:29:1
-   |
-LL | fn rio_grande() {}
-   | -^^^^^^^^^^^^^^^^^
-   | |
-   | help: try making it public: `pub`
+error: const items should never be #[no_mangle]
+  --> $DIR/suggestions.rs:32:18
    |
-   = note: #[warn(private_no_mangle_fns)] on by default
+LL |     #[no_mangle] pub const DAUNTLESS: bool = true;
+   |                  ---------^^^^^^^^^^^^^^^^^^^^^^^^
+   |                  |
+   |                  help: try a static value: `pub static`
 
-warning: static is marked #[no_mangle], but not exported
-  --> $DIR/suggestions.rs:37:18
-   |
-LL |     #[no_mangle] pub static DAUNTLESS: bool = true;
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+warning: functions generic over types must be mangled
+  --> $DIR/suggestions.rs:35:18
    |
-   = help: try exporting the item with a `pub use` statement
+LL |     #[no_mangle] pub fn val_jean<T>() {}
+   |     ------------ ^^^^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     help: remove this attribute
 
-warning: function is marked #[no_mangle], but not exported
+error: const items should never be #[no_mangle]
   --> $DIR/suggestions.rs:40:18
    |
-LL |     #[no_mangle] pub fn val_jean() {}
-   |                  ^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: try exporting the item with a `pub use` statement
-
-warning: static is marked #[no_mangle], but not exported
-  --> $DIR/suggestions.rs:45:18
-   |
-LL |     #[no_mangle] pub(crate) static VETAR: bool = true;
-   |                  ----------^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[no_mangle] pub(crate) const VETAR: bool = true;
+   |                  ----------------^^^^^^^^^^^^^^^^^^^^
    |                  |
-   |                  help: try making it public: `pub`
+   |                  help: try a static value: `pub static`
 
-warning: function is marked #[no_mangle], but not exported
-  --> $DIR/suggestions.rs:48:18
+warning: functions generic over types must be mangled
+  --> $DIR/suggestions.rs:43:18
    |
-LL |     #[no_mangle] pub(crate) fn crossfield() {}
-   |                  ----------^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  help: try making it public: `pub`
+LL |     #[no_mangle] pub(crate) fn crossfield<T>() {}
+   |     ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     help: remove this attribute
 
 warning: denote infinite loops with `loop { ... }`
-  --> $DIR/suggestions.rs:61:5
+  --> $DIR/suggestions.rs:56:5
    |
 LL |     while true {
    |     ^^^^^^^^^^ help: use `loop`
@@ -126,7 +106,7 @@ LL |     while true {
    = note: #[warn(while_true)] on by default
 
 warning: the `warp_factor:` in this pattern is redundant
-  --> $DIR/suggestions.rs:76:23
+  --> $DIR/suggestions.rs:71:23
    |
 LL |             Equinox { warp_factor: warp_factor } => {}
    |                       ------------^^^^^^^^^^^^
@@ -135,5 +115,5 @@ LL |             Equinox { warp_factor: warp_factor } => {}
    |
    = note: #[warn(non_shorthand_field_patterns)] on by default
 
-error: aborting due to previous error
+error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/macros/issue-54441.rs b/src/test/ui/macros/issue-54441.rs
new file mode 100644 (file)
index 0000000..b45aedb
--- /dev/null
@@ -0,0 +1,13 @@
+#![feature(macros_in_extern)]
+
+macro_rules! m {
+    () => {
+        let //~ ERROR expected
+    };
+}
+
+extern "C" {
+    m!();
+}
+
+fn main() {}
diff --git a/src/test/ui/macros/issue-54441.stderr b/src/test/ui/macros/issue-54441.stderr
new file mode 100644 (file)
index 0000000..aa1edb2
--- /dev/null
@@ -0,0 +1,14 @@
+error: expected one of `crate`, `fn`, `pub`, `static`, or `type`, found `let`
+  --> $DIR/issue-54441.rs:5:9
+   |
+LL | #![feature(macros_in_extern)]
+   | - expected one of `crate`, `fn`, `pub`, `static`, or `type` here
+...
+LL |         let //~ ERROR expected
+   |         ^^^ unexpected token
+...
+LL |     m!();
+   |     ----- in this macro invocation
+
+error: aborting due to previous error
+
index f876aa281d11195297e9805bc5453361db6c5291..df2902c0674efaf7cf3fa93a4848f215f8db6760 100644 (file)
@@ -6,7 +6,7 @@ LL |     let y = &mut x;
 LL |     Foo::bar(&x); //~ERROR cannot borrow `x`
    |              ^^ immutable borrow occurs here
 LL |     y.use_mut();
-   |     - borrow later used here
+   |     - mutable borrow later used here
 
 error[E0499]: cannot borrow `x` as mutable more than once at a time
   --> $DIR/method-self-arg-2.rs:30:14
@@ -16,7 +16,7 @@ LL |     let y = &mut x;
 LL |     Foo::baz(&mut x); //~ERROR cannot borrow `x`
    |              ^^^^^^ second mutable borrow occurs here
 LL |     y.use_mut();
-   |     - borrow later used here
+   |     - first borrow later used here
 
 error: aborting due to 2 previous errors
 
index e23a6beb87eaff235a8d72a56716e9a51e6d8ce6..3fc4fa3cac81fda1c6272627c623a6b9c324b3b0 100644 (file)
@@ -2,11 +2,10 @@ error[E0499]: cannot borrow `*f` as mutable more than once at a time
   --> $DIR/moves-based-on-type-no-recursive-stack-closure.rs:30:27
    |
 LL |                     (f.c)(f, true);
-   |                     ------^-------
-   |                     |     |
-   |                     |     second mutable borrow occurs here
+   |                     ----- ^ second mutable borrow occurs here
+   |                     |
    |                     first mutable borrow occurs here
-   |                     borrow later used here
+   |                     first borrow later used by call
 
 error[E0382]: borrow of moved value: `f`
   --> $DIR/moves-based-on-type-no-recursive-stack-closure.rs:42:5
index e2758f810db7d67a18ca43912d0bec300df9acb5..7b5a63b267fd82a2ac0de912ee165affe3f07fee 100644 (file)
@@ -6,7 +6,7 @@ LL |     let b1 = &mut *b;
 LL |     let b2 = &mut *b; //~ ERROR cannot borrow
    |                    ^ second mutable borrow occurs here
 LL |     b1.use_mut();
-   |     -- borrow later used here
+   |     -- first borrow later used here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/mut/no-mut-lint-for-desugared-mut.rs b/src/test/ui/mut/no-mut-lint-for-desugared-mut.rs
new file mode 100644 (file)
index 0000000..419d580
--- /dev/null
@@ -0,0 +1,8 @@
+// run-pass
+
+#![deny(unused_mut)]
+#![allow(unreachable_code)]
+
+fn main() {
+    for _ in { return (); 0..3 } {} // ok
+}
index 28353a8bc2be7cd96173b85ba924110d998d6d35..4da597791ef572e4edc3ebdb2866ac0fa48bb11a 100644 (file)
@@ -1,16 +1,14 @@
 error[E0597]: `v` does not live long enough
   --> $DIR/borrowed-local-error.rs:20:9
    |
-LL |       let x = gimme({
-   |  _____________-
-LL | |         let v = (22,);
-LL | |         &v
-   | |         ^^ borrowed value does not live long enough
-LL | |         //~^ ERROR `v` does not live long enough [E0597]
-LL | |     });
-   | |_____-- borrow later used here
-   |       |
-   |       `v` dropped here while still borrowed
+LL |     let x = gimme({
+   |             ----- borrow later used by call
+LL |         let v = (22,);
+LL |         &v
+   |         ^^ borrowed value does not live long enough
+LL |         //~^ ERROR `v` does not live long enough [E0597]
+LL |     });
+   |     - `v` dropped here while still borrowed
 
 error: aborting due to previous error
 
index 5c5a66e7e21df2d5ba39950cbe9e607c28fa14c3..ff8a83024f12ad4ffd678fa783d4281918c561de 100644 (file)
@@ -8,7 +8,7 @@ LL |     let p: &'a u8 = &*block.current;
    |                     ^^^^^^^^^^^^^^^ immutable borrow occurs here
 LL |     //~^ ERROR cannot borrow `*block.current` as immutable because it is also borrowed as mutable
 LL |     drop(x);
-   |          - borrow later used here
+   |          - mutable borrow later used here
 
 error: aborting due to previous error
 
index 0042b5d7d529b316050daab10ef89296ed26a403..9306926bf387bb41e511f4dbaff83d7e48124937 100644 (file)
@@ -8,7 +8,7 @@ LL |     || x; //~ ERROR
    |     |
    |     immutable borrow occurs here
 LL |     r.use_mut();
-   |     - borrow later used here
+   |     - mutable borrow later used here
 
 error[E0499]: cannot borrow `x` as mutable more than once at a time
   --> $DIR/closure-access-spans.rs:23:5
@@ -20,7 +20,7 @@ LL |     || x = 2; //~ ERROR
    |     |
    |     second mutable borrow occurs here
 LL |     r.use_mut();
-   |     - borrow later used here
+   |     - first borrow later used here
 
 error[E0500]: closure requires unique access to `x` but it is already borrowed
   --> $DIR/closure-access-spans.rs:29:5
@@ -32,7 +32,7 @@ LL |     || *x = 2; //~ ERROR
    |     |
    |     closure construction occurs here
 LL |     r.use_mut();
-   |     - borrow later used here
+   |     - first borrow later used here
 
 error[E0503]: cannot use `x` because it was mutably borrowed
   --> $DIR/closure-access-spans.rs:35:13
index 1b9420b3c0bf327749bbcbf9d3b6360d893b3d6d..3e423dadd192c430e1d270428ac8b1a6e074d952 100644 (file)
@@ -20,7 +20,7 @@ LL |     let f = || x;
 LL |     let y = &mut x; //~ ERROR
    |             ^^^^^^ mutable borrow occurs here
 LL |     f.use_ref();
-   |     - borrow later used here
+   |     - immutable borrow later used here
 
 error[E0597]: `x` does not live long enough
   --> $DIR/closure-borrow-spans.rs:31:16
@@ -68,7 +68,7 @@ LL |     let f = || x = 0;
 LL |     let y = &x; //~ ERROR
    |             ^^ immutable borrow occurs here
 LL |     f.use_ref();
-   |     - borrow later used here
+   |     - mutable borrow later used here
 
 error[E0499]: cannot borrow `x` as mutable more than once at a time
   --> $DIR/closure-borrow-spans.rs:56:13
@@ -80,7 +80,7 @@ LL |     let f = || x = 0;
 LL |     let y = &mut x; //~ ERROR
    |             ^^^^^^ second mutable borrow occurs here
 LL |     f.use_ref();
-   |     - borrow later used here
+   |     - first borrow later used here
 
 error[E0597]: `x` does not live long enough
   --> $DIR/closure-borrow-spans.rs:64:16
@@ -128,7 +128,7 @@ LL |     let f = || *x = 0;
 LL |     let y = &x; //~ ERROR
    |             ^^ borrow occurs here
 LL |     f.use_ref();
-   |     - borrow later used here
+   |     - first borrow later used here
 
 error[E0501]: cannot borrow `x` as mutable because previous closure requires unique access
   --> $DIR/closure-borrow-spans.rs:89:13
@@ -140,7 +140,7 @@ LL |     let f = || *x = 0;
 LL |     let y = &mut x; //~ ERROR
    |             ^^^^^^ borrow occurs here
 LL |     f.use_ref();
-   |     - borrow later used here
+   |     - first borrow later used here
 
 error[E0597]: `x` does not live long enough
   --> $DIR/closure-borrow-spans.rs:98:17
index a35271bdcfeff81c5b66b4e748f10f4e8e889a22..60862d0f22952ad4004d5cda200c105761377bbb 100644 (file)
@@ -8,7 +8,7 @@ LL |         v[0] += 1; //~ ERROR cannot assign to `v[..]` because it is borrowe
    |         ^^^^^^^^^ assignment to borrowed `v[..]` occurs here
 ...
 LL | }
-   | - borrow later used here, when `p` is dropped
+   | - borrow might be used here, when `p` is dropped and runs the `Drop` code for type `WrapMayNotDangle`
 
 error[E0506]: cannot assign to `v[..]` because it is borrowed
   --> $DIR/drop-no-may-dangle.rs:33:5
@@ -19,7 +19,7 @@ LL |     let p: WrapMayNotDangle<&usize> = WrapMayNotDangle { value: &v[0] };
 LL |     v[0] += 1; //~ ERROR cannot assign to `v[..]` because it is borrowed
    |     ^^^^^^^^^ assignment to borrowed `v[..]` occurs here
 LL | }
-   | - borrow later used here, when `p` is dropped
+   | - borrow might be used here, when `p` is dropped and runs the `Drop` code for type `WrapMayNotDangle`
 
 error: aborting due to 2 previous errors
 
index 580dce3c0fe632691f65bc1d8d35d1e153275397..a22f3032f304986cc826cf2e7b63c6fdbf72a972 100644 (file)
@@ -43,7 +43,7 @@ LL |         match map.get() {
 LL |                 map.set(String::new()); // Ideally, this would not error.
    |                 ^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
    |
-note: borrowed value must be valid for the anonymous lifetime #1 defined on the function body at 26:1...
+note: immutable borrowed value must be valid for the anonymous lifetime #1 defined on the function body at 26:1...
   --> $DIR/get_default.rs:26:1
    |
 LL | / fn ok(map: &mut Map) -> &String {
@@ -64,7 +64,7 @@ LL |             Some(v) => {
 LL |                 map.set(String::new()); // Both AST and MIR error here
    |                 ^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
    |
-note: borrowed value must be valid for the anonymous lifetime #1 defined on the function body at 41:1...
+note: immutable borrowed value must be valid for the anonymous lifetime #1 defined on the function body at 41:1...
   --> $DIR/get_default.rs:41:1
    |
 LL | / fn err(map: &mut Map) -> &String {
@@ -85,7 +85,7 @@ LL |         match map.get() {
 LL |                 map.set(String::new()); // Ideally, just AST would error here
    |                 ^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
    |
-note: borrowed value must be valid for the anonymous lifetime #1 defined on the function body at 41:1...
+note: immutable borrowed value must be valid for the anonymous lifetime #1 defined on the function body at 41:1...
   --> $DIR/get_default.rs:41:1
    |
 LL | / fn err(map: &mut Map) -> &String {
index 2f8eab907c7bb5185353420d28460e9ac2cd38e6..8c93eb059e8cdd80c59e2cc4eee358ec8b8b59b3 100644 (file)
@@ -43,7 +43,7 @@ LL |         match map.get() {
 LL |                 map.set(String::new()); // Ideally, this would not error.
    |                 ^^^ mutable borrow occurs here
    |
-note: borrowed value must be valid for the anonymous lifetime #1 defined on the function body at 26:1...
+note: immutable borrowed value must be valid for the anonymous lifetime #1 defined on the function body at 26:1...
   --> $DIR/get_default.rs:26:1
    |
 LL | / fn ok(map: &mut Map) -> &String {
@@ -64,7 +64,7 @@ LL |             Some(v) => {
 LL |                 map.set(String::new()); // Both AST and MIR error here
    |                 ^^^ mutable borrow occurs here
    |
-note: borrowed value must be valid for the anonymous lifetime #1 defined on the function body at 41:1...
+note: immutable borrowed value must be valid for the anonymous lifetime #1 defined on the function body at 41:1...
   --> $DIR/get_default.rs:41:1
    |
 LL | / fn err(map: &mut Map) -> &String {
@@ -85,7 +85,7 @@ LL |         match map.get() {
 LL |                 map.set(String::new()); // Ideally, just AST would error here
    |                 ^^^ mutable borrow occurs here
    |
-note: borrowed value must be valid for the anonymous lifetime #1 defined on the function body at 41:1...
+note: immutable borrowed value must be valid for the anonymous lifetime #1 defined on the function body at 41:1...
   --> $DIR/get_default.rs:41:1
    |
 LL | / fn err(map: &mut Map) -> &String {
diff --git a/src/test/ui/nll/issue-21114-ebfull.rs b/src/test/ui/nll/issue-21114-ebfull.rs
new file mode 100644 (file)
index 0000000..f573896
--- /dev/null
@@ -0,0 +1,20 @@
+// (this works, but only in NLL)
+// compile-pass
+#![feature(nll)]
+
+use std::collections::HashMap;
+use std::sync::Mutex;
+
+fn i_used_to_be_able_to(foo: &Mutex<HashMap<usize, usize>>) -> Vec<(usize, usize)> {
+    let mut foo = foo.lock().unwrap();
+
+    foo.drain().collect()
+}
+
+fn but_after_nightly_update_now_i_gotta(foo: &Mutex<HashMap<usize, usize>>) -> Vec<(usize, usize)> {
+    let mut foo = foo.lock().unwrap();
+
+    return foo.drain().collect();
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/issue-21114-kixunil.rs b/src/test/ui/nll/issue-21114-kixunil.rs
new file mode 100644 (file)
index 0000000..2add951
--- /dev/null
@@ -0,0 +1,19 @@
+// (this works, but only in NLL)
+// compile-pass
+#![feature(nll)]
+
+fn from_stdin(min: u64) -> Vec<u64> {
+    use std::io::BufRead;
+
+    let stdin = std::io::stdin();
+    let stdin = stdin.lock();
+
+    stdin.lines()
+        .map(Result::unwrap)
+        .map(|val| val.parse())
+        .map(Result::unwrap)
+        .filter(|val| *val >= min)
+        .collect()
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/issue-32382-index-assoc-type-with-lifetime.rs b/src/test/ui/nll/issue-32382-index-assoc-type-with-lifetime.rs
new file mode 100644 (file)
index 0000000..a114d70
--- /dev/null
@@ -0,0 +1,42 @@
+#![feature(nll)]
+// compile-pass
+
+// rust-lang/rust#32382: Borrow checker used to complain about
+// `foobar_3` in the `impl` below, presumably due to some interaction
+// between the use of a lifetime in the associated type and the use of
+// the overloaded operator[]. This regression test ensures that we do
+// not resume complaining about it in the future.
+
+
+use std::marker::PhantomData;
+use std::ops::Index;
+
+pub trait Context: Clone {
+    type Container: ?Sized;
+    fn foobar_1( container: &Self::Container ) -> &str;
+    fn foobar_2( container: &Self::Container ) -> &str;
+    fn foobar_3( container: &Self::Container ) -> &str;
+}
+
+#[derive(Clone)]
+struct Foobar<'a> {
+    phantom: PhantomData<&'a ()>
+}
+
+impl<'a> Context for Foobar<'a> {
+    type Container = [&'a str];
+
+    fn foobar_1<'r>( container: &'r [&'a str] ) -> &'r str {
+        container[0]
+    }
+
+    fn foobar_2<'r>( container: &'r Self::Container ) -> &'r str {
+        container.index( 0 )
+    }
+
+    fn foobar_3<'r>( container: &'r Self::Container ) -> &'r str {
+        container[0]
+    }
+}
+
+fn main() { }
index 2ecfe03e7de6250e2e60b50a1360f20ce5bf1b3e..44f7c52d2573253502ffec326ee34b7e6c470463 100644 (file)
@@ -1,19 +1,16 @@
 error[E0502]: cannot borrow `self.thing` as mutable because it is also borrowed as immutable
   --> $DIR/issue-51268.rs:28:9
    |
-LL |            self.thing.bar(|| {
-   |            ^              -- immutable borrow occurs here
-   |   _________|
-   |  |_________|
-   | ||
-LL | ||         //~^ ERROR cannot borrow `self.thing` as mutable because it is also borrowed as immutable [E0502]
-LL | ||             &self.number;
-   | ||              ---- first borrow occurs due to use of `self` in closure
-LL | ||         });
-   | ||          ^
-   | ||__________|
-   | |___________mutable borrow occurs here
-   |             borrow later used here
+LL |           self.thing.bar(|| {
+   |           ^          --- -- immutable borrow occurs here
+   |           |          |
+   |  _________|          immutable borrow later used by call
+   | |
+LL | |         //~^ ERROR cannot borrow `self.thing` as mutable because it is also borrowed as immutable [E0502]
+LL | |             &self.number;
+   | |              ---- first borrow occurs due to use of `self` in closure
+LL | |         });
+   | |__________^ mutable borrow occurs here
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/issue-52086.rs b/src/test/ui/nll/issue-52086.rs
new file mode 100644 (file)
index 0000000..248f4ba
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(nll)]
+
+use std::rc::Rc;
+use std::sync::Arc;
+
+struct Bar { field: Vec<i32> }
+
+fn main() {
+    let x = Rc::new(Bar { field: vec![] });
+    drop(x.field);
+
+    let y = Arc::new(Bar { field: vec![] });
+    drop(y.field);
+}
diff --git a/src/test/ui/nll/issue-52086.stderr b/src/test/ui/nll/issue-52086.stderr
new file mode 100644 (file)
index 0000000..1455c49
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0507]: cannot move out of an `Rc`
+  --> $DIR/issue-52086.rs:20:10
+   |
+LL |     drop(x.field);
+   |          ^^^^^^^ cannot move out of an `Rc`
+
+error[E0507]: cannot move out of an `Arc`
+  --> $DIR/issue-52086.rs:23:10
+   |
+LL |     drop(y.field);
+   |          ^^^^^^^ cannot move out of an `Arc`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0507`.
diff --git a/src/test/ui/nll/issue-54556-niconii.nll.stderr b/src/test/ui/nll/issue-54556-niconii.nll.stderr
new file mode 100644 (file)
index 0000000..40cd04d
--- /dev/null
@@ -0,0 +1,20 @@
+error[E0597]: `counter` does not live long enough
+  --> $DIR/issue-54556-niconii.rs:22:20
+   |
+LL |     if let Ok(_) = counter.lock() { }
+   |                    ^^^^^^^-------
+   |                    |
+   |                    borrowed value does not live long enough
+   |                    a temporary with access to the borrow is created here ...
+...
+LL | }
+   | -
+   | |
+   | `counter` dropped here while still borrowed
+   | ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `std::result::Result<MutexGuard<'_>, ()>`
+   |
+   = note: The temporary is part of an expression at the end of a block. Consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped.
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/issue-54556-niconii.rs b/src/test/ui/nll/issue-54556-niconii.rs
new file mode 100644 (file)
index 0000000..49b063f
--- /dev/null
@@ -0,0 +1,31 @@
+// This is a reduction of a concrete test illustrating a case that was
+// annoying to Rust developer niconii (see comment thread on #21114).
+//
+// With resolving issue #54556, pnkfelix hopes that the new diagnostic
+// output produced by NLL helps to *explain* the semantic significance
+// of temp drop order, and thus why inserting a semi-colon after the
+// `if let` expression in `main` works.
+
+struct Mutex;
+struct MutexGuard<'a>(&'a Mutex);
+
+impl Drop for Mutex { fn drop(&mut self) { println!("Mutex::drop"); } }
+impl<'a> Drop for MutexGuard<'a> { fn drop(&mut self) { println!("MutexGuard::drop");  } }
+
+impl Mutex {
+    fn lock(&self) -> Result<MutexGuard, ()> { Ok(MutexGuard(self)) }
+}
+
+fn main() {
+    let counter = Mutex;
+
+    if let Ok(_) = counter.lock() { }
+
+    // With this code as written, the dynamic semantics here implies
+    // that `Mutex::drop` for `counter` runs *before*
+    // `MutexGuard::drop`, which would be unsound since `MutexGuard`
+    // still has a reference to `counter`.
+    //
+    // The goal of #54556 is to explain that within a compiler
+    // diagnostic.
+}
diff --git a/src/test/ui/nll/issue-54556-niconii.stderr b/src/test/ui/nll/issue-54556-niconii.stderr
new file mode 100644 (file)
index 0000000..2d0de26
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0597]: `counter` does not live long enough
+  --> $DIR/issue-54556-niconii.rs:22:20
+   |
+LL |     if let Ok(_) = counter.lock() { }
+   |                    ^^^^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `counter` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/issue-54556-stephaneyfx.nll.stderr b/src/test/ui/nll/issue-54556-stephaneyfx.nll.stderr
new file mode 100644 (file)
index 0000000..0bf7648
--- /dev/null
@@ -0,0 +1,19 @@
+error[E0597]: `stmt` does not live long enough
+  --> $DIR/issue-54556-stephaneyfx.rs:27:21
+   |
+LL |     let rows = Rows(&stmt);
+   |                     ^^^^^ borrowed value does not live long enough
+LL |     rows.map(|row| row).next()
+   |     ------------------- a temporary with access to the borrow is created here ...
+...
+LL | }
+   | -
+   | |
+   | `stmt` dropped here while still borrowed
+   | ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `std::iter::Map<Rows<'_>, [closure@$DIR/issue-54556-stephaneyfx.rs:28:14: 28:23]>`
+   |
+   = note: The temporary is part of an expression at the end of a block. Consider forcing this temporary to be dropped sooner, before the block's local variables are dropped. For example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block.
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/issue-54556-stephaneyfx.rs b/src/test/ui/nll/issue-54556-stephaneyfx.rs
new file mode 100644 (file)
index 0000000..10a4e21
--- /dev/null
@@ -0,0 +1,35 @@
+// This is a reduction of a concrete test illustrating a case that was
+// annoying to Rust developer stephaneyfx (see issue #46413).
+//
+// With resolving issue #54556, pnkfelix hopes that the new diagnostic
+// output produced by NLL helps to *explain* the semantic significance
+// of temp drop order, and thus why storing the result in `x` and then
+// returning `x` works.
+
+pub struct Statement;
+
+pub struct Rows<'stmt>(&'stmt Statement);
+
+impl<'stmt> Drop for Rows<'stmt> {
+    fn drop(&mut self) {}
+}
+
+impl<'stmt> Iterator for Rows<'stmt> {
+    type Item = String;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        None
+    }
+}
+
+fn get_names() -> Option<String> {
+    let stmt = Statement;
+    let rows = Rows(&stmt);
+    rows.map(|row| row).next()
+    // let x = rows.map(|row| row).next();
+    // x
+    //
+    // Removing the map works too as does removing the Drop impl.
+}
+
+fn main() {}
diff --git a/src/test/ui/nll/issue-54556-stephaneyfx.stderr b/src/test/ui/nll/issue-54556-stephaneyfx.stderr
new file mode 100644 (file)
index 0000000..4e581a5
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0597]: `stmt` does not live long enough
+  --> $DIR/issue-54556-stephaneyfx.rs:27:22
+   |
+LL |     let rows = Rows(&stmt);
+   |                      ^^^^ borrowed value does not live long enough
+...
+LL | }
+   | - `stmt` dropped here while still borrowed
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/issue-54556-temps-in-tail-diagnostic.nll.stderr b/src/test/ui/nll/issue-54556-temps-in-tail-diagnostic.nll.stderr
new file mode 100644 (file)
index 0000000..513dca7
--- /dev/null
@@ -0,0 +1,19 @@
+error[E0597]: `_thing1` does not live long enough
+  --> $DIR/issue-54556-temps-in-tail-diagnostic.rs:5:11
+   |
+LL |         D(&_thing1).end()
+   |         --^^^^^^^^-
+   |         | |
+   |         | borrowed value does not live long enough
+   |         a temporary with access to the borrow is created here ...
+LL |     }
+   |     - `_thing1` dropped here while still borrowed
+LL | 
+LL |     ;
+   |     - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
+   |
+   = note: The temporary is part of an expression at the end of a block. Consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped.
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/issue-54556-temps-in-tail-diagnostic.rs b/src/test/ui/nll/issue-54556-temps-in-tail-diagnostic.rs
new file mode 100644 (file)
index 0000000..63b0433
--- /dev/null
@@ -0,0 +1,23 @@
+fn main() {
+    {
+        let mut _thing1 = D(Box::new("thing1"));
+        // D("other").next(&_thing1).end()
+        D(&_thing1).end()
+    }
+
+    ;
+}
+
+#[derive(Debug)]
+struct D<T: std::fmt::Debug>(T);
+
+impl<T: std::fmt::Debug>  Drop for D<T> {
+    fn drop(&mut self) {
+        println!("dropping {:?})", self);
+    }
+}
+
+impl<T: std::fmt::Debug> D<T> {
+    fn next<U: std::fmt::Debug>(&self, _other: U) -> D<U> { D(_other) }
+    fn end(&self) { }
+}
diff --git a/src/test/ui/nll/issue-54556-temps-in-tail-diagnostic.stderr b/src/test/ui/nll/issue-54556-temps-in-tail-diagnostic.stderr
new file mode 100644 (file)
index 0000000..a74970f
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0597]: `_thing1` does not live long enough
+  --> $DIR/issue-54556-temps-in-tail-diagnostic.rs:5:12
+   |
+LL |         D(&_thing1).end()
+   |            ^^^^^^^ borrowed value does not live long enough
+LL |     }
+   |     - `_thing1` dropped here while still borrowed
+LL | 
+LL |     ;
+   |     - borrowed value needs to live until here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/issue-54556-used-vs-unused-tails.nll.stderr b/src/test/ui/nll/issue-54556-used-vs-unused-tails.nll.stderr
new file mode 100644 (file)
index 0000000..9911fc9
--- /dev/null
@@ -0,0 +1,113 @@
+error[E0597]: `_t1` does not live long enough
+  --> $DIR/issue-54556-used-vs-unused-tails.rs:10:55
+   |
+LL |     {              let mut _t1 = D(Box::new("t1")); D(&_t1).end()    } ; // suggest `;`
+   |                                                     --^^^^-          - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
+   |                                                     | |              |
+   |                                                     | |              `_t1` dropped here while still borrowed
+   |                                                     | borrowed value does not live long enough
+   |                                                     a temporary with access to the borrow is created here ...
+   |
+   = note: The temporary is part of an expression at the end of a block. Consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped.
+
+error[E0597]: `_t1` does not live long enough
+  --> $DIR/issue-54556-used-vs-unused-tails.rs:12:55
+   |
+LL |     {            { let mut _t1 = D(Box::new("t1")); D(&_t1).end() }  } ; // suggest `;`
+   |                                                     --^^^^-       -    - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
+   |                                                     | |           |
+   |                                                     | |           `_t1` dropped here while still borrowed
+   |                                                     | borrowed value does not live long enough
+   |                                                     a temporary with access to the borrow is created here ...
+   |
+   = note: The temporary is part of an expression at the end of a block. Consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped.
+
+error[E0597]: `_t1` does not live long enough
+  --> $DIR/issue-54556-used-vs-unused-tails.rs:14:55
+   |
+LL |     {            { let mut _t1 = D(Box::new("t1")); D(&_t1).end() }; }   // suggest `;`
+   |                                                     --^^^^-       -- ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
+   |                                                     | |           |
+   |                                                     | |           `_t1` dropped here while still borrowed
+   |                                                     | borrowed value does not live long enough
+   |                                                     a temporary with access to the borrow is created here ...
+   |
+   = note: The temporary is part of an expression at the end of a block. Consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped.
+
+error[E0597]: `_t1` does not live long enough
+  --> $DIR/issue-54556-used-vs-unused-tails.rs:16:55
+   |
+LL |     let _ =      { let mut _t1 = D(Box::new("t1")); D(&_t1).end()    } ; // suggest `;`
+   |                                                     --^^^^-          - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
+   |                                                     | |              |
+   |                                                     | |              `_t1` dropped here while still borrowed
+   |                                                     | borrowed value does not live long enough
+   |                                                     a temporary with access to the borrow is created here ...
+   |
+   = note: The temporary is part of an expression at the end of a block. Consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped.
+
+error[E0597]: `_t1` does not live long enough
+  --> $DIR/issue-54556-used-vs-unused-tails.rs:18:55
+   |
+LL |     let _u =     { let mut _t1 = D(Box::new("t1")); D(&_t1).unit()   } ; // suggest `;`
+   |                                                     --^^^^-          - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
+   |                                                     | |              |
+   |                                                     | |              `_t1` dropped here while still borrowed
+   |                                                     | borrowed value does not live long enough
+   |                                                     a temporary with access to the borrow is created here ...
+   |
+   = note: The temporary is part of an expression at the end of a block. Consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped.
+
+error[E0597]: `_t1` does not live long enough
+  --> $DIR/issue-54556-used-vs-unused-tails.rs:20:55
+   |
+LL |     let _x =     { let mut _t1 = D(Box::new("t1")); D(&_t1).end()    } ; // `let x = ...; x`
+   |                                                     --^^^^-          - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
+   |                                                     | |              |
+   |                                                     | |              `_t1` dropped here while still borrowed
+   |                                                     | borrowed value does not live long enough
+   |                                                     a temporary with access to the borrow is created here ...
+   |
+   = note: The temporary is part of an expression at the end of a block. Consider forcing this temporary to be dropped sooner, before the block's local variables are dropped. For example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block.
+
+error[E0597]: `_t1` does not live long enough
+  --> $DIR/issue-54556-used-vs-unused-tails.rs:24:55
+   |
+LL |     _y =         { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } ; // `let x = ...; x`
+   |                                                     --^^^^-       - - ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
+   |                                                     | |           |
+   |                                                     | |           `_t1` dropped here while still borrowed
+   |                                                     | borrowed value does not live long enough
+   |                                                     a temporary with access to the borrow is created here ...
+   |
+   = note: The temporary is part of an expression at the end of a block. Consider forcing this temporary to be dropped sooner, before the block's local variables are dropped. For example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block.
+
+error[E0597]: `_t1` does not live long enough
+  --> $DIR/issue-54556-used-vs-unused-tails.rs:30:55
+   |
+LL | fn f_local_ref() { let mut _t1 = D(Box::new("t1")); D(&_t1).unit()   }  // suggest `;`
+   |                                                     --^^^^-          -
+   |                                                     | |              |
+   |                                                     | |              `_t1` dropped here while still borrowed
+   |                                                     | |              ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
+   |                                                     | borrowed value does not live long enough
+   |                                                     a temporary with access to the borrow is created here ...
+   |
+   = note: The temporary is part of an expression at the end of a block. Consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped.
+
+error[E0597]: `_t1` does not live long enough
+  --> $DIR/issue-54556-used-vs-unused-tails.rs:32:55
+   |
+LL | fn f() -> String { let mut _t1 = D(Box::new("t1")); D(&_t1).end()   }   // `let x = ...; x`
+   |                                                     --^^^^-         -
+   |                                                     | |             |
+   |                                                     | |             `_t1` dropped here while still borrowed
+   |                                                     | |             ... and the borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `D`
+   |                                                     | borrowed value does not live long enough
+   |                                                     a temporary with access to the borrow is created here ...
+   |
+   = note: The temporary is part of an expression at the end of a block. Consider forcing this temporary to be dropped sooner, before the block's local variables are dropped. For example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block.
+
+error: aborting due to 9 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/issue-54556-used-vs-unused-tails.rs b/src/test/ui/nll/issue-54556-used-vs-unused-tails.rs
new file mode 100644 (file)
index 0000000..64e4f75
--- /dev/null
@@ -0,0 +1,48 @@
+// Ths test case is exploring the space of how blocs with tail
+// expressions and statements can be composed, trying to keep each
+// case on one line so that we can compare them via a vertical scan
+// with the human eye.
+
+// Each comment on the right side of the line is summarizing the
+// expected suggestion from the diagnostic for issue #54556.
+
+fn main() {
+    {              let mut _t1 = D(Box::new("t1")); D(&_t1).end()    } ; // suggest `;`
+
+    {            { let mut _t1 = D(Box::new("t1")); D(&_t1).end() }  } ; // suggest `;`
+
+    {            { let mut _t1 = D(Box::new("t1")); D(&_t1).end() }; }   // suggest `;`
+
+    let _ =      { let mut _t1 = D(Box::new("t1")); D(&_t1).end()    } ; // suggest `;`
+
+    let _u =     { let mut _t1 = D(Box::new("t1")); D(&_t1).unit()   } ; // suggest `;`
+
+    let _x =     { let mut _t1 = D(Box::new("t1")); D(&_t1).end()    } ; // `let x = ...; x`
+    let _x =     { let mut _t1 = D(Box::new("t1")); let x = D(&_t1).end(); x } ; // no error
+
+    let mut _y;
+    _y =         { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } ; // `let x = ...; x`
+    _y =         { let mut _t1 = D(Box::new("t1")); let x = D(&_t1).end(); x } ; // no error
+}
+
+fn f_param_ref(_t1: D<Box<&'static str>>) {         D(&_t1).unit()   }  // no error
+
+fn f_local_ref() { let mut _t1 = D(Box::new("t1")); D(&_t1).unit()   }  // suggest `;`
+
+fn f() -> String { let mut _t1 = D(Box::new("t1")); D(&_t1).end()   }   // `let x = ...; x`
+
+
+#[derive(Debug)]
+struct D<T: std::fmt::Debug>(T);
+
+impl<T: std::fmt::Debug>  Drop for D<T> {
+    fn drop(&mut self) {
+        println!("dropping {:?})", self);
+    }
+}
+
+impl<T: std::fmt::Debug> D<T> {
+    fn next<U: std::fmt::Debug>(&self, _other: U) -> D<U> { D(_other) }
+    fn end(&self) -> String { format!("End({:?})", self.0) }
+    fn unit(&self) { }
+}
diff --git a/src/test/ui/nll/issue-54556-used-vs-unused-tails.stderr b/src/test/ui/nll/issue-54556-used-vs-unused-tails.stderr
new file mode 100644 (file)
index 0000000..c75707b
--- /dev/null
@@ -0,0 +1,86 @@
+error[E0597]: `_t1` does not live long enough
+  --> $DIR/issue-54556-used-vs-unused-tails.rs:10:56
+   |
+LL |     {              let mut _t1 = D(Box::new("t1")); D(&_t1).end()    } ; // suggest `;`
+   |                                                        ^^^           - - borrowed value needs to live until here
+   |                                                        |             |
+   |                                                        |             `_t1` dropped here while still borrowed
+   |                                                        borrowed value does not live long enough
+
+error[E0597]: `_t1` does not live long enough
+  --> $DIR/issue-54556-used-vs-unused-tails.rs:12:56
+   |
+LL |     {            { let mut _t1 = D(Box::new("t1")); D(&_t1).end() }  } ; // suggest `;`
+   |                                                        ^^^        -    - borrowed value needs to live until here
+   |                                                        |          |
+   |                                                        |          `_t1` dropped here while still borrowed
+   |                                                        borrowed value does not live long enough
+
+error[E0597]: `_t1` does not live long enough
+  --> $DIR/issue-54556-used-vs-unused-tails.rs:14:56
+   |
+LL |     {            { let mut _t1 = D(Box::new("t1")); D(&_t1).end() }; }   // suggest `;`
+   |                                                        ^^^        -- borrowed value needs to live until here
+   |                                                        |          |
+   |                                                        |          `_t1` dropped here while still borrowed
+   |                                                        borrowed value does not live long enough
+
+error[E0597]: `_t1` does not live long enough
+  --> $DIR/issue-54556-used-vs-unused-tails.rs:16:56
+   |
+LL |     let _ =      { let mut _t1 = D(Box::new("t1")); D(&_t1).end()    } ; // suggest `;`
+   |                                                        ^^^           - - borrowed value needs to live until here
+   |                                                        |             |
+   |                                                        |             `_t1` dropped here while still borrowed
+   |                                                        borrowed value does not live long enough
+
+error[E0597]: `_t1` does not live long enough
+  --> $DIR/issue-54556-used-vs-unused-tails.rs:18:56
+   |
+LL |     let _u =     { let mut _t1 = D(Box::new("t1")); D(&_t1).unit()   } ; // suggest `;`
+   |                                                        ^^^           - - borrowed value needs to live until here
+   |                                                        |             |
+   |                                                        |             `_t1` dropped here while still borrowed
+   |                                                        borrowed value does not live long enough
+
+error[E0597]: `_t1` does not live long enough
+  --> $DIR/issue-54556-used-vs-unused-tails.rs:20:56
+   |
+LL |     let _x =     { let mut _t1 = D(Box::new("t1")); D(&_t1).end()    } ; // `let x = ...; x`
+   |                                                        ^^^           - - borrowed value needs to live until here
+   |                                                        |             |
+   |                                                        |             `_t1` dropped here while still borrowed
+   |                                                        borrowed value does not live long enough
+
+error[E0597]: `_t1` does not live long enough
+  --> $DIR/issue-54556-used-vs-unused-tails.rs:24:56
+   |
+LL |     _y =         { let mut _t1 = D(Box::new("t1")); D(&_t1).end() } ; // `let x = ...; x`
+   |                                                        ^^^        - - borrowed value needs to live until here
+   |                                                        |          |
+   |                                                        |          `_t1` dropped here while still borrowed
+   |                                                        borrowed value does not live long enough
+
+error[E0597]: `_t1` does not live long enough
+  --> $DIR/issue-54556-used-vs-unused-tails.rs:30:56
+   |
+LL | fn f_local_ref() { let mut _t1 = D(Box::new("t1")); D(&_t1).unit()   }  // suggest `;`
+   |                                                        ^^^           - `_t1` dropped here while still borrowed
+   |                                                        |
+   |                                                        borrowed value does not live long enough
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error[E0597]: `_t1` does not live long enough
+  --> $DIR/issue-54556-used-vs-unused-tails.rs:32:56
+   |
+LL | fn f() -> String { let mut _t1 = D(Box::new("t1")); D(&_t1).end()   }   // `let x = ...; x`
+   |                                                        ^^^          - `_t1` dropped here while still borrowed
+   |                                                        |
+   |                                                        borrowed value does not live long enough
+   |
+   = note: values in a scope are dropped in the opposite order they are created
+
+error: aborting due to 9 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/nll/issue-54556-wrap-it-up.nll.stderr b/src/test/ui/nll/issue-54556-wrap-it-up.nll.stderr
new file mode 100644 (file)
index 0000000..a13e59f
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/issue-54556-wrap-it-up.rs:27:5
+   |
+LL |     let wrap = Wrap { p: &mut x };
+   |                          ------ borrow of `x` occurs here
+...
+LL |     x = 1; //~ ERROR cannot assign to `x` because it is borrowed [E0506]
+   |     ^^^^^ assignment to borrowed `x` occurs here
+LL | }
+   | - borrow might be used here, when `foo` is dropped and runs the destructor for type `Foo<'_>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
diff --git a/src/test/ui/nll/issue-54556-wrap-it-up.rs b/src/test/ui/nll/issue-54556-wrap-it-up.rs
new file mode 100644 (file)
index 0000000..11dbef0
--- /dev/null
@@ -0,0 +1,28 @@
+// This is testing how the diagnostic from issue #54556 behaves when
+// the destructor code is attached to a place held in a field of the
+// temporary being dropped.
+//
+// Eventually it would be nice if the diagnostic would actually report
+// that specific place and its type that implements the `Drop` trait.
+// But for the short term, it is acceptable to just print out the
+// whole type of the temporary.
+
+#![allow(warnings)]
+
+struct Wrap<'p> { p: &'p mut i32 }
+
+impl<'p> Drop for Wrap<'p> {
+    fn drop(&mut self) {
+        *self.p += 1;
+    }
+}
+
+struct Foo<'p> { a: String, b: Wrap<'p> }
+
+fn main() {
+    let mut x = 0;
+    let wrap = Wrap { p: &mut x };
+    let s = String::from("str");
+    let foo = Foo { a: s, b: wrap };
+    x = 1; //~ ERROR cannot assign to `x` because it is borrowed [E0506]
+}
diff --git a/src/test/ui/nll/issue-54556-wrap-it-up.stderr b/src/test/ui/nll/issue-54556-wrap-it-up.stderr
new file mode 100644 (file)
index 0000000..a0c19b9
--- /dev/null
@@ -0,0 +1,12 @@
+error[E0506]: cannot assign to `x` because it is borrowed
+  --> $DIR/issue-54556-wrap-it-up.rs:27:5
+   |
+LL |     let wrap = Wrap { p: &mut x };
+   |                               - borrow of `x` occurs here
+...
+LL |     x = 1; //~ ERROR cannot assign to `x` because it is borrowed [E0506]
+   |     ^^^^^ assignment to borrowed `x` occurs here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0506`.
index 4c739cfe978f98f8859de55c2a09ecf6a8545d11..2869035c3f3ed3fa97246cd7158b48f75f206acb 100644 (file)
@@ -80,7 +80,7 @@ LL |     data.push('d');
    |     ^^^^ second mutable borrow occurs here
 ...
 LL |     capitalize(slice);
-   |                ----- borrow later used here
+   |                ----- first borrow later used here
 
 error[E0499]: cannot borrow `data` as mutable more than once at a time (Mir)
   --> $DIR/loan_ends_mid_block_vec.rs:27:5
@@ -92,7 +92,7 @@ LL |     data.push('e');
    |     ^^^^ second mutable borrow occurs here
 ...
 LL |     capitalize(slice);
-   |                ----- borrow later used here
+   |                ----- first borrow later used here
 
 error[E0499]: cannot borrow `data` as mutable more than once at a time (Mir)
   --> $DIR/loan_ends_mid_block_vec.rs:30:5
@@ -104,7 +104,7 @@ LL |     data.push('f');
    |     ^^^^ second mutable borrow occurs here
 ...
 LL |     capitalize(slice);
-   |                ----- borrow later used here
+   |                ----- first borrow later used here
 
 error: aborting due to 9 previous errors
 
index 6fc26d502d30de8b7edea00c4c60ab90c8c2c4ea..fc5417ac80c44377608f12cab1895e5f788435aa 100644 (file)
@@ -8,7 +8,7 @@ LL |     x = 1; //~ ERROR cannot assign to `x` because it is borrowed [E0506]
    |     ^^^^^ assignment to borrowed `x` occurs here
 LL |     // FIXME ^ Should not error in the future with implicit dtors, only manually implemented ones
 LL | }
-   | - borrow later used here, when `foo` is dropped
+   | - borrow might be used here, when `foo` is dropped and runs the destructor for type `Foo<'_>`
 
 error: aborting due to previous error
 
index 54be12f289545b15f25fe6bf2500ac556669d76b..6ae026fb169b068e817d0e9ef9d79ab907ca75fe 100644 (file)
@@ -7,7 +7,7 @@ LL |     let wrap = Wrap { p: &mut x };
 LL |     x = 1; //~ ERROR cannot assign to `x` because it is borrowed [E0506]
    |     ^^^^^ assignment to borrowed `x` occurs here
 LL | }
-   | - borrow later used here, when `foo` is dropped
+   | - borrow might be used here, when `foo` is dropped and runs the destructor for type `Foo<'_>`
 
 error: aborting due to previous error
 
index ee926e42793180485b58e5cb38a8d44ef5a239a3..dd16e9a0e840cad997c5c911f27dbb54c93f9a90 100644 (file)
@@ -8,7 +8,7 @@ LL |     x = 1; //~ ERROR cannot assign to `x` because it is borrowed [E0506]
    |     ^^^^^ assignment to borrowed `x` occurs here
 LL |     // FIXME ^ This currently errors and it should not.
 LL | }
-   | - borrow later used here, when `foo` is dropped
+   | - borrow might be used here, when `foo` is dropped and runs the destructor for type `Foo<'_>`
 
 error: aborting due to previous error
 
index cc842c29ccb1582769ef4e210a94f8a863d17db2..e8f427826ba33a65630a30c870d5d3cfc712e81f 100644 (file)
@@ -6,7 +6,7 @@ LL |     let wrap = Wrap { p: &mut x };
 LL |     x = 1; //~ ERROR cannot assign to `x` because it is borrowed [E0506]
    |     ^^^^^ assignment to borrowed `x` occurs here
 LL | }
-   | - borrow later used here, when `wrap` is dropped
+   | - borrow might be used here, when `wrap` is dropped and runs the `Drop` code for type `Wrap`
 
 error: aborting due to previous error
 
index 592768363096cae2d0d60a37ee35a0eefb81d24b..8b8268b5b2c4986bf9973beb5bfc450b926d857f 100644 (file)
@@ -25,13 +25,13 @@ LL |     let s = **r;
    |             cannot move out of borrowed content
    |             help: consider removing the `*`: `*r`
 
-error[E0507]: cannot move out of borrowed content
+error[E0507]: cannot move out of an `Rc`
   --> $DIR/move-errors.rs:40:13
    |
 LL |     let s = *r;
    |             ^^
    |             |
-   |             cannot move out of borrowed content
+   |             cannot move out of an `Rc`
    |             help: consider removing the `*`: `r`
 
 error[E0508]: cannot move out of type `[A; 1]`, a non-copy array
index fa3a5e0c0d733b8271273c7861500bfbb3fc62f3..c1bfa4bffc03cc236aac951c3be465e38fa27da7 100644 (file)
@@ -32,7 +32,7 @@ LL |         my_struct.field.push_str("Hello, world!");
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
 ...
 LL |     drop(value);
-   |          ----- borrow later used here
+   |          ----- immutable borrow later used here
 
 error: aborting due to 3 previous errors
 
index d966c62c85f902b35c4a677884e554e5e16ea5b3..eaa5e815de8243552a7ff81a121026b75fac2c1e 100644 (file)
@@ -32,7 +32,7 @@ LL |         my_struct.field.push_str("Hello, world!");
    |         ^^^^^^^^^^^^^^^ mutable borrow occurs here
 ...
 LL |     drop(value);
-   |          ----- borrow later used here
+   |          ----- immutable borrow later used here
 
 error: aborting due to 3 previous errors
 
index 7130aa64daba389a2bff77ee7db3fb3dc053aee6..d631bb58af62fb13004c30a99f5f2bb78f69f929 100644 (file)
@@ -32,7 +32,7 @@ LL |         my_struct.field.push_str("Hello, world!");
    |         ^^^^^^^^^^^^^^^ second mutable borrow occurs here
 ...
 LL |         value.len();
-   |         ----- borrow later used here
+   |         ----- first borrow later used here
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/parser/inverted-parameters.rs b/src/test/ui/parser/inverted-parameters.rs
new file mode 100644 (file)
index 0000000..a100deb
--- /dev/null
@@ -0,0 +1,39 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct S;
+
+impl S {
+    fn foo(&self, &str bar) {}
+    //~^ ERROR expected one of `:` or `@`
+    //~| HELP declare the type after the parameter binding
+    //~| SUGGESTION <identifier>: <type>
+}
+
+fn baz(S quux, xyzzy: i32) {}
+//~^ ERROR expected one of `:` or `@`
+//~| HELP declare the type after the parameter binding
+//~| SUGGESTION <identifier>: <type>
+
+fn one(i32 a b) {}
+//~^ ERROR expected one of `:` or `@`
+
+fn pattern((i32, i32) (a, b)) {}
+//~^ ERROR expected `:`
+
+fn fizz(i32) {}
+//~^ ERROR expected one of `:` or `@`
+
+fn missing_colon(quux S) {}
+//~^ ERROR expected one of `:` or `@`
+//~| HELP declare the type after the parameter binding
+//~| SUGGESTION <identifier>: <type>
+
+fn main() {}
diff --git a/src/test/ui/parser/inverted-parameters.stderr b/src/test/ui/parser/inverted-parameters.stderr
new file mode 100644 (file)
index 0000000..3f4f061
--- /dev/null
@@ -0,0 +1,47 @@
+error: expected one of `:` or `@`, found `bar`
+  --> $DIR/inverted-parameters.rs:14:24
+   |
+LL |     fn foo(&self, &str bar) {}
+   |                   -----^^^
+   |                   |    |
+   |                   |    expected one of `:` or `@` here
+   |                   help: declare the type after the parameter binding: `<identifier>: <type>`
+
+error: expected one of `:` or `@`, found `quux`
+  --> $DIR/inverted-parameters.rs:20:10
+   |
+LL | fn baz(S quux, xyzzy: i32) {}
+   |        --^^^^
+   |        | |
+   |        | expected one of `:` or `@` here
+   |        help: declare the type after the parameter binding: `<identifier>: <type>`
+
+error: expected one of `:` or `@`, found `a`
+  --> $DIR/inverted-parameters.rs:25:12
+   |
+LL | fn one(i32 a b) {}
+   |            ^ expected one of `:` or `@` here
+
+error: expected `:`, found `(`
+  --> $DIR/inverted-parameters.rs:28:23
+   |
+LL | fn pattern((i32, i32) (a, b)) {}
+   |                       ^ expected `:`
+
+error: expected one of `:` or `@`, found `)`
+  --> $DIR/inverted-parameters.rs:31:12
+   |
+LL | fn fizz(i32) {}
+   |            ^ expected one of `:` or `@` here
+
+error: expected one of `:` or `@`, found `S`
+  --> $DIR/inverted-parameters.rs:34:23
+   |
+LL | fn missing_colon(quux S) {}
+   |                  -----^
+   |                  |    |
+   |                  |    expected one of `:` or `@` here
+   |                  help: declare the type after the parameter binding: `<identifier>: <type>`
+
+error: aborting due to 6 previous errors
+
index 4235b4be27158745ab192e7114926ce99c28a4c7..1842790a1405faef0c81ebe26214e07f98beee46 100644 (file)
@@ -35,8 +35,6 @@ impl Tr1 for ext::Alias {} //~ ERROR type `ext::Priv` is private
 trait Tr2<T> {}
 impl<T> Tr2<T> for u8 {}
 fn g() -> impl Tr2<m::Alias> { 0 } //~ ERROR type `m::Priv` is private
-//~^ ERROR type `m::Priv` is private
 fn g_ext() -> impl Tr2<ext::Alias> { 0 } //~ ERROR type `ext::Priv` is private
-//~^ ERROR type `ext::Priv` is private
 
 fn main() {}
index 5b12ed5e5f473010977885ec0cfa295ea65eb9f0..38c21a77211b2aead4a73eb6c21e8e773528b2f4 100644 (file)
@@ -46,23 +46,11 @@ error: type `m::Priv` is private
 LL | fn g() -> impl Tr2<m::Alias> { 0 } //~ ERROR type `m::Priv` is private
    |           ^^^^^^^^^^^^^^^^^^
 
-error: type `m::Priv` is private
-  --> $DIR/private-type-in-interface.rs:37:16
-   |
-LL | fn g() -> impl Tr2<m::Alias> { 0 } //~ ERROR type `m::Priv` is private
-   |                ^^^^^^^^^^^^^
-
 error: type `ext::Priv` is private
-  --> $DIR/private-type-in-interface.rs:39:15
+  --> $DIR/private-type-in-interface.rs:38:15
    |
 LL | fn g_ext() -> impl Tr2<ext::Alias> { 0 } //~ ERROR type `ext::Priv` is private
    |               ^^^^^^^^^^^^^^^^^^^^
 
-error: type `ext::Priv` is private
-  --> $DIR/private-type-in-interface.rs:39:20
-   |
-LL | fn g_ext() -> impl Tr2<ext::Alias> { 0 } //~ ERROR type `ext::Priv` is private
-   |                    ^^^^^^^^^^^^^^^
-
-error: aborting due to 11 previous errors
+error: aborting due to 9 previous errors
 
index da6ebaaefadf1a6d28c21d47920e8591a9ee1337..f11cc77bbeaa12d871f7b3f957cbe8d1343262e6 100644 (file)
@@ -2,12 +2,11 @@ error[E0505]: cannot move out of `f` because it is borrowed
   --> $DIR/region-bound-on-closure-outlives-call.rs:12:25
    |
 LL |     (|x| f(x))(call_rec(f)) //~ ERROR cannot move out of `f`
-   |     --------------------^--
-   |     ||   |              |
-   |     ||   |              move out of `f` occurs here
+   |     ----------          ^ move out of `f` occurs here
+   |     ||   |
    |     ||   borrow occurs due to use in closure
    |     |borrow of `f` occurs here
-   |     borrow later used here
+   |     borrow later used by call
 
 error: aborting due to previous error
 
index f342155c8b1410b403b86e9e27f5ef569baa9c92..fa963714849b66f9836b2544ac15e62800682ccf 100644 (file)
@@ -2,21 +2,19 @@ error[E0502]: cannot borrow `v` as immutable because it is also borrowed as muta
   --> $DIR/regions-adjusted-lvalue-op.rs:24:16
    |
 LL |     v[0].oh_no(&v); //~ ERROR cannot borrow `v` as immutable because
-   |     -----------^^-
-   |     |          |
-   |     |          immutable borrow occurs here
+   |     -    ----- ^^ immutable borrow occurs here
+   |     |    |
+   |     |    mutable borrow later used by call
    |     mutable borrow occurs here
-   |     borrow later used here
 
 error[E0502]: cannot borrow `v` as immutable because it is also borrowed as mutable
   --> $DIR/regions-adjusted-lvalue-op.rs:25:16
    |
 LL |     (*v).oh_no(&v); //~ ERROR cannot borrow `v` as immutable because
-   |     -----------^^-
-   |     | |        |
-   |     | |        immutable borrow occurs here
-   |     | mutable borrow occurs here
-   |     borrow later used here
+   |       -  ----- ^^ immutable borrow occurs here
+   |       |  |
+   |       |  mutable borrow later used by call
+   |       mutable borrow occurs here
 
 error: aborting due to 2 previous errors
 
index 626ffad5ba70fd3a3cafd82282a8b2ec5496d373..84cd097e33ca9fcb011226933197616c511fc8a2 100644 (file)
@@ -7,7 +7,7 @@ LL |         foo.mutate();
    |         ^^^^^^^^^^^^ mutable borrow occurs here
 LL |         //~^ ERROR cannot borrow `foo` as mutable
 LL |         println!("foo={:?}", *string);
-   |                              ------- borrow used here, in later iteration of loop
+   |                              ------- immutable borrow used here, in later iteration of loop
 
 error: aborting due to previous error
 
index a05a3911aa771144eb177e4b291e274e5b49bc29..978ca66a0890c16953ef9aeaa7a3fb5bd18b377e 100644 (file)
@@ -1,16 +1,14 @@
 error[E0499]: cannot borrow `f` as mutable more than once at a time
   --> $DIR/borrowck-call-is-borrow-issue-12224.rs:22:16
    |
-LL |       f(Box::new(|| {
-   |       -          ^^ second mutable borrow occurs here
-   |       |
-   |  _____first mutable borrow occurs here
-   | |
-LL | |     //~^ ERROR: cannot borrow `f` as mutable more than once
-LL | |         f((Box::new(|| {})))
-   | |         - second borrow occurs due to use of `f` in closure
-LL | |     }));
-   | |_______- borrow later used here
+LL |     f(Box::new(|| {
+   |     -          ^^ second mutable borrow occurs here
+   |     |
+   |     first mutable borrow occurs here
+   |     first borrow later used by call
+LL |     //~^ ERROR: cannot borrow `f` as mutable more than once
+LL |         f((Box::new(|| {})))
+   |         - second borrow occurs due to use of `f` in closure
 
 error[E0596]: cannot borrow `*f` as mutable, as it is behind a `&` reference
   --> $DIR/borrowck-call-is-borrow-issue-12224.rs:35:5
@@ -40,17 +38,13 @@ LL |         foo(f);
 error[E0505]: cannot move out of `f` because it is borrowed
   --> $DIR/borrowck-call-is-borrow-issue-12224.rs:65:16
    |
-LL |       f(Box::new(|a| {
-   |       -          ^^^ move out of `f` occurs here
-   |       |
-   |  _____borrow of `f` occurs here
-   | |
-LL | |         foo(f);
-   | |             - move occurs due to use in closure
-LL | |         //~^ ERROR cannot move `f` into closure because it is borrowed
-LL | |         //~| ERROR cannot move out of captured outer variable in an `FnMut` closure
-LL | |     }), 3);
-   | |__________- borrow later used here
+LL |     f(Box::new(|a| {
+   |     -          ^^^ move out of `f` occurs here
+   |     |
+   |     borrow of `f` occurs here
+   |     borrow later used by call
+LL |         foo(f);
+   |             - move occurs due to use in closure
 
 error: aborting due to 5 previous errors
 
index 22f2f13f1f7cf60db1c8d206de3c0626b22dcb2c..99a839f76d33cf87eceed63eafa1da4f6e361f15 100644 (file)
@@ -2,9 +2,16 @@ error[E0597]: `*a` does not live long enough
   --> $DIR/destructor-restrictions.rs:18:10
    |
 LL |         *a.borrow() + 1
-   |          ^ borrowed value does not live long enough
+   |          ^---------
+   |          |
+   |          borrowed value does not live long enough
+   |          a temporary with access to the borrow is created here ...
 LL |     }; //~^ ERROR `*a` does not live long enough
-   |     - `*a` dropped here while still borrowed
+   |     -- ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `std::cell::Ref<'_, i32>`
+   |     |
+   |     `*a` dropped here while still borrowed
+   |
+   = note: The temporary is part of an expression at the end of a block. Consider forcing this temporary to be dropped sooner, before the block's local variables are dropped. For example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block.
 
 error: aborting due to previous error
 
index 08e4b9ec9faa2b055b1dacda481ac3232639ea48..52d4007f3f8f6cd84df7ce1a33ee4e5b5e294347 100644 (file)
@@ -8,7 +8,7 @@ LL | }
    | -
    | |
    | `*m` dropped here while still borrowed
-   | borrow later used here, when `m` is dropped
+   | borrow might be used here, when `m` is dropped and runs the destructor for type `std::boxed::Box<dyn Trait<'_>>`
 
 error: aborting due to previous error
 
index 74db695e7e5609bc1251cf74527bb8e0e55009f7..32abfd81f53a6a281b90537621e4d4fd32563ab0 100644 (file)
@@ -8,7 +8,7 @@ LL | }
    | -
    | |
    | `b2` dropped here while still borrowed
-   | borrow later used here, when `b1` is dropped
+   | borrow might be used here, when `b1` is dropped and runs the destructor for type `B<'_>`
    |
    = note: values in a scope are dropped in the opposite order they are defined
 
@@ -22,7 +22,7 @@ LL | }
    | -
    | |
    | `b3` dropped here while still borrowed
-   | borrow later used here, when `b1` is dropped
+   | borrow might be used here, when `b1` is dropped and runs the destructor for type `B<'_>`
    |
    = note: values in a scope are dropped in the opposite order they are defined
 
@@ -36,7 +36,7 @@ LL | }
    | -
    | |
    | `b1` dropped here while still borrowed
-   | borrow later used here, when `b1` is dropped
+   | borrow might be used here, when `b1` is dropped and runs the destructor for type `B<'_>`
 
 error: aborting due to 3 previous errors
 
index baf3cef2ae83c84a211c1da1b6614c715ac2e579..0c5c49c80de5d412f95be002e67379b41a8ee4d0 100644 (file)
@@ -8,7 +8,7 @@ LL | }
    | -
    | |
    | `d2` dropped here while still borrowed
-   | borrow later used here, when `d1` is dropped
+   | borrow might be used here, when `d1` is dropped and runs the `Drop` code for type `D`
    |
    = note: values in a scope are dropped in the opposite order they are defined
 
@@ -22,7 +22,7 @@ LL | }
    | -
    | |
    | `d1` dropped here while still borrowed
-   | borrow later used here, when `d1` is dropped
+   | borrow might be used here, when `d1` is dropped and runs the `Drop` code for type `D`
 
 error: aborting due to 2 previous errors
 
index 27a52360bb7010f6788f9d6551cffdbe9eb5bc07..fb68262b0ae2a0e6b7059d3a0a7829b2f0e06a0e 100644 (file)
@@ -7,7 +7,7 @@ LL | }
    | -
    | |
    | `bomb` dropped here while still borrowed
-   | borrow later used here, when `_w` is dropped
+   | borrow might be used here, when `_w` is dropped and runs the destructor for type `Wrap<&[&str]>`
    |
    = note: values in a scope are dropped in the opposite order they are defined
 
@@ -21,7 +21,7 @@ LL | }
    | -
    | |
    | `v` dropped here while still borrowed
-   | borrow later used here, when `_w` is dropped
+   | borrow might be used here, when `_w` is dropped and runs the destructor for closure
    |
    = note: values in a scope are dropped in the opposite order they are defined
 
index f7ff4e5169fd45e20cd7cfbfb3353fe6bd045762..ad62936b870c849f39d731bb87971b5f27af62bb 100644 (file)
@@ -8,7 +8,7 @@ LL | }
    | -
    | |
    | `c2` dropped here while still borrowed
-   | borrow later used here, when `c1` is dropped
+   | borrow might be used here, when `c1` is dropped and runs the destructor for type `C<'_>`
    |
    = note: values in a scope are dropped in the opposite order they are defined
 
@@ -22,7 +22,7 @@ LL | }
    | -
    | |
    | `c3` dropped here while still borrowed
-   | borrow later used here, when `c1` is dropped
+   | borrow might be used here, when `c1` is dropped and runs the destructor for type `C<'_>`
    |
    = note: values in a scope are dropped in the opposite order they are defined
 
@@ -36,7 +36,7 @@ LL | }
    | -
    | |
    | `c1` dropped here while still borrowed
-   | borrow later used here, when `c1` is dropped
+   | borrow might be used here, when `c1` is dropped and runs the destructor for type `C<'_>`
 
 error: aborting due to 3 previous errors
 
index fe0187f38637898f045a56766ae14cb0bfee185f..9e82884b95440f9a03be65136a8d0229778f418b 100644 (file)
@@ -2,17 +2,32 @@ error[E0597]: `y` does not live long enough
   --> $DIR/issue-23338-locals-die-before-temps-of-body.rs:20:5
    |
 LL |     y.borrow().clone()
-   |     ^ borrowed value does not live long enough
+   |     ^---------
+   |     |
+   |     borrowed value does not live long enough
+   |     a temporary with access to the borrow is created here ...
 LL | }
-   | - `y` dropped here while still borrowed
+   | -
+   | |
+   | `y` dropped here while still borrowed
+   | ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `std::cell::Ref<'_, std::string::String>`
+   |
+   = note: The temporary is part of an expression at the end of a block. Consider forcing this temporary to be dropped sooner, before the block's local variables are dropped. For example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block.
 
 error[E0597]: `y` does not live long enough
   --> $DIR/issue-23338-locals-die-before-temps-of-body.rs:27:9
    |
 LL |         y.borrow().clone()
-   |         ^ borrowed value does not live long enough
+   |         ^---------
+   |         |
+   |         borrowed value does not live long enough
+   |         a temporary with access to the borrow is created here ...
 LL |     };
-   |     - `y` dropped here while still borrowed
+   |     -- ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `std::cell::Ref<'_, std::string::String>`
+   |     |
+   |     `y` dropped here while still borrowed
+   |
+   = note: The temporary is part of an expression at the end of a block. Consider forcing this temporary to be dropped sooner, before the block's local variables are dropped. For example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block.
 
 error: aborting due to 2 previous errors
 
index b9834a3d4379e550b95321da5bcac9c68be8f405..fb995990f167ba1fb3451ffa968d5116c8709458 100644 (file)
@@ -8,7 +8,7 @@ LL | }
    | -
    | |
    | `d1` dropped here while still borrowed
-   | borrow later used here, when `_d` is dropped
+   | borrow might be used here, when `_d` is dropped and runs the `Drop` code for type `D_Child`
    |
    = note: values in a scope are dropped in the opposite order they are defined
 
index cd3d658aa8726eea3ba8f555cb0eee02e223efe4..5eaff66e72ea22974bb1f4985d08263cf3d41207 100644 (file)
@@ -7,7 +7,7 @@ LL | }
    | -
    | |
    | `d1` dropped here while still borrowed
-   | borrow later used here, when `_d` is dropped
+   | borrow might be used here, when `_d` is dropped and runs the `Drop` code for type `D_HasSelfMethod`
    |
    = note: values in a scope are dropped in the opposite order they are defined
 
@@ -20,7 +20,7 @@ LL | }
    | -
    | |
    | `d1` dropped here while still borrowed
-   | borrow later used here, when `_d` is dropped
+   | borrow might be used here, when `_d` is dropped and runs the `Drop` code for type `D_HasMethodWithSelfArg`
    |
    = note: values in a scope are dropped in the opposite order they are defined
 
@@ -33,7 +33,7 @@ LL | }
    | -
    | |
    | `d1` dropped here while still borrowed
-   | borrow later used here, when `_d` is dropped
+   | borrow might be used here, when `_d` is dropped and runs the `Drop` code for type `D_HasType`
    |
    = note: values in a scope are dropped in the opposite order they are defined
 
index 54c6ac43f347c33d93de70cf2624529f449cb7b1..26c74b653a11b592db92c3f97b2ae6d1267bb125 100644 (file)
@@ -7,7 +7,7 @@ LL | }
    | -
    | |
    | `d1` dropped here while still borrowed
-   | borrow later used here, when `d2` is dropped
+   | borrow might be used here, when `d2` is dropped and runs the `Drop` code for type `D`
    |
    = note: values in a scope are dropped in the opposite order they are defined
 
index a81b591d288eb234a93e9ab67851d73638385da6..9801f92ce64469f96c3b7f2e537678114e558433 100644 (file)
@@ -8,7 +8,7 @@ LL | }
    | -
    | |
    | `container` dropped here while still borrowed
-   | borrow later used here, when `container` is dropped
+   | borrow might be used here, when `container` is dropped and runs the destructor for type `Container<'_>`
 
 error: aborting due to previous error
 
index b6c28828120880ea36de2937eeda12862e16edc4..79d9dab17769b1589689e0a172012635d9805389 100644 (file)
@@ -7,7 +7,7 @@ LL | }
    | -
    | |
    | `ticking` dropped here while still borrowed
-   | borrow later used here, when `zook` is dropped
+   | borrow might be used here, when `zook` is dropped and runs the `Drop` code for type `Zook`
    |
    = note: values in a scope are dropped in the opposite order they are defined
 
index a1451866e677ca319378464196f9abf9d3a2e2aa..77bb311c61a403766de36f96a7375ce40f3833bd 100644 (file)
@@ -7,7 +7,7 @@ LL |     }
    |     -
    |     |
    |     `x` dropped here while still borrowed
-   |     borrow later used here, when `y` is dropped
+   |     borrow might be used here, when `y` is dropped and runs the `Drop` code for type `std::sync::Arc`
    |
    = note: values in a scope are dropped in the opposite order they are defined
 
@@ -20,7 +20,7 @@ LL |     }
    |     -
    |     |
    |     `x` dropped here while still borrowed
-   |     borrow later used here, when `y` is dropped
+   |     borrow might be used here, when `y` is dropped and runs the `Drop` code for type `std::rc::Rc`
    |
    = note: values in a scope are dropped in the opposite order they are defined
 
index 0f6f6e381d801e681e826be0f7d6fa3c6c9887c3..bc3a31b843fbce661a8936647e7554afcc4e3084 100644 (file)
@@ -8,7 +8,7 @@ LL | }
    | -
    | |
    | here, drop of `foo` needs exclusive access to `foo.data`, because the type `Foo<Concrete<'_>>` implements the `Drop` trait
-   | borrow later used here, when `foo` is dropped
+   | borrow might be used here, when `foo` is dropped and runs the `Drop` code for type `Foo`
    |
    = note: consider using a `let` binding to create a longer lived value
 
index 72acc54bffb321468473a4ffb1a2a0c488cf7898..21508303afc2105e7172abe380d58e82d254f4d1 100644 (file)
@@ -8,7 +8,7 @@ LL | }
    | -
    | |
    | `first_dropped` dropped here while still borrowed
-   | borrow later used here, when `foo1` is dropped
+   | borrow might be used here, when `foo1` is dropped and runs the `Drop` code for type `Foo`
    |
    = note: values in a scope are dropped in the opposite order they are defined
 
index a39050a5199117d7ae8273ffabe77a99b2ce536b..752f96988db0ef7e6e24e6a58bda1f77ad7ff66a 100644 (file)
@@ -8,7 +8,7 @@ LL | }
    | -
    | |
    | `first_dropped` dropped here while still borrowed
-   | borrow later used here, when `foo1` is dropped
+   | borrow might be used here, when `foo1` is dropped and runs the `Drop` code for type `Foo`
    |
    = note: values in a scope are dropped in the opposite order they are defined
 
index fcffea25702b92b23544da0303d61e8a1ca3fc55..7bf55c8e9973d10179a848b2dcecfd849234cb15 100644 (file)
@@ -8,7 +8,7 @@ LL | }
    | -
    | |
    | `first_dropped` dropped here while still borrowed
-   | borrow later used here, when `foo1` is dropped
+   | borrow might be used here, when `foo1` is dropped and runs the `Drop` code for type `Foo`
    |
    = note: values in a scope are dropped in the opposite order they are defined
 
index 6f7fbdcf4214543800958fc94026e0fd769f357e..fd789e79e9133438cc8abf39f5e7f80faf892d17 100644 (file)
@@ -7,7 +7,7 @@ LL |         let ss: &isize = &id(1);
 LL |     }
    |     - temporary value is freed at the end of this statement
 LL | }
-   | - borrow later used here, when `blah` is dropped
+   | - borrow might be used here, when `blah` is dropped and runs the destructor for type `std::boxed::Box<dyn Foo>`
    |
    = note: consider using a `let` binding to create a longer lived value
 
index 878ae36386371e884198de18717031aa84d74094..c17f502b77902a11d0507bf90364998e128bf862 100644 (file)
@@ -62,7 +62,7 @@ LL |     }
    |     - `z` dropped here while still borrowed
 ...
 LL | }
-   | - borrow later used here, when `tx` is dropped
+   | - borrow might be used here, when `tx` is dropped and runs the `Drop` code for type `std::sync::mpsc::Sender`
    |
    = note: values in a scope are dropped in the opposite order they are defined
 
index 292c007f5122518c24ad41cc1f0a42a77c722382..7ad7a1b0bcdb7ef5bd729a89dd4ee643788e8fcd 100644 (file)
@@ -8,7 +8,7 @@ LL | }
    | -
    | |
    | `c2` dropped here while still borrowed
-   | borrow later used here, when `c1` is dropped
+   | borrow might be used here, when `c1` is dropped and runs the destructor for type `C<'_>`
    |
    = note: values in a scope are dropped in the opposite order they are defined
 
@@ -22,7 +22,7 @@ LL | }
    | -
    | |
    | `c1` dropped here while still borrowed
-   | borrow later used here, when `c1` is dropped
+   | borrow might be used here, when `c1` is dropped and runs the destructor for type `C<'_>`
 
 error: aborting due to 2 previous errors
 
index 60905367063a48d47c82cd3fa96862618ace5e55..562544c79165dd33bacfb73689e73a5e373f397e 100644 (file)
@@ -8,7 +8,7 @@ LL | }
    | -
    | |
    | `x` dropped here while still borrowed
-   | borrow later used here, when `v` is dropped
+   | borrow might be used here, when `v` is dropped and runs the `Drop` code for type `Bag`
    |
    = note: values in a scope are dropped in the opposite order they are defined
 
@@ -22,7 +22,7 @@ LL | }
    | -
    | |
    | `y` dropped here while still borrowed
-   | borrow later used here, when `v` is dropped
+   | borrow might be used here, when `v` is dropped and runs the `Drop` code for type `Bag`
    |
    = note: values in a scope are dropped in the opposite order they are defined
 
index afd90237d16aee165d1c1b21092908bce203d592..ad01f84cd2c142c06c7f8f72ccf512a04cff495e 100644 (file)
@@ -10,7 +10,7 @@ LL | }
    | -
    | |
    | `factorial` dropped here while still borrowed
-   | borrow later used here, when `factorial` is dropped
+   | borrow might be used here, when `factorial` is dropped and runs the destructor for type `std::option::Option<std::boxed::Box<dyn std::ops::Fn(u32) -> u32>>`
 
 error[E0506]: cannot assign to `factorial` because it is borrowed
   --> $DIR/unboxed-closures-failed-recursive-fn-1.rs:30:5
index e2747e1bb62c40910de2285f212f3613b9517408..652a93e610f7e5a17014d5cd6a6945c2604219df 100644 (file)
@@ -2,11 +2,10 @@ error[E0499]: cannot borrow `*self` as mutable more than once at a time
   --> $DIR/unboxed-closures-recursive-fn-using-fn-mut.rs:32:21
    |
 LL |         (self.func)(self, arg)
-   |         ------------^^^^------
-   |         |           |
-   |         |           second mutable borrow occurs here
+   |         ----------- ^^^^ second mutable borrow occurs here
+   |         |
    |         first mutable borrow occurs here
-   |         borrow later used here
+   |         first borrow later used by call
 
 error: aborting due to previous error
 
index cff263231dde7d7f6ff32d51312487c2c54eded5..a5c6e5f1110e1e0b860a7e5afb83a9b7e0600cf3 100644 (file)
@@ -5,7 +5,7 @@ LL |     for x in &mut xs {
    |              -------
    |              |
    |              first mutable borrow occurs here
-   |              borrow used here, in later iteration of loop
+   |              first borrow used here, in later iteration of loop
 LL |         xs.push(1) //~ ERROR cannot borrow `xs`
    |         ^^ second mutable borrow occurs here
 
index 352480543c7e381529f8266e37b47c9cc7a8227e..5b717c45254ccc2dfb4f745c0c30fd734e335ba9 100644 (file)
@@ -61,11 +61,11 @@ struct Test {
     Test {
         name: "servo",
         repo: "https://github.com/servo/servo",
-        sha: "17e97b9320fdb7cdb33bbc5f4d0fde0653bbf2e4",
+        sha: "987e376ca7a4245dbc3e0c06e963278ee1ac92d1",
         lock: None,
         // Only test Stylo a.k.a. Quantum CSS, the parts of Servo going into Firefox.
         // This takes much less time to build than all of Servo and supports stable Rust.
-        packages: &["stylo_tests", "selectors"],
+        packages: &["selectors"],
     },
     Test {
         name: "webrender",
index e69fe2fb19b7b2f3b07fe1178c536810dabf896f..32b1d1fc157f71ed2f10b60fe28abe087a743618 160000 (submodule)
@@ -1 +1 @@
-Subproject commit e69fe2fb19b7b2f3b07fe1178c536810dabf896f
+Subproject commit 32b1d1fc157f71ed2f10b60fe28abe087a743618
index 755b172dd1b2cb23e73fc13386e6753784de752b..77ffe41d7f67960ddc4806f0e77c46ae19738620 100644 (file)
@@ -47,3 +47,11 @@ features = [
   "wincon",
   "wincrypt",
 ]
+
+[dependencies.serde_json]
+version = "1.0.31"
+features = ["raw_value"]
+
+[dependencies.rand]
+version = "0.5.5"
+features = ["i128_support"]